* gpgkeys_ldap.c (search_key, main): Make sure LDAP values are freed in
[gnupg.git] / keyserver / gpgkeys_ldap.c
1 /* gpgkeys_ldap.c - talk to a LDAP 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 <time.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #ifdef NEED_LBER_H
29 #include <lber.h>
30 #endif
31 #include <ldap.h>
32 #include "keyserver.h"
33
34 #ifdef __riscos__
35 #include "util.h"
36 #endif
37
38 #define GET    0
39 #define SEND   1
40 #define SEARCH 2
41 #define MAX_LINE 80
42
43 int verbose=0,include_disabled=0,include_revoked=0,include_subkeys=0;
44 char *basekeyspacedn=NULL;
45 char host[80]={'\0'};
46 char portstr[10]={'\0'};
47 char *pgpkeystr="pgpKey";
48 FILE *input=NULL,*output=NULL,*console=NULL;
49 LDAP *ldap=NULL;
50
51 struct keylist
52 {
53   char str[MAX_LINE];
54   struct keylist *next;
55 };
56
57 #ifdef __riscos__
58 RISCOS_GLOBAL_STATICS("LDAP Keyfetcher Heap")
59 #endif /* __riscos__ */
60
61 int
62 ldap_err_to_gpg_err(int err)
63 {
64   int ret;
65
66   switch(err)
67     {
68     case LDAP_ALREADY_EXISTS:
69       ret=KEYSERVER_KEY_EXISTS;
70       break;
71
72     case LDAP_SERVER_DOWN:
73       ret=KEYSERVER_UNREACHABLE;
74       break;
75
76     default:
77       ret=KEYSERVER_GENERAL_ERROR;
78       break;
79     }
80
81   return ret;
82 }
83
84 int
85 ldap_to_gpg_err(LDAP *ld)
86 {
87 #if defined(HAVE_LDAP_GET_OPTION)
88
89   int err;
90
91   if(ldap_get_option(ld,LDAP_OPT_ERROR_NUMBER,&err)==0)
92     return ldap_err_to_gpg_err(err);
93   else
94     return KEYSERVER_GENERAL_ERROR;
95
96 #elif defined(HAVE_LDAP_LD_ERRNO)
97
98   return ldap_err_to_gpg_err(ld->ld_errno);
99
100 #else
101
102   /* We should never get here since the LDAP library should always
103      have either ldap_get_option or ld_errno, but just in case... */
104   return KEYSERVER_GENERAL_ERROR;
105
106 #endif
107 }
108
109 int
110 send_key(int *eof)
111 {
112   int err,gotit=0,keysize=1,ret=KEYSERVER_INTERNAL_ERROR;
113   char *dn=NULL;
114   char line[MAX_LINE];
115   char *key[2]={NULL,NULL};
116   char keyid[17];
117   LDAPMod mod, *attrs[2];
118
119   memset (&mod, 0, sizeof mod);
120   mod.mod_op      = LDAP_MOD_ADD;
121   mod.mod_type    = pgpkeystr;
122   mod.mod_values  = key;
123   attrs[0]    = &mod;
124   attrs[1]    = NULL;
125
126   dn=malloc(strlen("pgpCertid=virtual,")+strlen(basekeyspacedn)+1);
127   if(dn==NULL)
128     {
129       fprintf(console,"gpgkeys: can't allocate memory for keyserver record\n");
130       ret=KEYSERVER_NO_MEMORY;
131       goto fail;
132     }
133
134   strcpy(dn,"pgpCertid=virtual,");
135   strcat(dn,basekeyspacedn);
136
137   key[0]=malloc(1);
138   if(key[0]==NULL)
139     {
140       fprintf(console,"gpgkeys: unable to allocate memory for key\n");
141       ret=KEYSERVER_NO_MEMORY;
142       goto fail;
143     }
144
145   key[0][0]='\0';
146
147   /* Read and throw away stdin until we see the BEGIN */
148
149   while(fgets(line,MAX_LINE,input)!=NULL)
150     if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1)
151       {
152         gotit=1;
153         break;
154       }
155
156   if(!gotit)
157     {
158       /* i.e. eof before the KEY BEGIN was found.  This isn't an
159          error. */
160       *eof=1;
161       ret=KEYSERVER_OK;
162       goto fail;
163     }
164
165   gotit=0;
166
167   /* Now slurp up everything until we see the END */
168
169   while(fgets(line,MAX_LINE,input)!=NULL)
170     if(sscanf(line,"KEY %16s END\n",keyid)==1)
171       {
172         gotit=1;
173         break;
174       }
175     else
176       {
177         keysize+=strlen(line);
178         key[0]=realloc(key[0],keysize);
179         if(key[0]==NULL)
180           {
181             fprintf(console,"gpgkeys: unable to reallocate for key\n");
182             ret=KEYSERVER_NO_MEMORY;
183             goto fail;
184           }
185
186         strcat(key[0],line);
187       }
188
189   if(!gotit)
190     {
191       fprintf(console,"gpgkeys: no KEY %s END found\n",keyid);
192       *eof=1;
193       ret=KEYSERVER_KEY_INCOMPLETE;
194       goto fail;
195     }
196
197   err=ldap_add_s(ldap,dn,attrs);
198   if(err!=LDAP_SUCCESS)
199     {
200       fprintf(console,"gpgkeys: error adding key %s to keyserver: %s\n",
201               keyid,ldap_err2string(err));
202       ret=ldap_err_to_gpg_err(err);
203       goto fail;
204     }
205
206   ret=KEYSERVER_OK;
207
208  fail:
209
210   free(key[0]);
211   free(dn);
212
213   if(ret!=0)
214     fprintf(output,"KEY %s FAILED %d\n",keyid,ret);
215
216   /* Not a fatal error */
217   if(ret==KEYSERVER_KEY_EXISTS)
218     ret=KEYSERVER_OK;
219
220   return ret;
221 }
222
223 /* Note that key-not-found is not a fatal error */
224 int
225 get_key(char *getkey)
226 {
227   char **vals;
228   LDAPMessage *res,*each;
229   int ret=KEYSERVER_INTERNAL_ERROR,err,count;
230   struct keylist *dupelist=NULL;
231   char search[62];
232   char *attrs[]={"replaceme","pgpuserid","pgpkeyid","pgpcertid","pgprevoked",
233                  "pgpdisabled","pgpkeycreatetime","modifytimestamp",
234                  "pgpkeysize","pgpkeytype",NULL};
235   attrs[0]=pgpkeystr; /* Some compilers don't like using variables as
236                          array initializers. */
237
238   /* Build the search string */
239
240   /* GPG can send us a v4 fingerprint, a v3 or v4 long key id, or a v3
241      or v4 short key id */
242
243   if(strncmp(getkey,"0x",2)==0)
244     getkey+=2;
245
246   if(strlen(getkey)==32)
247     {
248       fprintf(console,
249               "gpgkeys: LDAP keyservers do not support v3 fingerprints\n");
250       fprintf(output,"KEY 0x%s BEGIN\n",getkey);
251       fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED);
252       return KEYSERVER_NOT_SUPPORTED;
253     }
254
255   if(strlen(getkey)>16)
256     {
257       char *offset=&getkey[strlen(getkey)-16];
258
259       /* fingerprint.  Take the last 16 characters and treat it like a
260          long key id */
261
262       if(include_subkeys)
263         sprintf(search,"(|(pgpcertid=%.16s)(pgpsubkeyid=%.16s))",
264                 offset,offset);
265       else
266         sprintf(search,"(pgpcertid=%.16s)",offset);
267     }
268   else if(strlen(getkey)>8)
269     {
270       /* long key id */
271
272       if(include_subkeys)
273         sprintf(search,"(|(pgpcertid=%.16s)(pgpsubkeyid=%.16s))",
274                 getkey,getkey);
275       else
276         sprintf(search,"(pgpcertid=%.16s)",getkey);
277     }
278   else
279     {
280       /* short key id */
281     
282       sprintf(search,"(pgpkeyid=%.8s)",getkey);
283     }
284
285   fprintf(output,"KEY 0x%s BEGIN\n",getkey);
286
287   if(verbose>2)
288     fprintf(console,"gpgkeys: LDAP fetch for: %s\n",search);
289
290   if(!verbose)
291     attrs[1]=NULL;
292
293   if(verbose)
294     fprintf(console,"gpgkeys: requesting key 0x%s from ldap://%s%s%s\n",
295             getkey,host,portstr[0]?":":"",portstr[0]?portstr:"");
296
297   err=ldap_search_s(ldap,basekeyspacedn,
298                     LDAP_SCOPE_SUBTREE,search,attrs,0,&res);
299   if(err!=0)
300     {
301       int errtag=ldap_err_to_gpg_err(err);
302
303       fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err));
304       fprintf(output,"KEY 0x%s FAILED %d\n",getkey,errtag);
305       return errtag;
306     }
307
308   count=ldap_count_entries(ldap,res);
309   if(count<1)
310     {
311       fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
312       fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_KEY_NOT_FOUND);
313     }
314   else
315     {
316       /* There may be more than one unique result for a given keyID,
317          so we should fetch them all (test this by fetching short key
318          id 0xDEADBEEF). */
319
320       each=ldap_first_entry(ldap,res);
321       while(each!=NULL)
322         {
323           struct keylist *keyptr=dupelist;
324
325           /* Use the long keyid to remove duplicates.  The LDAP server
326              returns the same keyid more than once if there are
327              multiple user IDs on the key.  Note that this does NOT
328              mean that a keyid that exists multiple times on the
329              keyserver will not be fetched.  It means that each KEY,
330              no matter how many user IDs share it's keyid, will be
331              fetched only once.  If a keyid that belongs to more than
332              one key is fetched, the server quite properly responds
333              with all matching keys. -ds */
334
335           vals=ldap_get_values(ldap,each,"pgpcertid");
336           if(vals!=NULL)
337             {
338               while(keyptr!=NULL)
339                 {
340                   if(strcasecmp(keyptr->str,vals[0])==0)
341                     break;
342
343                   keyptr=keyptr->next;
344                 }
345
346               if(!keyptr)
347                 {
348                   /* it's not a duplicate, so add it */
349
350                   keyptr=malloc(sizeof(struct keylist));
351                   if(keyptr==NULL)
352                     {
353                       fprintf(console,"gpgkeys: out of memory when deduping "
354                               "key list\n");
355                       ret=KEYSERVER_NO_MEMORY;
356                       goto fail;
357                     }
358
359                   strncpy(keyptr->str,vals[0],MAX_LINE);
360                   keyptr->str[MAX_LINE-1]='\0';
361
362                   keyptr->next=dupelist;
363                   dupelist=keyptr;
364                   keyptr=NULL;
365                 }
366
367               ldap_value_free(vals);
368             }
369
370           if(!keyptr) /* it's not a duplicate */
371             {
372               if(verbose)
373                 {
374                   vals=ldap_get_values(ldap,each,"pgpuserid");
375                   if(vals!=NULL)
376                     {
377                       /* This is wrong, as the user ID is UTF8.  A
378                          better way to handle this would be to send it
379                          over to gpg and display it on that side of
380                          the pipe. */
381                       fprintf(console,"\nUser ID:\t%s\n",vals[0]);
382                       ldap_value_free(vals);
383                     }
384
385                   vals=ldap_get_values(ldap,each,"pgprevoked");
386                   if(vals!=NULL)
387                     {
388                       if(atoi(vals[0])==1)
389                         fprintf(console,"\t\t** KEY REVOKED **\n");
390                       ldap_value_free(vals);
391                     }
392
393                   vals=ldap_get_values(ldap,each,"pgpdisabled");
394                   if(vals!=NULL)
395                     {
396                       if(atoi(vals[0])==1)
397                         fprintf(console,"\t\t** KEY DISABLED **\n");
398                       ldap_value_free(vals);
399                     }
400
401                   vals=ldap_get_values(ldap,each,"pgpkeyid");
402                   if(vals!=NULL)
403                     {
404                       fprintf(console,"Short key ID:\t%s\n",vals[0]);
405                       ldap_value_free(vals);
406                     }
407
408                   vals=ldap_get_values(ldap,each,"pgpcertid");
409                   if(vals!=NULL)
410                     {
411                       fprintf(console,"Long key ID:\t%s\n",vals[0]);
412                       ldap_value_free(vals);
413                     }
414
415                   /* YYYYMMDDHHmmssZ */
416
417                   vals=ldap_get_values(ldap,each,"pgpkeycreatetime");
418                   if(vals!=NULL)
419                     {
420                       if(strlen(vals[0])==15)
421                         fprintf(console,"Key created:\t%.2s/%.2s/%.4s\n",
422                                 &vals[0][4],&vals[0][6],vals[0]);
423                       ldap_value_free(vals);
424                     }
425
426                   vals=ldap_get_values(ldap,each,"modifytimestamp");
427                   if(vals!=NULL)
428                     {
429                       if(strlen(vals[0])==15)
430                         fprintf(console,"Key modified:\t%.2s/%.2s/%.4s\n",
431                                 &vals[0][4],&vals[0][6],vals[0]);
432                       ldap_value_free(vals);
433                     }
434
435                   vals=ldap_get_values(ldap,each,"pgpkeysize");
436                   if(vals!=NULL)
437                     {
438                       fprintf(console,"Key size:\t%d\n",atoi(vals[0]));
439                       ldap_value_free(vals);
440                     }
441
442                   vals=ldap_get_values(ldap,each,"pgpkeytype");
443                   if(vals!=NULL)
444                     {
445                       fprintf(console,"Key type:\t%s\n",vals[0]);
446                       ldap_value_free(vals);
447                     }
448                 }
449
450               vals=ldap_get_values(ldap,each,pgpkeystr);
451               if(vals==NULL)
452                 {
453                   int errtag=ldap_to_gpg_err(ldap);
454
455                   fprintf(console,"gpgkeys: unable to retrieve key %s "
456                           "from keyserver\n",getkey);
457                   fprintf(output,"KEY 0x%s FAILED %d\n",getkey,errtag);
458                 }
459               else
460                 {
461                   fprintf(output,"%sKEY 0x%s END\n",vals[0],getkey);
462
463                   ldap_value_free(vals);
464                 }
465             }
466
467           each=ldap_next_entry(ldap,each);
468         }
469     }
470
471   ret=KEYSERVER_OK;
472
473  fail:
474   ldap_msgfree(res);
475
476   /* free up the dupe checker */
477   while(dupelist!=NULL)
478     {
479       struct keylist *keyptr=dupelist;
480
481       dupelist=keyptr->next;
482       free(keyptr);
483     }
484
485   return ret;
486 }
487
488 time_t ldap2epochtime(const char *timestr)
489 {
490   struct tm pgptime;
491
492   memset(&pgptime,0,sizeof(pgptime));
493
494   /* YYYYMMDDHHmmssZ */
495
496   sscanf(timestr,"%4d%2d%2d%2d%2d%2d",
497          &pgptime.tm_year,
498          &pgptime.tm_mon,
499          &pgptime.tm_mday,
500          &pgptime.tm_hour,
501          &pgptime.tm_min,
502          &pgptime.tm_sec);
503
504   pgptime.tm_year-=1900;
505   pgptime.tm_isdst=-1;
506   pgptime.tm_mon--;
507
508   return mktime(&pgptime);
509 }
510
511 void printquoted(FILE *stream,char *string,char delim)
512 {
513   while(*string)
514     {
515       if(*string==delim || *string=='\\')
516         fprintf(stream,"\\x%02x",*string);
517       else
518         fputc(*string,stream);
519
520       string++;
521     }
522 }
523
524 /* Returns 0 on success and -1 on error.  Note that key-not-found is
525    not an error! */
526 int
527 search_key(char *searchkey)
528 {
529   char **vals;
530   LDAPMessage *res,*each;
531   int err,count;
532   /* The maxium size of the search, including the optional stuff and
533      the trailing \0 */
534   char search[2+12+MAX_LINE+2+15+14+1+1];
535   char *attrs[]={"pgpcertid","pgpuserid","pgprevoked","pgpdisabled",
536                  "pgpkeycreatetime","pgpkeyexpiretime","modifytimestamp",
537                  "pgpkeysize","pgpkeytype",NULL};
538
539   fprintf(output,"SEARCH %s BEGIN\n",searchkey);
540
541   /* Build the search string */
542
543   sprintf(search,"%s(pgpuserid=*%s*)%s%s%s",
544           (!(include_disabled&&include_revoked))?"(&":"",
545           searchkey,
546           include_disabled?"":"(pgpdisabled=0)",
547           include_revoked?"":"(pgprevoked=0)",
548           !(include_disabled&&include_revoked)?")":"");
549
550   if(verbose>2)
551     fprintf(console,"gpgkeys: LDAP search for: %s\n",search);
552
553   fprintf(console,("gpgkeys: searching for \"%s\" from LDAP server %s\n"),
554           searchkey,host);
555
556   err=ldap_search_s(ldap,basekeyspacedn,
557                     LDAP_SCOPE_SUBTREE,search,attrs,0,&res);
558   if(err!=0)
559     {
560       int errtag=ldap_err_to_gpg_err(err);
561
562       fprintf(output,"SEARCH %s FAILED %d\n",searchkey,errtag);
563       fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err));
564       return errtag;
565     }
566
567   count=ldap_count_entries(ldap,res);
568
569   if(count<1)
570     fprintf(output,"COUNT 0\n");
571   else
572     {
573       fprintf(output,"COUNT %d\n",count);
574
575       each=ldap_first_entry(ldap,res);
576       while(each!=NULL)
577         {
578           int flags=0;
579
580           vals=ldap_get_values(ldap,each,"pgpcertid");
581           if(vals!=NULL)
582             {
583               fprintf(output,"%s:",vals[0]);
584               ldap_value_free(vals);
585             }
586           else
587             fputc(':',output);
588
589           vals=ldap_get_values(ldap,each,"pgpuserid");
590           if(vals!=NULL)
591             {
592               /* Need to escape any colons */
593               printquoted(output,vals[0],':');
594               fputc(':',output);
595               ldap_value_free(vals);
596             }
597           else
598             fputc(':',output);
599
600           vals=ldap_get_values(ldap,each,"pgprevoked");
601           if(vals!=NULL)
602             {
603               if(atoi(vals[0])==1)
604                 flags|=1;
605               ldap_value_free(vals);
606             }
607
608           vals=ldap_get_values(ldap,each,"pgpdisabled");
609           if(vals!=NULL)
610             {
611               if(atoi(vals[0])==1)
612                 flags|=2;
613               ldap_value_free(vals);
614             }
615
616           fprintf(output,"%d:",flags);
617
618           /* YYYYMMDDHHmmssZ */
619
620           vals=ldap_get_values(ldap,each,"pgpkeycreatetime");
621           if(vals!=NULL && strlen(vals[0])==15)
622             {
623               fprintf(output,"%u:",(unsigned int)ldap2epochtime(vals[0]));
624               ldap_value_free(vals);
625             }
626           else
627             fputc(':',output);
628
629           vals=ldap_get_values(ldap,each,"pgpkeyexpiretime");
630           if(vals!=NULL && strlen(vals[0])==15)
631             {
632               fprintf(output,"%u:",(unsigned int)ldap2epochtime(vals[0]));
633               ldap_value_free(vals);
634             }
635           else
636             fputc(':',output);
637
638           vals=ldap_get_values(ldap,each,"modifytimestamp");
639           if(vals!=NULL && strlen(vals[0])==15)
640             {
641               fprintf(output,"%u:",(unsigned int)ldap2epochtime(vals[0]));
642               ldap_value_free(vals);
643             }
644           else
645             fputc(':',output);
646
647           vals=ldap_get_values(ldap,each,"pgpkeytype");
648           if(vals!=NULL)
649             {
650               fprintf(output,"%s:",vals[0]);
651               ldap_value_free(vals);
652             }
653           else
654             fputc(':',output);
655
656           vals=ldap_get_values(ldap,each,"pgpkeysize");
657           if(vals!=NULL)
658             {
659               /* Not sure why, but some keys are listed with a key size of
660                  0.  Treat that like an unknown. */
661               if(atoi(vals[0])>0)
662                 fprintf(output,"%d",atoi(vals[0]));
663               ldap_value_free(vals);
664             }
665
666           fputc('\n',output);
667
668           each=ldap_next_entry(ldap,each);
669         }
670     }
671
672   ldap_msgfree(res);
673
674   fprintf(output,"SEARCH %s END\n",searchkey);
675
676   return KEYSERVER_OK;
677 }
678
679 void
680 fail_all(struct keylist *keylist,int action,int err)
681 {
682   if(!keylist)
683     return;
684
685   if(action==SEARCH)
686     {
687       fprintf(output,"SEARCH ");
688       while(keylist)
689         {
690           fprintf(output,"%s ",keylist->str);
691           keylist=keylist->next;
692         }
693       fprintf(output,"FAILED %d\n",err);
694     }
695   else
696     while(keylist)
697       {
698         fprintf(output,"KEY %s FAILED %d\n",keylist->str,err);
699         keylist=keylist->next;
700       }
701 }
702
703 int main(int argc,char *argv[])
704 {
705   int port=0,arg,err,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
706   char line[MAX_LINE],**vals;
707   int version,failed=0;
708   char *attrs[]={"basekeyspacedn","version","software",NULL};
709   LDAPMessage *res;
710   struct keylist *keylist=NULL,*keyptr=NULL;
711
712 #ifdef __riscos__
713   riscos_global_defaults();
714 #endif
715
716   console=stderr;
717
718   while((arg=getopt(argc,argv,"ho:"))!=-1)
719     switch(arg)
720       {
721       default:
722       case 'h':
723         fprintf(console,"-h\thelp\n");
724         fprintf(console,"-o\toutput to this file\n");
725         return KEYSERVER_OK;
726
727       case 'o':
728         output=fopen(optarg,"w");
729         if(output==NULL)
730           {
731             fprintf(console,"gpgkeys: Cannot open output file \"%s\": %s\n",
732                     optarg,strerror(errno));
733             return KEYSERVER_INTERNAL_ERROR;
734           }
735
736         break;
737       }
738
739   if(argc>optind)
740     {
741       input=fopen(argv[optind],"r");
742       if(input==NULL)
743         {
744           fprintf(console,"gpgkeys: Cannot open input file \"%s\": %s\n",
745                   argv[optind],strerror(errno));
746           return KEYSERVER_INTERNAL_ERROR;
747         }
748     }
749
750   if(input==NULL)
751     input=stdin;
752
753   if(output==NULL)
754     output=stdout;
755
756   /* Get the command and info block */
757
758   while(fgets(line,MAX_LINE,input)!=NULL)
759     {
760       char commandstr[7];
761       char optionstr[30];
762       char hash;
763
764       if(line[0]=='\n')
765         break;
766
767       if(sscanf(line,"%c",&hash)==1 && hash=='#')
768         continue;
769
770       if(sscanf(line,"COMMAND %6s\n",commandstr)==1)
771         {
772           commandstr[6]='\0';
773
774           if(strcasecmp(commandstr,"get")==0)
775             action=GET;
776           else if(strcasecmp(commandstr,"send")==0)
777             action=SEND;
778           else if(strcasecmp(commandstr,"search")==0)
779             action=SEARCH;
780
781           continue;
782         }
783
784       if(sscanf(line,"HOST %79s\n",host)==1)
785         {
786           host[79]='\0';
787           continue;
788         }
789
790       if(sscanf(line,"PORT %9s\n",portstr)==1)
791         {
792           portstr[9]='\0';
793           port=atoi(portstr);
794           continue;
795         }
796
797       if(sscanf(line,"VERSION %d\n",&version)==1)
798         {
799           if(version!=0)
800             {
801               ret=KEYSERVER_VERSION_ERROR;
802               goto fail;
803             }
804
805           continue;
806         }
807
808       if(sscanf(line,"OPTION %29s\n",optionstr)==1)
809         {
810           int no=0;
811           char *start=&optionstr[0];
812
813           optionstr[29]='\0';
814
815           if(strncasecmp(optionstr,"no-",3)==0)
816             {
817               no=1;
818               start=&optionstr[3];
819             }
820
821           if(strcasecmp(start,"verbose")==0)
822             {
823               if(no)
824                 verbose--;
825               else
826                 verbose++;
827             }
828           else if(strcasecmp(start,"include-disabled")==0)
829             {
830               if(no)
831                 include_disabled=0;
832               else
833                 include_disabled=1;
834             }
835           else if(strcasecmp(start,"include-revoked")==0)
836             {
837               if(no)
838                 include_revoked=0;
839               else
840                 include_revoked=1;
841             }
842           else if(strcasecmp(start,"include-subkeys")==0)
843             {
844               if(no)
845                 include_subkeys=0;
846               else
847                 include_subkeys=1;
848             }
849
850           continue;
851         }
852     }
853
854   /* If it's a GET or a SEARCH, the next thing to come in is the
855      keyids.  If it's a SEND, then there are no keyids. */
856
857   if(action==SEND)
858     while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
859   else if(action==GET || action==SEARCH)
860     {
861       for(;;)
862         {
863           struct keylist *work;
864
865           if(fgets(line,MAX_LINE,input)==NULL)
866             break;
867           else
868             {
869               if(line[0]=='\n')
870                 break;
871
872               work=malloc(sizeof(struct keylist));
873               if(work==NULL)
874                 {
875                   fprintf(console,"gpgkeys: out of memory while "
876                           "building key list\n");
877                   ret=KEYSERVER_NO_MEMORY;
878                   goto fail;
879                 }
880
881               strcpy(work->str,line);
882
883               /* Trim the trailing \n */
884               work->str[strlen(line)-1]='\0';
885
886               work->next=NULL;
887
888               /* Always attach at the end to keep the list in proper
889                  order for searching */
890               if(keylist==NULL)
891                 keylist=work;
892               else
893                 keyptr->next=work;
894
895               keyptr=work;
896             }
897         }
898     }
899   else
900     {
901       fprintf(console,"gpgkeys: no keyserver command specified\n");
902       goto fail;
903     }
904
905   /* Send the response */
906
907   fprintf(output,"VERSION 0\n");
908   fprintf(output,"PROGRAM %s\n\n",VERSION);
909
910   if(verbose>1)
911     {
912       fprintf(console,"Host:\t\t%s\n",host);
913       if(port)
914         fprintf(console,"Port:\t\t%d\n",port);
915       fprintf(console,"Command:\t%s\n",action==GET?"GET":
916               action==SEND?"SEND":"SEARCH");
917     }
918
919   ldap=ldap_init(host,port);
920   if(ldap==NULL)
921     {
922       fprintf(console,"gpgkeys: internal LDAP init error: %s\n",
923               strerror(errno));
924       fail_all(keylist,action,KEYSERVER_INTERNAL_ERROR);
925       goto fail;
926     }
927
928   err=ldap_simple_bind_s(ldap,NULL,NULL);
929   if(err!=0)
930     {
931       fprintf(console,"gpgkeys: internal LDAP bind error: %s\n",
932               ldap_err2string(err));
933       fail_all(keylist,action,ldap_err_to_gpg_err(err));
934       goto fail;
935     }
936
937   /* Get the magic info record */
938
939   err=ldap_search_s(ldap,"cn=PGPServerInfo",LDAP_SCOPE_BASE,
940                     "(objectclass=*)",attrs,0,&res);
941   if(err!=0)
942     {
943       fprintf(console,"gpgkeys: error retrieving LDAP server info: %s\n",
944               ldap_err2string(err));
945       fail_all(keylist,action,ldap_err_to_gpg_err(err));
946       goto fail;
947     }
948
949   if(ldap_count_entries(ldap,res)!=1)
950     {
951       fprintf(console,"gpgkeys: more than one serverinfo record\n");
952       fail_all(keylist,action,KEYSERVER_INTERNAL_ERROR);
953       goto fail;
954     }
955
956   if(verbose>1)
957     {
958       vals=ldap_get_values(ldap,res,"software");
959       if(vals!=NULL)
960         {
961           fprintf(console,"Server: \t%s\n",vals[0]);
962           ldap_value_free(vals);
963         }
964     }
965
966   vals=ldap_get_values(ldap,res,"version");
967   if(vals!=NULL)
968     {
969       if(verbose>1)
970         fprintf(console,"Version:\t%s\n",vals[0]);
971
972       /* If the version is high enough, use the new pgpKeyV2
973          attribute.  This design if iffy at best, but it matches how
974          PGP does it.  I figure the NAI folks assumed that there would
975          never be a LDAP keyserver vendor with a different numbering
976          scheme. */
977       if(atoi(vals[0])>1)
978         pgpkeystr="pgpKeyV2";
979
980       ldap_value_free(vals);
981     }
982
983   /* This is always "OU=ACTIVE,O=PGP KEYSPACE,C=US", but it might not
984      be in the future. */
985
986   vals=ldap_get_values(ldap,res,"basekeyspacedn");
987   if(vals!=NULL)
988     {
989       basekeyspacedn=strdup(vals[0]);
990       ldap_value_free(vals);
991       if(basekeyspacedn==NULL)
992         {
993           fprintf(console,"gpgkeys: can't allocate string space "
994                   "for LDAP base\n");
995           fail_all(keylist,action,KEYSERVER_NO_MEMORY);
996           goto fail;
997         }
998     }
999
1000   ldap_msgfree(res);
1001
1002   switch(action)
1003     {
1004     case GET:
1005       keyptr=keylist;
1006
1007       while(keyptr!=NULL)
1008         {
1009           if(get_key(keyptr->str)!=KEYSERVER_OK)
1010             failed++;
1011
1012           keyptr=keyptr->next;
1013         }
1014       break;
1015
1016     case SEND:
1017       {
1018         int eof=0;
1019
1020         do
1021           {
1022             if(send_key(&eof)!=KEYSERVER_OK)
1023               failed++;
1024           }
1025         while(!eof);
1026       }
1027       break;
1028
1029     case SEARCH:
1030       {
1031         char *searchkey=NULL;
1032         int len=0;
1033
1034         /* To search, we stick a * in between each key to search for.
1035            This means that if the user enters words, they'll get
1036            "enters*words".  If the user "enters words", they'll get
1037            "enters words" */
1038
1039         keyptr=keylist;
1040         while(keyptr!=NULL)
1041           {
1042             len+=strlen(keyptr->str)+1;
1043             keyptr=keyptr->next;
1044           }
1045
1046         searchkey=malloc(len+1);
1047         if(searchkey==NULL)
1048           {
1049             ret=KEYSERVER_NO_MEMORY;
1050             fail_all(keylist,action,KEYSERVER_NO_MEMORY);
1051             goto fail;
1052           }
1053
1054         searchkey[0]='\0';
1055
1056         keyptr=keylist;
1057         while(keyptr!=NULL)
1058           {
1059             strcat(searchkey,keyptr->str);
1060             strcat(searchkey,"*");
1061             keyptr=keyptr->next;
1062           }
1063
1064         /* Nail that last "*" */
1065         searchkey[strlen(searchkey)-1]='\0';
1066
1067         if(search_key(searchkey)!=KEYSERVER_OK)
1068           failed++;
1069
1070         free(searchkey);
1071       }
1072
1073       break;
1074     }
1075
1076   if(!failed)
1077     ret=KEYSERVER_OK;
1078
1079  fail:
1080
1081   while(keylist!=NULL)
1082     {
1083       struct keylist *current=keylist;
1084       keylist=keylist->next;
1085       free(current);
1086     }
1087
1088   if(input!=stdin)
1089     fclose(input);
1090
1091   if(output!=stdout)
1092     fclose(output);
1093
1094   if(ldap!=NULL)
1095     ldap_unbind_s(ldap);
1096
1097   free(basekeyspacedn);
1098
1099   return ret;
1100 }