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.
39 #include <curl/curl.h>
41 #include "curl-shim.h"
43 #include "keyserver.h"
46 #ifdef HAVE_DOSISH_SYSTEM
48 unsigned int set_timeout(unsigned int seconds
) {return 0;}
49 int register_timeout(void) {return 0;}
57 _exit(KEYSERVER_TIMEOUT
);
61 set_timeout(unsigned int seconds
)
63 return alarm(seconds
);
67 register_timeout(void)
69 #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
72 act
.sa_handler
=catch_alarm
;
73 sigemptyset(&act
.sa_mask
);
75 return sigaction(SIGALRM
,&act
,NULL
);
77 if(signal(SIGALRM
,catch_alarm
)==SIG_ERR
)
84 #endif /* !HAVE_DOSISH_SYSTEM */
89 struct ks_options
*opt
;
91 opt
=calloc(1,sizeof(struct ks_options
));
95 opt
->action
=KS_UNKNOWN
;
96 opt
->flags
.include_revoked
=1;
97 opt
->flags
.include_subkeys
=1;
98 opt
->flags
.check_cert
=1;
99 opt
->timeout
=DEFAULT_KEYSERVER_TIMEOUT
;
100 opt
->path
=strdup("/");
112 free_ks_options(struct ks_options
*opt
)
122 free(opt
->ca_cert_file
);
127 /* Returns 0 if we "ate" the line. Returns >0, a KEYSERVER_ error
128 code if that error applies. Returns -1 if we did not match the
131 parse_ks_options(char *line
,struct ks_options
*opt
)
134 char command
[MAX_COMMAND
+1];
135 char host
[MAX_HOST
+1];
136 char port
[MAX_PORT
+1];
137 char scheme
[MAX_SCHEME
+1];
138 char auth
[MAX_AUTH
+1];
139 char path
[URLMAX_PATH
+1];
140 char opaque
[MAX_OPAQUE
+1];
141 char option
[MAX_OPTION
+1];
146 if(sscanf(line
,"COMMAND %" MKSTRING(MAX_COMMAND
) "s\n",command
)==1)
148 command
[MAX_COMMAND
]='\0';
150 if(strcasecmp(command
,"get")==0)
152 else if(strcasecmp(command
,"getname")==0)
153 opt
->action
=KS_GETNAME
;
154 else if(strcasecmp(command
,"send")==0)
156 else if(strcasecmp(command
,"search")==0)
157 opt
->action
=KS_SEARCH
;
162 if(sscanf(line
,"HOST %" MKSTRING(MAX_HOST
) "s\n",host
)==1)
166 opt
->host
=strdup(host
);
168 return KEYSERVER_NO_MEMORY
;
172 if(sscanf(line
,"PORT %" MKSTRING(MAX_PORT
) "s\n",port
)==1)
176 opt
->port
=strdup(port
);
178 return KEYSERVER_NO_MEMORY
;
182 if(sscanf(line
,"SCHEME %" MKSTRING(MAX_SCHEME
) "s\n",scheme
)==1)
184 scheme
[MAX_SCHEME
]='\0';
186 opt
->scheme
=strdup(scheme
);
188 return KEYSERVER_NO_MEMORY
;
192 if(sscanf(line
,"AUTH %" MKSTRING(MAX_AUTH
) "s\n",auth
)==1)
196 opt
->auth
=strdup(auth
);
198 return KEYSERVER_NO_MEMORY
;
202 if(sscanf(line
,"PATH %" MKSTRING(URLMAX_PATH
) "s\n",path
)==1)
204 path
[URLMAX_PATH
]='\0';
206 opt
->path
=strdup(path
);
208 return KEYSERVER_NO_MEMORY
;
212 if(sscanf(line
,"OPAQUE %" MKSTRING(MAX_OPAQUE
) "s\n",opaque
)==1)
214 opaque
[MAX_OPAQUE
]='\0';
216 opt
->opaque
=strdup(opaque
);
218 return KEYSERVER_NO_MEMORY
;
222 if(sscanf(line
,"VERSION %d\n",&version
)==1)
224 if(version
!=KEYSERVER_PROTO_VERSION
)
225 return KEYSERVER_VERSION_ERROR
;
230 if(sscanf(line
,"OPTION %" MKSTRING(MAX_OPTION
) "[^\n]\n",option
)==1)
233 char *start
=&option
[0];
235 option
[MAX_OPTION
]='\0';
237 if(strncasecmp(option
,"no-",3)==0)
243 if(strncasecmp(start
,"verbose",7)==0)
247 else if(start
[7]=='=')
248 opt
->verbose
=atoi(&start
[8]);
252 else if(strcasecmp(start
,"include-disabled")==0)
255 opt
->flags
.include_disabled
=0;
257 opt
->flags
.include_disabled
=1;
259 else if(strcasecmp(start
,"include-revoked")==0)
262 opt
->flags
.include_revoked
=0;
264 opt
->flags
.include_revoked
=1;
266 else if(strcasecmp(start
,"include-subkeys")==0)
269 opt
->flags
.include_subkeys
=0;
271 opt
->flags
.include_subkeys
=1;
273 else if(strcasecmp(start
,"check-cert")==0)
276 opt
->flags
.check_cert
=0;
278 opt
->flags
.check_cert
=1;
280 else if(strncasecmp(start
,"debug",5)==0)
284 else if(start
[5]=='=')
285 opt
->debug
=atoi(&start
[6]);
286 else if(start
[5]=='\0')
289 else if(strncasecmp(start
,"timeout",7)==0)
293 else if(start
[7]=='=')
294 opt
->timeout
=atoi(&start
[8]);
295 else if(start
[7]=='\0')
296 opt
->timeout
=DEFAULT_KEYSERVER_TIMEOUT
;
298 else if(strncasecmp(start
,"ca-cert-file",12)==0)
302 free(opt
->ca_cert_file
);
303 opt
->ca_cert_file
=NULL
;
305 else if(start
[12]=='=')
307 free(opt
->ca_cert_file
);
308 opt
->ca_cert_file
=strdup(&start
[13]);
309 if(!opt
->ca_cert_file
)
310 return KEYSERVER_NO_MEMORY
;
319 ks_action_to_string(enum ks_action action
)
323 case KS_UNKNOWN
: return "UNKNOWN";
324 case KS_GET
: return "GET";
325 case KS_GETNAME
: return "GETNAME";
326 case KS_SEND
: return "SEND";
327 case KS_SEARCH
: return "SEARCH";
333 /* Canonicalize CRLF to just LF by stripping CRs. This actually makes
334 sense, since on Unix-like machines LF is correct, and on win32-like
335 machines, our output buffer is opened in textmode and will
336 re-canonicalize line endings back to CRLF. Since we only need to
337 handle armored keys, we don't have to worry about odd cases like
338 CRCRCR and the like. */
341 print_nocr(FILE *stream
,const char *str
)
352 classify_ks_search(const char **search
)
358 return KS_SEARCH_SUBSTR
;
361 return KS_SEARCH_EXACT
;
364 return KS_SEARCH_MAIL
;
367 return KS_SEARCH_MAILSUB
;
369 if((*search
)[1]=='x')
371 if(strlen(*search
)==10
372 && strspn(*search
,"abcdefABCDEF1234567890x")==10)
375 return KS_SEARCH_KEYID_SHORT
;
377 else if(strlen(*search
)==18
378 && strspn(*search
,"abcdefABCDEF1234567890x")==18)
381 return KS_SEARCH_KEYID_LONG
;
386 return KS_SEARCH_SUBSTR
;
391 curl_err_to_gpg_err(CURLcode error
)
395 case CURLE_OK
: return KEYSERVER_OK
;
396 case CURLE_UNSUPPORTED_PROTOCOL
: return KEYSERVER_SCHEME_NOT_FOUND
;
397 case CURLE_COULDNT_CONNECT
: return KEYSERVER_UNREACHABLE
;
398 case CURLE_FTP_COULDNT_RETR_FILE
: return KEYSERVER_KEY_NOT_FOUND
;
399 default: return KEYSERVER_INTERNAL_ERROR
;
403 #define B64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
406 curl_armor_writer(const unsigned char *buf
,size_t size
,void *cw_ctx
)
408 struct curl_writer_ctx
*ctx
=cw_ctx
;
413 for(;ctx
->armor_remaining
<3 && idx
<size
;ctx
->armor_remaining
++,idx
++)
414 ctx
->armor_ctx
[ctx
->armor_remaining
]=buf
[idx
];
416 if(ctx
->armor_remaining
==3)
418 /* Top 6 bytes of ctx->armor_ctx[0] */
419 fputc(B64
[(ctx
->armor_ctx
[0]>>2)&0x3F],ctx
->stream
);
420 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
422 fputc(B64
[(((ctx
->armor_ctx
[0]<<4)&0x30)
423 |((ctx
->armor_ctx
[1]>>4)&0x0F))&0x3F],ctx
->stream
);
424 /* Bottom 4 bytes of ctx->armor_ctx[1] and top 2 bytes of
426 fputc(B64
[(((ctx
->armor_ctx
[1]<<2)&0x3C)
427 |((ctx
->armor_ctx
[2]>>6)&0x03))&0x3F],ctx
->stream
);
428 /* Bottom 6 bytes of ctx->armor_ctx[2] */
429 fputc(B64
[(ctx
->armor_ctx
[2]&0x3F)],ctx
->stream
);
434 fputc('\n',ctx
->stream
);
438 ctx
->armor_remaining
=0;
445 curl_writer(const void *ptr
,size_t size
,size_t nmemb
,void *cw_ctx
)
447 struct curl_writer_ctx
*ctx
=cw_ctx
;
451 if(!ctx
->flags
.initialized
)
456 /* The object we're fetching is in binary form */
460 fprintf(ctx
->stream
,BEGIN
"\n\n");
465 ctx
->flags
.initialized
=1;
469 curl_armor_writer(ptr
,size
*nmemb
,cw_ctx
);
472 /* scan the incoming data for our marker */
473 for(i
=0;!ctx
->flags
.done
&& i
<(size
*nmemb
);i
++)
475 if(buf
[i
]==ctx
->marker
[ctx
->markeridx
])
478 if(ctx
->marker
[ctx
->markeridx
]=='\0')
484 /* We've found the BEGIN marker, so now we're
485 looking for the END marker. */
489 fprintf(ctx
->stream
,BEGIN
);
499 /* Canonicalize CRLF to just LF by stripping CRs. This
500 actually makes sense, since on Unix-like machines LF
501 is correct, and on win32-like machines, our output
502 buffer is opened in textmode and will re-canonicalize
503 line endings back to CRLF. Since this code is just
504 for handling armored keys, we don't have to worry
505 about odd cases like CRCRCR and the like. */
508 fputc(buf
[i
],ctx
->stream
);
517 curl_writer_finalize(struct curl_writer_ctx
*ctx
)
521 if(ctx
->armor_remaining
==2)
523 /* Top 6 bytes of ctx->armorctx[0] */
524 fputc(B64
[(ctx
->armor_ctx
[0]>>2)&0x3F],ctx
->stream
);
525 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
527 fputc(B64
[(((ctx
->armor_ctx
[0]<<4)&0x30)
528 |((ctx
->armor_ctx
[1]>>4)&0x0F))&0x3F],ctx
->stream
);
529 /* Bottom 4 bytes of ctx->armor_ctx[1] */
530 fputc(B64
[((ctx
->armor_ctx
[1]<<2)&0x3C)],ctx
->stream
);
532 fputc('=',ctx
->stream
);
534 else if(ctx
->armor_remaining
==1)
536 /* Top 6 bytes of ctx->armor_ctx[0] */
537 fputc(B64
[(ctx
->armor_ctx
[0]>>2)&0x3F],ctx
->stream
);
538 /* Bottom 2 bytes of ctx->armor_ctx[0] */
539 fputc(B64
[((ctx
->armor_ctx
[0]<<4)&0x30)],ctx
->stream
);
541 fputc('=',ctx
->stream
);
543 fputc('=',ctx
->stream
);
546 fprintf(ctx
->stream
,"\n"END
);
553 ks_hextobyte (const char *s
)
557 if ( *s
>= '0' && *s
<= '9' )
559 else if ( *s
>= 'A' && *s
<= 'F' )
560 c
= 16 * (10 + *s
- 'A');
561 else if ( *s
>= 'a' && *s
<= 'f' )
562 c
= 16 * (10 + *s
- 'a');
566 if ( *s
>= '0' && *s
<= '9' )
568 else if ( *s
>= 'A' && *s
<= 'F' )
570 else if ( *s
>= 'a' && *s
<= 'f' )
578 /* Non localized version of toupper. */
582 if (c
>= 'a' && c
<= 'z')
588 /* Non localized version of strcasecmp. */
590 ks_strcasecmp (const char *a
, const char *b
)
595 for (; *a
&& *b
; a
++, b
++)
597 if (*a
!= *b
&& ks_toupper (*a
) != ks_toupper (*b
))
600 return *a
== *b
? 0 : (ks_toupper (*a
) - ks_toupper (*b
));