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