Fix debian bug#543530
[gnupg.git] / keyserver / gpgkeys_hkp.c
blob64a3a7029496615e7be84095cc417be5aa8ce579
1 /* gpgkeys_hkp.c - talk to an HKP keyserver
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
3 * 2009 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 * In addition, as a special exception, the Free Software Foundation
21 * gives permission to link the code of the keyserver helper tools:
22 * gpgkeys_ldap, gpgkeys_curl and gpgkeys_hkp with the OpenSSL
23 * project's "OpenSSL" library (or with modified versions of it that
24 * use the same license as the "OpenSSL" library), and distribute the
25 * linked executables. You must obey the GNU General Public License
26 * in all respects for all of the code used other than "OpenSSL". If
27 * you modify this file, you may extend this exception to your version
28 * of the file, but you are not obligated to do so. If you do not
29 * wish to do so, delete this exception statement from your version.
32 #include <config.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #ifdef HAVE_GETOPT_H
39 #include <getopt.h>
40 #endif
41 #ifdef HAVE_LIBCURL
42 #include <curl/curl.h>
43 #else
44 #include "curl-shim.h"
45 #endif
46 #ifdef USE_DNS_SRV
47 #include "srv.h"
48 #endif
49 #include "keyserver.h"
50 #include "ksutil.h"
52 extern char *optarg;
53 extern int optind;
55 static FILE *input,*output,*console;
56 static CURL *curl;
57 static struct ks_options *opt;
58 static char errorbuffer[CURL_ERROR_SIZE];
59 static char *proto,*port;
61 static size_t
62 curl_mrindex_writer(const void *ptr,size_t size,size_t nmemb,void *stream)
64 static int checked=0,swallow=0;
66 if(!checked)
68 /* If the document begins with a '<', assume it's a HTML
69 response, which we don't support. Discard the whole message
70 body. GPG can handle it, but this is an optimization to deal
71 with it on this side of the pipe. */
72 const char *buf=ptr;
73 if(buf[0]=='<')
74 swallow=1;
76 checked=1;
79 if(swallow || fwrite(ptr,size,nmemb,stream)==nmemb)
80 return size*nmemb;
81 else
82 return 0;
85 /* Append but avoid creating a double slash // in the path. */
86 static char *
87 append_path(char *dest,const char *src)
89 size_t n=strlen(dest);
91 if(src[0]=='/' && n>0 && dest[n-1]=='/')
92 dest[n-1]='\0';
94 return strcat(dest,src);
97 int
98 send_key(int *r_eof)
100 CURLcode res;
101 char request[MAX_URL+15];
102 int begin=0,end=0,ret=KEYSERVER_INTERNAL_ERROR;
103 char keyid[17],state[6];
104 char line[MAX_LINE];
105 char *key=NULL,*encoded_key=NULL;
106 size_t keylen=0,keymax=0;
108 /* Read and throw away input until we see the BEGIN */
110 while(fgets(line,MAX_LINE,input)!=NULL)
111 if(sscanf(line,"KEY%*[ ]%16s%*[ ]%5s\n",keyid,state)==2
112 && strcmp(state,"BEGIN")==0)
114 begin=1;
115 break;
118 if(!begin)
120 /* i.e. eof before the KEY BEGIN was found. This isn't an
121 error. */
122 *r_eof=1;
123 ret=KEYSERVER_OK;
124 goto fail;
127 /* Now slurp up everything until we see the END */
129 while(fgets(line,MAX_LINE,input))
130 if(sscanf(line,"KEY%*[ ]%16s%*[ ]%3s\n",keyid,state)==2
131 && strcmp(state,"END")==0)
133 end=1;
134 break;
136 else
138 if(strlen(line)+keylen>keymax)
140 char *tmp;
142 keymax+=200;
143 tmp=realloc(key,keymax+1);
144 if(!tmp)
146 free(key);
147 fprintf(console,"gpgkeys: out of memory\n");
148 ret=KEYSERVER_NO_MEMORY;
149 goto fail;
152 key=tmp;
155 strcpy(&key[keylen],line);
156 keylen+=strlen(line);
159 if(!end)
161 fprintf(console,"gpgkeys: no KEY %s END found\n",keyid);
162 *r_eof=1;
163 ret=KEYSERVER_KEY_INCOMPLETE;
164 goto fail;
167 encoded_key=curl_escape(key,keylen);
168 if(!encoded_key)
170 fprintf(console,"gpgkeys: out of memory\n");
171 ret=KEYSERVER_NO_MEMORY;
172 goto fail;
175 free(key);
177 key=malloc(8+strlen(encoded_key)+1);
178 if(!key)
180 fprintf(console,"gpgkeys: out of memory\n");
181 ret=KEYSERVER_NO_MEMORY;
182 goto fail;
185 strcpy(key,"keytext=");
186 strcat(key,encoded_key);
188 strcpy(request,proto);
189 strcat(request,"://");
190 strcat(request,opt->host);
191 strcat(request,":");
192 strcat(request,port);
193 strcat(request,opt->path);
194 /* request is MAX_URL+15 bytes long - MAX_URL covers the whole URL,
195 including any supplied path. The 15 covers /pks/add. */
196 append_path(request,"/pks/add");
198 if(opt->verbose>2)
199 fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
201 curl_easy_setopt(curl,CURLOPT_URL,request);
202 curl_easy_setopt(curl,CURLOPT_POST,1L);
203 curl_easy_setopt(curl,CURLOPT_POSTFIELDS,key);
204 curl_easy_setopt(curl,CURLOPT_FAILONERROR,1L);
206 res=curl_easy_perform(curl);
207 if(res!=0)
209 fprintf(console,"gpgkeys: HTTP post error %d: %s\n",res,errorbuffer);
210 ret=curl_err_to_gpg_err(res);
211 goto fail;
213 else
214 fprintf(output,"\nKEY %s SENT\n",keyid);
216 ret=KEYSERVER_OK;
218 fail:
219 free(key);
220 curl_free(encoded_key);
222 if(ret!=0 && begin)
223 fprintf(output,"KEY %s FAILED %d\n",keyid,ret);
225 return ret;
228 static int
229 get_key(char *getkey)
231 CURLcode res;
232 char request[MAX_URL+60];
233 char *offset;
234 struct curl_writer_ctx ctx;
236 memset(&ctx,0,sizeof(ctx));
238 /* Build the search string. HKP only uses the short key IDs. */
240 if(strncmp(getkey,"0x",2)==0)
241 getkey+=2;
243 fprintf(output,"KEY 0x%s BEGIN\n",getkey);
245 if(strlen(getkey)==32)
247 fprintf(console,
248 "gpgkeys: HKP keyservers do not support v3 fingerprints\n");
249 fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED);
250 return KEYSERVER_NOT_SUPPORTED;
253 strcpy(request,proto);
254 strcat(request,"://");
255 strcat(request,opt->host);
256 strcat(request,":");
257 strcat(request,port);
258 strcat(request,opt->path);
259 /* request is MAX_URL+55 bytes long - MAX_URL covers the whole URL,
260 including any supplied path. The 60 overcovers this /pks/... etc
261 string plus the 8 bytes of key id */
262 append_path(request,"/pks/lookup?op=get&options=mr&search=0x");
264 /* fingerprint or long key id. Take the last 8 characters and treat
265 it like a short key id */
266 if(strlen(getkey)>8)
267 offset=&getkey[strlen(getkey)-8];
268 else
269 offset=getkey;
271 strcat(request,offset);
273 if(opt->verbose>2)
274 fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
276 curl_easy_setopt(curl,CURLOPT_URL,request);
277 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
278 ctx.stream=output;
279 curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
281 res=curl_easy_perform(curl);
282 if(res!=CURLE_OK)
284 fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
285 fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
287 else
289 curl_writer_finalize(&ctx);
290 if(!ctx.flags.done)
292 fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
293 fprintf(output,"\nKEY 0x%s FAILED %d\n",
294 getkey,KEYSERVER_KEY_NOT_FOUND);
296 else
297 fprintf(output,"\nKEY 0x%s END\n",getkey);
300 return KEYSERVER_OK;
303 static int
304 get_name(const char *getkey)
306 CURLcode res;
307 char *request=NULL;
308 char *searchkey_encoded;
309 int ret=KEYSERVER_INTERNAL_ERROR;
310 struct curl_writer_ctx ctx;
312 memset(&ctx,0,sizeof(ctx));
314 searchkey_encoded=curl_escape((char *)getkey,0);
315 if(!searchkey_encoded)
317 fprintf(console,"gpgkeys: out of memory\n");
318 ret=KEYSERVER_NO_MEMORY;
319 goto fail;
322 request=malloc(MAX_URL+60+strlen(searchkey_encoded));
323 if(!request)
325 fprintf(console,"gpgkeys: out of memory\n");
326 ret=KEYSERVER_NO_MEMORY;
327 goto fail;
330 fprintf(output,"NAME %s BEGIN\n",getkey);
332 strcpy(request,proto);
333 strcat(request,"://");
334 strcat(request,opt->host);
335 strcat(request,":");
336 strcat(request,port);
337 strcat(request,opt->path);
338 append_path(request,"/pks/lookup?op=get&options=mr&search=");
339 strcat(request,searchkey_encoded);
341 if(opt->action==KS_GETNAME)
342 strcat(request,"&exact=on");
344 if(opt->verbose>2)
345 fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
347 curl_easy_setopt(curl,CURLOPT_URL,request);
348 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
349 ctx.stream=output;
350 curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
352 res=curl_easy_perform(curl);
353 if(res!=CURLE_OK)
355 fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
356 ret=curl_err_to_gpg_err(res);
358 else
360 curl_writer_finalize(&ctx);
361 if(!ctx.flags.done)
363 fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
364 ret=KEYSERVER_KEY_NOT_FOUND;
366 else
368 fprintf(output,"\nNAME %s END\n",getkey);
369 ret=KEYSERVER_OK;
373 fail:
374 curl_free(searchkey_encoded);
375 free(request);
377 if(ret!=KEYSERVER_OK)
378 fprintf(output,"\nNAME %s FAILED %d\n",getkey,ret);
380 return ret;
383 static int
384 search_key(const char *searchkey)
386 CURLcode res;
387 char *request=NULL;
388 char *searchkey_encoded;
389 int ret=KEYSERVER_INTERNAL_ERROR;
390 enum ks_search_type search_type;
392 search_type=classify_ks_search(&searchkey);
394 if(opt->debug)
395 fprintf(console,"gpgkeys: search type is %d, and key is \"%s\"\n",
396 search_type,searchkey);
398 searchkey_encoded=curl_escape((char *)searchkey,0);
399 if(!searchkey_encoded)
401 fprintf(console,"gpgkeys: out of memory\n");
402 ret=KEYSERVER_NO_MEMORY;
403 goto fail;
406 request=malloc(MAX_URL+60+strlen(searchkey_encoded));
407 if(!request)
409 fprintf(console,"gpgkeys: out of memory\n");
410 ret=KEYSERVER_NO_MEMORY;
411 goto fail;
414 fprintf(output,"SEARCH %s BEGIN\n",searchkey);
416 strcpy(request,proto);
417 strcat(request,"://");
418 strcat(request,opt->host);
419 strcat(request,":");
420 strcat(request,port);
421 strcat(request,opt->path);
422 append_path(request,"/pks/lookup?op=index&options=mr&search=");
424 /* HKP keyservers like the 0x to be present when searching by
425 keyid */
426 if(search_type==KS_SEARCH_KEYID_SHORT || search_type==KS_SEARCH_KEYID_LONG)
427 strcat(request,"0x");
429 strcat(request,searchkey_encoded);
431 if(search_type!=KS_SEARCH_SUBSTR)
432 strcat(request,"&exact=on");
434 if(opt->verbose>2)
435 fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
437 curl_easy_setopt(curl,CURLOPT_URL,request);
438 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_mrindex_writer);
439 curl_easy_setopt(curl,CURLOPT_FILE,output);
441 res=curl_easy_perform(curl);
442 if(res!=0)
444 fprintf(console,"gpgkeys: HTTP search error %d: %s\n",res,errorbuffer);
445 ret=curl_err_to_gpg_err(res);
447 else
449 fprintf(output,"\nSEARCH %s END\n",searchkey);
450 ret=KEYSERVER_OK;
453 fail:
455 curl_free(searchkey_encoded);
456 free(request);
458 if(ret!=KEYSERVER_OK)
459 fprintf(output,"\nSEARCH %s FAILED %d\n",searchkey,ret);
461 return ret;
464 void
465 fail_all(struct keylist *keylist,int err)
467 if(!keylist)
468 return;
470 if(opt->action==KS_SEARCH)
472 fprintf(output,"SEARCH ");
473 while(keylist)
475 fprintf(output,"%s ",keylist->str);
476 keylist=keylist->next;
478 fprintf(output,"FAILED %d\n",err);
480 else
481 while(keylist)
483 fprintf(output,"KEY %s FAILED %d\n",keylist->str,err);
484 keylist=keylist->next;
488 #ifdef HAVE_LIBCURL
489 /* If there is a SRV record, take the highest ranked possibility.
490 This is a hack, as we don't proceed downwards. */
491 static void
492 srv_replace(const char *srvtag)
494 #ifdef USE_DNS_SRV
495 struct srventry *srvlist=NULL;
496 int srvcount;
498 if(!srvtag)
499 return;
501 if(1+strlen(srvtag)+6+strlen(opt->host)+1<=MAXDNAME)
503 char srvname[MAXDNAME];
505 strcpy(srvname,"_");
506 strcat(srvname,srvtag);
507 strcat(srvname,"._tcp.");
508 strcat(srvname,opt->host);
509 srvcount=getsrv(srvname,&srvlist);
512 if(srvlist)
514 char *newname,*newport;
516 newname=strdup(srvlist->target);
517 newport=malloc(MAX_PORT);
518 if(newname && newport)
520 free(opt->host);
521 free(opt->port);
522 opt->host=newname;
523 snprintf(newport,MAX_PORT,"%u",srvlist->port);
524 opt->port=newport;
526 else
528 free(newname);
529 free(newport);
532 #endif
534 #endif
536 static void
537 show_help (FILE *fp)
539 fprintf (fp,"-h, --help\thelp\n");
540 fprintf (fp,"-V\t\tmachine readable version\n");
541 fprintf (fp,"--version\thuman readable version\n");
542 fprintf (fp,"-o\t\toutput to this file\n");
546 main(int argc,char *argv[])
548 int arg,ret=KEYSERVER_INTERNAL_ERROR,try_srv=1;
549 char line[MAX_LINE];
550 int failed=0;
551 struct keylist *keylist=NULL,*keyptr=NULL;
552 char *proxy=NULL;
553 struct curl_slist *headers=NULL;
555 console=stderr;
557 /* Kludge to implement standard GNU options. */
558 if (argc > 1 && !strcmp (argv[1], "--version"))
560 printf ("gpgkeys_hkp (GnuPG) %s\n", VERSION);
561 printf ("Uses: %s\n", curl_version());
562 return 0;
564 else if (argc > 1 && !strcmp (argv[1], "--help"))
566 show_help (stdout);
567 return 0;
570 while((arg=getopt(argc,argv,"hVo:"))!=-1)
571 switch(arg)
573 default:
574 case 'h':
575 show_help (console);
576 return KEYSERVER_OK;
578 case 'V':
579 fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION);
580 return KEYSERVER_OK;
582 case 'o':
583 output=fopen(optarg,"w");
584 if(output==NULL)
586 fprintf(console,"gpgkeys: Cannot open output file `%s': %s\n",
587 optarg,strerror(errno));
588 return KEYSERVER_INTERNAL_ERROR;
591 break;
594 if(argc>optind)
596 input=fopen(argv[optind],"r");
597 if(input==NULL)
599 fprintf(console,"gpgkeys: Cannot open input file `%s': %s\n",
600 argv[optind],strerror(errno));
601 return KEYSERVER_INTERNAL_ERROR;
605 if(input==NULL)
606 input=stdin;
608 if(output==NULL)
609 output=stdout;
611 opt=init_ks_options();
612 if(!opt)
613 return KEYSERVER_NO_MEMORY;
615 /* Get the command and info block */
617 while(fgets(line,MAX_LINE,input)!=NULL)
619 int err;
620 char option[MAX_OPTION+1];
622 if(line[0]=='\n')
623 break;
625 err=parse_ks_options(line,opt);
626 if(err>0)
628 ret=err;
629 goto fail;
631 else if(err==0)
632 continue;
634 if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
636 int no=0;
637 char *start=&option[0];
639 option[MAX_OPTION]='\0';
641 if(strncasecmp(option,"no-",3)==0)
643 no=1;
644 start=&option[3];
647 if(strncasecmp(start,"http-proxy",10)==0)
649 if(no)
651 free(proxy);
652 proxy=strdup("");
654 else if(start[10]=='=')
656 if(strlen(&start[11])<MAX_PROXY)
658 free(proxy);
659 proxy=strdup(&start[11]);
663 else if(strcasecmp(start,"try-dns-srv")==0)
665 if(no)
666 try_srv=0;
667 else
668 try_srv=1;
671 continue;
675 if(!opt->scheme)
677 fprintf(console,"gpgkeys: no scheme supplied!\n");
678 ret=KEYSERVER_SCHEME_NOT_FOUND;
679 goto fail;
682 if(ks_strcasecmp(opt->scheme,"hkps")==0)
684 proto="https";
685 port="443";
687 else
689 proto="http";
690 port="11371";
693 if(!opt->host)
695 fprintf(console,"gpgkeys: no keyserver host provided\n");
696 goto fail;
699 if(opt->timeout && register_timeout()==-1)
701 fprintf(console,"gpgkeys: unable to register timeout handler\n");
702 return KEYSERVER_INTERNAL_ERROR;
705 curl_global_init(CURL_GLOBAL_DEFAULT);
706 curl=curl_easy_init();
707 if(!curl)
709 fprintf(console,"gpgkeys: unable to initialize curl\n");
710 ret=KEYSERVER_INTERNAL_ERROR;
711 goto fail;
714 /* If the user gives a :port, then disable SRV. The semantics of a
715 specified port and SRV do not play well together. */
716 if(opt->port)
717 port=opt->port;
718 else if(try_srv)
720 char *srvtag;
722 if(ks_strcasecmp(opt->scheme,"hkp")==0)
723 srvtag="pgpkey-http";
724 else if(ks_strcasecmp(opt->scheme,"hkps")==0)
725 srvtag="pgpkey-https";
726 else
727 srvtag=NULL;
729 #ifdef HAVE_LIBCURL
730 /* We're using libcurl, so fake SRV support via our wrapper.
731 This isn't as good as true SRV support, as we do not try all
732 possible targets at one particular level and work our way
733 down the list, but it's better than nothing. */
734 srv_replace(srvtag);
735 #else
736 /* We're using our internal curl shim, so we can use its (true)
737 SRV support. Obviously, CURLOPT_SRVTAG_GPG_HACK isn't a real
738 libcurl option. It's specific to our shim. */
739 curl_easy_setopt(curl,CURLOPT_SRVTAG_GPG_HACK,srvtag);
740 #endif
743 curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
745 if(opt->auth)
746 curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth);
748 if(opt->debug)
750 fprintf(console,"gpgkeys: curl version = %s\n",curl_version());
751 curl_easy_setopt(curl,CURLOPT_STDERR,console);
752 curl_easy_setopt(curl,CURLOPT_VERBOSE,1L);
755 curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,(long)opt->flags.check_cert);
756 curl_easy_setopt(curl,CURLOPT_CAINFO,opt->ca_cert_file);
758 /* Avoid caches to get the most recent copy of the key. This is bug
759 #1061. In pre-curl versions of the code, we didn't do it. Then
760 we did do it (as a curl default) until curl changed the default.
761 Now we're doing it again, but in such a way that changing
762 defaults in the future won't impact us. We set both the Pragma
763 and Cache-Control versions of the header, so we're good with both
764 HTTP 1.0 and 1.1. */
765 headers=curl_slist_append(headers,"Pragma: no-cache");
766 if(headers)
767 headers=curl_slist_append(headers,"Cache-Control: no-cache");
769 if(!headers)
771 fprintf(console,"gpgkeys: out of memory when building HTTP headers\n");
772 ret=KEYSERVER_NO_MEMORY;
773 goto fail;
776 curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
778 if(proxy)
779 curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
781 /* If it's a GET or a SEARCH, the next thing to come in is the
782 keyids. If it's a SEND, then there are no keyids. */
784 if(opt->action==KS_SEND)
785 while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
786 else if(opt->action==KS_GET
787 || opt->action==KS_GETNAME || opt->action==KS_SEARCH)
789 for(;;)
791 struct keylist *work;
793 if(fgets(line,MAX_LINE,input)==NULL)
794 break;
795 else
797 if(line[0]=='\n' || line[0]=='\0')
798 break;
800 work=malloc(sizeof(struct keylist));
801 if(work==NULL)
803 fprintf(console,"gpgkeys: out of memory while "
804 "building key list\n");
805 ret=KEYSERVER_NO_MEMORY;
806 goto fail;
809 strcpy(work->str,line);
811 /* Trim the trailing \n */
812 work->str[strlen(line)-1]='\0';
814 work->next=NULL;
816 /* Always attach at the end to keep the list in proper
817 order for searching */
818 if(keylist==NULL)
819 keylist=work;
820 else
821 keyptr->next=work;
823 keyptr=work;
827 else
829 fprintf(console,"gpgkeys: no keyserver command specified\n");
830 goto fail;
833 /* Send the response */
835 fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
836 fprintf(output,"PROGRAM %s\n\n",VERSION);
838 if(opt->verbose>1)
840 fprintf(console,"Host:\t\t%s\n",opt->host);
841 if(opt->port)
842 fprintf(console,"Port:\t\t%s\n",opt->port);
843 if(strcmp(opt->path,"/")!=0)
844 fprintf(console,"Path:\t\t%s\n",opt->path);
845 fprintf(console,"Command:\t%s\n",ks_action_to_string(opt->action));
848 if(opt->action==KS_GET)
850 keyptr=keylist;
852 while(keyptr!=NULL)
854 set_timeout(opt->timeout);
856 if(get_key(keyptr->str)!=KEYSERVER_OK)
857 failed++;
859 keyptr=keyptr->next;
862 else if(opt->action==KS_GETNAME)
864 keyptr=keylist;
866 while(keyptr!=NULL)
868 set_timeout(opt->timeout);
870 if(get_name(keyptr->str)!=KEYSERVER_OK)
871 failed++;
873 keyptr=keyptr->next;
876 else if(opt->action==KS_SEND)
878 int myeof=0;
882 set_timeout(opt->timeout);
884 if(send_key(&myeof)!=KEYSERVER_OK)
885 failed++;
887 while(!myeof);
889 else if(opt->action==KS_SEARCH)
891 char *searchkey=NULL;
892 int len=0;
894 set_timeout(opt->timeout);
896 /* To search, we stick a space in between each key to search
897 for. */
899 keyptr=keylist;
900 while(keyptr!=NULL)
902 len+=strlen(keyptr->str)+1;
903 keyptr=keyptr->next;
906 searchkey=malloc(len+1);
907 if(searchkey==NULL)
909 ret=KEYSERVER_NO_MEMORY;
910 fail_all(keylist,KEYSERVER_NO_MEMORY);
911 goto fail;
914 searchkey[0]='\0';
916 keyptr=keylist;
917 while(keyptr!=NULL)
919 strcat(searchkey,keyptr->str);
920 strcat(searchkey," ");
921 keyptr=keyptr->next;
924 /* Nail that last space */
925 if(*searchkey)
926 searchkey[strlen(searchkey)-1]='\0';
928 if(search_key(searchkey)!=KEYSERVER_OK)
929 failed++;
931 free(searchkey);
933 else
934 abort();
936 if(!failed)
937 ret=KEYSERVER_OK;
939 fail:
940 while(keylist!=NULL)
942 struct keylist *current=keylist;
943 keylist=keylist->next;
944 free(current);
947 if(input!=stdin)
948 fclose(input);
950 if(output!=stdout)
951 fclose(output);
953 free_ks_options(opt);
955 curl_slist_free_all(headers);
957 if(curl)
958 curl_easy_cleanup(curl);
960 free(proxy);
962 return ret;