* gpg.texi (GPG Configuration Options): Make http_proxy option
[gnupg.git] / keyserver / ksutil.c
blob18158fc810b014de0d38fd2a89d8292ab9e5239c
1 /* ksutil.c - general keyserver utility functions
2 * Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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.
21 * In addition, as a special exception, the Free Software Foundation
22 * gives permission to link the code of the keyserver helper tools:
23 * gpgkeys_ldap, gpgkeys_curl and gpgkeys_hkp with the OpenSSL
24 * project's "OpenSSL" library (or with modified versions of it that
25 * use the same license as the "OpenSSL" library), and distribute the
26 * linked executables. You must obey the GNU General Public License
27 * in all respects for all of the code used other than "OpenSSL". If
28 * you modify this file, you may extend this exception to your version
29 * of the file, but you are not obligated to do so. If you do not
30 * wish to do so, delete this exception statement from your version.
33 #include <config.h>
34 #include <signal.h>
35 #include <unistd.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
40 #ifdef HAVE_LIBCURL
41 #include <curl/curl.h>
42 #else
43 #include "curl-shim.h"
44 #endif
45 #include "keyserver.h"
46 #include "ksutil.h"
48 #ifdef HAVE_DOSISH_SYSTEM
50 unsigned int set_timeout(unsigned int seconds) {return 0;}
51 int register_timeout(void) {return 0;}
53 #else
55 static void
56 catch_alarm(int foo)
58 (void)foo;
59 _exit(KEYSERVER_TIMEOUT);
62 unsigned int
63 set_timeout(unsigned int seconds)
65 return alarm(seconds);
68 int
69 register_timeout(void)
71 #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
72 struct sigaction act;
74 act.sa_handler=catch_alarm;
75 sigemptyset(&act.sa_mask);
76 act.sa_flags=0;
77 return sigaction(SIGALRM,&act,NULL);
78 #else
79 if(signal(SIGALRM,catch_alarm)==SIG_ERR)
80 return -1;
81 else
82 return 0;
83 #endif
86 #endif /* !HAVE_DOSISH_SYSTEM */
88 struct ks_options *
89 init_ks_options(void)
91 struct ks_options *opt;
93 opt=calloc(1,sizeof(struct ks_options));
95 if(opt)
97 opt->action=KS_UNKNOWN;
98 opt->flags.include_revoked=1;
99 opt->flags.include_subkeys=1;
100 opt->flags.check_cert=1;
101 opt->timeout=DEFAULT_KEYSERVER_TIMEOUT;
102 opt->path=strdup("/");
103 if(!opt->path)
105 free(opt);
106 opt=NULL;
110 return opt;
113 void
114 free_ks_options(struct ks_options *opt)
116 if(opt)
118 free(opt->host);
119 free(opt->port);
120 free(opt->scheme);
121 free(opt->auth);
122 free(opt->path);
123 free(opt->opaque);
124 free(opt->ca_cert_file);
125 free(opt);
129 /* Returns 0 if we "ate" the line. Returns >0, a KEYSERVER_ error
130 code if that error applies. Returns -1 if we did not match the
131 line at all. */
133 parse_ks_options(char *line,struct ks_options *opt)
135 int version;
136 char command[MAX_COMMAND+1];
137 char host[MAX_HOST+1];
138 char port[MAX_PORT+1];
139 char scheme[MAX_SCHEME+1];
140 char auth[MAX_AUTH+1];
141 char path[URLMAX_PATH+1];
142 char opaque[MAX_OPAQUE+1];
143 char option[MAX_OPTION+1];
145 if(line[0]=='#')
146 return 0;
148 if(sscanf(line,"COMMAND %" MKSTRING(MAX_COMMAND) "s\n",command)==1)
150 command[MAX_COMMAND]='\0';
152 if(strcasecmp(command,"get")==0)
153 opt->action=KS_GET;
154 else if(strcasecmp(command,"getname")==0)
155 opt->action=KS_GETNAME;
156 else if(strcasecmp(command,"send")==0)
157 opt->action=KS_SEND;
158 else if(strcasecmp(command,"search")==0)
159 opt->action=KS_SEARCH;
161 return 0;
164 if(sscanf(line,"HOST %" MKSTRING(MAX_HOST) "s\n",host)==1)
166 host[MAX_HOST]='\0';
167 free(opt->host);
168 opt->host=strdup(host);
169 if(!opt->host)
170 return KEYSERVER_NO_MEMORY;
171 return 0;
174 if(sscanf(line,"PORT %" MKSTRING(MAX_PORT) "s\n",port)==1)
176 port[MAX_PORT]='\0';
177 free(opt->port);
178 opt->port=strdup(port);
179 if(!opt->port)
180 return KEYSERVER_NO_MEMORY;
181 return 0;
184 if(sscanf(line,"SCHEME %" MKSTRING(MAX_SCHEME) "s\n",scheme)==1)
186 scheme[MAX_SCHEME]='\0';
187 free(opt->scheme);
188 opt->scheme=strdup(scheme);
189 if(!opt->scheme)
190 return KEYSERVER_NO_MEMORY;
191 return 0;
194 if(sscanf(line,"AUTH %" MKSTRING(MAX_AUTH) "s\n",auth)==1)
196 auth[MAX_AUTH]='\0';
197 free(opt->auth);
198 opt->auth=strdup(auth);
199 if(!opt->auth)
200 return KEYSERVER_NO_MEMORY;
201 return 0;
204 if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1)
206 path[URLMAX_PATH]='\0';
207 free(opt->path);
208 opt->path=strdup(path);
209 if(!opt->path)
210 return KEYSERVER_NO_MEMORY;
211 return 0;
214 if(sscanf(line,"OPAQUE %" MKSTRING(MAX_OPAQUE) "s\n",opaque)==1)
216 opaque[MAX_OPAQUE]='\0';
217 free(opt->opaque);
218 opt->opaque=strdup(opaque);
219 if(!opt->opaque)
220 return KEYSERVER_NO_MEMORY;
221 return 0;
224 if(sscanf(line,"VERSION %d\n",&version)==1)
226 if(version!=KEYSERVER_PROTO_VERSION)
227 return KEYSERVER_VERSION_ERROR;
229 return 0;
232 if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "[^\n]\n",option)==1)
234 int no=0;
235 char *start=&option[0];
237 option[MAX_OPTION]='\0';
239 if(strncasecmp(option,"no-",3)==0)
241 no=1;
242 start=&option[3];
245 if(strncasecmp(start,"verbose",7)==0)
247 if(no)
248 opt->verbose=0;
249 else if(start[7]=='=')
250 opt->verbose=atoi(&start[8]);
251 else
252 opt->verbose++;
254 else if(strcasecmp(start,"include-disabled")==0)
256 if(no)
257 opt->flags.include_disabled=0;
258 else
259 opt->flags.include_disabled=1;
261 else if(strcasecmp(start,"include-revoked")==0)
263 if(no)
264 opt->flags.include_revoked=0;
265 else
266 opt->flags.include_revoked=1;
268 else if(strcasecmp(start,"include-subkeys")==0)
270 if(no)
271 opt->flags.include_subkeys=0;
272 else
273 opt->flags.include_subkeys=1;
275 else if(strcasecmp(start,"check-cert")==0)
277 if(no)
278 opt->flags.check_cert=0;
279 else
280 opt->flags.check_cert=1;
282 else if(strncasecmp(start,"debug",5)==0)
284 if(no)
285 opt->debug=0;
286 else if(start[5]=='=')
287 opt->debug=atoi(&start[6]);
288 else if(start[5]=='\0')
289 opt->debug=1;
291 else if(strncasecmp(start,"timeout",7)==0)
293 if(no)
294 opt->timeout=0;
295 else if(start[7]=='=')
296 opt->timeout=atoi(&start[8]);
297 else if(start[7]=='\0')
298 opt->timeout=DEFAULT_KEYSERVER_TIMEOUT;
300 else if(strncasecmp(start,"ca-cert-file",12)==0)
302 if(no)
304 free(opt->ca_cert_file);
305 opt->ca_cert_file=NULL;
307 else if(start[12]=='=')
309 free(opt->ca_cert_file);
310 opt->ca_cert_file=strdup(&start[13]);
311 if(!opt->ca_cert_file)
312 return KEYSERVER_NO_MEMORY;
317 return -1;
320 const char *
321 ks_action_to_string(enum ks_action action)
323 switch(action)
325 case KS_UNKNOWN: return "UNKNOWN";
326 case KS_GET: return "GET";
327 case KS_GETNAME: return "GETNAME";
328 case KS_SEND: return "SEND";
329 case KS_SEARCH: return "SEARCH";
332 return "?";
335 /* Canonicalize CRLF to just LF by stripping CRs. This actually makes
336 sense, since on Unix-like machines LF is correct, and on win32-like
337 machines, our output buffer is opened in textmode and will
338 re-canonicalize line endings back to CRLF. Since we only need to
339 handle armored keys, we don't have to worry about odd cases like
340 CRCRCR and the like. */
342 void
343 print_nocr(FILE *stream,const char *str)
345 while(*str)
347 if(*str!='\r')
348 fputc(*str,stream);
349 str++;
353 enum ks_search_type
354 classify_ks_search(const char **search)
356 switch(**search)
358 case '*':
359 (*search)++;
360 return KS_SEARCH_SUBSTR;
361 case '=':
362 (*search)++;
363 return KS_SEARCH_EXACT;
364 case '<':
365 (*search)++;
366 return KS_SEARCH_MAIL;
367 case '@':
368 (*search)++;
369 return KS_SEARCH_MAILSUB;
370 case '0':
371 if((*search)[1]=='x')
373 if(strlen(*search)==10
374 && strspn(*search,"abcdefABCDEF1234567890x")==10)
376 (*search)+=2;
377 return KS_SEARCH_KEYID_SHORT;
379 else if(strlen(*search)==18
380 && strspn(*search,"abcdefABCDEF1234567890x")==18)
382 (*search)+=2;
383 return KS_SEARCH_KEYID_LONG;
386 /* fall through */
387 default:
388 return KS_SEARCH_SUBSTR;
393 curl_err_to_gpg_err(CURLcode error)
395 switch(error)
397 case CURLE_OK: return KEYSERVER_OK;
398 case CURLE_UNSUPPORTED_PROTOCOL: return KEYSERVER_SCHEME_NOT_FOUND;
399 case CURLE_COULDNT_CONNECT: return KEYSERVER_UNREACHABLE;
400 case CURLE_FTP_COULDNT_RETR_FILE: return KEYSERVER_KEY_NOT_FOUND;
401 default: return KEYSERVER_INTERNAL_ERROR;
405 #define B64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
407 static void
408 curl_armor_writer(const unsigned char *buf,size_t size,void *cw_ctx)
410 struct curl_writer_ctx *ctx=cw_ctx;
411 size_t idx=0;
413 while(idx<size)
415 for(;ctx->armor_remaining<3 && idx<size;ctx->armor_remaining++,idx++)
416 ctx->armor_ctx[ctx->armor_remaining]=buf[idx];
418 if(ctx->armor_remaining==3)
420 /* Top 6 bytes of ctx->armor_ctx[0] */
421 fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
422 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
423 ctx->armor_ctx[1] */
424 fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30)
425 |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream);
426 /* Bottom 4 bytes of ctx->armor_ctx[1] and top 2 bytes of
427 ctx->armor_ctx[2] */
428 fputc(B64[(((ctx->armor_ctx[1]<<2)&0x3C)
429 |((ctx->armor_ctx[2]>>6)&0x03))&0x3F],ctx->stream);
430 /* Bottom 6 bytes of ctx->armor_ctx[2] */
431 fputc(B64[(ctx->armor_ctx[2]&0x3F)],ctx->stream);
433 ctx->linelen+=4;
434 if(ctx->linelen>=70)
436 fputc('\n',ctx->stream);
437 ctx->linelen=0;
440 ctx->armor_remaining=0;
446 size_t
447 curl_writer(const void *ptr,size_t size,size_t nmemb,void *cw_ctx)
449 struct curl_writer_ctx *ctx=cw_ctx;
450 const char *buf=ptr;
451 size_t i;
453 if(!ctx->flags.initialized)
455 if(size*nmemb==0)
456 return 0;
458 /* The object we're fetching is in binary form */
459 if(*buf&0x80)
461 ctx->flags.armor=1;
462 fprintf(ctx->stream,BEGIN"\n\n");
464 else
465 ctx->marker=BEGIN;
467 ctx->flags.initialized=1;
470 if(ctx->flags.armor)
471 curl_armor_writer(ptr,size*nmemb,cw_ctx);
472 else
474 /* scan the incoming data for our marker */
475 for(i=0;!ctx->flags.done && i<(size*nmemb);i++)
477 if(buf[i]==ctx->marker[ctx->markeridx])
479 ctx->markeridx++;
480 if(ctx->marker[ctx->markeridx]=='\0')
482 if(ctx->flags.begun)
483 ctx->flags.done=1;
484 else
486 /* We've found the BEGIN marker, so now we're
487 looking for the END marker. */
488 ctx->flags.begun=1;
489 ctx->marker=END;
490 ctx->markeridx=0;
491 fprintf(ctx->stream,BEGIN);
492 continue;
496 else
497 ctx->markeridx=0;
499 if(ctx->flags.begun)
501 /* Canonicalize CRLF to just LF by stripping CRs. This
502 actually makes sense, since on Unix-like machines LF
503 is correct, and on win32-like machines, our output
504 buffer is opened in textmode and will re-canonicalize
505 line endings back to CRLF. Since this code is just
506 for handling armored keys, we don't have to worry
507 about odd cases like CRCRCR and the like. */
509 if(buf[i]!='\r')
510 fputc(buf[i],ctx->stream);
515 return size*nmemb;
518 void
519 curl_writer_finalize(struct curl_writer_ctx *ctx)
521 if(ctx->flags.armor)
523 if(ctx->armor_remaining==2)
525 /* Top 6 bytes of ctx->armorctx[0] */
526 fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
527 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
528 ctx->armor_ctx[1] */
529 fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30)
530 |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream);
531 /* Bottom 4 bytes of ctx->armor_ctx[1] */
532 fputc(B64[((ctx->armor_ctx[1]<<2)&0x3C)],ctx->stream);
533 /* Pad */
534 fputc('=',ctx->stream);
536 else if(ctx->armor_remaining==1)
538 /* Top 6 bytes of ctx->armor_ctx[0] */
539 fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
540 /* Bottom 2 bytes of ctx->armor_ctx[0] */
541 fputc(B64[((ctx->armor_ctx[0]<<4)&0x30)],ctx->stream);
542 /* Pad */
543 fputc('=',ctx->stream);
544 /* Pad */
545 fputc('=',ctx->stream);
548 fprintf(ctx->stream,"\n"END);
549 ctx->flags.done=1;
555 ks_hextobyte (const char *s)
557 int c;
559 if ( *s >= '0' && *s <= '9' )
560 c = 16 * (*s - '0');
561 else if ( *s >= 'A' && *s <= 'F' )
562 c = 16 * (10 + *s - 'A');
563 else if ( *s >= 'a' && *s <= 'f' )
564 c = 16 * (10 + *s - 'a');
565 else
566 return -1;
567 s++;
568 if ( *s >= '0' && *s <= '9' )
569 c += *s - '0';
570 else if ( *s >= 'A' && *s <= 'F' )
571 c += 10 + *s - 'A';
572 else if ( *s >= 'a' && *s <= 'f' )
573 c += 10 + *s - 'a';
574 else
575 return -1;
576 return c;
580 /* Non localized version of toupper. */
581 int
582 ks_toupper (int c)
584 if (c >= 'a' && c <= 'z')
585 c &= ~0x20;
586 return c;
590 /* Non localized version of strcasecmp. */
592 ks_strcasecmp (const char *a, const char *b)
594 if (a == b)
595 return 0;
597 for (; *a && *b; a++, b++)
599 if (*a != *b && ks_toupper (*a) != ks_toupper (*b))
600 break;
602 return *a == *b? 0 : (ks_toupper (*a) - ks_toupper (*b));