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.
38 #ifdef HAVE_W32_SYSTEM
43 #include <curl/curl.h>
45 #include "curl-shim.h"
48 #include "keyserver.h"
51 #ifdef HAVE_DOSISH_SYSTEM
53 unsigned int set_timeout(unsigned int seconds
) {return 0;}
54 int register_timeout(void) {return 0;}
62 _exit(KEYSERVER_TIMEOUT
);
66 set_timeout(unsigned int seconds
)
68 return alarm(seconds
);
72 register_timeout(void)
74 #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
77 act
.sa_handler
=catch_alarm
;
78 sigemptyset(&act
.sa_mask
);
80 return sigaction(SIGALRM
,&act
,NULL
);
82 if(signal(SIGALRM
,catch_alarm
)==SIG_ERR
)
89 #endif /* !HAVE_DOSISH_SYSTEM */
91 #ifdef HAVE_W32_SYSTEM
93 w32_init_sockets (void)
95 static int initialized
;
96 static WSADATA wsdata
;
100 WSAStartup (0x0202, &wsdata
);
104 #endif /*HAVE_W32_SYSTEM*/
108 init_ks_options(void)
110 struct ks_options
*opt
;
112 opt
=calloc(1,sizeof(struct ks_options
));
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("/");
133 free_ks_options(struct ks_options
*opt
)
143 free(opt
->ca_cert_file
);
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
152 parse_ks_options(char *line
,struct ks_options
*opt
)
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];
167 if(sscanf(line
,"COMMAND %" MKSTRING(MAX_COMMAND
) "s\n",command
)==1)
169 command
[MAX_COMMAND
]='\0';
171 if(strcasecmp(command
,"get")==0)
173 else if(strcasecmp(command
,"getname")==0)
174 opt
->action
=KS_GETNAME
;
175 else if(strcasecmp(command
,"send")==0)
177 else if(strcasecmp(command
,"search")==0)
178 opt
->action
=KS_SEARCH
;
183 if(sscanf(line
,"HOST %" MKSTRING(MAX_HOST
) "s\n",host
)==1)
187 opt
->host
=strdup(host
);
189 return KEYSERVER_NO_MEMORY
;
193 if(sscanf(line
,"PORT %" MKSTRING(MAX_PORT
) "s\n",port
)==1)
197 opt
->port
=strdup(port
);
199 return KEYSERVER_NO_MEMORY
;
203 if(sscanf(line
,"SCHEME %" MKSTRING(MAX_SCHEME
) "s\n",scheme
)==1)
205 scheme
[MAX_SCHEME
]='\0';
207 opt
->scheme
=strdup(scheme
);
209 return KEYSERVER_NO_MEMORY
;
213 if(sscanf(line
,"AUTH %" MKSTRING(MAX_AUTH
) "s\n",auth
)==1)
217 opt
->auth
=strdup(auth
);
219 return KEYSERVER_NO_MEMORY
;
223 if(sscanf(line
,"PATH %" MKSTRING(URLMAX_PATH
) "s\n",path
)==1)
225 path
[URLMAX_PATH
]='\0';
227 opt
->path
=strdup(path
);
229 return KEYSERVER_NO_MEMORY
;
233 if(sscanf(line
,"OPAQUE %" MKSTRING(MAX_OPAQUE
) "s\n",opaque
)==1)
235 opaque
[MAX_OPAQUE
]='\0';
237 opt
->opaque
=strdup(opaque
);
239 return KEYSERVER_NO_MEMORY
;
243 if(sscanf(line
,"VERSION %d\n",&version
)==1)
245 if(version
!=KEYSERVER_PROTO_VERSION
)
246 return KEYSERVER_VERSION_ERROR
;
251 if(sscanf(line
,"OPTION %" MKSTRING(MAX_OPTION
) "[^\n]\n",option
)==1)
254 char *start
=&option
[0];
256 option
[MAX_OPTION
]='\0';
258 if(strncasecmp(option
,"no-",3)==0)
264 if(strncasecmp(start
,"verbose",7)==0)
268 else if(start
[7]=='=')
269 opt
->verbose
=atoi(&start
[8]);
273 else if(strcasecmp(start
,"include-disabled")==0)
276 opt
->flags
.include_disabled
=0;
278 opt
->flags
.include_disabled
=1;
280 else if(strcasecmp(start
,"include-revoked")==0)
283 opt
->flags
.include_revoked
=0;
285 opt
->flags
.include_revoked
=1;
287 else if(strcasecmp(start
,"include-subkeys")==0)
290 opt
->flags
.include_subkeys
=0;
292 opt
->flags
.include_subkeys
=1;
294 else if(strcasecmp(start
,"check-cert")==0)
297 opt
->flags
.check_cert
=0;
299 opt
->flags
.check_cert
=1;
301 else if(strncasecmp(start
,"debug",5)==0)
305 else if(start
[5]=='=')
306 opt
->debug
=atoi(&start
[6]);
307 else if(start
[5]=='\0')
310 else if(strncasecmp(start
,"timeout",7)==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)
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
;
340 ks_action_to_string(enum ks_action 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";
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. */
362 print_nocr(FILE *stream
,const char *str
)
373 classify_ks_search(const char **search
)
379 return KS_SEARCH_SUBSTR
;
382 return KS_SEARCH_EXACT
;
385 return KS_SEARCH_MAIL
;
388 return KS_SEARCH_MAILSUB
;
390 if((*search
)[1]=='x')
392 if(strlen(*search
)==10
393 && strspn(*search
,"abcdefABCDEF1234567890x")==10)
396 return KS_SEARCH_KEYID_SHORT
;
398 else if(strlen(*search
)==18
399 && strspn(*search
,"abcdefABCDEF1234567890x")==18)
402 return KS_SEARCH_KEYID_LONG
;
407 return KS_SEARCH_SUBSTR
;
412 curl_err_to_gpg_err(CURLcode 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+/"
427 curl_armor_writer(const unsigned char *buf
,size_t size
,void *cw_ctx
)
429 struct curl_writer_ctx
*ctx
=cw_ctx
;
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
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
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
);
455 fputc('\n',ctx
->stream
);
459 ctx
->armor_remaining
=0;
466 curl_writer(const void *ptr
,size_t size
,size_t nmemb
,void *cw_ctx
)
468 struct curl_writer_ctx
*ctx
=cw_ctx
;
472 if(!ctx
->flags
.initialized
)
477 /* The object we're fetching is in binary form */
481 fprintf(ctx
->stream
,BEGIN
"\n\n");
486 ctx
->flags
.initialized
=1;
490 curl_armor_writer(ptr
,size
*nmemb
,cw_ctx
);
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
])
499 if(ctx
->marker
[ctx
->markeridx
]=='\0')
505 /* We've found the BEGIN marker, so now we're
506 looking for the END marker. */
510 fprintf(ctx
->stream
,BEGIN
);
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. */
529 fputc(buf
[i
],ctx
->stream
);
538 curl_writer_finalize(struct curl_writer_ctx
*ctx
)
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
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
);
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
);
562 fputc('=',ctx
->stream
);
564 fputc('=',ctx
->stream
);
567 fprintf(ctx
->stream
,"\n"END
);
574 ks_hextobyte (const char *s
)
578 if ( *s
>= '0' && *s
<= '9' )
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');
587 if ( *s
>= '0' && *s
<= '9' )
589 else if ( *s
>= 'A' && *s
<= 'F' )
591 else if ( *s
>= 'a' && *s
<= 'f' )
599 /* Non localized version of toupper. */
603 if (c
>= 'a' && c
<= 'z')
609 /* Non localized version of strcasecmp. */
611 ks_strcasecmp (const char *a
, const char *b
)
616 for (; *a
&& *b
; a
++, b
++)
618 if (*a
!= *b
&& ks_toupper (*a
) != ks_toupper (*b
))
621 return *a
== *b
? 0 : (ks_toupper (*a
) - ks_toupper (*b
));