gpg: Fix honoring --cert-digest-algo when recreating a cert
[gnupg.git] / keyserver / ksutil.c
1 /* ksutil.c - general keyserver utility functions
2  * Copyright (C) 2004, 2005, 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  * In addition, as a special exception, the Free Software Foundation
20  * gives permission to link the code of the keyserver helper tools:
21  * gpgkeys_ldap, gpgkeys_curl and gpgkeys_hkp with the OpenSSL
22  * project's "OpenSSL" library (or with modified versions of it that
23  * use the same license as the "OpenSSL" library), and distribute the
24  * linked executables.  You must obey the GNU General Public License
25  * in all respects for all of the code used other than "OpenSSL".  If
26  * you modify this file, you may extend this exception to your version
27  * of the file, but you are not obligated to do so.  If you do not
28  * wish to do so, delete this exception statement from your version.
29  */
30
31 #include <config.h>
32 #include <signal.h>
33 #include <unistd.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37
38 #ifdef HAVE_W32_SYSTEM
39 #include <windows.h>
40 #endif
41
42 #ifdef HAVE_LIBCURL
43 #include <curl/curl.h>
44 #else
45 #include "curl-shim.h"
46 #endif
47 #include "util.h"
48 #include "keyserver.h"
49 #include "ksutil.h"
50
51 #ifdef HAVE_DOSISH_SYSTEM
52
53 unsigned int set_timeout(unsigned int seconds) {return 0;}
54 int register_timeout(void) {return 0;}
55
56 #else
57
58 static void
59 catch_alarm(int foo)
60 {
61   (void)foo;
62   _exit(KEYSERVER_TIMEOUT);
63 }
64
65 unsigned int
66 set_timeout(unsigned int seconds)
67 {
68   return alarm(seconds);
69 }
70
71 int
72 register_timeout(void)
73 {
74 #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
75   struct sigaction act;
76
77   act.sa_handler=catch_alarm;
78   sigemptyset(&act.sa_mask);
79   act.sa_flags=0;
80   return sigaction(SIGALRM,&act,NULL);
81 #else 
82   if(signal(SIGALRM,catch_alarm)==SIG_ERR)
83     return -1;
84   else
85     return 0;
86 #endif
87 }
88
89 #endif /* !HAVE_DOSISH_SYSTEM */
90
91 #ifdef HAVE_W32_SYSTEM
92 void
93 w32_init_sockets (void)
94 {
95   static int initialized;
96   static WSADATA wsdata;
97
98   if (!initialized)
99     {
100       WSAStartup (0x0202, &wsdata);
101       initialized = 1;
102     }
103 }
104 #endif /*HAVE_W32_SYSTEM*/
105
106
107 struct ks_options *
108 init_ks_options(void)
109 {
110   struct ks_options *opt;
111
112   opt=calloc(1,sizeof(struct ks_options));
113
114   if(opt)
115     {
116       opt->action=KS_UNKNOWN;
117       opt->flags.include_revoked=1;
118       opt->flags.include_subkeys=1;
119       opt->flags.check_cert=1;
120       opt->timeout=DEFAULT_KEYSERVER_TIMEOUT;
121       opt->path=strdup("/");
122       if(!opt->path)
123         {
124           free(opt);
125           opt=NULL;
126         }
127     }
128
129   return opt;
130 }
131
132 void
133 free_ks_options(struct ks_options *opt)
134 {
135   if(opt)
136     {
137       free(opt->host);
138       free(opt->port);
139       free(opt->scheme);
140       free(opt->auth);
141       free(opt->path);
142       free(opt->opaque);
143       free(opt->ca_cert_file);
144       free(opt);
145     }
146 }
147
148 /* Returns 0 if we "ate" the line.  Returns >0, a KEYSERVER_ error
149    code if that error applies.  Returns -1 if we did not match the
150    line at all. */
151 int
152 parse_ks_options(char *line,struct ks_options *opt)
153 {
154   int version;
155   char command[MAX_COMMAND+1];
156   char host[MAX_HOST+1];
157   char port[MAX_PORT+1];
158   char scheme[MAX_SCHEME+1];
159   char auth[MAX_AUTH+1];
160   char path[URLMAX_PATH+1];
161   char opaque[MAX_OPAQUE+1];
162   char option[MAX_OPTION+1];
163
164   if(line[0]=='#')
165     return 0;
166
167   if(sscanf(line,"COMMAND %" MKSTRING(MAX_COMMAND) "s\n",command)==1)
168     {
169       command[MAX_COMMAND]='\0';
170
171       if(strcasecmp(command,"get")==0)
172         opt->action=KS_GET;
173       else if(strcasecmp(command,"getname")==0)
174         opt->action=KS_GETNAME;
175       else if(strcasecmp(command,"send")==0)
176         opt->action=KS_SEND;
177       else if(strcasecmp(command,"search")==0)
178         opt->action=KS_SEARCH;
179
180       return 0;
181     }
182
183   if(sscanf(line,"HOST %" MKSTRING(MAX_HOST) "s\n",host)==1)
184     {
185       host[MAX_HOST]='\0';
186       free(opt->host);
187       opt->host=strdup(host);
188       if(!opt->host)
189         return KEYSERVER_NO_MEMORY;
190       return 0;
191     }
192
193   if(sscanf(line,"PORT %" MKSTRING(MAX_PORT) "s\n",port)==1)
194     {
195       port[MAX_PORT]='\0';
196       free(opt->port);
197       opt->port=strdup(port);
198       if(!opt->port)
199         return KEYSERVER_NO_MEMORY;
200       return 0;
201     }
202
203   if(sscanf(line,"SCHEME %" MKSTRING(MAX_SCHEME) "s\n",scheme)==1)
204     {
205       scheme[MAX_SCHEME]='\0';
206       free(opt->scheme);
207       opt->scheme=strdup(scheme);
208       if(!opt->scheme)
209         return KEYSERVER_NO_MEMORY;
210       return 0;
211     }
212
213   if(sscanf(line,"AUTH %" MKSTRING(MAX_AUTH) "s\n",auth)==1)
214     {
215       auth[MAX_AUTH]='\0';
216       free(opt->auth);
217       opt->auth=strdup(auth);
218       if(!opt->auth)
219         return KEYSERVER_NO_MEMORY;
220       return 0;
221     }
222
223   if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1)
224     {
225       path[URLMAX_PATH]='\0';
226       free(opt->path);
227       opt->path=strdup(path);
228       if(!opt->path)
229         return KEYSERVER_NO_MEMORY;
230       return 0;
231     }
232
233   if(sscanf(line,"OPAQUE %" MKSTRING(MAX_OPAQUE) "s\n",opaque)==1)
234     {
235       opaque[MAX_OPAQUE]='\0';
236       free(opt->opaque);
237       opt->opaque=strdup(opaque);
238       if(!opt->opaque)
239         return KEYSERVER_NO_MEMORY;
240       return 0;
241     }
242
243   if(sscanf(line,"VERSION %d\n",&version)==1)
244     {
245       if(version!=KEYSERVER_PROTO_VERSION)
246         return KEYSERVER_VERSION_ERROR;
247
248       return 0;
249     }
250
251   if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "[^\n]\n",option)==1)
252     {
253       int no=0;
254       char *start=&option[0];
255
256       option[MAX_OPTION]='\0';
257
258       if(strncasecmp(option,"no-",3)==0)
259         {
260           no=1;
261           start=&option[3];
262         }
263
264       if(strncasecmp(start,"verbose",7)==0)
265         {
266           if(no)
267             opt->verbose=0;
268           else if(start[7]=='=')
269             opt->verbose=atoi(&start[8]);
270           else
271             opt->verbose++;
272         }
273       else if(strcasecmp(start,"include-disabled")==0)
274         {
275           if(no)
276             opt->flags.include_disabled=0;
277           else
278             opt->flags.include_disabled=1;
279         }
280       else if(strcasecmp(start,"include-revoked")==0)
281         {
282           if(no)
283             opt->flags.include_revoked=0;
284           else
285             opt->flags.include_revoked=1;
286         }
287       else if(strcasecmp(start,"include-subkeys")==0)
288         {
289           if(no)
290             opt->flags.include_subkeys=0;
291           else
292             opt->flags.include_subkeys=1;
293         }
294       else if(strcasecmp(start,"check-cert")==0)
295         {
296           if(no)
297             opt->flags.check_cert=0;
298           else
299             opt->flags.check_cert=1;
300         }
301       else if(strncasecmp(start,"debug",5)==0)
302         {
303           if(no)
304             opt->debug=0;
305           else if(start[5]=='=')
306             opt->debug=atoi(&start[6]);
307           else if(start[5]=='\0')
308             opt->debug=1;
309         }
310       else if(strncasecmp(start,"timeout",7)==0)
311         {
312           if(no)
313             opt->timeout=0;
314           else if(start[7]=='=')
315             opt->timeout=atoi(&start[8]);
316           else if(start[7]=='\0')
317             opt->timeout=DEFAULT_KEYSERVER_TIMEOUT;
318         }
319       else if(strncasecmp(start,"ca-cert-file",12)==0)
320         {
321           if(no)
322             {
323               free(opt->ca_cert_file);
324               opt->ca_cert_file=NULL;
325             }
326           else if(start[12]=='=')
327             {
328               free(opt->ca_cert_file);
329               opt->ca_cert_file = make_filename_try (start+13, NULL);
330               if(!opt->ca_cert_file)
331                 return KEYSERVER_NO_MEMORY;
332             }
333         }
334     }
335
336   return -1;
337 }
338
339 const char *
340 ks_action_to_string(enum ks_action action)
341 {
342   switch(action)
343     {
344     case KS_UNKNOWN: return "UNKNOWN";
345     case KS_GET:     return "GET";
346     case KS_GETNAME: return "GETNAME";
347     case KS_SEND:    return "SEND";
348     case KS_SEARCH:  return "SEARCH";
349     }
350
351   return "?";
352 }
353
354 /* Canonicalize CRLF to just LF by stripping CRs.  This actually makes
355    sense, since on Unix-like machines LF is correct, and on win32-like
356    machines, our output buffer is opened in textmode and will
357    re-canonicalize line endings back to CRLF.  Since we only need to
358    handle armored keys, we don't have to worry about odd cases like
359    CRCRCR and the like. */
360
361 void
362 print_nocr(FILE *stream,const char *str)
363 {
364   while(*str)
365     {
366       if(*str!='\r')
367         fputc(*str,stream);
368       str++;
369     }
370 }
371
372 enum ks_search_type
373 classify_ks_search(const char **search)
374 {
375   switch(**search)
376     {
377     case '*':
378       (*search)++;
379       return KS_SEARCH_SUBSTR;
380     case '=':
381       (*search)++;
382       return KS_SEARCH_EXACT;
383     case '<':
384       (*search)++;
385       return KS_SEARCH_MAIL;
386     case '@':
387       (*search)++;
388       return KS_SEARCH_MAILSUB;
389     case '0':
390       if((*search)[1]=='x')
391         {
392           if(strlen(*search)==10
393              && strspn(*search,"abcdefABCDEF1234567890x")==10)
394             {
395               (*search)+=2;
396               return KS_SEARCH_KEYID_SHORT;
397             }
398           else if(strlen(*search)==18
399                   && strspn(*search,"abcdefABCDEF1234567890x")==18)
400             {
401               (*search)+=2;
402               return KS_SEARCH_KEYID_LONG;
403             }
404         }
405       /* fall through */
406     default:
407       return KS_SEARCH_SUBSTR;
408     }
409 }
410
411 int
412 curl_err_to_gpg_err(CURLcode error)
413 {
414   switch(error)
415     {
416     case CURLE_OK:                    return KEYSERVER_OK;
417     case CURLE_UNSUPPORTED_PROTOCOL:  return KEYSERVER_SCHEME_NOT_FOUND;
418     case CURLE_COULDNT_CONNECT:       return KEYSERVER_UNREACHABLE;
419     case CURLE_FTP_COULDNT_RETR_FILE: return KEYSERVER_KEY_NOT_FOUND;
420     default: return KEYSERVER_INTERNAL_ERROR;
421     }
422 }
423
424 #define B64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
425
426 static void
427 curl_armor_writer(const unsigned char *buf,size_t size,void *cw_ctx)
428 {
429   struct curl_writer_ctx *ctx=cw_ctx;
430   size_t idx=0;
431
432   while(idx<size)
433     {
434       for(;ctx->armor_remaining<3 && idx<size;ctx->armor_remaining++,idx++)
435         ctx->armor_ctx[ctx->armor_remaining]=buf[idx];
436
437       if(ctx->armor_remaining==3)
438         {
439           /* Top 6 bytes of ctx->armor_ctx[0] */
440           fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
441           /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
442              ctx->armor_ctx[1] */
443           fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30)
444                      |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream);
445           /* Bottom 4 bytes of ctx->armor_ctx[1] and top 2 bytes of
446              ctx->armor_ctx[2] */
447           fputc(B64[(((ctx->armor_ctx[1]<<2)&0x3C)
448                      |((ctx->armor_ctx[2]>>6)&0x03))&0x3F],ctx->stream);
449           /* Bottom 6 bytes of ctx->armor_ctx[2] */
450           fputc(B64[(ctx->armor_ctx[2]&0x3F)],ctx->stream);
451
452           ctx->linelen+=4;
453           if(ctx->linelen>=70)
454             {
455               fputc('\n',ctx->stream);
456               ctx->linelen=0;
457             }
458
459           ctx->armor_remaining=0;
460         }
461     }
462
463 }
464
465 size_t
466 curl_writer(const void *ptr,size_t size,size_t nmemb,void *cw_ctx)
467 {
468   struct curl_writer_ctx *ctx=cw_ctx;
469   const char *buf=ptr;
470   size_t i;
471
472   if(!ctx->flags.initialized)
473     {
474       if(size*nmemb==0)
475         return 0;
476
477       /* The object we're fetching is in binary form */
478       if(*buf&0x80)
479         {
480           ctx->flags.armor=1;
481           fprintf(ctx->stream,BEGIN"\n\n");
482         }
483       else
484         ctx->marker=BEGIN;
485
486       ctx->flags.initialized=1;
487     }
488
489   if(ctx->flags.armor)
490     curl_armor_writer(ptr,size*nmemb,cw_ctx);
491   else
492     {
493       /* scan the incoming data for our marker */
494       for(i=0;!ctx->flags.done && i<(size*nmemb);i++)
495         {
496           if(buf[i]==ctx->marker[ctx->markeridx])
497             {
498               ctx->markeridx++;
499               if(ctx->marker[ctx->markeridx]=='\0')
500                 {
501                   if(ctx->flags.begun)
502                     ctx->flags.done=1;
503                   else
504                     {
505                       /* We've found the BEGIN marker, so now we're
506                          looking for the END marker. */
507                       ctx->flags.begun=1;
508                       ctx->marker=END;
509                       ctx->markeridx=0;
510                       fprintf(ctx->stream,BEGIN);
511                       continue;
512                     }
513                 }
514             }
515           else
516             ctx->markeridx=0;
517
518           if(ctx->flags.begun)
519             {
520               /* Canonicalize CRLF to just LF by stripping CRs.  This
521                  actually makes sense, since on Unix-like machines LF
522                  is correct, and on win32-like machines, our output
523                  buffer is opened in textmode and will re-canonicalize
524                  line endings back to CRLF.  Since this code is just
525                  for handling armored keys, we don't have to worry
526                  about odd cases like CRCRCR and the like. */
527
528               if(buf[i]!='\r')
529                 fputc(buf[i],ctx->stream);
530             }
531         }
532     }
533
534   return size*nmemb;
535 }
536
537 void
538 curl_writer_finalize(struct curl_writer_ctx *ctx)
539 {
540   if(ctx->flags.armor)
541     {
542       if(ctx->armor_remaining==2)
543         {
544           /* Top 6 bytes of ctx->armorctx[0] */
545           fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
546           /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
547              ctx->armor_ctx[1] */
548           fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30)
549                      |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream);
550           /* Bottom 4 bytes of ctx->armor_ctx[1] */
551           fputc(B64[((ctx->armor_ctx[1]<<2)&0x3C)],ctx->stream);
552           /* Pad */
553           fputc('=',ctx->stream);
554         }
555       else if(ctx->armor_remaining==1)
556         {
557           /* Top 6 bytes of ctx->armor_ctx[0] */
558           fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
559           /* Bottom 2 bytes of ctx->armor_ctx[0] */
560           fputc(B64[((ctx->armor_ctx[0]<<4)&0x30)],ctx->stream);
561           /* Pad */
562           fputc('=',ctx->stream);
563           /* Pad */
564           fputc('=',ctx->stream);
565         }
566
567       fprintf(ctx->stream,"\n"END);
568       ctx->flags.done=1;
569     }
570 }
571
572
573 int
574 ks_hextobyte (const char *s)
575 {
576   int c;
577
578   if ( *s >= '0' && *s <= '9' )
579     c = 16 * (*s - '0');
580   else if ( *s >= 'A' && *s <= 'F' )
581     c = 16 * (10 + *s - 'A');
582   else if ( *s >= 'a' && *s <= 'f' )
583     c = 16 * (10 + *s - 'a');
584   else
585     return -1;
586   s++;
587   if ( *s >= '0' && *s <= '9' )
588     c += *s - '0';
589   else if ( *s >= 'A' && *s <= 'F' )
590     c += 10 + *s - 'A';
591   else if ( *s >= 'a' && *s <= 'f' )
592     c += 10 + *s - 'a';
593   else
594     return -1;
595   return c;
596 }
597
598
599 /* Non localized version of toupper.  */
600 int 
601 ks_toupper (int c)
602 {
603   if (c >= 'a' && c <= 'z')
604     c &= ~0x20;
605   return c;
606 }
607
608
609 /* Non localized version of strcasecmp.  */
610 int
611 ks_strcasecmp (const char *a, const char *b)
612 {
613   if (a == b)
614     return 0;
615
616   for (; *a && *b; a++, b++)
617     {
618       if (*a != *b && ks_toupper (*a) != ks_toupper (*b))
619         break;
620     }
621   return *a == *b? 0 : (ks_toupper (*a) - ks_toupper (*b));
622 }