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"
47 #include "keyserver.h"
50 #ifdef HAVE_DOSISH_SYSTEM
52 unsigned int set_timeout(unsigned int seconds
) {return 0;}
53 int register_timeout(void) {return 0;}
61 _exit(KEYSERVER_TIMEOUT
);
65 set_timeout(unsigned int seconds
)
67 return alarm(seconds
);
71 register_timeout(void)
73 #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
76 act
.sa_handler
=catch_alarm
;
77 sigemptyset(&act
.sa_mask
);
79 return sigaction(SIGALRM
,&act
,NULL
);
81 if(signal(SIGALRM
,catch_alarm
)==SIG_ERR
)
88 #endif /* !HAVE_DOSISH_SYSTEM */
90 #ifdef HAVE_W32_SYSTEM
92 w32_init_sockets (void)
94 static int initialized
;
95 static WSADATA wsdata
;
99 WSAStartup (0x0202, &wsdata
);
103 #endif /*HAVE_W32_SYSTEM*/
107 init_ks_options(void)
109 struct ks_options
*opt
;
111 opt
=calloc(1,sizeof(struct ks_options
));
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("/");
132 free_ks_options(struct ks_options
*opt
)
142 free(opt
->ca_cert_file
);
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
151 parse_ks_options(char *line
,struct ks_options
*opt
)
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];
166 if(sscanf(line
,"COMMAND %" MKSTRING(MAX_COMMAND
) "s\n",command
)==1)
168 command
[MAX_COMMAND
]='\0';
170 if(strcasecmp(command
,"get")==0)
172 else if(strcasecmp(command
,"getname")==0)
173 opt
->action
=KS_GETNAME
;
174 else if(strcasecmp(command
,"send")==0)
176 else if(strcasecmp(command
,"search")==0)
177 opt
->action
=KS_SEARCH
;
182 if(sscanf(line
,"HOST %" MKSTRING(MAX_HOST
) "s\n",host
)==1)
186 opt
->host
=strdup(host
);
188 return KEYSERVER_NO_MEMORY
;
192 if(sscanf(line
,"PORT %" MKSTRING(MAX_PORT
) "s\n",port
)==1)
196 opt
->port
=strdup(port
);
198 return KEYSERVER_NO_MEMORY
;
202 if(sscanf(line
,"SCHEME %" MKSTRING(MAX_SCHEME
) "s\n",scheme
)==1)
204 scheme
[MAX_SCHEME
]='\0';
206 opt
->scheme
=strdup(scheme
);
208 return KEYSERVER_NO_MEMORY
;
212 if(sscanf(line
,"AUTH %" MKSTRING(MAX_AUTH
) "s\n",auth
)==1)
216 opt
->auth
=strdup(auth
);
218 return KEYSERVER_NO_MEMORY
;
222 if(sscanf(line
,"PATH %" MKSTRING(URLMAX_PATH
) "s\n",path
)==1)
224 path
[URLMAX_PATH
]='\0';
226 opt
->path
=strdup(path
);
228 return KEYSERVER_NO_MEMORY
;
232 if(sscanf(line
,"OPAQUE %" MKSTRING(MAX_OPAQUE
) "s\n",opaque
)==1)
234 opaque
[MAX_OPAQUE
]='\0';
236 opt
->opaque
=strdup(opaque
);
238 return KEYSERVER_NO_MEMORY
;
242 if(sscanf(line
,"VERSION %d\n",&version
)==1)
244 if(version
!=KEYSERVER_PROTO_VERSION
)
245 return KEYSERVER_VERSION_ERROR
;
250 if(sscanf(line
,"OPTION %" MKSTRING(MAX_OPTION
) "[^\n]\n",option
)==1)
253 char *start
=&option
[0];
255 option
[MAX_OPTION
]='\0';
257 if(strncasecmp(option
,"no-",3)==0)
263 if(strncasecmp(start
,"verbose",7)==0)
267 else if(start
[7]=='=')
268 opt
->verbose
=atoi(&start
[8]);
272 else if(strcasecmp(start
,"include-disabled")==0)
275 opt
->flags
.include_disabled
=0;
277 opt
->flags
.include_disabled
=1;
279 else if(strcasecmp(start
,"include-revoked")==0)
282 opt
->flags
.include_revoked
=0;
284 opt
->flags
.include_revoked
=1;
286 else if(strcasecmp(start
,"include-subkeys")==0)
289 opt
->flags
.include_subkeys
=0;
291 opt
->flags
.include_subkeys
=1;
293 else if(strcasecmp(start
,"check-cert")==0)
296 opt
->flags
.check_cert
=0;
298 opt
->flags
.check_cert
=1;
300 else if(strncasecmp(start
,"debug",5)==0)
304 else if(start
[5]=='=')
305 opt
->debug
=atoi(&start
[6]);
306 else if(start
[5]=='\0')
309 else if(strncasecmp(start
,"timeout",7)==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)
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
;
339 ks_action_to_string(enum ks_action 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";
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. */
361 print_nocr(FILE *stream
,const char *str
)
372 classify_ks_search(const char **search
)
378 return KS_SEARCH_SUBSTR
;
381 return KS_SEARCH_EXACT
;
384 return KS_SEARCH_MAIL
;
387 return KS_SEARCH_MAILSUB
;
389 if((*search
)[1]=='x')
391 if(strlen(*search
)==10
392 && strspn(*search
,"abcdefABCDEF1234567890x")==10)
395 return KS_SEARCH_KEYID_SHORT
;
397 else if(strlen(*search
)==18
398 && strspn(*search
,"abcdefABCDEF1234567890x")==18)
401 return KS_SEARCH_KEYID_LONG
;
406 return KS_SEARCH_SUBSTR
;
411 curl_err_to_gpg_err(CURLcode 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+/"
426 curl_armor_writer(const unsigned char *buf
,size_t size
,void *cw_ctx
)
428 struct curl_writer_ctx
*ctx
=cw_ctx
;
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
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
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
);
454 fputc('\n',ctx
->stream
);
458 ctx
->armor_remaining
=0;
465 curl_writer(const void *ptr
,size_t size
,size_t nmemb
,void *cw_ctx
)
467 struct curl_writer_ctx
*ctx
=cw_ctx
;
471 if(!ctx
->flags
.initialized
)
476 /* The object we're fetching is in binary form */
480 fprintf(ctx
->stream
,BEGIN
"\n\n");
485 ctx
->flags
.initialized
=1;
489 curl_armor_writer(ptr
,size
*nmemb
,cw_ctx
);
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
])
498 if(ctx
->marker
[ctx
->markeridx
]=='\0')
504 /* We've found the BEGIN marker, so now we're
505 looking for the END marker. */
509 fprintf(ctx
->stream
,BEGIN
);
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. */
528 fputc(buf
[i
],ctx
->stream
);
537 curl_writer_finalize(struct curl_writer_ctx
*ctx
)
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
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
);
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
);
561 fputc('=',ctx
->stream
);
563 fputc('=',ctx
->stream
);
566 fprintf(ctx
->stream
,"\n"END
);
573 ks_hextobyte (const char *s
)
577 if ( *s
>= '0' && *s
<= '9' )
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');
586 if ( *s
>= '0' && *s
<= '9' )
588 else if ( *s
>= 'A' && *s
<= 'F' )
590 else if ( *s
>= 'a' && *s
<= 'f' )
598 /* Non localized version of toupper. */
602 if (c
>= 'a' && c
<= 'z')
608 /* Non localized version of strcasecmp. */
610 ks_strcasecmp (const char *a
, const char *b
)
615 for (; *a
&& *b
; a
++, b
++)
617 if (*a
!= *b
&& ks_toupper (*a
) != ks_toupper (*b
))
620 return *a
== *b
? 0 : (ks_toupper (*a
) - ks_toupper (*b
));