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 2 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * In addition, as a special exception, the Free Software Foundation
22 * gives permission to link the code of the keyserver helper tools:
23 * gpgkeys_ldap, gpgkeys_curl and gpgkeys_hkp with the OpenSSL
24 * project's "OpenSSL" library (or with modified versions of it that
25 * use the same license as the "OpenSSL" library), and distribute the
26 * linked executables. You must obey the GNU General Public License
27 * in all respects for all of the code used other than "OpenSSL". If
28 * you modify this file, you may extend this exception to your version
29 * of the file, but you are not obligated to do so. If you do not
30 * wish to do so, delete this exception statement from your version.
41 #include <curl/curl.h>
43 #include "curl-shim.h"
45 #include "keyserver.h"
48 #ifdef HAVE_DOSISH_SYSTEM
50 unsigned int set_timeout(unsigned int seconds
) {return 0;}
51 int register_timeout(void) {return 0;}
59 _exit(KEYSERVER_TIMEOUT
);
63 set_timeout(unsigned int seconds
)
65 return alarm(seconds
);
69 register_timeout(void)
71 #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
74 act
.sa_handler
=catch_alarm
;
75 sigemptyset(&act
.sa_mask
);
77 return sigaction(SIGALRM
,&act
,NULL
);
79 if(signal(SIGALRM
,catch_alarm
)==SIG_ERR
)
86 #endif /* !HAVE_DOSISH_SYSTEM */
91 struct ks_options
*opt
;
93 opt
=calloc(1,sizeof(struct ks_options
));
97 opt
->action
=KS_UNKNOWN
;
98 opt
->flags
.include_revoked
=1;
99 opt
->flags
.include_subkeys
=1;
100 opt
->flags
.check_cert
=1;
101 opt
->timeout
=DEFAULT_KEYSERVER_TIMEOUT
;
102 opt
->path
=strdup("/");
114 free_ks_options(struct ks_options
*opt
)
124 free(opt
->ca_cert_file
);
129 /* Returns 0 if we "ate" the line. Returns >0, a KEYSERVER_ error
130 code if that error applies. Returns -1 if we did not match the
133 parse_ks_options(char *line
,struct ks_options
*opt
)
136 char command
[MAX_COMMAND
+1];
137 char host
[MAX_HOST
+1];
138 char port
[MAX_PORT
+1];
139 char scheme
[MAX_SCHEME
+1];
140 char auth
[MAX_AUTH
+1];
141 char path
[URLMAX_PATH
+1];
142 char opaque
[MAX_OPAQUE
+1];
143 char option
[MAX_OPTION
+1];
148 if(sscanf(line
,"COMMAND %" MKSTRING(MAX_COMMAND
) "s\n",command
)==1)
150 command
[MAX_COMMAND
]='\0';
152 if(strcasecmp(command
,"get")==0)
154 else if(strcasecmp(command
,"getname")==0)
155 opt
->action
=KS_GETNAME
;
156 else if(strcasecmp(command
,"send")==0)
158 else if(strcasecmp(command
,"search")==0)
159 opt
->action
=KS_SEARCH
;
164 if(sscanf(line
,"HOST %" MKSTRING(MAX_HOST
) "s\n",host
)==1)
168 opt
->host
=strdup(host
);
170 return KEYSERVER_NO_MEMORY
;
174 if(sscanf(line
,"PORT %" MKSTRING(MAX_PORT
) "s\n",port
)==1)
178 opt
->port
=strdup(port
);
180 return KEYSERVER_NO_MEMORY
;
184 if(sscanf(line
,"SCHEME %" MKSTRING(MAX_SCHEME
) "s\n",scheme
)==1)
186 scheme
[MAX_SCHEME
]='\0';
188 opt
->scheme
=strdup(scheme
);
190 return KEYSERVER_NO_MEMORY
;
194 if(sscanf(line
,"AUTH %" MKSTRING(MAX_AUTH
) "s\n",auth
)==1)
198 opt
->auth
=strdup(auth
);
200 return KEYSERVER_NO_MEMORY
;
204 if(sscanf(line
,"PATH %" MKSTRING(URLMAX_PATH
) "s\n",path
)==1)
206 path
[URLMAX_PATH
]='\0';
208 opt
->path
=strdup(path
);
210 return KEYSERVER_NO_MEMORY
;
214 if(sscanf(line
,"OPAQUE %" MKSTRING(MAX_OPAQUE
) "s\n",opaque
)==1)
216 opaque
[MAX_OPAQUE
]='\0';
218 opt
->opaque
=strdup(opaque
);
220 return KEYSERVER_NO_MEMORY
;
224 if(sscanf(line
,"VERSION %d\n",&version
)==1)
226 if(version
!=KEYSERVER_PROTO_VERSION
)
227 return KEYSERVER_VERSION_ERROR
;
232 if(sscanf(line
,"OPTION %" MKSTRING(MAX_OPTION
) "[^\n]\n",option
)==1)
235 char *start
=&option
[0];
237 option
[MAX_OPTION
]='\0';
239 if(strncasecmp(option
,"no-",3)==0)
245 if(strncasecmp(start
,"verbose",7)==0)
249 else if(start
[7]=='=')
250 opt
->verbose
=atoi(&start
[8]);
254 else if(strcasecmp(start
,"include-disabled")==0)
257 opt
->flags
.include_disabled
=0;
259 opt
->flags
.include_disabled
=1;
261 else if(strcasecmp(start
,"include-revoked")==0)
264 opt
->flags
.include_revoked
=0;
266 opt
->flags
.include_revoked
=1;
268 else if(strcasecmp(start
,"include-subkeys")==0)
271 opt
->flags
.include_subkeys
=0;
273 opt
->flags
.include_subkeys
=1;
275 else if(strcasecmp(start
,"check-cert")==0)
278 opt
->flags
.check_cert
=0;
280 opt
->flags
.check_cert
=1;
282 else if(strncasecmp(start
,"debug",5)==0)
286 else if(start
[5]=='=')
287 opt
->debug
=atoi(&start
[6]);
288 else if(start
[5]=='\0')
291 else if(strncasecmp(start
,"timeout",7)==0)
295 else if(start
[7]=='=')
296 opt
->timeout
=atoi(&start
[8]);
297 else if(start
[7]=='\0')
298 opt
->timeout
=DEFAULT_KEYSERVER_TIMEOUT
;
300 else if(strncasecmp(start
,"ca-cert-file",12)==0)
304 free(opt
->ca_cert_file
);
305 opt
->ca_cert_file
=NULL
;
307 else if(start
[12]=='=')
309 free(opt
->ca_cert_file
);
310 opt
->ca_cert_file
=strdup(&start
[13]);
311 if(!opt
->ca_cert_file
)
312 return KEYSERVER_NO_MEMORY
;
321 ks_action_to_string(enum ks_action action
)
325 case KS_UNKNOWN
: return "UNKNOWN";
326 case KS_GET
: return "GET";
327 case KS_GETNAME
: return "GETNAME";
328 case KS_SEND
: return "SEND";
329 case KS_SEARCH
: return "SEARCH";
335 /* Canonicalize CRLF to just LF by stripping CRs. This actually makes
336 sense, since on Unix-like machines LF is correct, and on win32-like
337 machines, our output buffer is opened in textmode and will
338 re-canonicalize line endings back to CRLF. Since we only need to
339 handle armored keys, we don't have to worry about odd cases like
340 CRCRCR and the like. */
343 print_nocr(FILE *stream
,const char *str
)
354 classify_ks_search(const char **search
)
360 return KS_SEARCH_SUBSTR
;
363 return KS_SEARCH_EXACT
;
366 return KS_SEARCH_MAIL
;
369 return KS_SEARCH_MAILSUB
;
371 if((*search
)[1]=='x')
373 if(strlen(*search
)==10
374 && strspn(*search
,"abcdefABCDEF1234567890x")==10)
377 return KS_SEARCH_KEYID_SHORT
;
379 else if(strlen(*search
)==18
380 && strspn(*search
,"abcdefABCDEF1234567890x")==18)
383 return KS_SEARCH_KEYID_LONG
;
388 return KS_SEARCH_SUBSTR
;
393 curl_err_to_gpg_err(CURLcode error
)
397 case CURLE_OK
: return KEYSERVER_OK
;
398 case CURLE_UNSUPPORTED_PROTOCOL
: return KEYSERVER_SCHEME_NOT_FOUND
;
399 case CURLE_COULDNT_CONNECT
: return KEYSERVER_UNREACHABLE
;
400 case CURLE_FTP_COULDNT_RETR_FILE
: return KEYSERVER_KEY_NOT_FOUND
;
401 default: return KEYSERVER_INTERNAL_ERROR
;
405 #define B64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
408 curl_armor_writer(const unsigned char *buf
,size_t size
,void *cw_ctx
)
410 struct curl_writer_ctx
*ctx
=cw_ctx
;
415 for(;ctx
->armor_remaining
<3 && idx
<size
;ctx
->armor_remaining
++,idx
++)
416 ctx
->armor_ctx
[ctx
->armor_remaining
]=buf
[idx
];
418 if(ctx
->armor_remaining
==3)
420 /* Top 6 bytes of ctx->armor_ctx[0] */
421 fputc(B64
[(ctx
->armor_ctx
[0]>>2)&0x3F],ctx
->stream
);
422 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
424 fputc(B64
[(((ctx
->armor_ctx
[0]<<4)&0x30)
425 |((ctx
->armor_ctx
[1]>>4)&0x0F))&0x3F],ctx
->stream
);
426 /* Bottom 4 bytes of ctx->armor_ctx[1] and top 2 bytes of
428 fputc(B64
[(((ctx
->armor_ctx
[1]<<2)&0x3C)
429 |((ctx
->armor_ctx
[2]>>6)&0x03))&0x3F],ctx
->stream
);
430 /* Bottom 6 bytes of ctx->armor_ctx[2] */
431 fputc(B64
[(ctx
->armor_ctx
[2]&0x3F)],ctx
->stream
);
436 fputc('\n',ctx
->stream
);
440 ctx
->armor_remaining
=0;
447 curl_writer(const void *ptr
,size_t size
,size_t nmemb
,void *cw_ctx
)
449 struct curl_writer_ctx
*ctx
=cw_ctx
;
453 if(!ctx
->flags
.initialized
)
458 /* The object we're fetching is in binary form */
462 fprintf(ctx
->stream
,BEGIN
"\n\n");
467 ctx
->flags
.initialized
=1;
471 curl_armor_writer(ptr
,size
*nmemb
,cw_ctx
);
474 /* scan the incoming data for our marker */
475 for(i
=0;!ctx
->flags
.done
&& i
<(size
*nmemb
);i
++)
477 if(buf
[i
]==ctx
->marker
[ctx
->markeridx
])
480 if(ctx
->marker
[ctx
->markeridx
]=='\0')
486 /* We've found the BEGIN marker, so now we're
487 looking for the END marker. */
491 fprintf(ctx
->stream
,BEGIN
);
501 /* Canonicalize CRLF to just LF by stripping CRs. This
502 actually makes sense, since on Unix-like machines LF
503 is correct, and on win32-like machines, our output
504 buffer is opened in textmode and will re-canonicalize
505 line endings back to CRLF. Since this code is just
506 for handling armored keys, we don't have to worry
507 about odd cases like CRCRCR and the like. */
510 fputc(buf
[i
],ctx
->stream
);
519 curl_writer_finalize(struct curl_writer_ctx
*ctx
)
523 if(ctx
->armor_remaining
==2)
525 /* Top 6 bytes of ctx->armorctx[0] */
526 fputc(B64
[(ctx
->armor_ctx
[0]>>2)&0x3F],ctx
->stream
);
527 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
529 fputc(B64
[(((ctx
->armor_ctx
[0]<<4)&0x30)
530 |((ctx
->armor_ctx
[1]>>4)&0x0F))&0x3F],ctx
->stream
);
531 /* Bottom 4 bytes of ctx->armor_ctx[1] */
532 fputc(B64
[((ctx
->armor_ctx
[1]<<2)&0x3C)],ctx
->stream
);
534 fputc('=',ctx
->stream
);
536 else if(ctx
->armor_remaining
==1)
538 /* Top 6 bytes of ctx->armor_ctx[0] */
539 fputc(B64
[(ctx
->armor_ctx
[0]>>2)&0x3F],ctx
->stream
);
540 /* Bottom 2 bytes of ctx->armor_ctx[0] */
541 fputc(B64
[((ctx
->armor_ctx
[0]<<4)&0x30)],ctx
->stream
);
543 fputc('=',ctx
->stream
);
545 fputc('=',ctx
->stream
);
548 fprintf(ctx
->stream
,"\n"END
);
555 ks_hextobyte (const char *s
)
559 if ( *s
>= '0' && *s
<= '9' )
561 else if ( *s
>= 'A' && *s
<= 'F' )
562 c
= 16 * (10 + *s
- 'A');
563 else if ( *s
>= 'a' && *s
<= 'f' )
564 c
= 16 * (10 + *s
- 'a');
568 if ( *s
>= '0' && *s
<= '9' )
570 else if ( *s
>= 'A' && *s
<= 'F' )
572 else if ( *s
>= 'a' && *s
<= 'f' )
580 /* Non localized version of toupper. */
584 if (c
>= 'a' && c
<= 'z')
590 /* Non localized version of strcasecmp. */
592 ks_strcasecmp (const char *a
, const char *b
)
597 for (; *a
&& *b
; a
++, b
++)
599 if (*a
!= *b
&& ks_toupper (*a
) != ks_toupper (*b
))
602 return *a
== *b
? 0 : (ks_toupper (*a
) - ks_toupper (*b
));