gpg: Make commit 2b3cb2ee actually work
[gnupg.git] / keyserver / gpgkeys_hkp.c
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.
4  *
5  * This file is part of GnuPG.
6  *
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.
11  *
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.
16  *
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/>.
19  *
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.
30  */
31
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"
52
53 extern char *optarg;
54 extern int optind;
55
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;
61
62 static size_t
63 curl_mrindex_writer(const void *ptr,size_t size,size_t nmemb,void *stream)
64 {
65   static int checked=0,swallow=0;
66
67   if(!checked)
68     {
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;
76
77       checked=1;
78     }
79
80   if(swallow || fwrite(ptr,size,nmemb,stream)==nmemb)
81     return size*nmemb;
82   else
83     return 0;
84 }
85
86 /* Append but avoid creating a double slash // in the path. */
87 static char *
88 append_path(char *dest,const char *src)
89 {
90   size_t n=strlen(dest);
91
92   if(src[0]=='/' && n>0 && dest[n-1]=='/')
93     dest[n-1]='\0';
94
95   return strcat(dest,src);
96 }
97
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)
102 {
103   size_t n;
104
105   if (path[0] == '/' && (n=strlen (string)) && string[n-1] == '/')
106     return path+1;
107   else
108     return path;
109 }
110
111
112 int
113 send_key(int *r_eof)
114 {
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;
122
123   /* Read and throw away input until we see the BEGIN */
124
125   while(fgets(line,MAX_LINE,input)!=NULL)
126     if(sscanf(line,"KEY%*[ ]%16s%*[ ]%5s\n",keyid,state)==2
127        && strcmp(state,"BEGIN")==0)
128       {
129         begin=1;
130         break;
131       }
132
133   if(!begin)
134     {
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;
140     }
141
142   /* Now slurp up everything until we see the END */
143
144   while(fgets(line,MAX_LINE,input))
145     if(sscanf(line,"KEY%*[ ]%16s%*[ ]%3s\n",keyid,state)==2
146        && strcmp(state,"END")==0)
147       {
148         end=1;
149         break;
150       }
151     else
152       {
153         if(strlen(line)+keylen>keymax)
154           {
155             char *tmp;
156
157             keymax+=200;
158             tmp=realloc(key,keymax+1);
159             if(!tmp)
160               {
161                 free(key);
162                 fprintf(console,"gpgkeys: out of memory\n");
163                 ret=KEYSERVER_NO_MEMORY;
164                 goto fail;
165               }
166
167             key=tmp;
168           }
169
170         strcpy(&key[keylen],line);
171         keylen+=strlen(line);
172       }
173
174   if(!end)
175     {
176       fprintf(console,"gpgkeys: no KEY %s END found\n",keyid);
177       *r_eof=1;
178       ret=KEYSERVER_KEY_INCOMPLETE;
179       goto fail;
180     }
181
182   encoded_key=curl_escape(key,keylen);
183   if(!encoded_key)
184     {
185       fprintf(console,"gpgkeys: out of memory\n");
186       ret=KEYSERVER_NO_MEMORY;
187       goto fail;
188     }
189
190   free(key);
191
192   key = strconcat ("keytext=", encoded_key, NULL);
193   if(!key)
194     {
195       fprintf(console,"gpgkeys: out of memory\n");
196       ret=KEYSERVER_NO_MEMORY;
197       goto fail;
198     }
199
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");
209
210   if(opt->verbose>2)
211     fprintf(console,"gpgkeys: HTTP URL is '%s'\n",request);
212
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);
217
218   res=curl_easy_perform(curl);
219   if(res!=0)
220     {
221       fprintf(console,"gpgkeys: HTTP post error %d: %s\n",res,errorbuffer);
222       ret=curl_err_to_gpg_err(res);
223       goto fail;
224     }
225   else
226     fprintf(output,"\nKEY %s SENT\n",keyid);
227
228   ret=KEYSERVER_OK;
229
230  fail:
231   xfree (key);
232   curl_free(encoded_key);
233
234   if(ret!=0 && begin)
235     fprintf(output,"KEY %s FAILED %d\n",keyid,ret);
236
237   return ret;
238 }
239
240 static int
241 get_key(char *getkey)
242 {
243   CURLcode res;
244   char request[MAX_URL+92];
245   char *offset;
246   struct curl_writer_ctx ctx;
247   size_t keylen;
248
249   memset(&ctx,0,sizeof(ctx));
250
251   /* Build the search string.  HKP only uses the short key IDs. */
252
253   if(strncmp(getkey,"0x",2)==0)
254     getkey+=2;
255
256   fprintf(output,"KEY 0x%s BEGIN\n",getkey);
257
258   if(strlen(getkey)==32)
259     {
260       fprintf(console,
261               "gpgkeys: HKP keyservers do not support v3 fingerprints\n");
262       fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED);
263       return KEYSERVER_NOT_SUPPORTED;
264     }
265
266   strcpy(request,proto);
267   strcat(request,"://");
268   strcat(request,opt->host);
269   strcat(request,":");
270   strcat(request,port);
271   strcat(request,opt->path);
272   /* request is MAX_URL+55 bytes long - MAX_URL covers the whole URL,
273      including any supplied path.  The 92 overcovers this /pks/... etc
274      string plus the 8, 16, or 40 bytes of key id/fingerprint */
275   append_path(request,"/pks/lookup?op=get&options=mr&search=0x");
276
277   /* send only fingerprint, long key id, or short keyid.  see:
278      https://tools.ietf.org/html/draft-shaw-openpgp-hkp-00#section-3.1.1.1 */
279   keylen = strlen(getkey);
280   if(keylen >= 40)
281     offset=&getkey[keylen-40];
282   else if(keylen >= 16)
283     offset=&getkey[keylen-16];
284   else if(keylen >= 8)
285     offset=&getkey[keylen-8];
286   else
287     offset=getkey;
288
289   strcat(request,offset);
290
291   if(opt->verbose>2)
292     fprintf(console,"gpgkeys: HTTP URL is '%s'\n",request);
293
294   curl_easy_setopt(curl,CURLOPT_URL,request);
295   curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
296   ctx.stream=output;
297   curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
298
299   res=curl_easy_perform(curl);
300   if(res!=CURLE_OK)
301     {
302       fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
303       fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
304     }
305   else
306     {
307       curl_writer_finalize(&ctx);
308       if(!ctx.flags.done)
309         {
310           fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
311           fprintf(output,"\nKEY 0x%s FAILED %d\n",
312                   getkey,KEYSERVER_KEY_NOT_FOUND);
313         }
314       else
315         fprintf(output,"\nKEY 0x%s END\n",getkey);
316     }
317
318   return KEYSERVER_OK;
319 }
320
321 static int
322 get_name(const char *getkey)
323 {
324   CURLcode res;
325   char *request=NULL;
326   char *searchkey_encoded;
327   int ret=KEYSERVER_INTERNAL_ERROR;
328   struct curl_writer_ctx ctx;
329
330   memset(&ctx,0,sizeof(ctx));
331
332   searchkey_encoded=curl_escape((char *)getkey,0);
333   if(!searchkey_encoded)
334     {
335       fprintf(console,"gpgkeys: out of memory\n");
336       ret=KEYSERVER_NO_MEMORY;
337       goto fail;
338     }
339
340   request = strconcat
341     (proto,
342      "://",
343      opt->host,
344      ":",
345      port,
346      opt->path,
347      appendable_path (opt->path,"/pks/lookup?op=get&options=mr&search="),
348      searchkey_encoded,
349      "&exact=on",
350      NULL);
351   if(!request)
352     {
353       fprintf(console,"gpgkeys: out of memory\n");
354       ret=KEYSERVER_NO_MEMORY;
355       goto fail;
356     }
357   
358   fprintf(output,"NAME %s BEGIN\n",getkey);
359
360   if(opt->verbose>2)
361     fprintf(console,"gpgkeys: HTTP URL is '%s'\n",request);
362
363   curl_easy_setopt(curl,CURLOPT_URL,request);
364   curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
365   ctx.stream=output;
366   curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
367
368   res=curl_easy_perform(curl);
369   if(res!=CURLE_OK)
370     {
371       fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
372       ret=curl_err_to_gpg_err(res);
373     }
374   else
375     {
376       curl_writer_finalize(&ctx);
377       if(!ctx.flags.done)
378         {
379           fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
380           ret=KEYSERVER_KEY_NOT_FOUND;
381         }
382       else
383         {
384           fprintf(output,"\nNAME %s END\n",getkey);
385           ret=KEYSERVER_OK;
386         }
387     }
388
389  fail:
390   curl_free(searchkey_encoded);
391   xfree (request);
392
393   if(ret!=KEYSERVER_OK)
394     fprintf(output,"\nNAME %s FAILED %d\n",getkey,ret);
395
396   return ret;
397 }
398
399 static int
400 search_key(const char *searchkey)
401 {
402   CURLcode res;
403   char *request=NULL;
404   char *searchkey_encoded;
405   int ret=KEYSERVER_INTERNAL_ERROR;
406   enum ks_search_type search_type;
407   const char *hexprefix;
408
409   search_type=classify_ks_search(&searchkey);
410
411   if(opt->debug)
412     fprintf(console,"gpgkeys: search type is %d, and key is \"%s\"\n",
413             search_type,searchkey);
414
415   searchkey_encoded=curl_escape((char *)searchkey,0);
416   if(!searchkey_encoded)
417     {
418       fprintf(console,"gpgkeys: out of memory\n");
419       ret=KEYSERVER_NO_MEMORY;
420       goto fail;
421     }
422
423   /* HKP keyservers like the 0x to be present when searching by
424      keyid.  */
425   hexprefix = (search_type==KS_SEARCH_KEYID_SHORT
426                || search_type==KS_SEARCH_KEYID_LONG)? "0x":"";
427
428   request = strconcat
429     (proto,
430      "://",
431      opt->host,
432      ":",
433      port,
434      opt->path,
435      appendable_path (opt->path, "/pks/lookup?op=index&options=mr&search="),
436      hexprefix,
437      searchkey_encoded,
438      NULL);
439   if(!request)
440     {
441       fprintf(console,"gpgkeys: out of memory\n");
442       ret=KEYSERVER_NO_MEMORY;
443       goto fail;
444     }
445
446   fprintf(output,"SEARCH %s BEGIN\n",searchkey);
447
448   if(opt->verbose>2)
449     fprintf(console,"gpgkeys: HTTP URL is '%s'\n",request);
450
451   curl_easy_setopt(curl,CURLOPT_URL,request);
452   curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_mrindex_writer);
453   curl_easy_setopt(curl,CURLOPT_FILE,output);
454
455   res=curl_easy_perform(curl);
456   if(res!=0)
457     {
458       fprintf(console,"gpgkeys: HTTP search error %d: %s\n",res,errorbuffer);
459       ret=curl_err_to_gpg_err(res);
460     }
461   else
462     {
463       fprintf(output,"\nSEARCH %s END\n",searchkey);
464       ret=KEYSERVER_OK;
465     }
466
467  fail:
468   curl_free(searchkey_encoded);
469   xfree (request);
470
471   if(ret!=KEYSERVER_OK)
472     fprintf(output,"\nSEARCH %s FAILED %d\n",searchkey,ret);
473
474   return ret;
475 }
476
477 void
478 fail_all(struct keylist *keylist,int err)
479 {
480   if(!keylist)
481     return;
482
483   if(opt->action==KS_SEARCH)
484     {
485       fprintf(output,"SEARCH ");
486       while(keylist)
487         {
488           fprintf(output,"%s ",keylist->str);
489           keylist=keylist->next;
490         }
491       fprintf(output,"FAILED %d\n",err);
492     }
493   else
494     while(keylist)
495       {
496         fprintf(output,"KEY %s FAILED %d\n",keylist->str,err);
497         keylist=keylist->next;
498       }
499 }
500
501 #ifdef HAVE_LIBCURL
502 /* If there is a SRV record, take the highest ranked possibility.
503    This is a hack, as we don't proceed downwards. */
504 static void
505 srv_replace(const char *srvtag)
506 {
507 #ifdef USE_DNS_SRV
508   struct srventry *srvlist=NULL;
509   int srvcount;
510
511   if(!srvtag)
512     return;
513
514   if(1+strlen(srvtag)+6+strlen(opt->host)+1<=MAXDNAME)
515     {
516       char srvname[MAXDNAME];
517
518       strcpy(srvname,"_");
519       strcat(srvname,srvtag);
520       strcat(srvname,"._tcp.");
521       strcat(srvname,opt->host);
522       srvcount=getsrv(srvname,&srvlist);
523     }
524
525   if(srvlist)
526     {
527       char *newname,*newport;
528
529       newname=strdup(srvlist->target);
530       newport=malloc(MAX_PORT);
531       if(newname && newport)
532         {
533           free(opt->host);
534           free(opt->port);
535           opt->host=newname;
536           snprintf(newport,MAX_PORT,"%u",srvlist->port);
537           opt->port=newport;
538         }
539       else
540         {
541           free(newname);
542           free(newport);
543         }
544     }
545 #endif
546 }
547 #endif
548
549 static void 
550 show_help (FILE *fp)
551 {
552   fprintf (fp,"-h, --help\thelp\n");
553   fprintf (fp,"-V\t\tmachine readable version\n");
554   fprintf (fp,"--version\thuman readable version\n");
555   fprintf (fp,"-o\t\toutput to this file\n");
556 }
557
558 int
559 main(int argc,char *argv[])
560 {
561   int arg,ret=KEYSERVER_INTERNAL_ERROR,try_srv=1;
562   char line[MAX_LINE];
563   int failed=0;
564   struct keylist *keylist=NULL,*keyptr=NULL;
565   char *proxy=NULL;
566   struct curl_slist *headers=NULL;
567
568   console=stderr;
569
570   /* Kludge to implement standard GNU options.  */
571   if (argc > 1 && !strcmp (argv[1], "--version"))
572     {
573       printf ("gpgkeys_hkp (GnuPG) %s\n", VERSION);
574       printf ("Uses: %s\n", curl_version());
575       return 0;
576     }
577   else if (argc > 1 && !strcmp (argv[1], "--help"))
578     {
579       show_help (stdout);
580       return 0;
581     }
582
583   while((arg=getopt(argc,argv,"hVo:"))!=-1)
584     switch(arg)
585       {
586       default:
587       case 'h':
588         show_help (console);
589         return KEYSERVER_OK;
590
591       case 'V':
592         fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION);
593         return KEYSERVER_OK;
594
595       case 'o':
596         output=fopen(optarg,"w");
597         if(output==NULL)
598           {
599             fprintf(console,"gpgkeys: Cannot open output file '%s': %s\n",
600                     optarg,strerror(errno));
601             return KEYSERVER_INTERNAL_ERROR;
602           }
603
604         break;
605       }
606
607   if(argc>optind)
608     {
609       input=fopen(argv[optind],"r");
610       if(input==NULL)
611         {
612           fprintf(console,"gpgkeys: Cannot open input file '%s': %s\n",
613                   argv[optind],strerror(errno));
614           return KEYSERVER_INTERNAL_ERROR;
615         }
616     }
617
618   if(input==NULL)
619     input=stdin;
620
621   if(output==NULL)
622     output=stdout;
623
624   opt=init_ks_options();
625   if(!opt)
626     return KEYSERVER_NO_MEMORY;
627
628   /* Get the command and info block */
629
630   while(fgets(line,MAX_LINE,input)!=NULL)
631     {
632       int err;
633       char option[MAX_OPTION+1];
634
635       if(line[0]=='\n')
636         break;
637
638       err=parse_ks_options(line,opt);
639       if(err>0)
640         {
641           ret=err;
642           goto fail;
643         }
644       else if(err==0)
645         continue;
646
647       if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
648         {
649           int no=0;
650           char *start=&option[0];
651
652           option[MAX_OPTION]='\0';
653
654           if(strncasecmp(option,"no-",3)==0)
655             {
656               no=1;
657               start=&option[3];
658             }
659
660           if(strncasecmp(start,"http-proxy",10)==0)
661             {
662               if(no)
663                 {
664                   free(proxy);
665                   proxy=strdup("");
666                 }
667               else if(start[10]=='=')
668                 {
669                   if(strlen(&start[11])<MAX_PROXY)
670                     {
671                       free(proxy);
672                       proxy=strdup(&start[11]);
673                     }
674                 }
675             }
676           else if(strcasecmp(start,"try-dns-srv")==0)
677             {
678               if(no)
679                 try_srv=0;
680               else
681                 try_srv=1;
682             }
683
684           continue;
685         }
686     }
687
688   if(!opt->scheme)
689     {
690       fprintf(console,"gpgkeys: no scheme supplied!\n");
691       ret=KEYSERVER_SCHEME_NOT_FOUND;
692       goto fail;
693     }
694
695   if(ascii_strcasecmp(opt->scheme,"hkps")==0)
696     {
697       proto="https";
698       port="443";
699     }
700   else
701     {
702       proto="http";
703       port="11371";
704     }
705
706   if(!opt->host)
707     {
708       fprintf(console,"gpgkeys: no keyserver host provided\n");
709       goto fail;
710     }
711
712   if(opt->timeout && register_timeout()==-1)
713     {
714       fprintf(console,"gpgkeys: unable to register timeout handler\n");
715       return KEYSERVER_INTERNAL_ERROR;
716     }
717
718   curl_global_init(CURL_GLOBAL_DEFAULT);
719   curl=curl_easy_init();
720   if(!curl)
721     {
722       fprintf(console,"gpgkeys: unable to initialize curl\n");
723       ret=KEYSERVER_INTERNAL_ERROR;
724       goto fail;
725     }
726
727   /* If the user gives a :port, then disable SRV.  The semantics of a
728      specified port and SRV do not play well together. */
729   if(opt->port)
730     port=opt->port;
731   else if(try_srv)
732     {
733       char *srvtag;
734
735       if(ks_strcasecmp(opt->scheme,"hkp")==0)
736         srvtag="pgpkey-http";
737       else if(ks_strcasecmp(opt->scheme,"hkps")==0)
738         srvtag="pgpkey-https";
739       else
740         srvtag=NULL;
741
742 #ifdef HAVE_LIBCURL
743       /* We're using libcurl, so fake SRV support via our wrapper.
744          This isn't as good as true SRV support, as we do not try all
745          possible targets at one particular level and work our way
746          down the list, but it's better than nothing. */      
747       srv_replace(srvtag);
748 #else
749       /* We're using our internal curl shim, so we can use its (true)
750          SRV support.  Obviously, CURLOPT_SRVTAG_GPG_HACK isn't a real
751          libcurl option.  It's specific to our shim. */
752       curl_easy_setopt(curl,CURLOPT_SRVTAG_GPG_HACK,srvtag);
753 #endif
754     }
755
756   curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
757
758   if(opt->auth)
759     curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth);
760
761   if(opt->debug)
762     {
763       fprintf(console,"gpgkeys: curl version = %s\n",curl_version());
764       curl_easy_setopt(curl,CURLOPT_STDERR,console);
765       curl_easy_setopt(curl,CURLOPT_VERBOSE,1L);
766     }
767
768   curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,(long)opt->flags.check_cert);
769   curl_easy_setopt(curl,CURLOPT_CAINFO,opt->ca_cert_file);
770
771   /* Avoid caches to get the most recent copy of the key.  This is bug
772      #1061.  In pre-curl versions of the code, we didn't do it.  Then
773      we did do it (as a curl default) until curl changed the default.
774      Now we're doing it again, but in such a way that changing
775      defaults in the future won't impact us.  We set both the Pragma
776      and Cache-Control versions of the header, so we're good with both
777      HTTP 1.0 and 1.1. */
778   headers=curl_slist_append(headers,"Pragma: no-cache");
779   if(headers)
780     headers=curl_slist_append(headers,"Cache-Control: no-cache");
781
782   if(!headers)
783     {
784       fprintf(console,"gpgkeys: out of memory when building HTTP headers\n");
785       ret=KEYSERVER_NO_MEMORY;
786       goto fail;
787     }
788
789   curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
790
791   if(proxy)
792     curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
793
794   /* If it's a GET or a SEARCH, the next thing to come in is the
795      keyids.  If it's a SEND, then there are no keyids. */
796
797   if(opt->action==KS_SEND)
798     while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
799   else if(opt->action==KS_GET
800           || opt->action==KS_GETNAME || opt->action==KS_SEARCH)
801     {
802       for(;;)
803         {
804           struct keylist *work;
805
806           if(fgets(line,MAX_LINE,input)==NULL)
807             break;
808           else
809             {
810               if(line[0]=='\n' || line[0]=='\0')
811                 break;
812
813               work=malloc(sizeof(struct keylist));
814               if(work==NULL)
815                 {
816                   fprintf(console,"gpgkeys: out of memory while "
817                           "building key list\n");
818                   ret=KEYSERVER_NO_MEMORY;
819                   goto fail;
820                 }
821
822               strcpy(work->str,line);
823
824               /* Trim the trailing \n */
825               work->str[strlen(line)-1]='\0';
826
827               work->next=NULL;
828
829               /* Always attach at the end to keep the list in proper
830                  order for searching */
831               if(keylist==NULL)
832                 keylist=work;
833               else
834                 keyptr->next=work;
835
836               keyptr=work;
837             }
838         }
839     }
840   else
841     {
842       fprintf(console,"gpgkeys: no keyserver command specified\n");
843       goto fail;
844     }
845
846   /* Send the response */
847
848   fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
849   fprintf(output,"PROGRAM %s\n\n",VERSION);
850
851   if(opt->verbose>1)
852     {
853       fprintf(console,"Host:\t\t%s\n",opt->host);
854       if(opt->port)
855         fprintf(console,"Port:\t\t%s\n",opt->port);
856       if(strcmp(opt->path,"/")!=0)
857         fprintf(console,"Path:\t\t%s\n",opt->path);
858       fprintf(console,"Command:\t%s\n",ks_action_to_string(opt->action));
859     }
860
861   if(opt->action==KS_GET)
862     {
863       keyptr=keylist;
864
865       while(keyptr!=NULL)
866         {
867           set_timeout(opt->timeout);
868
869           if(get_key(keyptr->str)!=KEYSERVER_OK)
870             failed++;
871
872           keyptr=keyptr->next;
873         }
874     }
875   else if(opt->action==KS_GETNAME)
876     {
877       keyptr=keylist;
878
879       while(keyptr!=NULL)
880         {
881           set_timeout(opt->timeout);
882
883           if(get_name(keyptr->str)!=KEYSERVER_OK)
884             failed++;
885
886           keyptr=keyptr->next;
887         }
888     }
889   else if(opt->action==KS_SEND)
890     {
891       int myeof=0;
892
893       do
894         {
895           set_timeout(opt->timeout);
896
897           if(send_key(&myeof)!=KEYSERVER_OK)
898             failed++;
899         }
900       while(!myeof);
901     }
902   else if(opt->action==KS_SEARCH)
903     {
904       char *searchkey=NULL;
905       int len=0;
906
907       set_timeout(opt->timeout);
908
909       /* To search, we stick a space in between each key to search
910          for. */
911
912       keyptr=keylist;
913       while(keyptr!=NULL)
914         {
915           len+=strlen(keyptr->str)+1;
916           keyptr=keyptr->next;
917         }
918
919       searchkey=malloc(len+1);
920       if(searchkey==NULL)
921         {
922           ret=KEYSERVER_NO_MEMORY;
923           fail_all(keylist,KEYSERVER_NO_MEMORY);
924           goto fail;
925         }
926
927       searchkey[0]='\0';
928
929       keyptr=keylist;
930       while(keyptr!=NULL)
931         {
932           strcat(searchkey,keyptr->str);
933           strcat(searchkey," ");
934           keyptr=keyptr->next;
935         }
936
937       /* Nail that last space */
938       if(*searchkey)
939         searchkey[strlen(searchkey)-1]='\0';
940
941       if(search_key(searchkey)!=KEYSERVER_OK)
942         failed++;
943
944       free(searchkey);
945     }
946   else
947     abort();
948
949   if(!failed)
950     ret=KEYSERVER_OK;
951
952  fail:
953   while(keylist!=NULL)
954     {
955       struct keylist *current=keylist;
956       keylist=keylist->next;
957       free(current);
958     }
959
960   if(input!=stdin)
961     fclose(input);
962
963   if(output!=stdout)
964     fclose(output);
965
966   free_ks_options(opt);
967
968   curl_slist_free_all(headers);
969
970   if(curl)
971     curl_easy_cleanup(curl);
972
973   free(proxy);
974
975   return ret;
976 }