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