Translation fix
[gnupg.git] / keyserver / ksutil.c
blobb25f8eb7b74bc9e078a1e389262fa06c27349fb3
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 "keyserver.h"
48 #include "ksutil.h"
50 #ifdef HAVE_DOSISH_SYSTEM
52 unsigned int set_timeout(unsigned int seconds) {return 0;}
53 int register_timeout(void) {return 0;}
55 #else
57 static void
58 catch_alarm(int foo)
60 (void)foo;
61 _exit(KEYSERVER_TIMEOUT);
64 unsigned int
65 set_timeout(unsigned int seconds)
67 return alarm(seconds);
70 int
71 register_timeout(void)
73 #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
74 struct sigaction act;
76 act.sa_handler=catch_alarm;
77 sigemptyset(&act.sa_mask);
78 act.sa_flags=0;
79 return sigaction(SIGALRM,&act,NULL);
80 #else
81 if(signal(SIGALRM,catch_alarm)==SIG_ERR)
82 return -1;
83 else
84 return 0;
85 #endif
88 #endif /* !HAVE_DOSISH_SYSTEM */
90 #ifdef HAVE_W32_SYSTEM
91 void
92 w32_init_sockets (void)
94 static int initialized;
95 static WSADATA wsdata;
97 if (!initialized)
99 WSAStartup (0x0202, &wsdata);
100 initialized = 1;
103 #endif /*HAVE_W32_SYSTEM*/
106 struct ks_options *
107 init_ks_options(void)
109 struct ks_options *opt;
111 opt=calloc(1,sizeof(struct ks_options));
113 if(opt)
115 opt->action=KS_UNKNOWN;
116 opt->flags.include_revoked=1;
117 opt->flags.include_subkeys=1;
118 opt->flags.check_cert=1;
119 opt->timeout=DEFAULT_KEYSERVER_TIMEOUT;
120 opt->path=strdup("/");
121 if(!opt->path)
123 free(opt);
124 opt=NULL;
128 return opt;
131 void
132 free_ks_options(struct ks_options *opt)
134 if(opt)
136 free(opt->host);
137 free(opt->port);
138 free(opt->scheme);
139 free(opt->auth);
140 free(opt->path);
141 free(opt->opaque);
142 free(opt->ca_cert_file);
143 free(opt);
147 /* Returns 0 if we "ate" the line. Returns >0, a KEYSERVER_ error
148 code if that error applies. Returns -1 if we did not match the
149 line at all. */
151 parse_ks_options(char *line,struct ks_options *opt)
153 int version;
154 char command[MAX_COMMAND+1];
155 char host[MAX_HOST+1];
156 char port[MAX_PORT+1];
157 char scheme[MAX_SCHEME+1];
158 char auth[MAX_AUTH+1];
159 char path[URLMAX_PATH+1];
160 char opaque[MAX_OPAQUE+1];
161 char option[MAX_OPTION+1];
163 if(line[0]=='#')
164 return 0;
166 if(sscanf(line,"COMMAND %" MKSTRING(MAX_COMMAND) "s\n",command)==1)
168 command[MAX_COMMAND]='\0';
170 if(strcasecmp(command,"get")==0)
171 opt->action=KS_GET;
172 else if(strcasecmp(command,"getname")==0)
173 opt->action=KS_GETNAME;
174 else if(strcasecmp(command,"send")==0)
175 opt->action=KS_SEND;
176 else if(strcasecmp(command,"search")==0)
177 opt->action=KS_SEARCH;
179 return 0;
182 if(sscanf(line,"HOST %" MKSTRING(MAX_HOST) "s\n",host)==1)
184 host[MAX_HOST]='\0';
185 free(opt->host);
186 opt->host=strdup(host);
187 if(!opt->host)
188 return KEYSERVER_NO_MEMORY;
189 return 0;
192 if(sscanf(line,"PORT %" MKSTRING(MAX_PORT) "s\n",port)==1)
194 port[MAX_PORT]='\0';
195 free(opt->port);
196 opt->port=strdup(port);
197 if(!opt->port)
198 return KEYSERVER_NO_MEMORY;
199 return 0;
202 if(sscanf(line,"SCHEME %" MKSTRING(MAX_SCHEME) "s\n",scheme)==1)
204 scheme[MAX_SCHEME]='\0';
205 free(opt->scheme);
206 opt->scheme=strdup(scheme);
207 if(!opt->scheme)
208 return KEYSERVER_NO_MEMORY;
209 return 0;
212 if(sscanf(line,"AUTH %" MKSTRING(MAX_AUTH) "s\n",auth)==1)
214 auth[MAX_AUTH]='\0';
215 free(opt->auth);
216 opt->auth=strdup(auth);
217 if(!opt->auth)
218 return KEYSERVER_NO_MEMORY;
219 return 0;
222 if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1)
224 path[URLMAX_PATH]='\0';
225 free(opt->path);
226 opt->path=strdup(path);
227 if(!opt->path)
228 return KEYSERVER_NO_MEMORY;
229 return 0;
232 if(sscanf(line,"OPAQUE %" MKSTRING(MAX_OPAQUE) "s\n",opaque)==1)
234 opaque[MAX_OPAQUE]='\0';
235 free(opt->opaque);
236 opt->opaque=strdup(opaque);
237 if(!opt->opaque)
238 return KEYSERVER_NO_MEMORY;
239 return 0;
242 if(sscanf(line,"VERSION %d\n",&version)==1)
244 if(version!=KEYSERVER_PROTO_VERSION)
245 return KEYSERVER_VERSION_ERROR;
247 return 0;
250 if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "[^\n]\n",option)==1)
252 int no=0;
253 char *start=&option[0];
255 option[MAX_OPTION]='\0';
257 if(strncasecmp(option,"no-",3)==0)
259 no=1;
260 start=&option[3];
263 if(strncasecmp(start,"verbose",7)==0)
265 if(no)
266 opt->verbose=0;
267 else if(start[7]=='=')
268 opt->verbose=atoi(&start[8]);
269 else
270 opt->verbose++;
272 else if(strcasecmp(start,"include-disabled")==0)
274 if(no)
275 opt->flags.include_disabled=0;
276 else
277 opt->flags.include_disabled=1;
279 else if(strcasecmp(start,"include-revoked")==0)
281 if(no)
282 opt->flags.include_revoked=0;
283 else
284 opt->flags.include_revoked=1;
286 else if(strcasecmp(start,"include-subkeys")==0)
288 if(no)
289 opt->flags.include_subkeys=0;
290 else
291 opt->flags.include_subkeys=1;
293 else if(strcasecmp(start,"check-cert")==0)
295 if(no)
296 opt->flags.check_cert=0;
297 else
298 opt->flags.check_cert=1;
300 else if(strncasecmp(start,"debug",5)==0)
302 if(no)
303 opt->debug=0;
304 else if(start[5]=='=')
305 opt->debug=atoi(&start[6]);
306 else if(start[5]=='\0')
307 opt->debug=1;
309 else if(strncasecmp(start,"timeout",7)==0)
311 if(no)
312 opt->timeout=0;
313 else if(start[7]=='=')
314 opt->timeout=atoi(&start[8]);
315 else if(start[7]=='\0')
316 opt->timeout=DEFAULT_KEYSERVER_TIMEOUT;
318 else if(strncasecmp(start,"ca-cert-file",12)==0)
320 if(no)
322 free(opt->ca_cert_file);
323 opt->ca_cert_file=NULL;
325 else if(start[12]=='=')
327 free(opt->ca_cert_file);
328 opt->ca_cert_file=strdup(&start[13]);
329 if(!opt->ca_cert_file)
330 return KEYSERVER_NO_MEMORY;
335 return -1;
338 const char *
339 ks_action_to_string(enum ks_action action)
341 switch(action)
343 case KS_UNKNOWN: return "UNKNOWN";
344 case KS_GET: return "GET";
345 case KS_GETNAME: return "GETNAME";
346 case KS_SEND: return "SEND";
347 case KS_SEARCH: return "SEARCH";
350 return "?";
353 /* Canonicalize CRLF to just LF by stripping CRs. This actually makes
354 sense, since on Unix-like machines LF is correct, and on win32-like
355 machines, our output buffer is opened in textmode and will
356 re-canonicalize line endings back to CRLF. Since we only need to
357 handle armored keys, we don't have to worry about odd cases like
358 CRCRCR and the like. */
360 void
361 print_nocr(FILE *stream,const char *str)
363 while(*str)
365 if(*str!='\r')
366 fputc(*str,stream);
367 str++;
371 enum ks_search_type
372 classify_ks_search(const char **search)
374 switch(**search)
376 case '*':
377 (*search)++;
378 return KS_SEARCH_SUBSTR;
379 case '=':
380 (*search)++;
381 return KS_SEARCH_EXACT;
382 case '<':
383 (*search)++;
384 return KS_SEARCH_MAIL;
385 case '@':
386 (*search)++;
387 return KS_SEARCH_MAILSUB;
388 case '0':
389 if((*search)[1]=='x')
391 if(strlen(*search)==10
392 && strspn(*search,"abcdefABCDEF1234567890x")==10)
394 (*search)+=2;
395 return KS_SEARCH_KEYID_SHORT;
397 else if(strlen(*search)==18
398 && strspn(*search,"abcdefABCDEF1234567890x")==18)
400 (*search)+=2;
401 return KS_SEARCH_KEYID_LONG;
404 /* fall through */
405 default:
406 return KS_SEARCH_SUBSTR;
411 curl_err_to_gpg_err(CURLcode error)
413 switch(error)
415 case CURLE_OK: return KEYSERVER_OK;
416 case CURLE_UNSUPPORTED_PROTOCOL: return KEYSERVER_SCHEME_NOT_FOUND;
417 case CURLE_COULDNT_CONNECT: return KEYSERVER_UNREACHABLE;
418 case CURLE_FTP_COULDNT_RETR_FILE: return KEYSERVER_KEY_NOT_FOUND;
419 default: return KEYSERVER_INTERNAL_ERROR;
423 #define B64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
425 static void
426 curl_armor_writer(const unsigned char *buf,size_t size,void *cw_ctx)
428 struct curl_writer_ctx *ctx=cw_ctx;
429 size_t idx=0;
431 while(idx<size)
433 for(;ctx->armor_remaining<3 && idx<size;ctx->armor_remaining++,idx++)
434 ctx->armor_ctx[ctx->armor_remaining]=buf[idx];
436 if(ctx->armor_remaining==3)
438 /* Top 6 bytes of ctx->armor_ctx[0] */
439 fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
440 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
441 ctx->armor_ctx[1] */
442 fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30)
443 |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream);
444 /* Bottom 4 bytes of ctx->armor_ctx[1] and top 2 bytes of
445 ctx->armor_ctx[2] */
446 fputc(B64[(((ctx->armor_ctx[1]<<2)&0x3C)
447 |((ctx->armor_ctx[2]>>6)&0x03))&0x3F],ctx->stream);
448 /* Bottom 6 bytes of ctx->armor_ctx[2] */
449 fputc(B64[(ctx->armor_ctx[2]&0x3F)],ctx->stream);
451 ctx->linelen+=4;
452 if(ctx->linelen>=70)
454 fputc('\n',ctx->stream);
455 ctx->linelen=0;
458 ctx->armor_remaining=0;
464 size_t
465 curl_writer(const void *ptr,size_t size,size_t nmemb,void *cw_ctx)
467 struct curl_writer_ctx *ctx=cw_ctx;
468 const char *buf=ptr;
469 size_t i;
471 if(!ctx->flags.initialized)
473 if(size*nmemb==0)
474 return 0;
476 /* The object we're fetching is in binary form */
477 if(*buf&0x80)
479 ctx->flags.armor=1;
480 fprintf(ctx->stream,BEGIN"\n\n");
482 else
483 ctx->marker=BEGIN;
485 ctx->flags.initialized=1;
488 if(ctx->flags.armor)
489 curl_armor_writer(ptr,size*nmemb,cw_ctx);
490 else
492 /* scan the incoming data for our marker */
493 for(i=0;!ctx->flags.done && i<(size*nmemb);i++)
495 if(buf[i]==ctx->marker[ctx->markeridx])
497 ctx->markeridx++;
498 if(ctx->marker[ctx->markeridx]=='\0')
500 if(ctx->flags.begun)
501 ctx->flags.done=1;
502 else
504 /* We've found the BEGIN marker, so now we're
505 looking for the END marker. */
506 ctx->flags.begun=1;
507 ctx->marker=END;
508 ctx->markeridx=0;
509 fprintf(ctx->stream,BEGIN);
510 continue;
514 else
515 ctx->markeridx=0;
517 if(ctx->flags.begun)
519 /* Canonicalize CRLF to just LF by stripping CRs. This
520 actually makes sense, since on Unix-like machines LF
521 is correct, and on win32-like machines, our output
522 buffer is opened in textmode and will re-canonicalize
523 line endings back to CRLF. Since this code is just
524 for handling armored keys, we don't have to worry
525 about odd cases like CRCRCR and the like. */
527 if(buf[i]!='\r')
528 fputc(buf[i],ctx->stream);
533 return size*nmemb;
536 void
537 curl_writer_finalize(struct curl_writer_ctx *ctx)
539 if(ctx->flags.armor)
541 if(ctx->armor_remaining==2)
543 /* Top 6 bytes of ctx->armorctx[0] */
544 fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
545 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
546 ctx->armor_ctx[1] */
547 fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30)
548 |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream);
549 /* Bottom 4 bytes of ctx->armor_ctx[1] */
550 fputc(B64[((ctx->armor_ctx[1]<<2)&0x3C)],ctx->stream);
551 /* Pad */
552 fputc('=',ctx->stream);
554 else if(ctx->armor_remaining==1)
556 /* Top 6 bytes of ctx->armor_ctx[0] */
557 fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream);
558 /* Bottom 2 bytes of ctx->armor_ctx[0] */
559 fputc(B64[((ctx->armor_ctx[0]<<4)&0x30)],ctx->stream);
560 /* Pad */
561 fputc('=',ctx->stream);
562 /* Pad */
563 fputc('=',ctx->stream);
566 fprintf(ctx->stream,"\n"END);
567 ctx->flags.done=1;
573 ks_hextobyte (const char *s)
575 int c;
577 if ( *s >= '0' && *s <= '9' )
578 c = 16 * (*s - '0');
579 else if ( *s >= 'A' && *s <= 'F' )
580 c = 16 * (10 + *s - 'A');
581 else if ( *s >= 'a' && *s <= 'f' )
582 c = 16 * (10 + *s - 'a');
583 else
584 return -1;
585 s++;
586 if ( *s >= '0' && *s <= '9' )
587 c += *s - '0';
588 else if ( *s >= 'A' && *s <= 'F' )
589 c += 10 + *s - 'A';
590 else if ( *s >= 'a' && *s <= 'f' )
591 c += 10 + *s - 'a';
592 else
593 return -1;
594 return c;
598 /* Non localized version of toupper. */
599 int
600 ks_toupper (int c)
602 if (c >= 'a' && c <= 'z')
603 c &= ~0x20;
604 return c;
608 /* Non localized version of strcasecmp. */
610 ks_strcasecmp (const char *a, const char *b)
612 if (a == b)
613 return 0;
615 for (; *a && *b; a++, b++)
617 if (*a != *b && ks_toupper (*a) != ks_toupper (*b))
618 break;
620 return *a == *b? 0 : (ks_toupper (*a) - ks_toupper (*b));