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