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