[scd] Memory leak fix.
[gnupg.git] / keyserver / ksutil.c
blobcc46b92a998f223d8d55963e9c428e6822b66880
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 3 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, see <http://www.gnu.org/licenses/>.
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.
31 #include <config.h>
32 #include <signal.h>
33 #include <unistd.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
38 #ifdef HAVE_W32_SYSTEM
39 #include <windows.h>
40 #endif
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"
51 #ifdef HAVE_DOSISH_SYSTEM
53 unsigned int set_timeout(unsigned int seconds) {return 0;}
54 int register_timeout(void) {return 0;}
56 #else
58 static void
59 catch_alarm(int foo)
61 (void)foo;
62 _exit(KEYSERVER_TIMEOUT);
65 unsigned int
66 set_timeout(unsigned int seconds)
68 return alarm(seconds);
71 int
72 register_timeout(void)
74 #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
75 struct sigaction act;
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
89 #endif /* !HAVE_DOSISH_SYSTEM */
91 #ifdef HAVE_W32_SYSTEM
92 void
93 w32_init_sockets (void)
95 static int initialized;
96 static WSADATA wsdata;
98 if (!initialized)
100 WSAStartup (0x0202, &wsdata);
101 initialized = 1;
104 #endif /*HAVE_W32_SYSTEM*/
107 struct ks_options *
108 init_ks_options(void)
110 struct ks_options *opt;
112 opt=calloc(1,sizeof(struct ks_options));
114 if(opt)
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)
124 free(opt);
125 opt=NULL;
129 return opt;
132 void
133 free_ks_options(struct ks_options *opt)
135 if(opt)
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);
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. */
152 parse_ks_options(char *line,struct ks_options *opt)
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];
164 if(line[0]=='#')
165 return 0;
167 if(sscanf(line,"COMMAND %" MKSTRING(MAX_COMMAND) "s\n",command)==1)
169 command[MAX_COMMAND]='\0';
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;
180 return 0;
183 if(sscanf(line,"HOST %" MKSTRING(MAX_HOST) "s\n",host)==1)
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;
193 if(sscanf(line,"PORT %" MKSTRING(MAX_PORT) "s\n",port)==1)
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;
203 if(sscanf(line,"SCHEME %" MKSTRING(MAX_SCHEME) "s\n",scheme)==1)
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;
213 if(sscanf(line,"AUTH %" MKSTRING(MAX_AUTH) "s\n",auth)==1)
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;
223 if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1)
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;
233 if(sscanf(line,"OPAQUE %" MKSTRING(MAX_OPAQUE) "s\n",opaque)==1)
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;
243 if(sscanf(line,"VERSION %d\n",&version)==1)
245 if(version!=KEYSERVER_PROTO_VERSION)
246 return KEYSERVER_VERSION_ERROR;
248 return 0;
251 if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "[^\n]\n",option)==1)
253 int no=0;
254 char *start=&option[0];
256 option[MAX_OPTION]='\0';
258 if(strncasecmp(option,"no-",3)==0)
260 no=1;
261 start=&option[3];
264 if(strncasecmp(start,"verbose",7)==0)
266 if(no)
267 opt->verbose=0;
268 else if(start[7]=='=')
269 opt->verbose=atoi(&start[8]);
270 else
271 opt->verbose++;
273 else if(strcasecmp(start,"include-disabled")==0)
275 if(no)
276 opt->flags.include_disabled=0;
277 else
278 opt->flags.include_disabled=1;
280 else if(strcasecmp(start,"include-revoked")==0)
282 if(no)
283 opt->flags.include_revoked=0;
284 else
285 opt->flags.include_revoked=1;
287 else if(strcasecmp(start,"include-subkeys")==0)
289 if(no)
290 opt->flags.include_subkeys=0;
291 else
292 opt->flags.include_subkeys=1;
294 else if(strcasecmp(start,"check-cert")==0)
296 if(no)
297 opt->flags.check_cert=0;
298 else
299 opt->flags.check_cert=1;
301 else if(strncasecmp(start,"debug",5)==0)
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;
310 else if(strncasecmp(start,"timeout",7)==0)
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;
319 else if(strncasecmp(start,"ca-cert-file",12)==0)
321 if(no)
323 free(opt->ca_cert_file);
324 opt->ca_cert_file=NULL;
326 else if(start[12]=='=')
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;
336 return -1;
339 const char *
340 ks_action_to_string(enum ks_action action)
342 switch(action)
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";
351 return "?";
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. */
361 void
362 print_nocr(FILE *stream,const char *str)
364 while(*str)
366 if(*str!='\r')
367 fputc(*str,stream);
368 str++;
372 enum ks_search_type
373 classify_ks_search(const char **search)
375 switch(**search)
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')
392 if(strlen(*search)==10
393 && strspn(*search,"abcdefABCDEF1234567890x")==10)
395 (*search)+=2;
396 return KS_SEARCH_KEYID_SHORT;
398 else if(strlen(*search)==18
399 && strspn(*search,"abcdefABCDEF1234567890x")==18)
401 (*search)+=2;
402 return KS_SEARCH_KEYID_LONG;
405 /* fall through */
406 default:
407 return KS_SEARCH_SUBSTR;
412 curl_err_to_gpg_err(CURLcode error)
414 switch(error)
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;
424 #define B64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
426 static void
427 curl_armor_writer(const unsigned char *buf,size_t size,void *cw_ctx)
429 struct curl_writer_ctx *ctx=cw_ctx;
430 size_t idx=0;
432 while(idx<size)
434 for(;ctx->armor_remaining<3 && idx<size;ctx->armor_remaining++,idx++)
435 ctx->armor_ctx[ctx->armor_remaining]=buf[idx];
437 if(ctx->armor_remaining==3)
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);
452 ctx->linelen+=4;
453 if(ctx->linelen>=70)
455 fputc('\n',ctx->stream);
456 ctx->linelen=0;
459 ctx->armor_remaining=0;
465 size_t
466 curl_writer(const void *ptr,size_t size,size_t nmemb,void *cw_ctx)
468 struct curl_writer_ctx *ctx=cw_ctx;
469 const char *buf=ptr;
470 size_t i;
472 if(!ctx->flags.initialized)
474 if(size*nmemb==0)
475 return 0;
477 /* The object we're fetching is in binary form */
478 if(*buf&0x80)
480 ctx->flags.armor=1;
481 fprintf(ctx->stream,BEGIN"\n\n");
483 else
484 ctx->marker=BEGIN;
486 ctx->flags.initialized=1;
489 if(ctx->flags.armor)
490 curl_armor_writer(ptr,size*nmemb,cw_ctx);
491 else
493 /* scan the incoming data for our marker */
494 for(i=0;!ctx->flags.done && i<(size*nmemb);i++)
496 if(buf[i]==ctx->marker[ctx->markeridx])
498 ctx->markeridx++;
499 if(ctx->marker[ctx->markeridx]=='\0')
501 if(ctx->flags.begun)
502 ctx->flags.done=1;
503 else
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;
515 else
516 ctx->markeridx=0;
518 if(ctx->flags.begun)
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. */
528 if(buf[i]!='\r')
529 fputc(buf[i],ctx->stream);
534 return size*nmemb;
537 void
538 curl_writer_finalize(struct curl_writer_ctx *ctx)
540 if(ctx->flags.armor)
542 if(ctx->armor_remaining==2)
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);
555 else if(ctx->armor_remaining==1)
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);
567 fprintf(ctx->stream,"\n"END);
568 ctx->flags.done=1;
574 ks_hextobyte (const char *s)
576 int c;
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;
599 /* Non localized version of toupper. */
600 int
601 ks_toupper (int c)
603 if (c >= 'a' && c <= 'z')
604 c &= ~0x20;
605 return c;
609 /* Non localized version of strcasecmp. */
611 ks_strcasecmp (const char *a, const char *b)
613 if (a == b)
614 return 0;
616 for (; *a && *b; a++, b++)
618 if (*a != *b && ks_toupper (*a) != ks_toupper (*b))
619 break;
621 return *a == *b? 0 : (ks_toupper (*a) - ks_toupper (*b));