Changed to GPLv3.
[gnupg.git] / tools / make-dns-cert.c
1 /* make-dns-cert.c - An OpenPGP-to-DNS CERT conversion tool
2  * Copyright (C) 2006 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <unistd.h>
22 #ifdef HAVE_GETOPT_H
23 #include <getopt.h>
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32
33 /* We use TYPE37 instead of CERT since not all nameservers can handle
34    CERT yet... */
35
36 static int
37 cert_key(const char *name,const char *keyfile)
38 {
39   int fd,ret=1,err,i;
40   struct stat statbuf;
41
42   fd=open(keyfile,O_RDONLY);
43   if(fd==-1)
44     {
45       fprintf(stderr,"Cannot open key file %s: %s\n",keyfile,strerror(errno));
46       return 1;
47     }
48
49   err=fstat(fd,&statbuf);
50   if(err==-1)
51     {
52       fprintf(stderr,"Unable to stat key file %s: %s\n",
53               keyfile,strerror(errno));
54       goto fail;
55     }
56
57   if(statbuf.st_size>65536)
58     {
59       fprintf(stderr,"Key %s too large for CERT encoding\n",keyfile);
60       goto fail;
61     }
62
63   if(statbuf.st_size>16384)
64     fprintf(stderr,"Warning: key file %s is larger than the default"
65             " GnuPG max-cert-size\n",keyfile);
66
67   printf("%s\tTYPE37\t\\# %u 0003 0000 00 ",
68          name,(unsigned int)statbuf.st_size+5);
69
70   err=1;
71   while(err!=0)
72     {
73       unsigned char buffer[1024];
74
75       err=read(fd,buffer,1024);
76       if(err==-1)
77         {
78           fprintf(stderr,"Unable to read key file %s: %s\n",
79                   keyfile,strerror(errno));
80           goto fail;
81         }
82
83       for(i=0;i<err;i++)
84         printf("%02X",buffer[i]);
85     }
86
87   printf("\n");
88
89   ret=0;
90
91  fail:
92   close(fd);
93
94   return ret;
95 }
96
97 static int
98 url_key(const char *name,const char *fpr,const char *url)
99 {
100   int len=6,fprlen=0;
101
102   if(fpr)
103     {
104       const char *tmp = fpr;
105       while (*tmp)
106         {
107           if ((*tmp >= 'A' && *tmp <= 'F') ||
108               (*tmp >= 'a' && *tmp <= 'f') ||
109               (*tmp >= '0' && *tmp <= '9'))
110             {
111               fprlen++;
112             }
113           else if (*tmp != ' ' && *tmp != '\t')
114             {
115               fprintf(stderr,"Fingerprint must consist of only hex digits"
116                       " and whitespace\n");
117               return 1;
118             }
119
120           tmp++;
121         }
122
123       if(fprlen%2)
124         {
125           fprintf(stderr,"Fingerprint must be an even number of characters\n");
126           return 1;
127         }
128
129       fprlen/=2;
130       len+=fprlen;
131     }
132
133   if(url)
134     len+=strlen(url);
135
136   if(!fpr && !url)
137     {
138       fprintf(stderr,
139               "Cannot generate a CERT without either a fingerprint or URL\n");
140       return 1;
141     }
142
143   printf("%s\tTYPE37\t\\# %d 0006 0000 00 %02X",name,len,fprlen);
144
145   if(fpr)
146     printf(" %s",fpr);
147
148   if(url)
149     {
150       const char *c;
151       printf(" ");
152       for(c=url;*c;c++)
153         printf("%02X",*c);
154     }
155
156   printf("\n");
157
158   return 0;
159 }
160
161 static void
162 usage(FILE *stream)
163 {
164   fprintf(stream,"make-dns-cert\n");
165   fprintf(stream,"\t-f\tfingerprint\n");
166   fprintf(stream,"\t-u\tURL\n");
167   fprintf(stream,"\t-k\tkey file\n");
168   fprintf(stream,"\t-n\tDNS name\n");
169 }
170
171 int
172 main(int argc,char *argv[])
173 {
174   int arg,err=1;
175   char *fpr=NULL,*url=NULL,*keyfile=NULL,*name=NULL;
176
177   if(argc==1)
178     {
179       usage(stderr);
180       return 1;
181     }
182   else if(argc>1 && strcmp(argv[1],"--version")==0)
183     {
184       printf("make-dns-cert (GnuPG) " VERSION "\n");
185       return 0;
186     }
187   else if(argc>1 && strcmp(argv[1],"--help")==0)
188     {
189       usage(stdout);
190       return 0;
191     }
192
193   while((arg=getopt(argc,argv,"hf:u:k:n:"))!=-1)
194     switch(arg)
195       {
196       default:
197       case 'h':
198         usage(stdout);
199         exit(0);
200
201       case 'f':
202         fpr=optarg;
203         break;
204
205       case 'u':
206         url=optarg;
207         break;
208
209       case 'k':
210         keyfile=optarg;
211         break;
212
213       case 'n':
214         name=optarg;
215         break;
216       }
217
218   if(!name)
219     {
220       fprintf(stderr,"No name provided\n");
221       return 1;
222     }
223
224   if(keyfile && (fpr || url))
225     {
226       fprintf(stderr,"Cannot generate a CERT record with both a keyfile and"
227               " a fingerprint or URL\n");
228       return 1;
229     }
230
231   if(keyfile)
232     err=cert_key(name,keyfile);
233   else
234     err=url_key(name,fpr,url);
235
236   return err;
237 }