7772bd43c4ebf389fcbfe4457bf6e22654bea60e
[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 && strlen(vals[0])==15)
419                     {
420                       fprintf(console,"Key created:\t%.2s/%.2s/%.4s\n",
421                               &vals[0][4],&vals[0][6],vals[0]);
422                       ldap_value_free(vals);
423                     }
424
425                   vals=ldap_get_values(ldap,each,"modifytimestamp");
426                   if(vals!=NULL && strlen(vals[0])==15)
427                     {
428                       fprintf(console,"Key modified:\t%.2s/%.2s/%.4s\n",
429                               &vals[0][4],&vals[0][6],vals[0]);
430                       ldap_value_free(vals);
431                     }
432
433                   vals=ldap_get_values(ldap,each,"pgpkeysize");
434                   if(vals!=NULL)
435                     {
436                       fprintf(console,"Key size:\t%d\n",atoi(vals[0]));
437                       ldap_value_free(vals);
438                     }
439
440                   vals=ldap_get_values(ldap,each,"pgpkeytype");
441                   if(vals!=NULL)
442                     {
443                       fprintf(console,"Key type:\t%s\n",vals[0]);
444                       ldap_value_free(vals);
445                     }
446                 }
447
448               vals=ldap_get_values(ldap,each,pgpkeystr);
449               if(vals==NULL)
450                 {
451                   int errtag=ldap_to_gpg_err(ldap);
452
453                   fprintf(console,"gpgkeys: unable to retrieve key %s "
454                           "from keyserver\n",getkey);
455                   fprintf(output,"KEY 0x%s FAILED %d\n",getkey,errtag);
456                 }
457               else
458                 {
459                   fprintf(output,"%sKEY 0x%s END\n",vals[0],getkey);
460
461                   ldap_value_free(vals);
462                 }
463             }
464
465           each=ldap_next_entry(ldap,each);
466         }
467     }
468
469   ret=KEYSERVER_OK;
470
471  fail:
472   ldap_msgfree(res);
473
474   /* free up the dupe checker */
475   while(dupelist!=NULL)
476     {
477       struct keylist *keyptr=dupelist;
478
479       dupelist=keyptr->next;
480       free(keyptr);
481     }
482
483   return ret;
484 }
485
486 time_t ldap2epochtime(const char *timestr)
487 {
488   struct tm pgptime;
489
490   memset(&pgptime,0,sizeof(pgptime));
491
492   /* YYYYMMDDHHmmssZ */
493
494   sscanf(timestr,"%4d%2d%2d%2d%2d%2d",
495          &pgptime.tm_year,
496          &pgptime.tm_mon,
497          &pgptime.tm_mday,
498          &pgptime.tm_hour,
499          &pgptime.tm_min,
500          &pgptime.tm_sec);
501
502   pgptime.tm_year-=1900;
503   pgptime.tm_isdst=-1;
504   pgptime.tm_mon--;
505
506   return mktime(&pgptime);
507 }
508
509 void printquoted(FILE *stream,char *string,char delim)
510 {
511   while(*string)
512     {
513       if(*string==delim || *string=='\\')
514         fprintf(stream,"\\x%02x",*string);
515       else
516         fputc(*string,stream);
517
518       string++;
519     }
520 }
521
522 /* Returns 0 on success and -1 on error.  Note that key-not-found is
523    not an error! */
524 int
525 search_key(char *searchkey)
526 {
527   char **vals;
528   LDAPMessage *res,*each;
529   int err,count;
530   /* The maxium size of the search, including the optional stuff and
531      the trailing \0 */
532   char search[2+12+MAX_LINE+2+15+14+1+1];
533   char *attrs[]={"pgpcertid","pgpuserid","pgprevoked","pgpdisabled",
534                  "pgpkeycreatetime","pgpkeyexpiretime","modifytimestamp",
535                  "pgpkeysize","pgpkeytype",NULL};
536
537   fprintf(output,"SEARCH %s BEGIN\n",searchkey);
538
539   /* Build the search string */
540
541   sprintf(search,"%s(pgpuserid=*%s*)%s%s%s",
542           (!(include_disabled&&include_revoked))?"(&":"",
543           searchkey,
544           include_disabled?"":"(pgpdisabled=0)",
545           include_revoked?"":"(pgprevoked=0)",
546           !(include_disabled&&include_revoked)?")":"");
547
548   if(verbose>2)
549     fprintf(console,"gpgkeys: LDAP search for: %s\n",search);
550
551   fprintf(console,("gpgkeys: searching for \"%s\" from LDAP server %s\n"),
552           searchkey,host);
553
554   err=ldap_search_s(ldap,basekeyspacedn,
555                     LDAP_SCOPE_SUBTREE,search,attrs,0,&res);
556   if(err!=0)
557     {
558       int errtag=ldap_err_to_gpg_err(err);
559
560       fprintf(output,"SEARCH %s FAILED %d\n",searchkey,errtag);
561       fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err));
562       return errtag;
563     }
564
565   count=ldap_count_entries(ldap,res);
566
567   if(count<1)
568     fprintf(output,"COUNT 0\n");
569   else
570     {
571       fprintf(output,"COUNT %d\n",count);
572
573       each=ldap_first_entry(ldap,res);
574       while(each!=NULL)
575         {
576           int flags=0;
577
578           vals=ldap_get_values(ldap,each,"pgpcertid");
579           if(vals!=NULL)
580             {
581               fprintf(output,"%s:",vals[0]);
582               ldap_value_free(vals);
583             }
584           else
585             fputc(':',output);
586
587           vals=ldap_get_values(ldap,each,"pgpuserid");
588           if(vals!=NULL)
589             {
590               /* Need to escape any colons */
591               printquoted(output,vals[0],':');
592               fputc(':',output);
593               ldap_value_free(vals);
594             }
595           else
596             fputc(':',output);
597
598           vals=ldap_get_values(ldap,each,"pgprevoked");
599           if(vals!=NULL)
600             {
601               if(atoi(vals[0])==1)
602                 flags|=1;
603               ldap_value_free(vals);
604             }
605
606           vals=ldap_get_values(ldap,each,"pgpdisabled");
607           if(vals!=NULL)
608             {
609               if(atoi(vals[0])==1)
610                 flags|=2;
611               ldap_value_free(vals);
612             }
613
614           fprintf(output,"%d:",flags);
615
616           /* YYYYMMDDHHmmssZ */
617
618           vals=ldap_get_values(ldap,each,"pgpkeycreatetime");
619           if(vals!=NULL && strlen(vals[0])==15)
620             {
621               fprintf(output,"%u:",(unsigned int)ldap2epochtime(vals[0]));
622               ldap_value_free(vals);
623             }
624           else
625             fputc(':',output);
626
627           vals=ldap_get_values(ldap,each,"pgpkeyexpiretime");
628           if(vals!=NULL && strlen(vals[0])==15)
629             {
630               fprintf(output,"%u:",(unsigned int)ldap2epochtime(vals[0]));
631               ldap_value_free(vals);
632             }
633           else
634             fputc(':',output);
635
636           vals=ldap_get_values(ldap,each,"modifytimestamp");
637           if(vals!=NULL && strlen(vals[0])==15)
638             {
639               fprintf(output,"%u:",(unsigned int)ldap2epochtime(vals[0]));
640               ldap_value_free(vals);
641             }
642           else
643             fputc(':',output);
644
645           vals=ldap_get_values(ldap,each,"pgpkeytype");
646           if(vals!=NULL)
647             {
648               fprintf(output,"%s:",vals[0]);
649               ldap_value_free(vals);
650             }
651           else
652             fputc(':',output);
653
654           vals=ldap_get_values(ldap,each,"pgpkeysize");
655           if(vals!=NULL)
656             {
657               /* Not sure why, but some keys are listed with a key size of
658                  0.  Treat that like an unknown. */
659               if(atoi(vals[0])>0)
660                 fprintf(output,"%d",atoi(vals[0]));
661               ldap_value_free(vals);
662             }
663
664           fputc('\n',output);
665
666           each=ldap_next_entry(ldap,each);
667         }
668     }
669
670   ldap_msgfree(res);
671
672   fprintf(output,"SEARCH %s END\n",searchkey);
673
674   return KEYSERVER_OK;
675 }
676
677 void
678 fail_all(struct keylist *keylist,int action,int err)
679 {
680   if(!keylist)
681     return;
682
683   if(action==SEARCH)
684     {
685       fprintf(output,"SEARCH ");
686       while(keylist)
687         {
688           fprintf(output,"%s ",keylist->str);
689           keylist=keylist->next;
690         }
691       fprintf(output,"FAILED %d\n",err);
692     }
693   else
694     while(keylist)
695       {
696         fprintf(output,"KEY %s FAILED %d\n",keylist->str,err);
697         keylist=keylist->next;
698       }
699 }
700
701 int main(int argc,char *argv[])
702 {
703   int port=0,arg,err,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
704   char line[MAX_LINE],**vals;
705   int version,failed=0;
706   char *attrs[]={"basekeyspacedn","version","software",NULL};
707   LDAPMessage *res;
708   struct keylist *keylist=NULL,*keyptr=NULL;
709
710 #ifdef __riscos__
711   riscos_global_defaults();
712 #endif
713
714   console=stderr;
715
716   while((arg=getopt(argc,argv,"ho:"))!=-1)
717     switch(arg)
718       {
719       default:
720       case 'h':
721         fprintf(console,"-h\thelp\n");
722         fprintf(console,"-o\toutput to this file\n");
723         return KEYSERVER_OK;
724
725       case 'o':
726         output=fopen(optarg,"w");
727         if(output==NULL)
728           {
729             fprintf(console,"gpgkeys: Cannot open output file \"%s\": %s\n",
730                     optarg,strerror(errno));
731             return KEYSERVER_INTERNAL_ERROR;
732           }
733
734         break;
735       }
736
737   if(argc>optind)
738     {
739       input=fopen(argv[optind],"r");
740       if(input==NULL)
741         {
742           fprintf(console,"gpgkeys: Cannot open input file \"%s\": %s\n",
743                   argv[optind],strerror(errno));
744           return KEYSERVER_INTERNAL_ERROR;
745         }
746     }
747
748   if(input==NULL)
749     input=stdin;
750
751   if(output==NULL)
752     output=stdout;
753
754   /* Get the command and info block */
755
756   while(fgets(line,MAX_LINE,input)!=NULL)
757     {
758       char commandstr[7];
759       char optionstr[30];
760       char hash;
761
762       if(line[0]=='\n')
763         break;
764
765       if(sscanf(line,"%c",&hash)==1 && hash=='#')
766         continue;
767
768       if(sscanf(line,"COMMAND %6s\n",commandstr)==1)
769         {
770           commandstr[6]='\0';
771
772           if(strcasecmp(commandstr,"get")==0)
773             action=GET;
774           else if(strcasecmp(commandstr,"send")==0)
775             action=SEND;
776           else if(strcasecmp(commandstr,"search")==0)
777             action=SEARCH;
778
779           continue;
780         }
781
782       if(sscanf(line,"HOST %79s\n",host)==1)
783         {
784           host[79]='\0';
785           continue;
786         }
787
788       if(sscanf(line,"PORT %9s\n",portstr)==1)
789         {
790           portstr[9]='\0';
791           port=atoi(portstr);
792           continue;
793         }
794
795       if(sscanf(line,"VERSION %d\n",&version)==1)
796         {
797           if(version!=0)
798             {
799               ret=KEYSERVER_VERSION_ERROR;
800               goto fail;
801             }
802
803           continue;
804         }
805
806       if(sscanf(line,"OPTION %29s\n",optionstr)==1)
807         {
808           int no=0;
809           char *start=&optionstr[0];
810
811           optionstr[29]='\0';
812
813           if(strncasecmp(optionstr,"no-",3)==0)
814             {
815               no=1;
816               start=&optionstr[3];
817             }
818
819           if(strcasecmp(start,"verbose")==0)
820             {
821               if(no)
822                 verbose--;
823               else
824                 verbose++;
825             }
826           else if(strcasecmp(start,"include-disabled")==0)
827             {
828               if(no)
829                 include_disabled=0;
830               else
831                 include_disabled=1;
832             }
833           else if(strcasecmp(start,"include-revoked")==0)
834             {
835               if(no)
836                 include_revoked=0;
837               else
838                 include_revoked=1;
839             }
840           else if(strcasecmp(start,"include-subkeys")==0)
841             {
842               if(no)
843                 include_subkeys=0;
844               else
845                 include_subkeys=1;
846             }
847
848           continue;
849         }
850     }
851
852   /* If it's a GET or a SEARCH, the next thing to come in is the
853      keyids.  If it's a SEND, then there are no keyids. */
854
855   if(action==SEND)
856     while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
857   else if(action==GET || action==SEARCH)
858     {
859       for(;;)
860         {
861           struct keylist *work;
862
863           if(fgets(line,MAX_LINE,input)==NULL)
864             break;
865           else
866             {
867               if(line[0]=='\n')
868                 break;
869
870               work=malloc(sizeof(struct keylist));
871               if(work==NULL)
872                 {
873                   fprintf(console,"gpgkeys: out of memory while "
874                           "building key list\n");
875                   ret=KEYSERVER_NO_MEMORY;
876                   goto fail;
877                 }
878
879               strcpy(work->str,line);
880
881               /* Trim the trailing \n */
882               work->str[strlen(line)-1]='\0';
883
884               work->next=NULL;
885
886               /* Always attach at the end to keep the list in proper
887                  order for searching */
888               if(keylist==NULL)
889                 keylist=work;
890               else
891                 keyptr->next=work;
892
893               keyptr=work;
894             }
895         }
896     }
897   else
898     {
899       fprintf(console,"gpgkeys: no keyserver command specified\n");
900       goto fail;
901     }
902
903   /* Send the response */
904
905   fprintf(output,"VERSION 0\n");
906   fprintf(output,"PROGRAM %s\n\n",VERSION);
907
908   if(verbose>1)
909     {
910       fprintf(console,"Host:\t\t%s\n",host);
911       if(port)
912         fprintf(console,"Port:\t\t%d\n",port);
913       fprintf(console,"Command:\t%s\n",action==GET?"GET":
914               action==SEND?"SEND":"SEARCH");
915     }
916
917   ldap=ldap_init(host,port);
918   if(ldap==NULL)
919     {
920       fprintf(console,"gpgkeys: internal LDAP init error: %s\n",
921               strerror(errno));
922       fail_all(keylist,action,KEYSERVER_INTERNAL_ERROR);
923       goto fail;
924     }
925
926   err=ldap_simple_bind_s(ldap,NULL,NULL);
927   if(err!=0)
928     {
929       fprintf(console,"gpgkeys: internal LDAP bind error: %s\n",
930               ldap_err2string(err));
931       fail_all(keylist,action,ldap_err_to_gpg_err(err));
932       goto fail;
933     }
934
935   /* Get the magic info record */
936
937   err=ldap_search_s(ldap,"cn=PGPServerInfo",LDAP_SCOPE_BASE,
938                     "(objectclass=*)",attrs,0,&res);
939   if(err!=0)
940     {
941       fprintf(console,"gpgkeys: error retrieving LDAP server info: %s\n",
942               ldap_err2string(err));
943       fail_all(keylist,action,ldap_err_to_gpg_err(err));
944       goto fail;
945     }
946
947   if(ldap_count_entries(ldap,res)!=1)
948     {
949       fprintf(console,"gpgkeys: more than one serverinfo record\n");
950       fail_all(keylist,action,KEYSERVER_INTERNAL_ERROR);
951       goto fail;
952     }
953
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
964   vals=ldap_get_values(ldap,res,"version");
965   if(vals!=NULL)
966     {
967       if(verbose>1)
968         fprintf(console,"Version:\t%s\n",vals[0]);
969
970       /* If the version is high enough, use the new pgpKeyV2
971          attribute.  This design if iffy at best, but it matches how
972          PGP does it.  I figure the NAI folks assumed that there would
973          never be a LDAP keyserver vendor with a different numbering
974          scheme. */
975       if(atoi(vals[0])>1)
976         pgpkeystr="pgpKeyV2";
977
978       ldap_value_free(vals);
979     }
980
981   /* This is always "OU=ACTIVE,O=PGP KEYSPACE,C=US", but it might not
982      be in the future. */
983
984   vals=ldap_get_values(ldap,res,"basekeyspacedn");
985   if(vals!=NULL)
986     {
987       basekeyspacedn=strdup(vals[0]);
988       ldap_value_free(vals);
989       if(basekeyspacedn==NULL)
990         {
991           fprintf(console,"gpgkeys: can't allocate string space "
992                   "for LDAP base\n");
993           fail_all(keylist,action,KEYSERVER_NO_MEMORY);
994           goto fail;
995         }
996     }
997
998   ldap_msgfree(res);
999
1000   switch(action)
1001     {
1002     case GET:
1003       keyptr=keylist;
1004
1005       while(keyptr!=NULL)
1006         {
1007           if(get_key(keyptr->str)!=KEYSERVER_OK)
1008             failed++;
1009
1010           keyptr=keyptr->next;
1011         }
1012       break;
1013
1014     case SEND:
1015       {
1016         int eof=0;
1017
1018         do
1019           {
1020             if(send_key(&eof)!=KEYSERVER_OK)
1021               failed++;
1022           }
1023         while(!eof);
1024       }
1025       break;
1026
1027     case SEARCH:
1028       {
1029         char *searchkey=NULL;
1030         int len=0;
1031
1032         /* To search, we stick a * in between each key to search for.
1033            This means that if the user enters words, they'll get
1034            "enters*words".  If the user "enters words", they'll get
1035            "enters words" */
1036
1037         keyptr=keylist;
1038         while(keyptr!=NULL)
1039           {
1040             len+=strlen(keyptr->str)+1;
1041             keyptr=keyptr->next;
1042           }
1043
1044         searchkey=malloc(len+1);
1045         if(searchkey==NULL)
1046           {
1047             ret=KEYSERVER_NO_MEMORY;
1048             fail_all(keylist,action,KEYSERVER_NO_MEMORY);
1049             goto fail;
1050           }
1051
1052         searchkey[0]='\0';
1053
1054         keyptr=keylist;
1055         while(keyptr!=NULL)
1056           {
1057             strcat(searchkey,keyptr->str);
1058             strcat(searchkey,"*");
1059             keyptr=keyptr->next;
1060           }
1061
1062         /* Nail that last "*" */
1063         searchkey[strlen(searchkey)-1]='\0';
1064
1065         if(search_key(searchkey)!=KEYSERVER_OK)
1066           failed++;
1067
1068         free(searchkey);
1069       }
1070
1071       break;
1072     }
1073
1074   if(!failed)
1075     ret=KEYSERVER_OK;
1076
1077  fail:
1078
1079   while(keylist!=NULL)
1080     {
1081       struct keylist *current=keylist;
1082       keylist=keylist->next;
1083       free(current);
1084     }
1085
1086   if(input!=stdin)
1087     fclose(input);
1088
1089   if(output!=stdout)
1090     fclose(output);
1091
1092   if(ldap!=NULL)
1093     ldap_unbind_s(ldap);
1094
1095   free(basekeyspacedn);
1096
1097   return ret;
1098 }