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