ee6421ab7d870bca401d8854e85128b88b0dc705
[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      opt->action == KS_GETNAME? "&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      opt->action == KS_GETNAME? "&exact=on":"",
439      NULL);
440   if(!request)
441     {
442       fprintf(console,"gpgkeys: out of memory\n");
443       ret=KEYSERVER_NO_MEMORY;
444       goto fail;
445     }
446
447   fprintf(output,"SEARCH %s BEGIN\n",searchkey);
448
449   if(opt->verbose>2)
450     fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
451
452   curl_easy_setopt(curl,CURLOPT_URL,request);
453   curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_mrindex_writer);
454   curl_easy_setopt(curl,CURLOPT_FILE,output);
455
456   res=curl_easy_perform(curl);
457   if(res!=0)
458     {
459       fprintf(console,"gpgkeys: HTTP search error %d: %s\n",res,errorbuffer);
460       ret=curl_err_to_gpg_err(res);
461     }
462   else
463     {
464       fprintf(output,"\nSEARCH %s END\n",searchkey);
465       ret=KEYSERVER_OK;
466     }
467
468  fail:
469   curl_free(searchkey_encoded);
470   xfree (request);
471
472   if(ret!=KEYSERVER_OK)
473     fprintf(output,"\nSEARCH %s FAILED %d\n",searchkey,ret);
474
475   return ret;
476 }
477
478 void
479 fail_all(struct keylist *keylist,int err)
480 {
481   if(!keylist)
482     return;
483
484   if(opt->action==KS_SEARCH)
485     {
486       fprintf(output,"SEARCH ");
487       while(keylist)
488         {
489           fprintf(output,"%s ",keylist->str);
490           keylist=keylist->next;
491         }
492       fprintf(output,"FAILED %d\n",err);
493     }
494   else
495     while(keylist)
496       {
497         fprintf(output,"KEY %s FAILED %d\n",keylist->str,err);
498         keylist=keylist->next;
499       }
500 }
501
502 #ifdef HAVE_LIBCURL
503 /* If there is a SRV record, take the highest ranked possibility.
504    This is a hack, as we don't proceed downwards. */
505 static void
506 srv_replace(const char *srvtag)
507 {
508 #ifdef USE_DNS_SRV
509   struct srventry *srvlist=NULL;
510   int srvcount;
511
512   if(!srvtag)
513     return;
514
515   if(1+strlen(srvtag)+6+strlen(opt->host)+1<=MAXDNAME)
516     {
517       char srvname[MAXDNAME];
518
519       strcpy(srvname,"_");
520       strcat(srvname,srvtag);
521       strcat(srvname,"._tcp.");
522       strcat(srvname,opt->host);
523       srvcount=getsrv(srvname,&srvlist);
524     }
525
526   if(srvlist)
527     {
528       char *newname,*newport;
529
530       newname=strdup(srvlist->target);
531       newport=malloc(MAX_PORT);
532       if(newname && newport)
533         {
534           free(opt->host);
535           free(opt->port);
536           opt->host=newname;
537           snprintf(newport,MAX_PORT,"%u",srvlist->port);
538           opt->port=newport;
539         }
540       else
541         {
542           free(newname);
543           free(newport);
544         }
545     }
546 #endif
547 }
548 #endif
549
550 static void 
551 show_help (FILE *fp)
552 {
553   fprintf (fp,"-h, --help\thelp\n");
554   fprintf (fp,"-V\t\tmachine readable version\n");
555   fprintf (fp,"--version\thuman readable version\n");
556   fprintf (fp,"-o\t\toutput to this file\n");
557 }
558
559 int
560 main(int argc,char *argv[])
561 {
562   int arg,ret=KEYSERVER_INTERNAL_ERROR,try_srv=1;
563   char line[MAX_LINE];
564   int failed=0;
565   struct keylist *keylist=NULL,*keyptr=NULL;
566   char *proxy=NULL;
567   struct curl_slist *headers=NULL;
568
569   console=stderr;
570
571   /* Kludge to implement standard GNU options.  */
572   if (argc > 1 && !strcmp (argv[1], "--version"))
573     {
574       printf ("gpgkeys_hkp (GnuPG) %s\n", VERSION);
575       printf ("Uses: %s\n", curl_version());
576       return 0;
577     }
578   else if (argc > 1 && !strcmp (argv[1], "--help"))
579     {
580       show_help (stdout);
581       return 0;
582     }
583
584   while((arg=getopt(argc,argv,"hVo:"))!=-1)
585     switch(arg)
586       {
587       default:
588       case 'h':
589         show_help (console);
590         return KEYSERVER_OK;
591
592       case 'V':
593         fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION);
594         return KEYSERVER_OK;
595
596       case 'o':
597         output=fopen(optarg,"w");
598         if(output==NULL)
599           {
600             fprintf(console,"gpgkeys: Cannot open output file `%s': %s\n",
601                     optarg,strerror(errno));
602             return KEYSERVER_INTERNAL_ERROR;
603           }
604
605         break;
606       }
607
608   if(argc>optind)
609     {
610       input=fopen(argv[optind],"r");
611       if(input==NULL)
612         {
613           fprintf(console,"gpgkeys: Cannot open input file `%s': %s\n",
614                   argv[optind],strerror(errno));
615           return KEYSERVER_INTERNAL_ERROR;
616         }
617     }
618
619   if(input==NULL)
620     input=stdin;
621
622   if(output==NULL)
623     output=stdout;
624
625   opt=init_ks_options();
626   if(!opt)
627     return KEYSERVER_NO_MEMORY;
628
629   /* Get the command and info block */
630
631   while(fgets(line,MAX_LINE,input)!=NULL)
632     {
633       int err;
634       char option[MAX_OPTION+1];
635
636       if(line[0]=='\n')
637         break;
638
639       err=parse_ks_options(line,opt);
640       if(err>0)
641         {
642           ret=err;
643           goto fail;
644         }
645       else if(err==0)
646         continue;
647
648       if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
649         {
650           int no=0;
651           char *start=&option[0];
652
653           option[MAX_OPTION]='\0';
654
655           if(strncasecmp(option,"no-",3)==0)
656             {
657               no=1;
658               start=&option[3];
659             }
660
661           if(strncasecmp(start,"http-proxy",10)==0)
662             {
663               if(no)
664                 {
665                   free(proxy);
666                   proxy=strdup("");
667                 }
668               else if(start[10]=='=')
669                 {
670                   if(strlen(&start[11])<MAX_PROXY)
671                     {
672                       free(proxy);
673                       proxy=strdup(&start[11]);
674                     }
675                 }
676             }
677           else if(strcasecmp(start,"try-dns-srv")==0)
678             {
679               if(no)
680                 try_srv=0;
681               else
682                 try_srv=1;
683             }
684
685           continue;
686         }
687     }
688
689   if(!opt->scheme)
690     {
691       fprintf(console,"gpgkeys: no scheme supplied!\n");
692       ret=KEYSERVER_SCHEME_NOT_FOUND;
693       goto fail;
694     }
695
696   if(ks_strcasecmp(opt->scheme,"hkps")==0)
697     {
698       proto="https";
699       port="443";
700     }
701   else
702     {
703       proto="http";
704       port="11371";
705     }
706
707   if(!opt->host)
708     {
709       fprintf(console,"gpgkeys: no keyserver host provided\n");
710       goto fail;
711     }
712
713   if(opt->timeout && register_timeout()==-1)
714     {
715       fprintf(console,"gpgkeys: unable to register timeout handler\n");
716       return KEYSERVER_INTERNAL_ERROR;
717     }
718
719   curl_global_init(CURL_GLOBAL_DEFAULT);
720   curl=curl_easy_init();
721   if(!curl)
722     {
723       fprintf(console,"gpgkeys: unable to initialize curl\n");
724       ret=KEYSERVER_INTERNAL_ERROR;
725       goto fail;
726     }
727
728   /* If the user gives a :port, then disable SRV.  The semantics of a
729      specified port and SRV do not play well together. */
730   if(opt->port)
731     port=opt->port;
732   else if(try_srv)
733     {
734       char *srvtag;
735
736       if(ks_strcasecmp(opt->scheme,"hkp")==0)
737         srvtag="pgpkey-http";
738       else if(ks_strcasecmp(opt->scheme,"hkps")==0)
739         srvtag="pgpkey-https";
740       else
741         srvtag=NULL;
742
743 #ifdef HAVE_LIBCURL
744       /* We're using libcurl, so fake SRV support via our wrapper.
745          This isn't as good as true SRV support, as we do not try all
746          possible targets at one particular level and work our way
747          down the list, but it's better than nothing. */      
748       srv_replace(srvtag);
749 #else
750       /* We're using our internal curl shim, so we can use its (true)
751          SRV support.  Obviously, CURLOPT_SRVTAG_GPG_HACK isn't a real
752          libcurl option.  It's specific to our shim. */
753       curl_easy_setopt(curl,CURLOPT_SRVTAG_GPG_HACK,srvtag);
754 #endif
755     }
756
757   curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
758
759   if(opt->auth)
760     curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth);
761
762   if(opt->debug)
763     {
764       fprintf(console,"gpgkeys: curl version = %s\n",curl_version());
765       curl_easy_setopt(curl,CURLOPT_STDERR,console);
766       curl_easy_setopt(curl,CURLOPT_VERBOSE,1L);
767     }
768
769   curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,(long)opt->flags.check_cert);
770   curl_easy_setopt(curl,CURLOPT_CAINFO,opt->ca_cert_file);
771
772   /* Avoid caches to get the most recent copy of the key.  This is bug
773      #1061.  In pre-curl versions of the code, we didn't do it.  Then
774      we did do it (as a curl default) until curl changed the default.
775      Now we're doing it again, but in such a way that changing
776      defaults in the future won't impact us.  We set both the Pragma
777      and Cache-Control versions of the header, so we're good with both
778      HTTP 1.0 and 1.1. */
779   headers=curl_slist_append(headers,"Pragma: no-cache");
780   if(headers)
781     headers=curl_slist_append(headers,"Cache-Control: no-cache");
782
783   if(!headers)
784     {
785       fprintf(console,"gpgkeys: out of memory when building HTTP headers\n");
786       ret=KEYSERVER_NO_MEMORY;
787       goto fail;
788     }
789
790   curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
791
792   if(proxy)
793     curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
794
795   /* If it's a GET or a SEARCH, the next thing to come in is the
796      keyids.  If it's a SEND, then there are no keyids. */
797
798   if(opt->action==KS_SEND)
799     while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
800   else if(opt->action==KS_GET
801           || opt->action==KS_GETNAME || opt->action==KS_SEARCH)
802     {
803       for(;;)
804         {
805           struct keylist *work;
806
807           if(fgets(line,MAX_LINE,input)==NULL)
808             break;
809           else
810             {
811               if(line[0]=='\n' || line[0]=='\0')
812                 break;
813
814               work=malloc(sizeof(struct keylist));
815               if(work==NULL)
816                 {
817                   fprintf(console,"gpgkeys: out of memory while "
818                           "building key list\n");
819                   ret=KEYSERVER_NO_MEMORY;
820                   goto fail;
821                 }
822
823               strcpy(work->str,line);
824
825               /* Trim the trailing \n */
826               work->str[strlen(line)-1]='\0';
827
828               work->next=NULL;
829
830               /* Always attach at the end to keep the list in proper
831                  order for searching */
832               if(keylist==NULL)
833                 keylist=work;
834               else
835                 keyptr->next=work;
836
837               keyptr=work;
838             }
839         }
840     }
841   else
842     {
843       fprintf(console,"gpgkeys: no keyserver command specified\n");
844       goto fail;
845     }
846
847   /* Send the response */
848
849   fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
850   fprintf(output,"PROGRAM %s\n\n",VERSION);
851
852   if(opt->verbose>1)
853     {
854       fprintf(console,"Host:\t\t%s\n",opt->host);
855       if(opt->port)
856         fprintf(console,"Port:\t\t%s\n",opt->port);
857       if(strcmp(opt->path,"/")!=0)
858         fprintf(console,"Path:\t\t%s\n",opt->path);
859       fprintf(console,"Command:\t%s\n",ks_action_to_string(opt->action));
860     }
861
862   if(opt->action==KS_GET)
863     {
864       keyptr=keylist;
865
866       while(keyptr!=NULL)
867         {
868           set_timeout(opt->timeout);
869
870           if(get_key(keyptr->str)!=KEYSERVER_OK)
871             failed++;
872
873           keyptr=keyptr->next;
874         }
875     }
876   else if(opt->action==KS_GETNAME)
877     {
878       keyptr=keylist;
879
880       while(keyptr!=NULL)
881         {
882           set_timeout(opt->timeout);
883
884           if(get_name(keyptr->str)!=KEYSERVER_OK)
885             failed++;
886
887           keyptr=keyptr->next;
888         }
889     }
890   else if(opt->action==KS_SEND)
891     {
892       int myeof=0;
893
894       do
895         {
896           set_timeout(opt->timeout);
897
898           if(send_key(&myeof)!=KEYSERVER_OK)
899             failed++;
900         }
901       while(!myeof);
902     }
903   else if(opt->action==KS_SEARCH)
904     {
905       char *searchkey=NULL;
906       int len=0;
907
908       set_timeout(opt->timeout);
909
910       /* To search, we stick a space in between each key to search
911          for. */
912
913       keyptr=keylist;
914       while(keyptr!=NULL)
915         {
916           len+=strlen(keyptr->str)+1;
917           keyptr=keyptr->next;
918         }
919
920       searchkey=malloc(len+1);
921       if(searchkey==NULL)
922         {
923           ret=KEYSERVER_NO_MEMORY;
924           fail_all(keylist,KEYSERVER_NO_MEMORY);
925           goto fail;
926         }
927
928       searchkey[0]='\0';
929
930       keyptr=keylist;
931       while(keyptr!=NULL)
932         {
933           strcat(searchkey,keyptr->str);
934           strcat(searchkey," ");
935           keyptr=keyptr->next;
936         }
937
938       /* Nail that last space */
939       if(*searchkey)
940         searchkey[strlen(searchkey)-1]='\0';
941
942       if(search_key(searchkey)!=KEYSERVER_OK)
943         failed++;
944
945       free(searchkey);
946     }
947   else
948     abort();
949
950   if(!failed)
951     ret=KEYSERVER_OK;
952
953  fail:
954   while(keylist!=NULL)
955     {
956       struct keylist *current=keylist;
957       keylist=keylist->next;
958       free(current);
959     }
960
961   if(input!=stdin)
962     fclose(input);
963
964   if(output!=stdout)
965     fclose(output);
966
967   free_ks_options(opt);
968
969   curl_slist_free_all(headers);
970
971   if(curl)
972     curl_easy_cleanup(curl);
973
974   free(proxy);
975
976   return ret;
977 }