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