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