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,
30 #include <curl/curl.h>
32 #include "curl-shim.h"
34 #include "keyserver.h"
37 #ifdef HAVE_DOSISH_SYSTEM
39 unsigned int set_timeout(unsigned int seconds
) {return 0;}
40 int register_timeout(void) {return 0;}
48 _exit(KEYSERVER_TIMEOUT
);
52 set_timeout(unsigned int seconds
)
54 return alarm(seconds
);
58 register_timeout(void)
60 #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
63 act
.sa_handler
=catch_alarm
;
64 sigemptyset(&act
.sa_mask
);
66 return sigaction(SIGALRM
,&act
,NULL
);
68 if(signal(SIGALRM
,catch_alarm
)==SIG_ERR
)
75 #endif /* !HAVE_DOSISH_SYSTEM */
80 struct ks_options
*opt
;
82 opt
=calloc(1,sizeof(struct ks_options
));
86 opt
->action
=KS_UNKNOWN
;
87 opt
->flags
.include_revoked
=1;
88 opt
->flags
.include_subkeys
=1;
89 opt
->flags
.check_cert
=1;
90 opt
->timeout
=DEFAULT_KEYSERVER_TIMEOUT
;
91 opt
->path
=strdup("/");
103 free_ks_options(struct ks_options
*opt
)
113 free(opt
->ca_cert_file
);
118 /* Returns 0 if we "ate" the line. Returns >0, a KEYSERVER_ error
119 code if that error applies. Returns -1 if we did not match the
122 parse_ks_options(char *line
,struct ks_options
*opt
)
125 char command
[MAX_COMMAND
+1];
126 char host
[MAX_HOST
+1];
127 char port
[MAX_PORT
+1];
128 char scheme
[MAX_SCHEME
+1];
129 char auth
[MAX_AUTH
+1];
130 char path
[URLMAX_PATH
+1];
131 char opaque
[MAX_OPAQUE
+1];
132 char option
[MAX_OPTION
+1];
137 if(sscanf(line
,"COMMAND %" MKSTRING(MAX_COMMAND
) "s\n",command
)==1)
139 command
[MAX_COMMAND
]='\0';
141 if(strcasecmp(command
,"get")==0)
143 else if(strcasecmp(command
,"getname")==0)
144 opt
->action
=KS_GETNAME
;
145 else if(strcasecmp(command
,"send")==0)
147 else if(strcasecmp(command
,"search")==0)
148 opt
->action
=KS_SEARCH
;
153 if(sscanf(line
,"HOST %" MKSTRING(MAX_HOST
) "s\n",host
)==1)
157 opt
->host
=strdup(host
);
159 return KEYSERVER_NO_MEMORY
;
163 if(sscanf(line
,"PORT %" MKSTRING(MAX_PORT
) "s\n",port
)==1)
167 opt
->port
=strdup(port
);
169 return KEYSERVER_NO_MEMORY
;
173 if(sscanf(line
,"SCHEME %" MKSTRING(MAX_SCHEME
) "s\n",scheme
)==1)
175 scheme
[MAX_SCHEME
]='\0';
177 opt
->scheme
=strdup(scheme
);
179 return KEYSERVER_NO_MEMORY
;
183 if(sscanf(line
,"AUTH %" MKSTRING(MAX_AUTH
) "s\n",auth
)==1)
187 opt
->auth
=strdup(auth
);
189 return KEYSERVER_NO_MEMORY
;
193 if(sscanf(line
,"PATH %" MKSTRING(URLMAX_PATH
) "s\n",path
)==1)
195 path
[URLMAX_PATH
]='\0';
197 opt
->path
=strdup(path
);
199 return KEYSERVER_NO_MEMORY
;
203 if(sscanf(line
,"OPAQUE %" MKSTRING(MAX_OPAQUE
) "s\n",opaque
)==1)
205 opaque
[MAX_OPAQUE
]='\0';
207 opt
->opaque
=strdup(opaque
);
209 return KEYSERVER_NO_MEMORY
;
213 if(sscanf(line
,"VERSION %d\n",&version
)==1)
215 if(version
!=KEYSERVER_PROTO_VERSION
)
216 return KEYSERVER_VERSION_ERROR
;
221 if(sscanf(line
,"OPTION %" MKSTRING(MAX_OPTION
) "[^\n]\n",option
)==1)
224 char *start
=&option
[0];
226 option
[MAX_OPTION
]='\0';
228 if(strncasecmp(option
,"no-",3)==0)
234 if(strncasecmp(start
,"verbose",7)==0)
238 else if(start
[7]=='=')
239 opt
->verbose
=atoi(&start
[8]);
243 else if(strcasecmp(start
,"include-disabled")==0)
246 opt
->flags
.include_disabled
=0;
248 opt
->flags
.include_disabled
=1;
250 else if(strcasecmp(start
,"include-revoked")==0)
253 opt
->flags
.include_revoked
=0;
255 opt
->flags
.include_revoked
=1;
257 else if(strcasecmp(start
,"include-subkeys")==0)
260 opt
->flags
.include_subkeys
=0;
262 opt
->flags
.include_subkeys
=1;
264 else if(strcasecmp(start
,"check-cert")==0)
267 opt
->flags
.check_cert
=0;
269 opt
->flags
.check_cert
=1;
271 else if(strncasecmp(start
,"debug",5)==0)
275 else if(start
[5]=='=')
276 opt
->debug
=atoi(&start
[6]);
277 else if(start
[5]=='\0')
280 else if(strncasecmp(start
,"timeout",7)==0)
284 else if(start
[7]=='=')
285 opt
->timeout
=atoi(&start
[8]);
286 else if(start
[7]=='\0')
287 opt
->timeout
=DEFAULT_KEYSERVER_TIMEOUT
;
289 else if(strncasecmp(start
,"ca-cert-file",12)==0)
293 free(opt
->ca_cert_file
);
294 opt
->ca_cert_file
=NULL
;
296 else if(start
[12]=='=')
298 free(opt
->ca_cert_file
);
299 opt
->ca_cert_file
=strdup(&start
[13]);
300 if(!opt
->ca_cert_file
)
301 return KEYSERVER_NO_MEMORY
;
310 ks_action_to_string(enum ks_action action
)
314 case KS_UNKNOWN
: return "UNKNOWN";
315 case KS_GET
: return "GET";
316 case KS_GETNAME
: return "GETNAME";
317 case KS_SEND
: return "SEND";
318 case KS_SEARCH
: return "SEARCH";
324 /* Canonicalize CRLF to just LF by stripping CRs. This actually makes
325 sense, since on Unix-like machines LF is correct, and on win32-like
326 machines, our output buffer is opened in textmode and will
327 re-canonicalize line endings back to CRLF. Since we only need to
328 handle armored keys, we don't have to worry about odd cases like
329 CRCRCR and the like. */
332 print_nocr(FILE *stream
,const char *str
)
343 classify_ks_search(const char **search
)
349 return KS_SEARCH_SUBSTR
;
352 return KS_SEARCH_EXACT
;
355 return KS_SEARCH_MAIL
;
358 return KS_SEARCH_MAILSUB
;
360 if((*search
)[1]=='x')
362 if(strlen(*search
)==10
363 && strspn(*search
,"abcdefABCDEF1234567890x")==10)
366 return KS_SEARCH_KEYID_SHORT
;
368 else if(strlen(*search
)==18
369 && strspn(*search
,"abcdefABCDEF1234567890x")==18)
372 return KS_SEARCH_KEYID_LONG
;
377 return KS_SEARCH_SUBSTR
;
382 curl_err_to_gpg_err(CURLcode error
)
386 case CURLE_OK
: return KEYSERVER_OK
;
387 case CURLE_UNSUPPORTED_PROTOCOL
: return KEYSERVER_SCHEME_NOT_FOUND
;
388 case CURLE_COULDNT_CONNECT
: return KEYSERVER_UNREACHABLE
;
389 case CURLE_FTP_COULDNT_RETR_FILE
: return KEYSERVER_KEY_NOT_FOUND
;
390 default: return KEYSERVER_INTERNAL_ERROR
;
394 #define B64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
397 curl_armor_writer(const unsigned char *buf
,size_t size
,void *cw_ctx
)
399 struct curl_writer_ctx
*ctx
=cw_ctx
;
404 for(;ctx
->armor_remaining
<3 && idx
<size
;ctx
->armor_remaining
++,idx
++)
405 ctx
->armor_ctx
[ctx
->armor_remaining
]=buf
[idx
];
407 if(ctx
->armor_remaining
==3)
409 /* Top 6 bytes of ctx->armor_ctx[0] */
410 fputc(B64
[(ctx
->armor_ctx
[0]>>2)&0x3F],ctx
->stream
);
411 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
413 fputc(B64
[(((ctx
->armor_ctx
[0]<<4)&0x30)
414 |((ctx
->armor_ctx
[1]>>4)&0x0F))&0x3F],ctx
->stream
);
415 /* Bottom 4 bytes of ctx->armor_ctx[1] and top 2 bytes of
417 fputc(B64
[(((ctx
->armor_ctx
[1]<<2)&0x3C)
418 |((ctx
->armor_ctx
[2]>>6)&0x03))&0x3F],ctx
->stream
);
419 /* Bottom 6 bytes of ctx->armor_ctx[2] */
420 fputc(B64
[(ctx
->armor_ctx
[2]&0x3F)],ctx
->stream
);
425 fputc('\n',ctx
->stream
);
429 ctx
->armor_remaining
=0;
436 curl_writer(const void *ptr
,size_t size
,size_t nmemb
,void *cw_ctx
)
438 struct curl_writer_ctx
*ctx
=cw_ctx
;
442 if(!ctx
->flags
.initialized
)
447 /* The object we're fetching is in binary form */
451 fprintf(ctx
->stream
,BEGIN
"\n\n");
456 ctx
->flags
.initialized
=1;
460 curl_armor_writer(ptr
,size
*nmemb
,cw_ctx
);
463 /* scan the incoming data for our marker */
464 for(i
=0;!ctx
->flags
.done
&& i
<(size
*nmemb
);i
++)
466 if(buf
[i
]==ctx
->marker
[ctx
->markeridx
])
469 if(ctx
->marker
[ctx
->markeridx
]=='\0')
475 /* We've found the BEGIN marker, so now we're
476 looking for the END marker. */
480 fprintf(ctx
->stream
,BEGIN
);
490 /* Canonicalize CRLF to just LF by stripping CRs. This
491 actually makes sense, since on Unix-like machines LF
492 is correct, and on win32-like machines, our output
493 buffer is opened in textmode and will re-canonicalize
494 line endings back to CRLF. Since this code is just
495 for handling armored keys, we don't have to worry
496 about odd cases like CRCRCR and the like. */
499 fputc(buf
[i
],ctx
->stream
);
508 curl_writer_finalize(struct curl_writer_ctx
*ctx
)
512 if(ctx
->armor_remaining
==2)
514 /* Top 6 bytes of ctx->armorctx[0] */
515 fputc(B64
[(ctx
->armor_ctx
[0]>>2)&0x3F],ctx
->stream
);
516 /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of
518 fputc(B64
[(((ctx
->armor_ctx
[0]<<4)&0x30)
519 |((ctx
->armor_ctx
[1]>>4)&0x0F))&0x3F],ctx
->stream
);
520 /* Bottom 4 bytes of ctx->armor_ctx[1] */
521 fputc(B64
[((ctx
->armor_ctx
[1]<<2)&0x3C)],ctx
->stream
);
523 fputc('=',ctx
->stream
);
525 else if(ctx
->armor_remaining
==1)
527 /* Top 6 bytes of ctx->armor_ctx[0] */
528 fputc(B64
[(ctx
->armor_ctx
[0]>>2)&0x3F],ctx
->stream
);
529 /* Bottom 2 bytes of ctx->armor_ctx[0] */
530 fputc(B64
[((ctx
->armor_ctx
[0]<<4)&0x30)],ctx
->stream
);
532 fputc('=',ctx
->stream
);
534 fputc('=',ctx
->stream
);
537 fprintf(ctx
->stream
,"\n"END
);