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