Forgot to commit this:
[gnupg.git] / g10 / keyserver.c
1 /* keyserver.c - generic keyserver code
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 <ctype.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <assert.h>
27 #include "filter.h"
28 #include "keydb.h"
29 #include "status.h"
30 #include "exec.h"
31 #include "main.h"
32 #include "i18n.h"
33 #include "hkp.h"
34 #include "iobuf.h"
35 #include "memory.h"
36 #include "options.h"
37 #include "packet.h"
38 #include "keyserver-internal.h"
39 #include "util.h"
40
41 #define KEYSERVER_PROTO_VERSION 0
42
43 #define GET    0
44 #define SEND   1
45 #define SEARCH 2
46
47 struct kopts
48 {
49   char *name;
50   int tell; /* tell remote process about this one */
51   int *flag;
52 } keyserver_opts[]=
53 {
54   {"include-revoked",1,&opt.keyserver_options.include_revoked},
55   {"include-disabled",1,&opt.keyserver_options.include_disabled},
56   {"include-subkeys",1,&opt.keyserver_options.include_subkeys},
57   {"keep-temp-files",0,&opt.keyserver_options.keep_temp_files},
58   {"honor-http-proxy",1,&opt.keyserver_options.honor_http_proxy},
59   {"broken-http-proxy",1,&opt.keyserver_options.broken_http_proxy},
60   {"refresh-add-fake-v3-keyids",0,&opt.keyserver_options.fake_v3_keyids},
61   {"auto-key-retrieve",0,&opt.keyserver_options.auto_key_retrieve},
62   {NULL}
63 };
64
65 void 
66 parse_keyserver_options(char *options)
67 {
68   char *tok;
69
70   while((tok=strsep(&options," ,")))
71     {
72       int i,hit=0;
73
74       if(tok[0]=='\0')
75         continue;
76
77       for(i=0;keyserver_opts[i].name;i++)
78         {
79           if(ascii_strcasecmp(tok,keyserver_opts[i].name)==0)
80             {
81               *(keyserver_opts[i].flag)=1;
82               hit=1;
83               break;
84             }
85           else if(ascii_memcasecmp("no-",tok,3)==0 &&
86                   ascii_strcasecmp(&tok[3],keyserver_opts[i].name)==0)
87             {
88               *(keyserver_opts[i].flag)=0;
89               hit=1;
90               break;
91             }
92         }
93
94       /* These options need more than just a flag */
95       if(!hit)
96         {
97           if(ascii_strcasecmp(tok,"verbose")==0)
98             opt.keyserver_options.verbose++;
99           else if(ascii_strcasecmp(tok,"no-verbose")==0)
100             opt.keyserver_options.verbose--;
101 #ifdef EXEC_TEMPFILE_ONLY
102           else if(ascii_strcasecmp(tok,"use-temp-files")==0 ||
103                   ascii_strcasecmp(tok,"no-use-temp-files")==0)
104             log_info(_("Warning: keyserver option \"%s\" is not used "
105                        "on this platform\n"),tok);
106 #else
107           else if(ascii_strcasecmp(tok,"use-temp-files")==0)
108             opt.keyserver_options.use_temp_files=1;
109           else if(ascii_strcasecmp(tok,"no-use-temp-files")==0)
110             opt.keyserver_options.use_temp_files=0;
111 #endif
112           else
113             if(!parse_import_options(tok,
114                                      &opt.keyserver_options.import_options) &&
115                !parse_export_options(tok,
116                                      &opt.keyserver_options.export_options))
117               add_to_strlist(&opt.keyserver_options.other,tok);
118         }
119     }
120 }
121
122 int 
123 parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno)
124 {
125   int assume_hkp=0;
126
127   assert(uri!=NULL);
128
129   opt.keyserver_host=NULL;
130   opt.keyserver_port=NULL;
131   opt.keyserver_opaque=NULL;
132
133   /* Get the scheme */
134
135   opt.keyserver_scheme=strsep(&uri,":");
136   if(uri==NULL)
137     {
138       /* Assume HKP if there is no scheme */
139       assume_hkp=1;
140       uri=opt.keyserver_scheme;
141       opt.keyserver_scheme="hkp";
142     }
143
144   if(ascii_strcasecmp(opt.keyserver_scheme,"x-broken-hkp")==0)
145     {
146       deprecated_warning(configname,configlineno,"x-broken-hkp",
147                          "--keyserver-options ","broken-http-proxy");
148       opt.keyserver_scheme="hkp";
149       opt.keyserver_options.broken_http_proxy=1;
150     }
151   else if(ascii_strcasecmp(opt.keyserver_scheme,"x-hkp")==0)
152     {
153       /* Canonicalize this to "hkp" so it works with both the internal
154          and external keyserver interface. */
155       opt.keyserver_scheme="hkp";
156     }
157
158   if(assume_hkp || (uri[0]=='/' && uri[1]=='/'))
159     {
160       /* Two slashes means network path. */
161
162       /* Skip over the "//", if any */
163       if(!assume_hkp)
164         uri+=2;
165
166       /* Get the host */
167       opt.keyserver_host=strsep(&uri,":/");
168       if(opt.keyserver_host[0]=='\0')
169         return G10ERR_BAD_URI;
170
171       if(uri==NULL || uri[0]=='\0')
172         opt.keyserver_port=NULL;
173       else
174         {
175           char *ch;
176
177           /* Get the port */
178           opt.keyserver_port=strsep(&uri,"/");
179
180           /* Ports are digits only */
181           ch=opt.keyserver_port;
182           while(*ch!='\0')
183             {
184               if(!isdigit(*ch))
185                 return G10ERR_BAD_URI;
186
187               ch++;
188             }
189         }
190
191       /* (any path part of the URI is discarded for now as no keyserver
192          uses it yet) */
193     }
194   else if(uri[0]!='/')
195     {
196       /* No slash means opaque.  Just record the opaque blob and get
197          out. */
198       opt.keyserver_opaque=uri;
199       return 0;
200     }
201   else
202     {
203       /* One slash means absolute path.  We don't need to support that
204          yet. */
205       return G10ERR_BAD_URI;
206     }
207
208   if(opt.keyserver_scheme[0]=='\0')
209     return G10ERR_BAD_URI;
210
211   return 0;
212 }
213
214 /* Unquote only the delimiter character and backslashes (\x5C) */
215 static void 
216 printunquoted(char *string,char delim)
217 {
218   char *ch=string;
219
220   while(*ch)
221     {
222       if(*ch=='\\')
223         {
224           int c;
225
226           sscanf(ch,"\\x%02x",&c);
227           if(c==delim)
228             {
229               printf("%c",c);
230               ch+=3;
231             }
232           else if(c=='\\')
233             {
234               fputc('\\',stdout);
235               ch+=3;
236             }
237           else
238             fputc(*ch,stdout);
239         }
240       else
241         fputc(*ch,stdout);
242
243       ch++;
244     }
245 }
246
247 static int 
248 print_keyinfo(int count,char *keystring,KEYDB_SEARCH_DESC *desc)
249 {
250   char *certid,*userid,*keytype,*tok;
251   int flags,keysize=0;
252   time_t createtime=0,expiretime=0,modifytime=0;
253
254   if((certid=strsep(&keystring,":"))==NULL)
255     return -1;
256
257   classify_user_id (certid, desc);
258   if(desc->mode!=KEYDB_SEARCH_MODE_SHORT_KID &&
259      desc->mode!=KEYDB_SEARCH_MODE_LONG_KID &&
260      desc->mode!=KEYDB_SEARCH_MODE_FPR16 &&
261      desc->mode!=KEYDB_SEARCH_MODE_FPR20)
262     return -1;
263
264   if((tok=strsep(&keystring,":"))==NULL)
265     return -1;
266
267   userid=utf8_to_native(tok,strlen(tok),0);
268
269   if((tok=strsep(&keystring,":"))==NULL)
270     return -1;
271
272   flags=atoi(tok);
273
274   if((tok=strsep(&keystring,":"))==NULL)
275     return -1;
276
277   createtime=atoi(tok);
278
279   if((tok=strsep(&keystring,":"))==NULL)
280     return -1;
281
282   expiretime=atoi(tok);
283
284   if((tok=strsep(&keystring,":"))==NULL)
285     return -1;
286
287   modifytime=atoi(tok);
288
289   if((keytype=strsep(&keystring,":"))==NULL)
290     return -1;
291
292   /* The last one */
293   if(keystring!=NULL)
294     keysize=atoi(keystring);
295
296   printf("(%d)\t",count);
297
298   /* No need to check for control characters, as utf8_to_native does
299      this for us. */
300   printunquoted(userid,':');
301
302   if(flags&1)
303     printf(" (revoked)");
304   if(flags&2)
305     printf(" (disabled)");
306
307   if(keytype[0])
308     printf(" %s",keytype);
309
310   if(keysize>0)
311     printf(" %d",keysize);
312
313   printf("\n\t  created %s,",strtimestamp(createtime));
314
315   if(expiretime>0)
316     printf(" expires %s,",strtimestamp(expiretime));
317
318   printf(" key %s\n",certid);
319
320   return 0;
321 }
322
323 #define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\""
324 #define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\""
325
326 static int 
327 keyserver_spawn(int action,STRLIST list,
328                 KEYDB_SEARCH_DESC *desc,int count,int *prog)
329 {
330   int ret=0,i,gotversion=0,outofband=0;
331   STRLIST temp;
332   unsigned int maxlen=256,buflen;
333   char *command=NULL,*searchstr=NULL;
334   byte *line=NULL;
335   struct kopts *kopts;
336   struct exec_info *spawn;
337
338 #ifdef EXEC_TEMPFILE_ONLY
339   opt.keyserver_options.use_temp_files=1;
340 #endif
341
342   /* Build the filename for the helper to execute */
343
344   command=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1);
345   strcpy(command,"gpgkeys_");
346   strcat(command,opt.keyserver_scheme);
347
348   if(opt.keyserver_options.use_temp_files)
349     {
350       if(opt.keyserver_options.keep_temp_files)
351         {
352           command=m_realloc(command,strlen(command)+
353                             strlen(KEYSERVER_ARGS_KEEP)+1);
354           strcat(command,KEYSERVER_ARGS_KEEP);
355         }
356       else
357         {
358           command=m_realloc(command,strlen(command)+
359                             strlen(KEYSERVER_ARGS_NOKEEP)+1);
360           strcat(command,KEYSERVER_ARGS_NOKEEP);  
361         }
362
363       ret=exec_write(&spawn,NULL,command,NULL,0,0);
364     }
365   else
366     ret=exec_write(&spawn,command,NULL,NULL,0,0);
367
368   if(ret)
369     return ret;
370
371   fprintf(spawn->tochild,"# This is a gpg keyserver communications file\n");
372   fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
373   fprintf(spawn->tochild,"PROGRAM %s\n",VERSION);
374
375   if(opt.keyserver_opaque)
376     fprintf(spawn->tochild,"OPAQUE %s\n",opt.keyserver_opaque);
377   else
378     {
379       if(opt.keyserver_host)
380         fprintf(spawn->tochild,"HOST %s\n",opt.keyserver_host);
381
382       if(opt.keyserver_port)
383         fprintf(spawn->tochild,"PORT %s\n",opt.keyserver_port);
384     }
385
386   /* Write options */
387
388   for(i=0,kopts=keyserver_opts;kopts[i].name;i++)
389     if(*(kopts[i].flag) && kopts[i].tell)
390       fprintf(spawn->tochild,"OPTION %s\n",kopts[i].name);
391
392   for(i=0;i<opt.keyserver_options.verbose;i++)
393     fprintf(spawn->tochild,"OPTION verbose\n");
394
395   temp=opt.keyserver_options.other;
396
397   for(;temp;temp=temp->next)
398     fprintf(spawn->tochild,"OPTION %s\n",temp->d);
399
400   switch(action)
401     {
402     case GET:
403       {
404         fprintf(spawn->tochild,"COMMAND GET\n\n");
405
406         /* Which keys do we want? */
407
408         for(i=0;i<count;i++)
409           {
410             if(desc[i].mode==KEYDB_SEARCH_MODE_FPR20)
411               {
412                 int f;
413
414                 fprintf(spawn->tochild,"0x");
415
416                 for(f=0;f<MAX_FINGERPRINT_LEN;f++)
417                   fprintf(spawn->tochild,"%02X",(byte)desc[i].u.fpr[f]);
418
419                 fprintf(spawn->tochild,"\n");
420               }
421             else if(desc[i].mode==KEYDB_SEARCH_MODE_FPR16)
422               {
423                 int f;
424
425                 fprintf(spawn->tochild,"0x");
426
427                 for(f=0;f<16;f++)
428                   fprintf(spawn->tochild,"%02X",(byte)desc[i].u.fpr[f]);
429
430                 fprintf(spawn->tochild,"\n");
431               }
432             else if(desc[i].mode==KEYDB_SEARCH_MODE_LONG_KID)
433               fprintf(spawn->tochild,"0x%08lX%08lX\n",
434                       (ulong)desc[i].u.kid[0],
435                       (ulong)desc[i].u.kid[1]);
436             else
437               fprintf(spawn->tochild,"0x%08lX\n",
438                       (ulong)desc[i].u.kid[1]);
439           }
440
441         fprintf(spawn->tochild,"\n");
442
443         break;
444       }
445
446     case SEND:
447       {
448         STRLIST key;
449
450         /* Note the extra \n here to send an empty keylist block */
451         fprintf(spawn->tochild,"COMMAND SEND\n\n\n");
452
453         for(key=list;key!=NULL;key=key->next)
454           {
455             armor_filter_context_t afx;
456             IOBUF buffer=iobuf_temp();
457
458             temp=NULL;
459             add_to_strlist(&temp,key->d);
460
461             memset(&afx,0,sizeof(afx));
462             afx.what=1;
463             iobuf_push_filter(buffer,armor_filter,&afx);
464
465             if(export_pubkeys_stream(buffer,temp,
466                                      opt.keyserver_options.export_options)==-1)
467               iobuf_close(buffer);
468             else
469               {
470                 iobuf_flush_temp(buffer);
471
472                 fprintf(spawn->tochild,"KEY %s BEGIN\n",key->d);
473                 fwrite(iobuf_get_temp_buffer(buffer),
474                        iobuf_get_temp_length(buffer),1,spawn->tochild);
475                 fprintf(spawn->tochild,"KEY %s END\n",key->d);
476
477                 iobuf_close(buffer);
478               }
479
480             free_strlist(temp);
481           }
482
483         break;
484       }
485
486     case SEARCH:
487       {
488         STRLIST key;
489
490         fprintf(spawn->tochild,"COMMAND SEARCH\n\n");
491
492         /* Which keys do we want?  Remember that the gpgkeys_ program
493            is going to lump these together into a search string. */
494
495         for(key=list;key!=NULL;key=key->next)
496           {
497             fprintf(spawn->tochild,"%s\n",key->d);
498             if(key!=list)
499               {
500                 searchstr=m_realloc(searchstr,
501                                     strlen(searchstr)+strlen(key->d)+2);
502                 strcat(searchstr," ");
503               }
504             else
505               {
506                 searchstr=m_alloc(strlen(key->d)+1);
507                 searchstr[0]='\0';
508               }
509
510             strcat(searchstr,key->d);
511           }
512
513         fprintf(spawn->tochild,"\n");
514
515         break;
516       }
517
518     default:
519       log_fatal(_("no keyserver action!\n"));
520       break;
521     }
522
523   /* Done sending, so start reading. */
524   ret=exec_read(spawn);
525   if(ret)
526     goto fail;
527
528   /* Now handle the response */
529
530   for(;;)
531     {
532       char *ptr;
533
534       if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
535         {
536           ret=G10ERR_READ_FILE;
537           goto fail; /* i.e. EOF */
538         }
539
540       ptr=line;
541
542       if(*ptr=='\r')
543         ptr++;
544
545       if(*ptr=='\n')
546         ptr++;
547
548       if(*ptr=='\0')
549         break;
550
551       if(ascii_memcasecmp(ptr,"VERSION ",8)==0)
552         {
553           gotversion=1;
554
555           if(atoi(&ptr[8])!=KEYSERVER_PROTO_VERSION)
556             {
557               log_error(_("invalid keyserver protocol (us %d!=handler %d)\n"),
558                         KEYSERVER_PROTO_VERSION,atoi(&ptr[8]));
559               goto fail;
560             }
561         }
562       else if(ascii_memcasecmp(ptr,"PROGRAM ",8)==0)
563         {
564           if(ascii_memcasecmp(&ptr[8],VERSION,strlen(VERSION))!=0)
565             log_info(_("Warning: keyserver handler from a different "
566                        "version of GnuPG (%s)\n"),&ptr[8]);
567         }
568       else if(ascii_memcasecmp(ptr,"OPTION OUTOFBAND",16)==0)
569         outofband=1; /* Currently the only OPTION */
570     }
571
572   m_free(line);
573
574   if(!gotversion)
575     {
576       log_error(_("keyserver did not send VERSION\n"));
577       goto fail;
578     }
579
580   if(!outofband)
581     switch(action)
582       {
583       case GET:
584         {
585           void *stats_handle;
586
587           stats_handle=import_new_stats_handle();
588
589           /* Slurp up all the key data.  In the future, it might be nice
590              to look for KEY foo OUTOFBAND and FAILED indicators.  It's
591              harmless to ignore them, but ignoring them does make gpg
592              complain about "no valid OpenPGP data found".  One way to
593              do this could be to continue parsing this line-by-line and
594              make a temp iobuf for each key. */
595
596           import_keys_stream(spawn->fromchild,0,stats_handle);
597
598           import_print_stats(stats_handle);
599           import_release_stats_handle(stats_handle);
600
601           break;
602         }
603
604         /* Nothing to do here */
605       case SEND:
606         break;
607
608       case SEARCH:
609         {
610           line=NULL;
611           buflen = 0;
612           maxlen = 80;
613           /* Look for the COUNT line */
614           do
615             {
616               if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
617                 {
618                   ret=G10ERR_READ_FILE;
619                   goto fail; /* i.e. EOF */
620                 }
621             }
622           while(sscanf(line,"COUNT %d\n",&i)!=1);
623
624           keyserver_search_prompt(spawn->fromchild,i,searchstr);
625
626           break;
627         }
628
629       default:
630         log_fatal(_("no keyserver action!\n"));
631         break;
632       }
633
634  fail:
635   *prog=exec_finish(spawn);
636
637   return ret;
638 }
639
640 static int 
641 keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count)
642 {
643   int rc=0,ret=0;
644
645   if(opt.keyserver_scheme==NULL)
646     {
647       log_error(_("no keyserver known (use option --keyserver)\n"));
648       return G10ERR_BAD_URI;
649     }
650
651 #ifndef USE_EXTERNAL_HKP
652   /* Use the internal HKP code */
653   if(ascii_strcasecmp(opt.keyserver_scheme,"hkp")==0)
654     {
655       if(opt.keyserver_host==NULL)
656         {
657           log_error(_("no keyserver known (use option --keyserver)\n"));
658           return G10ERR_BAD_URI;
659         }
660       else
661         {
662           void *stats_handle = import_new_stats_handle ();
663
664           switch(action)
665             {
666             case GET:
667               for(count--;count>=0;count--)
668                 if(hkp_ask_import(&desc[count],stats_handle))
669                   log_inc_errorcount();
670               break;
671             case SEND:
672               return hkp_export(list);
673             case SEARCH:
674               return hkp_search(list);
675             }
676
677           import_print_stats (stats_handle);
678           import_release_stats_handle (stats_handle);
679
680           return 0;
681         }
682     }
683 #endif
684
685 #ifdef DISABLE_KEYSERVER_HELPERS
686   log_error(_("external keyserver calls are not supported in this build\n"));
687   return G10ERR_KEYSERVER;
688 #endif
689
690   /* It's not the internal HKP code, so try and spawn a handler for it */
691
692   rc=keyserver_spawn(action,list,desc,count,&ret);
693   if(ret)
694     {
695       switch(ret)
696         {
697         case KEYSERVER_SCHEME_NOT_FOUND:
698           log_error(_("no handler for keyserver scheme \"%s\"\n"),
699                     opt.keyserver_scheme);
700           break;
701
702         case KEYSERVER_NOT_SUPPORTED:
703           log_error(_("action \"%s\" not supported with keyserver "
704                       "scheme \"%s\"\n"),
705                     action==GET?"get":action==SEND?"send":
706                     action==SEARCH?"search":"unknown",
707                     opt.keyserver_scheme);
708
709         case KEYSERVER_INTERNAL_ERROR:
710         default:
711           log_error(_("keyserver internal error\n"));
712           break;
713         }
714
715       return G10ERR_KEYSERVER;
716     }
717
718   if(rc)
719     {
720       log_error(_("keyserver communications error: %s\n"),g10_errstr(rc));
721
722       return rc;
723     }
724
725   return 0;
726 }
727
728 int 
729 keyserver_export(STRLIST users)
730 {
731   /* We better ask for confirmation when the user entered --send-keys
732      without arguments.  Sending all keys might not be the thing he
733      intended to do */
734   if (users || opt.batch || opt.answer_yes)
735     ;
736   else if ( !cpr_get_answer_is_yes
737             ("keyserver_export.send_all",
738              _("Do you really want to send all your "
739                "public keys to the keyserver? (y/N) ")))
740     return -1;
741
742   return keyserver_work(SEND,users,NULL,0);
743 }
744
745 int 
746 keyserver_import(STRLIST users)
747 {
748   KEYDB_SEARCH_DESC *desc;
749   int num=100,count=0;
750   int rc=0;
751
752   /* Build a list of key ids */
753   desc=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num);
754
755   for(;users;users=users->next)
756     {
757       classify_user_id (users->d, &desc[count]);
758       if(desc[count].mode!=KEYDB_SEARCH_MODE_SHORT_KID &&
759          desc[count].mode!=KEYDB_SEARCH_MODE_LONG_KID &&
760          desc[count].mode!=KEYDB_SEARCH_MODE_FPR16 &&
761          desc[count].mode!=KEYDB_SEARCH_MODE_FPR20)
762         {
763           log_error(_("skipping invalid key ID \"%s\"\n"),users->d);
764           continue;
765         }
766
767       count++;
768       if(count==num)
769         {
770           num+=100;
771           desc=m_realloc(desc,sizeof(KEYDB_SEARCH_DESC)*num);
772         }
773     }
774
775   if(count>0)
776     rc=keyserver_work(GET,NULL,desc,count);
777
778   m_free(desc);
779
780   return rc;
781 }
782
783 int
784 keyserver_import_fprint(const byte *fprint,size_t fprint_len)
785 {
786   KEYDB_SEARCH_DESC desc;
787
788   memset(&desc,0,sizeof(desc));
789
790   if(fprint_len==16)
791     desc.mode=KEYDB_SEARCH_MODE_FPR16;
792   else if(fprint_len==20)
793     desc.mode=KEYDB_SEARCH_MODE_FPR20;
794   else
795     return -1;
796
797   memcpy(desc.u.fpr,fprint,fprint_len);
798
799   return keyserver_work(GET,NULL,&desc,1);
800 }
801
802 int 
803 keyserver_import_keyid(u32 *keyid)
804 {
805   KEYDB_SEARCH_DESC desc;
806
807   memset(&desc,0,sizeof(desc));
808
809   desc.mode=KEYDB_SEARCH_MODE_LONG_KID;
810   desc.u.kid[0]=keyid[0];
811   desc.u.kid[1]=keyid[1];
812
813   return keyserver_work(GET,NULL,&desc,1);
814 }
815
816 /* code mostly stolen from do_export_stream */
817 static int 
818 keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
819 {
820   int rc=0,ndesc,num=100;
821   KBNODE keyblock=NULL,node;
822   KEYDB_HANDLE kdbhd;
823   KEYDB_SEARCH_DESC *desc;
824   STRLIST sl;
825
826   *count=0;
827
828   *klist=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num);
829
830   kdbhd=keydb_new(0);
831
832   if(!users)
833     {
834       ndesc = 1;
835       desc = m_alloc_clear ( ndesc * sizeof *desc);
836       desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
837     }
838   else
839     {
840       for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) 
841         ;
842       desc = m_alloc ( ndesc * sizeof *desc);
843         
844       for (ndesc=0, sl=users; sl; sl = sl->next)
845         {
846           if(classify_user_id (sl->d, desc+ndesc))
847             ndesc++;
848           else
849             log_error (_("key `%s' not found: %s\n"),
850                        sl->d, g10_errstr (G10ERR_INV_USER_ID));
851         }
852     }
853
854   while (!(rc = keydb_search (kdbhd, desc, ndesc)))
855     {
856       if (!users) 
857         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
858
859       /* read the keyblock */
860       rc = keydb_get_keyblock (kdbhd, &keyblock );
861       if( rc )
862         {
863           log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
864           goto leave;
865         }
866
867       if((node=find_kbnode(keyblock,PKT_PUBLIC_KEY)))
868         {
869           /* This is to work around a bug in some keyservers (pksd and
870              OKS) that calculate v4 RSA keyids as if they were v3 RSA.
871              The answer is to refresh both the correct v4 keyid
872              (e.g. 99242560) and the fake v3 keyid (e.g. 68FDDBC7).
873              This only happens for key refresh using the HKP scheme
874              and if the refresh-add-fake-v3-keyids keyserver option is
875              set. */
876           if(fakev3 && is_RSA(node->pkt->pkt.public_key->pubkey_algo) &&
877              node->pkt->pkt.public_key->version>=4)
878             {
879               (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID;
880               mpi_get_keyid(node->pkt->pkt.public_key->pkey[0],
881                             (*klist)[*count].u.kid);
882               (*count)++;
883
884               if(*count==num)
885                 {
886                   num+=100;
887                   *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num);
888                 }
889             }
890
891           /* v4 keys get full fingerprints.  v3 keys get long keyids.
892              This is because it's easy to calculate any sort of key id
893              from a v4 fingerprint, but not a v3 fingerprint. */
894
895           if(node->pkt->pkt.public_key->version<4)
896             {
897               (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID;
898               keyid_from_pk(node->pkt->pkt.public_key,
899                             (*klist)[*count].u.kid);
900             }
901           else
902             {
903               size_t dummy;
904
905               (*klist)[*count].mode=KEYDB_SEARCH_MODE_FPR20;
906               fingerprint_from_pk(node->pkt->pkt.public_key,
907                                   (*klist)[*count].u.fpr,&dummy);
908             }
909
910           (*count)++;
911
912           if(*count==num)
913             {
914               num+=100;
915               *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num);
916             }
917         }
918     }
919
920   if(rc==-1)
921     rc=0;
922   
923  leave:
924   m_free(desc);
925   keydb_release(kdbhd);
926   release_kbnode(keyblock);
927
928   return rc;
929 }
930
931 /* Note this is different than the original HKP refresh.  It allows
932    usernames to refresh only part of the keyring. */
933
934 int 
935 keyserver_refresh(STRLIST users)
936 {
937   int rc,count,fakev3=0;
938   KEYDB_SEARCH_DESC *desc;
939
940   /* We switch merge_only on during a refresh, as 'refresh' should
941      never import new keys, even if their keyids match.  Is it worth
942      preserving the old merge_only value here? */
943   opt.merge_only=1;
944
945   /* If refresh_add_fake_v3_keyids is on and it's a HKP or MAILTO
946      scheme, then enable fake v3 keyid generation. */
947   if(opt.keyserver_options.fake_v3_keyids && opt.keyserver_scheme &&
948      (ascii_strcasecmp(opt.keyserver_scheme,"hkp")==0 ||
949       ascii_strcasecmp(opt.keyserver_scheme,"mailto")==0))
950     fakev3=1;
951
952   rc=keyidlist(users,&desc,&count,fakev3);
953   if(rc)
954     return rc;
955
956   if(count==1)
957     log_info(_("refreshing 1 key from %s\n"),opt.keyserver_uri);
958   else
959     log_info(_("refreshing %d keys from %s\n"),count,opt.keyserver_uri);
960
961   if(count>0)
962     rc=keyserver_work(GET,NULL,desc,count);
963
964   m_free(desc);
965
966   return 0;
967 }
968
969 int 
970 keyserver_search(STRLIST tokens)
971 {
972   if(tokens)
973     return keyserver_work(SEARCH,tokens,NULL,0);
974   else
975     return 0;
976 }
977
978 /* Count and searchstr are just for cosmetics.  If the count is too
979    small, it will grow safely.  If negative it disables the "Key x-y
980    of z" messages. */
981 void 
982 keyserver_search_prompt(IOBUF buffer,int count,const char *searchstr)
983 {
984   int i=0,validcount=1;
985   unsigned int maxlen=256,buflen=0;
986   KEYDB_SEARCH_DESC *desc;
987   byte *line=NULL;
988   char *answer;
989
990   if(count==0)
991     goto notfound;
992
993   if(count<0)
994     {
995       validcount=0;
996       count=10;
997     }
998
999   desc=m_alloc(count*sizeof(KEYDB_SEARCH_DESC));
1000
1001   /* Read each line and show it to the user */
1002
1003   for(;;)
1004     {
1005       int rl;
1006
1007       if(validcount && i%10==0)
1008         {
1009           printf("Keys %d-%d of %d",i+1,(i+10<count)?i+10:count,count);
1010           if(searchstr)
1011             printf(" for \"%s\"",searchstr);
1012           printf("\n");
1013         }
1014
1015       maxlen=1024;
1016       rl=iobuf_read_line(buffer,&line,&buflen,&maxlen);
1017       if(rl>0)
1018         {
1019           if(print_keyinfo(i+1,line,&desc[i])==0)
1020             {
1021               i++;
1022
1023               if(i==count)
1024                 {
1025                   count+=10;
1026                   desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC));
1027                   validcount=0;
1028                 }
1029             }
1030           else
1031             continue;
1032         }
1033
1034       if(rl==0 && i==0)
1035         {
1036           count=0;
1037           break;
1038         }
1039
1040       if(i%10==0 || rl==0)
1041         {
1042           answer=cpr_get_no_help("keysearch.prompt",
1043                                  _("Enter number(s), N)ext, or Q)uit > "));
1044           /* control-d */
1045           if(answer[0]=='\x04')
1046             {
1047               printf("Q\n");
1048               answer[0]='q';
1049             }
1050
1051           if(answer[0]=='q' || answer[0]=='Q')
1052             {
1053               m_free(answer);
1054               break;
1055             }
1056           else if(atoi(answer)>=1 && atoi(answer)<=i)
1057             {
1058               char *split=answer,*num;
1059
1060               while((num=strsep(&split," ,"))!=NULL)
1061                 if(atoi(num)>=1 && atoi(num)<=i)
1062                   keyserver_work(GET,NULL,&desc[atoi(num)-1],1);
1063
1064               m_free(answer);
1065               break;
1066             }
1067         }
1068     }
1069
1070   m_free(desc);
1071   m_free(line);
1072
1073  notfound:
1074   if(count==0)
1075     {
1076       if(searchstr)
1077         log_info(_("key \"%s\" not found on keyserver\n"),searchstr);
1078       else
1079         log_info(_("key not found on keyserver\n"));
1080       return;
1081     }
1082 }