* distfiles, _regex.h: Add _regex.h from glibc 2.3.1.
[gnupg.git] / keyserver / gpgkeys_hkp.c
1 /* gpgkeys_hkp.c - talk to an HKP keyserver
2  * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #define INCLUDED_BY_MAIN_MODULE 1
29 #include "util.h"
30 #include "http.h"
31 #include "keyserver.h"
32
33 #define GET    0
34 #define SEND   1
35 #define SEARCH 2
36 #define MAX_LINE 80
37
38 int verbose=0,include_revoked=0,include_disabled=0;
39 unsigned int http_flags=0;
40 char host[80]={'\0'},port[10]={'\0'};
41 FILE *input=NULL,*output=NULL,*console=NULL;
42
43 struct keylist
44 {
45   char str[MAX_LINE];
46   struct keylist *next;
47 };
48
49 #ifdef __riscos__
50 RISCOS_GLOBAL_STATICS("HKP Keyfetcher Heap")
51 #endif /* __riscos__ */
52
53 int
54 urlencode_filter( void *opaque, int control,
55                   IOBUF a, byte *buf, size_t *ret_len)
56 {
57     size_t size = *ret_len;
58     int rc=0;
59
60     if( control == IOBUFCTRL_FLUSH ) {
61         const byte *p;
62         for(p=buf; size; p++, size-- ) {
63             if( isalnum(*p) || *p == '-' )
64                 iobuf_put( a, *p );
65             else if( *p == ' ' )
66                 iobuf_put( a, '+' );
67             else {
68                 char numbuf[5];
69                 sprintf(numbuf, "%%%02X", *p );
70                 iobuf_writestr(a, numbuf );
71             }
72         }
73     }
74     else if( control == IOBUFCTRL_DESC )
75         *(char**)buf = "urlencode_filter";
76     return rc;
77 }
78
79 int
80 send_key(int *eof)
81 {
82   int rc,gotit=0,ret=KEYSERVER_INTERNAL_ERROR;
83   char keyid[17];
84   char *request;
85   struct http_context hd;
86   unsigned int status;
87   IOBUF temp = iobuf_temp();
88   char line[MAX_LINE];
89
90   request=malloc(strlen(host)+100);
91   if(!request)
92     {
93       fprintf(console,"gpgkeys: out of memory\n");
94       return KEYSERVER_NO_MEMORY;
95     }
96
97   iobuf_push_filter(temp,urlencode_filter,NULL);
98
99   /* Read and throw away input until we see the BEGIN */
100
101   while(fgets(line,MAX_LINE,input)!=NULL)
102     if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1)
103       {
104         gotit=1;
105         break;
106       }
107
108   if(!gotit)
109     {
110       /* i.e. eof before the KEY BEGIN was found.  This isn't an
111          error. */
112       *eof=1;
113       ret=KEYSERVER_OK;
114       goto fail;
115     }
116
117   gotit=0;
118
119   /* Now slurp up everything until we see the END */
120
121   while(fgets(line,MAX_LINE,input))
122     if(sscanf(line,"KEY %16s END\n",keyid)==1)
123       {
124         gotit=1;
125         break;
126       }
127     else
128       if(iobuf_writestr(temp,line))
129         {
130           fprintf(console,"gpgkeys: internal iobuf error\n");
131           goto fail;
132         }
133
134   if(!gotit)
135     {
136       fprintf(console,"gpgkeys: no KEY %s END found\n",keyid);
137       *eof=1;
138       ret=KEYSERVER_KEY_INCOMPLETE;
139       goto fail;
140     }
141
142   iobuf_flush_temp(temp);
143
144   sprintf(request,"x-hkp://%s%s%s/pks/add",
145           host,port[0]?":":"",port[0]?port:"");
146
147   if(verbose>2)
148     fprintf(console,"gpgkeys: HTTP URL is \"%s\"\n",request);
149
150   rc=http_open(&hd,HTTP_REQ_POST,request,http_flags);
151   if(rc)
152     {
153       fprintf(console,"gpgkeys: unable to connect to `%s'\n",host);
154       goto fail;
155     }
156
157   sprintf(request,"Content-Length: %u\r\n",
158           (unsigned)iobuf_get_temp_length(temp)+9);
159   iobuf_writestr(hd.fp_write,request);
160
161   http_start_data(&hd);
162
163   iobuf_writestr(hd.fp_write,"keytext=");
164   iobuf_write(hd.fp_write,
165               iobuf_get_temp_buffer(temp),iobuf_get_temp_length(temp));
166   iobuf_put(hd.fp_write,'\n');
167
168   rc=http_wait_response(&hd,&status);
169   if(rc)
170     {
171       fprintf(console,"gpgkeys: error sending to `%s': %s\n",
172               host,g10_errstr(rc));
173       goto fail;
174     }
175
176   if((status/100)!=2)
177     {
178       fprintf(console,"gpgkeys: remote server returned error %d\n",status);
179       fprintf(output,"KEY %s FAILED %d\n",keyid,ret);
180       goto fail;
181     }
182
183   fprintf(output,"KEY %s SENT\n",keyid);
184
185   ret=KEYSERVER_OK;
186
187  fail:
188   free(request);
189   iobuf_close(temp);
190   http_close(&hd);
191
192   return ret;
193 }
194
195 int
196 get_key(char *getkey)
197 {
198   int rc,gotit=0;
199   char search[29];
200   char *request;
201   struct http_context hd;
202
203   /* Build the search string.  HKP only uses the short key IDs. */
204
205   if(strncmp(getkey,"0x",2)==0)
206     getkey+=2;
207
208   if(strlen(getkey)==32)
209     {
210       fprintf(console,
211               "gpgkeys: HKP keyservers do not support v3 fingerprints\n");
212       fprintf(output,"KEY 0x%s BEGIN\n",getkey);
213       fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED);
214       return KEYSERVER_NOT_SUPPORTED;
215     }
216
217  if(strlen(getkey)>8)
218     {
219       char *offset=&getkey[strlen(getkey)-8];
220
221       /* fingerprint or long key id.  Take the last 8 characters and
222          treat it like a short key id */
223
224       sprintf(search,"0x%.8s",offset);
225     }
226  else
227    {
228       /* short key id */
229     
230       sprintf(search,"0x%.8s",getkey);
231     }
232
233   fprintf(output,"KEY 0x%s BEGIN\n",getkey);
234
235   if(verbose)
236     fprintf(console,"gpgkeys: requesting key 0x%s from hkp://%s%s%s\n",
237             getkey,host,port[0]?":":"",port[0]?port:"");
238
239   request=malloc(strlen(host)+100);
240   if(!request)
241     {
242       fprintf(console,"gpgkeys: out of memory\n");
243       return KEYSERVER_NO_MEMORY;
244     }
245
246   sprintf(request,"x-hkp://%s%s%s/pks/lookup?op=get&search=%s",
247           host,port[0]?":":"",port[0]?port:"", search);
248
249   if(verbose>2)
250     fprintf(console,"gpgkeys: HTTP URL is \"%s\"\n",request);
251
252   rc=http_open_document(&hd,request,http_flags);
253   if(rc!=0)
254     {
255       fprintf(console,"gpgkeys: HKP fetch error: %s\n",
256               rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc));
257       fprintf(output,"KEY 0x%s FAILED %d\n",getkey,
258             rc==G10ERR_NETWORK?KEYSERVER_UNREACHABLE:KEYSERVER_INTERNAL_ERROR);
259     }
260   else
261     {
262       unsigned int maxlen=1024,buflen;
263       byte *line=NULL;
264
265       while(iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen))
266         {
267           maxlen=1024;
268
269           if(gotit)
270             {
271               fprintf(output,line);
272               if(strcmp(line,"-----END PGP PUBLIC KEY BLOCK-----\n")==0)
273                 break;
274             }
275           else
276             if(strcmp(line,"-----BEGIN PGP PUBLIC KEY BLOCK-----\n")==0)
277               {
278                 fprintf(output,line);
279                 gotit=1;
280               }
281         }
282
283       if(gotit)
284         fprintf(output,"KEY 0x%s END\n",getkey);
285       else
286         {
287           fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
288           fprintf(output,"KEY 0x%s FAILED %d\n",
289                   getkey,KEYSERVER_KEY_NOT_FOUND);
290         }
291
292       m_free(line);
293     }
294
295   free(request);
296
297   return KEYSERVER_OK;
298 }
299
300 /* Remove anything <between brackets> and de-urlencode in place.  Note
301    that this requires all brackets to be closed on the same line.  It
302    also means that the result is never larger than the input. */
303 void
304 dehtmlize(char *line)
305 {
306   int parsedindex=0;
307   char *parsed=line;
308
309   while(*line!='\0')
310     {
311       switch(*line)
312         {
313         case '<':
314           while(*line!='>' && *line!='\0')
315             line++;
316
317           if(*line!='\0')
318             line++;
319           break;
320
321         case '&':
322           if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='l') &&
323              (*(line+2)!='\0' && ascii_tolower(*(line+2))=='t') &&
324              (*(line+3)!='\0' && *(line+3)==';'))
325             {
326               parsed[parsedindex++]='<';
327               line+=4;
328               break;
329             }
330           else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='g') &&
331                   (*(line+2)!='\0' && ascii_tolower(*(line+2))=='t') &&
332                   (*(line+3)!='\0' && *(line+3)==';'))
333             {
334               parsed[parsedindex++]='>';
335               line+=4;
336               break;
337             }
338           else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='a') &&
339                   (*(line+2)!='\0' && ascii_tolower(*(line+2))=='m') &&
340                   (*(line+3)!='\0' && ascii_tolower(*(line+3))=='p') &&
341                   (*(line+4)!='\0' && *(line+4)==';'))
342             {
343               parsed[parsedindex++]='&';
344               line+=5;
345               break;
346             }
347
348         default:
349           parsed[parsedindex++]=*line;
350           line++;
351           break;
352         }
353     }
354
355   parsed[parsedindex]='\0';
356
357   /* Chop off any trailing whitespace.  Note that the HKP servers have
358      \r\n as line endings, and the NAI HKP servers have just \n. */
359
360   if(parsedindex>0)
361     {
362       parsedindex--;
363       while(isspace(((unsigned char *)parsed)[parsedindex]))
364         {
365           parsed[parsedindex]='\0';
366           parsedindex--;
367         }
368     }
369 }
370
371 int
372 write_quoted(IOBUF a, const char *buf, char delim)
373 {
374   char quoted[5];
375
376   sprintf(quoted,"%%%02X",delim);
377
378   while(*buf)
379     {
380       if(*buf==delim)
381         {
382           if(iobuf_writestr(a,quoted))
383             return -1;
384         }
385       else if(*buf=='%')
386         {
387           if(iobuf_writestr(a,"%25"))
388             return -1;
389         }
390       else
391         {
392           if(iobuf_writebyte(a,*buf))
393             return -1;
394         }
395
396       buf++;
397     }
398
399   return 0;
400 }
401
402 /* pub  2048/<a href="/pks/lookup?op=get&search=0x3CB3B415">3CB3B415</a> 1998/04/03 David M. Shaw &lt;<a href="/pks/lookup?op=get&search=0x3CB3B415">dshaw@jabberwocky.com</a>&gt; */
403
404 /* Luckily enough, both the HKP server and NAI HKP interface to their
405    LDAP server are close enough in output so the same function can
406    parse them both. */
407
408 int 
409 parse_hkp_index(IOBUF buffer,char *line)
410 {
411   int ret=0;
412
413   /* printf("Open %d, LINE: \"%s\"\n",open,line); */
414
415   dehtmlize(line);
416
417   /* printf("Now open %d, LINE: \"%s\"\n",open,line); */
418
419   if(line[0]=='\0')
420     return 0;
421   else if(ascii_strncasecmp(line,"pub",3)==0)
422     {
423       char *tok,*keyid,*uid=NULL,number[15];
424       int bits=0,type=0,disabled=0,revoked=0;
425       u32 createtime=0;
426
427       line+=3;
428
429       if(*line=='-')
430         {
431           disabled=1;
432           if(!include_disabled)
433             return 0;
434         }
435
436       line++;
437
438       tok=strsep(&line,"/");
439       if(tok==NULL)
440         return ret;
441
442       if(tok[strlen(tok)-1]=='R')
443         type=1;
444       else if(tok[strlen(tok)-1]=='D')
445         type=17;
446
447       bits=atoi(tok);
448
449       keyid=strsep(&line," ");
450
451       tok=strsep(&line," ");
452       if(tok!=NULL)
453         {
454           char *temp=tok;
455
456           /* The date parser wants '-' instead of '/', so... */
457           while(*temp!='\0')
458             {
459               if(*temp=='/')
460                 *temp='-';
461
462               temp++;
463             }
464
465           createtime=scan_isodatestr(tok);
466         }
467
468       if(line!=NULL)
469         {
470           while(*line==' ' && *line!='\0')
471             line++;
472
473           if(*line!='\0')
474             {
475               if(strncmp(line,"*** KEY REVOKED ***",19)==0)
476                 {
477                   revoked=1;
478                   if(!include_revoked)
479                     return 0;
480                 }
481               else
482                 uid=line;
483             }
484         }
485
486       if(keyid)
487         {
488           iobuf_writestr(buffer,"pub:");
489
490           write_quoted(buffer,keyid,':');
491
492           iobuf_writestr(buffer,":");
493
494           if(type)
495             {
496               sprintf(number,"%d",type);
497               write_quoted(buffer,number,':');
498             }
499
500           iobuf_writestr(buffer,":");
501
502           if(bits)
503             {
504               sprintf(number,"%d",bits);
505               write_quoted(buffer,number,':');
506             }
507
508           iobuf_writestr(buffer,":");
509
510           if(createtime)
511             {
512               sprintf(number,"%d",createtime);
513               write_quoted(buffer,number,':');
514             }
515
516           iobuf_writestr(buffer,"::");
517
518           if(revoked)
519             write_quoted(buffer,"r",':');
520
521           if(disabled)
522             write_quoted(buffer,"d",':');
523
524           if(uid)
525             {
526               iobuf_writestr(buffer,"\nuid:");
527               write_quoted(buffer,uid,':');
528             }
529                   
530           iobuf_writestr(buffer,"\n");
531
532           ret=1;
533         }
534     }
535   else if(ascii_strncasecmp(line,"   ",3)==0)
536     {
537       while(*line==' ' && *line!='\0')
538         line++;
539
540       if(*line!='\0')
541         {
542           iobuf_writestr(buffer,"uid:");
543           write_quoted(buffer,line,':');
544           iobuf_writestr(buffer,"\n");
545         }
546     }
547
548 #if 0
549   else if(open)
550     {
551       /* Try and catch some bastardization of HKP.  If we don't have
552          certain unchanging landmarks, we can't reliably parse the
553          response.  This only complains about problems within the key
554          section itself.  Headers and footers should not matter. */
555
556       fprintf(console,"gpgkeys: this keyserver does not support searching\n");
557       ret=-1;
558     }
559 #endif
560
561   return ret;
562 }
563
564 void
565 handle_old_hkp_index(IOBUF inp)
566 {
567   int ret,rc,count=0;
568   unsigned int buflen;
569   byte *line=NULL;
570   IOBUF buffer=iobuf_temp();
571
572   do
573     {
574       unsigned int maxlen=1024;
575
576       /* This is a judgement call.  Is it better to slurp up all the
577          results before prompting the user?  On the one hand, it
578          probably makes the keyserver happier to not be blocked on
579          sending for a long time while the user picks a key.  On the
580          other hand, it might be nice for the server to be able to
581          stop sending before a large search result page is
582          complete. */
583
584       rc=iobuf_read_line(inp,&line,&buflen,&maxlen);
585
586       ret=parse_hkp_index(buffer,line);
587       if(ret==-1)
588         break;
589
590       if(rc!=0)
591         count+=ret;
592     }
593   while(rc!=0);
594
595   m_free(line);
596
597   if(ret>-1)
598     fprintf(output,"info:1:%d\n%s",count,iobuf_get_temp_buffer(buffer));
599
600   iobuf_close(buffer);
601 }
602
603 int
604 search_key(char *searchkey)
605 {
606   int max=0,len=0,ret=KEYSERVER_INTERNAL_ERROR,rc;
607   struct http_context hd;
608   char *search=NULL,*request=NULL,*skey=searchkey;
609
610   fprintf(output,"SEARCH %s BEGIN\n",searchkey);
611
612   /* Build the search string.  It's going to need url-encoding. */
613
614   while(*skey!='\0')
615     {
616       if(max-len<3)
617         {
618           max+=100;
619           search=realloc(search,max+1); /* Note +1 for \0 */
620           if (!search)
621             {
622               fprintf(console,"gpgkeys: out of memory\n");
623               ret=KEYSERVER_NO_MEMORY;
624               goto fail;
625             }
626         }
627
628       if(isalnum(*skey) || *skey=='-')
629         search[len++]=*skey;
630       else if(*skey==' ')
631         search[len++]='+';
632       else
633         {
634           sprintf(&search[len],"%%%02X",*skey);
635           len+=3;
636         }
637
638       skey++;
639     }
640
641   search[len]='\0';
642
643   fprintf(console,("gpgkeys: searching for \"%s\" from HKP server %s\n"),
644           searchkey,host);
645
646   request=malloc(strlen(host)+100+strlen(search));
647   if(!request)
648     {
649       fprintf(console,"gpgkeys: out of memory\n");
650       ret=KEYSERVER_NO_MEMORY;
651       goto fail;
652     }
653
654   sprintf(request,"x-hkp://%s%s%s/pks/lookup?op=index&options=mr&search=%s",
655           host,port[0]?":":"",port[0]?port:"",search);
656
657  if(verbose>2)
658     fprintf(console,"gpgkeys: HTTP URL is \"%s\"\n",request);
659
660   rc=http_open_document(&hd,request,http_flags);
661   if(rc)
662     {
663       fprintf(console,"gpgkeys: can't search keyserver `%s': %s\n",
664               host,rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc));
665     }
666   else
667     {
668       unsigned int maxlen=1024,buflen;
669       byte *line=NULL;
670
671       /* Is it a pksd that knows how to handle machine-readable
672          format? */
673
674       rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen);
675       if(line[0]=='<')
676         handle_old_hkp_index(hd.fp_read);
677       else
678         do
679           {
680             fprintf(output,"%s",line);
681             maxlen=1024;
682             rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen);
683           }
684         while(rc!=0);
685
686       m_free(line);
687
688       http_close(&hd);
689
690       fprintf(output,"SEARCH %s END\n",searchkey);
691
692       ret=KEYSERVER_OK;
693     }
694
695  fail:
696
697   free(request);
698   free(search);
699
700   if(ret!=KEYSERVER_OK)
701     fprintf(output,"SEARCH %s FAILED %d\n",searchkey,ret);
702
703   return ret;
704 }
705
706 void
707 fail_all(struct keylist *keylist,int action,int err)
708 {
709   if(!keylist)
710     return;
711
712   if(action==SEARCH)
713     {
714       fprintf(output,"SEARCH ");
715       while(keylist)
716         {
717           fprintf(output,"%s ",keylist->str);
718           keylist=keylist->next;
719         }
720       fprintf(output,"FAILED %d\n",err);
721     }
722   else
723     while(keylist)
724       {
725         fprintf(output,"KEY %s FAILED %d\n",keylist->str,err);
726         keylist=keylist->next;
727       }
728 }
729
730 int
731 main(int argc,char *argv[])
732 {
733   int arg,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
734   char line[MAX_LINE];
735   int failed=0;
736   struct keylist *keylist=NULL,*keyptr=NULL;
737
738 #ifdef __riscos__
739   riscos_global_defaults();
740 #endif
741
742   console=stderr;
743
744   while((arg=getopt(argc,argv,"ho:"))!=-1)
745     switch(arg)
746       {
747       default:
748       case 'h':
749         fprintf(console,"-h\thelp\n");
750         fprintf(console,"-o\toutput to this file\n");
751         return KEYSERVER_OK;
752
753       case 'o':
754         output=fopen(optarg,"w");
755         if(output==NULL)
756           {
757             fprintf(console,"gpgkeys: Cannot open output file \"%s\": %s\n",
758                     optarg,strerror(errno));
759             return KEYSERVER_INTERNAL_ERROR;
760           }
761
762         break;
763       }
764
765   if(argc>optind)
766     {
767       input=fopen(argv[optind],"r");
768       if(input==NULL)
769         {
770           fprintf(console,"gpgkeys: Cannot open input file \"%s\": %s\n",
771                   argv[optind],strerror(errno));
772           return KEYSERVER_INTERNAL_ERROR;
773         }
774     }
775
776   if(input==NULL)
777     input=stdin;
778
779   if(output==NULL)
780     output=stdout;
781
782   /* Get the command and info block */
783
784   while(fgets(line,MAX_LINE,input)!=NULL)
785     {
786       int version;
787       char commandstr[7];
788       char optionstr[30];
789       char hash;
790
791       if(line[0]=='\n')
792         break;
793
794       if(sscanf(line,"%c",&hash)==1 && hash=='#')
795         continue;
796
797       if(sscanf(line,"COMMAND %6s\n",commandstr)==1)
798         {
799           commandstr[6]='\0';
800
801           if(strcasecmp(commandstr,"get")==0)
802             action=GET;
803           else if(strcasecmp(commandstr,"send")==0)
804             action=SEND;
805           else if(strcasecmp(commandstr,"search")==0)
806             action=SEARCH;
807
808           continue;
809         }
810
811       if(sscanf(line,"HOST %79s\n",host)==1)
812         {
813           host[79]='\0';
814           continue;
815         }
816
817       if(sscanf(line,"PORT %9s\n",port)==1)
818         {
819           port[9]='\0';
820           continue;
821         }
822
823       if(sscanf(line,"VERSION %d\n",&version)==1)
824         {
825           if(version!=KEYSERVER_PROTO_VERSION)
826             {
827               ret=KEYSERVER_VERSION_ERROR;
828               goto fail;
829             }
830
831           continue;
832         }
833
834       if(sscanf(line,"OPTION %29s\n",optionstr)==1)
835         {
836           int no=0;
837           char *start=&optionstr[0];
838
839           optionstr[29]='\0';
840
841           if(strncasecmp(optionstr,"no-",3)==0)
842             {
843               no=1;
844               start=&optionstr[3];
845             }
846
847           if(strcasecmp(start,"verbose")==0)
848             {
849               if(no)
850                 verbose--;
851               else
852                 verbose++;
853             }
854           else if(strcasecmp(start,"include-revoked")==0)
855             {
856               if(no)
857                 include_revoked=0;
858               else
859                 include_revoked=1;
860             }
861           else if(strcasecmp(start,"include-disabled")==0)
862             {
863               if(no)
864                 include_disabled=0;
865               else
866                 include_disabled=1;
867             }
868           else if(strcasecmp(start,"honor-http-proxy")==0)
869             {
870               if(no)
871                 http_flags&=~HTTP_FLAG_TRY_PROXY;
872               else
873                 http_flags|=HTTP_FLAG_TRY_PROXY;
874
875             }
876           else if(strcasecmp(start,"broken-http-proxy")==0)
877             {
878               if(no)
879                 http_flags&=~HTTP_FLAG_NO_SHUTDOWN;
880               else
881                 http_flags|=HTTP_FLAG_NO_SHUTDOWN;
882             }
883
884           continue;
885         }
886     }
887
888   /* If it's a GET or a SEARCH, the next thing to come in is the
889      keyids.  If it's a SEND, then there are no keyids. */
890
891   if(action==SEND)
892     while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
893   else if(action==GET || action==SEARCH)
894     {
895       for(;;)
896         {
897           struct keylist *work;
898
899           if(fgets(line,MAX_LINE,input)==NULL)
900             break;
901           else
902             {
903               if(line[0]=='\n')
904                 break;
905
906               work=malloc(sizeof(struct keylist));
907               if(work==NULL)
908                 {
909                   fprintf(console,"gpgkeys: out of memory while "
910                           "building key list\n");
911                   ret=KEYSERVER_NO_MEMORY;
912                   goto fail;
913                 }
914
915               strcpy(work->str,line);
916
917               /* Trim the trailing \n */
918               work->str[strlen(line)-1]='\0';
919
920               work->next=NULL;
921
922               /* Always attach at the end to keep the list in proper
923                  order for searching */
924               if(keylist==NULL)
925                 keylist=work;
926               else
927                 keyptr->next=work;
928
929               keyptr=work;
930             }
931         }
932     }
933   else
934     {
935       fprintf(console,"gpgkeys: no keyserver command specified\n");
936       goto fail;
937     }
938
939   /* Send the response */
940
941   fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
942   fprintf(output,"PROGRAM %s\n\n",VERSION);
943
944   if(verbose>1)
945     {
946       fprintf(console,"Host:\t\t%s\n",host);
947       if(port[0])
948         fprintf(console,"Port:\t\t%s\n",port);
949       fprintf(console,"Command:\t%s\n",action==GET?"GET":
950               action==SEND?"SEND":"SEARCH");
951     }
952
953 #if 0
954   if(verbose>1)
955     {
956       vals=ldap_get_values(ldap,res,"software");
957       if(vals!=NULL)
958         {
959           fprintf(console,"Server: \t%s\n",vals[0]);
960           ldap_value_free(vals);
961         }
962
963       vals=ldap_get_values(ldap,res,"version");
964       if(vals!=NULL)
965         {
966           fprintf(console,"Version:\t%s\n",vals[0]);
967           ldap_value_free(vals);
968         }
969     }
970 #endif
971
972   switch(action)
973     {
974     case GET:
975       keyptr=keylist;
976
977       while(keyptr!=NULL)
978         {
979           if(get_key(keyptr->str)!=KEYSERVER_OK)
980             failed++;
981
982           keyptr=keyptr->next;
983         }
984       break;
985
986     case SEND:
987       {
988         int eof=0;
989
990         do
991           {
992             if(send_key(&eof)!=KEYSERVER_OK)
993               failed++;
994           }
995         while(!eof);
996       }
997       break;
998
999     case SEARCH:
1000       {
1001         char *searchkey=NULL;
1002         int len=0;
1003
1004         /* To search, we stick a space in between each key to search
1005            for. */
1006
1007         keyptr=keylist;
1008         while(keyptr!=NULL)
1009           {
1010             len+=strlen(keyptr->str)+1;
1011             keyptr=keyptr->next;
1012           }
1013
1014         searchkey=malloc(len+1);
1015         if(searchkey==NULL)
1016           {
1017             ret=KEYSERVER_NO_MEMORY;
1018             fail_all(keylist,action,KEYSERVER_NO_MEMORY);
1019             goto fail;
1020           }
1021
1022         searchkey[0]='\0';
1023
1024         keyptr=keylist;
1025         while(keyptr!=NULL)
1026           {
1027             strcat(searchkey,keyptr->str);
1028             strcat(searchkey," ");
1029             keyptr=keyptr->next;
1030           }
1031
1032         /* Nail that last space */
1033         searchkey[strlen(searchkey)-1]='\0';
1034
1035         if(search_key(searchkey)!=KEYSERVER_OK)
1036           failed++;
1037
1038         free(searchkey);
1039       }
1040
1041       break;
1042     }
1043
1044   if(!failed)
1045     ret=KEYSERVER_OK;
1046
1047  fail:
1048   while(keylist!=NULL)
1049     {
1050       struct keylist *current=keylist;
1051       keylist=keylist->next;
1052       free(current);
1053     }
1054
1055   if(input!=stdin)
1056     fclose(input);
1057
1058   if(output!=stdout)
1059     fclose(output);
1060
1061   return ret;
1062 }