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