Updated the german translation
[gnupg.git] / keyserver / gpgkeys_hkp.c
bloba44f091317aa04f7549342ee11bb424de9c314c9
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 #include "util.h"
47 #ifdef USE_DNS_SRV
48 #include "srv.h"
49 #endif
50 #include "keyserver.h"
51 #include "ksutil.h"
53 extern char *optarg;
54 extern int optind;
56 static FILE *input,*output,*console;
57 static CURL *curl;
58 static struct ks_options *opt;
59 static char errorbuffer[CURL_ERROR_SIZE];
60 static char *proto,*port;
62 static size_t
63 curl_mrindex_writer(const void *ptr,size_t size,size_t nmemb,void *stream)
65 static int checked=0,swallow=0;
67 if(!checked)
69 /* If the document begins with a '<', assume it's a HTML
70 response, which we don't support. Discard the whole message
71 body. GPG can handle it, but this is an optimization to deal
72 with it on this side of the pipe. */
73 const char *buf=ptr;
74 if(buf[0]=='<')
75 swallow=1;
77 checked=1;
80 if(swallow || fwrite(ptr,size,nmemb,stream)==nmemb)
81 return size*nmemb;
82 else
83 return 0;
86 /* Append but avoid creating a double slash // in the path. */
87 static char *
88 append_path(char *dest,const char *src)
90 size_t n=strlen(dest);
92 if(src[0]=='/' && n>0 && dest[n-1]=='/')
93 dest[n-1]='\0';
95 return strcat(dest,src);
98 /* Return a pointer into STRING so that appending PATH to STRING will
99 not yield a duplicated slash. */
100 static const char *
101 appendable_path (const char *string, const char *path)
103 size_t n;
105 if (path[0] == '/' && (n=strlen (string)) && string[n-1] == '/')
106 return path+1;
107 else
108 return path;
113 send_key(int *r_eof)
115 CURLcode res;
116 char request[MAX_URL+15];
117 int begin=0,end=0,ret=KEYSERVER_INTERNAL_ERROR;
118 char keyid[17],state[6];
119 char line[MAX_LINE];
120 char *key=NULL,*encoded_key=NULL;
121 size_t keylen=0,keymax=0;
123 /* Read and throw away input until we see the BEGIN */
125 while(fgets(line,MAX_LINE,input)!=NULL)
126 if(sscanf(line,"KEY%*[ ]%16s%*[ ]%5s\n",keyid,state)==2
127 && strcmp(state,"BEGIN")==0)
129 begin=1;
130 break;
133 if(!begin)
135 /* i.e. eof before the KEY BEGIN was found. This isn't an
136 error. */
137 *r_eof=1;
138 ret=KEYSERVER_OK;
139 goto fail;
142 /* Now slurp up everything until we see the END */
144 while(fgets(line,MAX_LINE,input))
145 if(sscanf(line,"KEY%*[ ]%16s%*[ ]%3s\n",keyid,state)==2
146 && strcmp(state,"END")==0)
148 end=1;
149 break;
151 else
153 if(strlen(line)+keylen>keymax)
155 char *tmp;
157 keymax+=200;
158 tmp=realloc(key,keymax+1);
159 if(!tmp)
161 free(key);
162 fprintf(console,"gpgkeys: out of memory\n");
163 ret=KEYSERVER_NO_MEMORY;
164 goto fail;
167 key=tmp;
170 strcpy(&key[keylen],line);
171 keylen+=strlen(line);
174 if(!end)
176 fprintf(console,"gpgkeys: no KEY %s END found\n",keyid);
177 *r_eof=1;
178 ret=KEYSERVER_KEY_INCOMPLETE;
179 goto fail;
182 encoded_key=curl_escape(key,keylen);
183 if(!encoded_key)
185 fprintf(console,"gpgkeys: out of memory\n");
186 ret=KEYSERVER_NO_MEMORY;
187 goto fail;
190 free(key);
192 key = strconcat ("keytext=", encoded_key, NULL);
193 if(!key)
195 fprintf(console,"gpgkeys: out of memory\n");
196 ret=KEYSERVER_NO_MEMORY;
197 goto fail;
200 strcpy(request,proto);
201 strcat(request,"://");
202 strcat(request,opt->host);
203 strcat(request,":");
204 strcat(request,port);
205 strcat(request,opt->path);
206 /* request is MAX_URL+15 bytes long - MAX_URL covers the whole URL,
207 including any supplied path. The 15 covers /pks/add. */
208 append_path(request,"/pks/add");
210 if(opt->verbose>2)
211 fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
213 curl_easy_setopt(curl,CURLOPT_URL,request);
214 curl_easy_setopt(curl,CURLOPT_POST,1L);
215 curl_easy_setopt(curl,CURLOPT_POSTFIELDS,key);
216 curl_easy_setopt(curl,CURLOPT_FAILONERROR,1L);
218 res=curl_easy_perform(curl);
219 if(res!=0)
221 fprintf(console,"gpgkeys: HTTP post error %d: %s\n",res,errorbuffer);
222 ret=curl_err_to_gpg_err(res);
223 goto fail;
225 else
226 fprintf(output,"\nKEY %s SENT\n",keyid);
228 ret=KEYSERVER_OK;
230 fail:
231 xfree (key);
232 curl_free(encoded_key);
234 if(ret!=0 && begin)
235 fprintf(output,"KEY %s FAILED %d\n",keyid,ret);
237 return ret;
240 static int
241 get_key(char *getkey)
243 CURLcode res;
244 char request[MAX_URL+60];
245 char *offset;
246 struct curl_writer_ctx ctx;
248 memset(&ctx,0,sizeof(ctx));
250 /* Build the search string. HKP only uses the short key IDs. */
252 if(strncmp(getkey,"0x",2)==0)
253 getkey+=2;
255 fprintf(output,"KEY 0x%s BEGIN\n",getkey);
257 if(strlen(getkey)==32)
259 fprintf(console,
260 "gpgkeys: HKP keyservers do not support v3 fingerprints\n");
261 fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED);
262 return KEYSERVER_NOT_SUPPORTED;
265 strcpy(request,proto);
266 strcat(request,"://");
267 strcat(request,opt->host);
268 strcat(request,":");
269 strcat(request,port);
270 strcat(request,opt->path);
271 /* request is MAX_URL+55 bytes long - MAX_URL covers the whole URL,
272 including any supplied path. The 60 overcovers this /pks/... etc
273 string plus the 8 bytes of key id */
274 append_path(request,"/pks/lookup?op=get&options=mr&search=0x");
276 /* fingerprint or long key id. Take the last 8 characters and treat
277 it like a short key id */
278 if(strlen(getkey)>8)
279 offset=&getkey[strlen(getkey)-8];
280 else
281 offset=getkey;
283 strcat(request,offset);
285 if(opt->verbose>2)
286 fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
288 curl_easy_setopt(curl,CURLOPT_URL,request);
289 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
290 ctx.stream=output;
291 curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
293 res=curl_easy_perform(curl);
294 if(res!=CURLE_OK)
296 fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
297 fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
299 else
301 curl_writer_finalize(&ctx);
302 if(!ctx.flags.done)
304 fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
305 fprintf(output,"\nKEY 0x%s FAILED %d\n",
306 getkey,KEYSERVER_KEY_NOT_FOUND);
308 else
309 fprintf(output,"\nKEY 0x%s END\n",getkey);
312 return KEYSERVER_OK;
315 static int
316 get_name(const char *getkey)
318 CURLcode res;
319 char *request=NULL;
320 char *searchkey_encoded;
321 int ret=KEYSERVER_INTERNAL_ERROR;
322 struct curl_writer_ctx ctx;
324 memset(&ctx,0,sizeof(ctx));
326 searchkey_encoded=curl_escape((char *)getkey,0);
327 if(!searchkey_encoded)
329 fprintf(console,"gpgkeys: out of memory\n");
330 ret=KEYSERVER_NO_MEMORY;
331 goto fail;
334 request = strconcat
335 (proto,
336 "://",
337 opt->host,
338 ":",
339 port,
340 opt->path,
341 appendable_path (opt->path,"/pks/lookup?op=get&options=mr&search="),
342 searchkey_encoded,
343 opt->action == KS_GETNAME? "&exact=on":"",
344 NULL);
345 if(!request)
347 fprintf(console,"gpgkeys: out of memory\n");
348 ret=KEYSERVER_NO_MEMORY;
349 goto fail;
352 fprintf(output,"NAME %s BEGIN\n",getkey);
354 if(opt->verbose>2)
355 fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
357 curl_easy_setopt(curl,CURLOPT_URL,request);
358 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
359 ctx.stream=output;
360 curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
362 res=curl_easy_perform(curl);
363 if(res!=CURLE_OK)
365 fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
366 ret=curl_err_to_gpg_err(res);
368 else
370 curl_writer_finalize(&ctx);
371 if(!ctx.flags.done)
373 fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
374 ret=KEYSERVER_KEY_NOT_FOUND;
376 else
378 fprintf(output,"\nNAME %s END\n",getkey);
379 ret=KEYSERVER_OK;
383 fail:
384 curl_free(searchkey_encoded);
385 xfree (request);
387 if(ret!=KEYSERVER_OK)
388 fprintf(output,"\nNAME %s FAILED %d\n",getkey,ret);
390 return ret;
393 static int
394 search_key(const char *searchkey)
396 CURLcode res;
397 char *request=NULL;
398 char *searchkey_encoded;
399 int ret=KEYSERVER_INTERNAL_ERROR;
400 enum ks_search_type search_type;
401 const char *hexprefix;
403 search_type=classify_ks_search(&searchkey);
405 if(opt->debug)
406 fprintf(console,"gpgkeys: search type is %d, and key is \"%s\"\n",
407 search_type,searchkey);
409 searchkey_encoded=curl_escape((char *)searchkey,0);
410 if(!searchkey_encoded)
412 fprintf(console,"gpgkeys: out of memory\n");
413 ret=KEYSERVER_NO_MEMORY;
414 goto fail;
417 /* HKP keyservers like the 0x to be present when searching by
418 keyid. */
419 hexprefix = (search_type==KS_SEARCH_KEYID_SHORT
420 || search_type==KS_SEARCH_KEYID_LONG)? "0x":"";
422 request = strconcat
423 (proto,
424 "://",
425 opt->host,
426 ":",
427 port,
428 opt->path,
429 appendable_path (opt->path, "/pks/lookup?op=index&options=mr&search="),
430 hexprefix,
431 searchkey_encoded,
432 opt->action == KS_GETNAME? "&exact=on":"",
433 NULL);
434 if(!request)
436 fprintf(console,"gpgkeys: out of memory\n");
437 ret=KEYSERVER_NO_MEMORY;
438 goto fail;
441 fprintf(output,"SEARCH %s BEGIN\n",searchkey);
443 if(opt->verbose>2)
444 fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
446 curl_easy_setopt(curl,CURLOPT_URL,request);
447 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_mrindex_writer);
448 curl_easy_setopt(curl,CURLOPT_FILE,output);
450 res=curl_easy_perform(curl);
451 if(res!=0)
453 fprintf(console,"gpgkeys: HTTP search error %d: %s\n",res,errorbuffer);
454 ret=curl_err_to_gpg_err(res);
456 else
458 fprintf(output,"\nSEARCH %s END\n",searchkey);
459 ret=KEYSERVER_OK;
462 fail:
463 curl_free(searchkey_encoded);
464 xfree (request);
466 if(ret!=KEYSERVER_OK)
467 fprintf(output,"\nSEARCH %s FAILED %d\n",searchkey,ret);
469 return ret;
472 void
473 fail_all(struct keylist *keylist,int err)
475 if(!keylist)
476 return;
478 if(opt->action==KS_SEARCH)
480 fprintf(output,"SEARCH ");
481 while(keylist)
483 fprintf(output,"%s ",keylist->str);
484 keylist=keylist->next;
486 fprintf(output,"FAILED %d\n",err);
488 else
489 while(keylist)
491 fprintf(output,"KEY %s FAILED %d\n",keylist->str,err);
492 keylist=keylist->next;
496 #ifdef HAVE_LIBCURL
497 /* If there is a SRV record, take the highest ranked possibility.
498 This is a hack, as we don't proceed downwards. */
499 static void
500 srv_replace(const char *srvtag)
502 #ifdef USE_DNS_SRV
503 struct srventry *srvlist=NULL;
504 int srvcount;
506 if(!srvtag)
507 return;
509 if(1+strlen(srvtag)+6+strlen(opt->host)+1<=MAXDNAME)
511 char srvname[MAXDNAME];
513 strcpy(srvname,"_");
514 strcat(srvname,srvtag);
515 strcat(srvname,"._tcp.");
516 strcat(srvname,opt->host);
517 srvcount=getsrv(srvname,&srvlist);
520 if(srvlist)
522 char *newname,*newport;
524 newname=strdup(srvlist->target);
525 newport=malloc(MAX_PORT);
526 if(newname && newport)
528 free(opt->host);
529 free(opt->port);
530 opt->host=newname;
531 snprintf(newport,MAX_PORT,"%u",srvlist->port);
532 opt->port=newport;
534 else
536 free(newname);
537 free(newport);
540 #endif
542 #endif
544 static void
545 show_help (FILE *fp)
547 fprintf (fp,"-h, --help\thelp\n");
548 fprintf (fp,"-V\t\tmachine readable version\n");
549 fprintf (fp,"--version\thuman readable version\n");
550 fprintf (fp,"-o\t\toutput to this file\n");
554 main(int argc,char *argv[])
556 int arg,ret=KEYSERVER_INTERNAL_ERROR,try_srv=1;
557 char line[MAX_LINE];
558 int failed=0;
559 struct keylist *keylist=NULL,*keyptr=NULL;
560 char *proxy=NULL;
561 struct curl_slist *headers=NULL;
563 console=stderr;
565 /* Kludge to implement standard GNU options. */
566 if (argc > 1 && !strcmp (argv[1], "--version"))
568 printf ("gpgkeys_hkp (GnuPG) %s\n", VERSION);
569 printf ("Uses: %s\n", curl_version());
570 return 0;
572 else if (argc > 1 && !strcmp (argv[1], "--help"))
574 show_help (stdout);
575 return 0;
578 while((arg=getopt(argc,argv,"hVo:"))!=-1)
579 switch(arg)
581 default:
582 case 'h':
583 show_help (console);
584 return KEYSERVER_OK;
586 case 'V':
587 fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION);
588 return KEYSERVER_OK;
590 case 'o':
591 output=fopen(optarg,"w");
592 if(output==NULL)
594 fprintf(console,"gpgkeys: Cannot open output file `%s': %s\n",
595 optarg,strerror(errno));
596 return KEYSERVER_INTERNAL_ERROR;
599 break;
602 if(argc>optind)
604 input=fopen(argv[optind],"r");
605 if(input==NULL)
607 fprintf(console,"gpgkeys: Cannot open input file `%s': %s\n",
608 argv[optind],strerror(errno));
609 return KEYSERVER_INTERNAL_ERROR;
613 if(input==NULL)
614 input=stdin;
616 if(output==NULL)
617 output=stdout;
619 opt=init_ks_options();
620 if(!opt)
621 return KEYSERVER_NO_MEMORY;
623 /* Get the command and info block */
625 while(fgets(line,MAX_LINE,input)!=NULL)
627 int err;
628 char option[MAX_OPTION+1];
630 if(line[0]=='\n')
631 break;
633 err=parse_ks_options(line,opt);
634 if(err>0)
636 ret=err;
637 goto fail;
639 else if(err==0)
640 continue;
642 if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
644 int no=0;
645 char *start=&option[0];
647 option[MAX_OPTION]='\0';
649 if(strncasecmp(option,"no-",3)==0)
651 no=1;
652 start=&option[3];
655 if(strncasecmp(start,"http-proxy",10)==0)
657 if(no)
659 free(proxy);
660 proxy=strdup("");
662 else if(start[10]=='=')
664 if(strlen(&start[11])<MAX_PROXY)
666 free(proxy);
667 proxy=strdup(&start[11]);
671 else if(strcasecmp(start,"try-dns-srv")==0)
673 if(no)
674 try_srv=0;
675 else
676 try_srv=1;
679 continue;
683 if(!opt->scheme)
685 fprintf(console,"gpgkeys: no scheme supplied!\n");
686 ret=KEYSERVER_SCHEME_NOT_FOUND;
687 goto fail;
690 if(ks_strcasecmp(opt->scheme,"hkps")==0)
692 proto="https";
693 port="443";
695 else
697 proto="http";
698 port="11371";
701 if(!opt->host)
703 fprintf(console,"gpgkeys: no keyserver host provided\n");
704 goto fail;
707 if(opt->timeout && register_timeout()==-1)
709 fprintf(console,"gpgkeys: unable to register timeout handler\n");
710 return KEYSERVER_INTERNAL_ERROR;
713 curl_global_init(CURL_GLOBAL_DEFAULT);
714 curl=curl_easy_init();
715 if(!curl)
717 fprintf(console,"gpgkeys: unable to initialize curl\n");
718 ret=KEYSERVER_INTERNAL_ERROR;
719 goto fail;
722 /* If the user gives a :port, then disable SRV. The semantics of a
723 specified port and SRV do not play well together. */
724 if(opt->port)
725 port=opt->port;
726 else if(try_srv)
728 char *srvtag;
730 if(ks_strcasecmp(opt->scheme,"hkp")==0)
731 srvtag="pgpkey-http";
732 else if(ks_strcasecmp(opt->scheme,"hkps")==0)
733 srvtag="pgpkey-https";
734 else
735 srvtag=NULL;
737 #ifdef HAVE_LIBCURL
738 /* We're using libcurl, so fake SRV support via our wrapper.
739 This isn't as good as true SRV support, as we do not try all
740 possible targets at one particular level and work our way
741 down the list, but it's better than nothing. */
742 srv_replace(srvtag);
743 #else
744 /* We're using our internal curl shim, so we can use its (true)
745 SRV support. Obviously, CURLOPT_SRVTAG_GPG_HACK isn't a real
746 libcurl option. It's specific to our shim. */
747 curl_easy_setopt(curl,CURLOPT_SRVTAG_GPG_HACK,srvtag);
748 #endif
751 curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
753 if(opt->auth)
754 curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth);
756 if(opt->debug)
758 fprintf(console,"gpgkeys: curl version = %s\n",curl_version());
759 curl_easy_setopt(curl,CURLOPT_STDERR,console);
760 curl_easy_setopt(curl,CURLOPT_VERBOSE,1L);
763 curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,(long)opt->flags.check_cert);
764 curl_easy_setopt(curl,CURLOPT_CAINFO,opt->ca_cert_file);
766 /* Avoid caches to get the most recent copy of the key. This is bug
767 #1061. In pre-curl versions of the code, we didn't do it. Then
768 we did do it (as a curl default) until curl changed the default.
769 Now we're doing it again, but in such a way that changing
770 defaults in the future won't impact us. We set both the Pragma
771 and Cache-Control versions of the header, so we're good with both
772 HTTP 1.0 and 1.1. */
773 headers=curl_slist_append(headers,"Pragma: no-cache");
774 if(headers)
775 headers=curl_slist_append(headers,"Cache-Control: no-cache");
777 if(!headers)
779 fprintf(console,"gpgkeys: out of memory when building HTTP headers\n");
780 ret=KEYSERVER_NO_MEMORY;
781 goto fail;
784 curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
786 if(proxy)
787 curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
789 /* If it's a GET or a SEARCH, the next thing to come in is the
790 keyids. If it's a SEND, then there are no keyids. */
792 if(opt->action==KS_SEND)
793 while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
794 else if(opt->action==KS_GET
795 || opt->action==KS_GETNAME || opt->action==KS_SEARCH)
797 for(;;)
799 struct keylist *work;
801 if(fgets(line,MAX_LINE,input)==NULL)
802 break;
803 else
805 if(line[0]=='\n' || line[0]=='\0')
806 break;
808 work=malloc(sizeof(struct keylist));
809 if(work==NULL)
811 fprintf(console,"gpgkeys: out of memory while "
812 "building key list\n");
813 ret=KEYSERVER_NO_MEMORY;
814 goto fail;
817 strcpy(work->str,line);
819 /* Trim the trailing \n */
820 work->str[strlen(line)-1]='\0';
822 work->next=NULL;
824 /* Always attach at the end to keep the list in proper
825 order for searching */
826 if(keylist==NULL)
827 keylist=work;
828 else
829 keyptr->next=work;
831 keyptr=work;
835 else
837 fprintf(console,"gpgkeys: no keyserver command specified\n");
838 goto fail;
841 /* Send the response */
843 fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
844 fprintf(output,"PROGRAM %s\n\n",VERSION);
846 if(opt->verbose>1)
848 fprintf(console,"Host:\t\t%s\n",opt->host);
849 if(opt->port)
850 fprintf(console,"Port:\t\t%s\n",opt->port);
851 if(strcmp(opt->path,"/")!=0)
852 fprintf(console,"Path:\t\t%s\n",opt->path);
853 fprintf(console,"Command:\t%s\n",ks_action_to_string(opt->action));
856 if(opt->action==KS_GET)
858 keyptr=keylist;
860 while(keyptr!=NULL)
862 set_timeout(opt->timeout);
864 if(get_key(keyptr->str)!=KEYSERVER_OK)
865 failed++;
867 keyptr=keyptr->next;
870 else if(opt->action==KS_GETNAME)
872 keyptr=keylist;
874 while(keyptr!=NULL)
876 set_timeout(opt->timeout);
878 if(get_name(keyptr->str)!=KEYSERVER_OK)
879 failed++;
881 keyptr=keyptr->next;
884 else if(opt->action==KS_SEND)
886 int myeof=0;
890 set_timeout(opt->timeout);
892 if(send_key(&myeof)!=KEYSERVER_OK)
893 failed++;
895 while(!myeof);
897 else if(opt->action==KS_SEARCH)
899 char *searchkey=NULL;
900 int len=0;
902 set_timeout(opt->timeout);
904 /* To search, we stick a space in between each key to search
905 for. */
907 keyptr=keylist;
908 while(keyptr!=NULL)
910 len+=strlen(keyptr->str)+1;
911 keyptr=keyptr->next;
914 searchkey=malloc(len+1);
915 if(searchkey==NULL)
917 ret=KEYSERVER_NO_MEMORY;
918 fail_all(keylist,KEYSERVER_NO_MEMORY);
919 goto fail;
922 searchkey[0]='\0';
924 keyptr=keylist;
925 while(keyptr!=NULL)
927 strcat(searchkey,keyptr->str);
928 strcat(searchkey," ");
929 keyptr=keyptr->next;
932 /* Nail that last space */
933 if(*searchkey)
934 searchkey[strlen(searchkey)-1]='\0';
936 if(search_key(searchkey)!=KEYSERVER_OK)
937 failed++;
939 free(searchkey);
941 else
942 abort();
944 if(!failed)
945 ret=KEYSERVER_OK;
947 fail:
948 while(keylist!=NULL)
950 struct keylist *current=keylist;
951 keylist=keylist->next;
952 free(current);
955 if(input!=stdin)
956 fclose(input);
958 if(output!=stdout)
959 fclose(output);
961 free_ks_options(opt);
963 curl_slist_free_all(headers);
965 if(curl)
966 curl_easy_cleanup(curl);
968 free(proxy);
970 return ret;