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