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