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