* exec.c, export.c, import.c, keyedit.c, keyserver.c, misc.c: "Warning" ->
[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 #ifndef FIXED_EXEC_PATH
343   /* Push the libdir into path */
344   set_exec_path(GNUPG_LIBEXECDIR,opt.exec_path_set);
345 #endif
346
347   /* Build the filename for the helper to execute */
348
349   command=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1);
350   strcpy(command,"gpgkeys_");
351   strcat(command,opt.keyserver_scheme);
352
353   if(opt.keyserver_options.use_temp_files)
354     {
355       if(opt.keyserver_options.keep_temp_files)
356         {
357           command=m_realloc(command,strlen(command)+
358                             strlen(KEYSERVER_ARGS_KEEP)+1);
359           strcat(command,KEYSERVER_ARGS_KEEP);
360         }
361       else
362         {
363           command=m_realloc(command,strlen(command)+
364                             strlen(KEYSERVER_ARGS_NOKEEP)+1);
365           strcat(command,KEYSERVER_ARGS_NOKEEP);  
366         }
367
368       ret=exec_write(&spawn,NULL,command,NULL,0,0);
369     }
370   else
371     ret=exec_write(&spawn,command,NULL,NULL,0,0);
372
373   if(ret)
374     return ret;
375
376   fprintf(spawn->tochild,"# This is a gpg keyserver communications file\n");
377   fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
378   fprintf(spawn->tochild,"PROGRAM %s\n",VERSION);
379
380   if(opt.keyserver_opaque)
381     fprintf(spawn->tochild,"OPAQUE %s\n",opt.keyserver_opaque);
382   else
383     {
384       if(opt.keyserver_host)
385         fprintf(spawn->tochild,"HOST %s\n",opt.keyserver_host);
386
387       if(opt.keyserver_port)
388         fprintf(spawn->tochild,"PORT %s\n",opt.keyserver_port);
389     }
390
391   /* Write options */
392
393   for(i=0,kopts=keyserver_opts;kopts[i].name;i++)
394     if(*(kopts[i].flag) && kopts[i].tell)
395       fprintf(spawn->tochild,"OPTION %s\n",kopts[i].name);
396
397   for(i=0;i<opt.keyserver_options.verbose;i++)
398     fprintf(spawn->tochild,"OPTION verbose\n");
399
400   temp=opt.keyserver_options.other;
401
402   for(;temp;temp=temp->next)
403     fprintf(spawn->tochild,"OPTION %s\n",temp->d);
404
405   switch(action)
406     {
407     case GET:
408       {
409         fprintf(spawn->tochild,"COMMAND GET\n\n");
410
411         /* Which keys do we want? */
412
413         for(i=0;i<count;i++)
414           {
415             if(desc[i].mode==KEYDB_SEARCH_MODE_FPR20)
416               {
417                 int f;
418
419                 fprintf(spawn->tochild,"0x");
420
421                 for(f=0;f<MAX_FINGERPRINT_LEN;f++)
422                   fprintf(spawn->tochild,"%02X",(byte)desc[i].u.fpr[f]);
423
424                 fprintf(spawn->tochild,"\n");
425               }
426             else if(desc[i].mode==KEYDB_SEARCH_MODE_FPR16)
427               {
428                 int f;
429
430                 fprintf(spawn->tochild,"0x");
431
432                 for(f=0;f<16;f++)
433                   fprintf(spawn->tochild,"%02X",(byte)desc[i].u.fpr[f]);
434
435                 fprintf(spawn->tochild,"\n");
436               }
437             else if(desc[i].mode==KEYDB_SEARCH_MODE_LONG_KID)
438               fprintf(spawn->tochild,"0x%08lX%08lX\n",
439                       (ulong)desc[i].u.kid[0],
440                       (ulong)desc[i].u.kid[1]);
441             else
442               fprintf(spawn->tochild,"0x%08lX\n",
443                       (ulong)desc[i].u.kid[1]);
444           }
445
446         fprintf(spawn->tochild,"\n");
447
448         break;
449       }
450
451     case SEND:
452       {
453         STRLIST key;
454
455         /* Note the extra \n here to send an empty keylist block */
456         fprintf(spawn->tochild,"COMMAND SEND\n\n\n");
457
458         for(key=list;key!=NULL;key=key->next)
459           {
460             armor_filter_context_t afx;
461             IOBUF buffer=iobuf_temp();
462
463             temp=NULL;
464             add_to_strlist(&temp,key->d);
465
466             memset(&afx,0,sizeof(afx));
467             afx.what=1;
468             iobuf_push_filter(buffer,armor_filter,&afx);
469
470             if(export_pubkeys_stream(buffer,temp,
471                                      opt.keyserver_options.export_options)==-1)
472               iobuf_close(buffer);
473             else
474               {
475                 iobuf_flush_temp(buffer);
476
477                 fprintf(spawn->tochild,"KEY %s BEGIN\n",key->d);
478                 fwrite(iobuf_get_temp_buffer(buffer),
479                        iobuf_get_temp_length(buffer),1,spawn->tochild);
480                 fprintf(spawn->tochild,"KEY %s END\n",key->d);
481
482                 iobuf_close(buffer);
483               }
484
485             free_strlist(temp);
486           }
487
488         break;
489       }
490
491     case SEARCH:
492       {
493         STRLIST key;
494
495         fprintf(spawn->tochild,"COMMAND SEARCH\n\n");
496
497         /* Which keys do we want?  Remember that the gpgkeys_ program
498            is going to lump these together into a search string. */
499
500         for(key=list;key!=NULL;key=key->next)
501           {
502             fprintf(spawn->tochild,"%s\n",key->d);
503             if(key!=list)
504               {
505                 searchstr=m_realloc(searchstr,
506                                     strlen(searchstr)+strlen(key->d)+2);
507                 strcat(searchstr," ");
508               }
509             else
510               {
511                 searchstr=m_alloc(strlen(key->d)+1);
512                 searchstr[0]='\0';
513               }
514
515             strcat(searchstr,key->d);
516           }
517
518         fprintf(spawn->tochild,"\n");
519
520         break;
521       }
522
523     default:
524       log_fatal(_("no keyserver action!\n"));
525       break;
526     }
527
528   /* Done sending, so start reading. */
529   ret=exec_read(spawn);
530   if(ret)
531     goto fail;
532
533   /* Now handle the response */
534
535   for(;;)
536     {
537       char *ptr;
538
539       if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
540         {
541           ret=G10ERR_READ_FILE;
542           goto fail; /* i.e. EOF */
543         }
544
545       ptr=line;
546
547       if(*ptr=='\r')
548         ptr++;
549
550       if(*ptr=='\n')
551         ptr++;
552
553       if(*ptr=='\0')
554         break;
555
556       if(ascii_memcasecmp(ptr,"VERSION ",8)==0)
557         {
558           gotversion=1;
559
560           if(atoi(&ptr[8])!=KEYSERVER_PROTO_VERSION)
561             {
562               log_error(_("invalid keyserver protocol (us %d!=handler %d)\n"),
563                         KEYSERVER_PROTO_VERSION,atoi(&ptr[8]));
564               goto fail;
565             }
566         }
567       else if(ascii_memcasecmp(ptr,"PROGRAM ",8)==0)
568         {
569           if(ascii_memcasecmp(&ptr[8],VERSION,strlen(VERSION))!=0)
570             log_info(_("WARNING: keyserver handler from a different "
571                        "version of GnuPG (%s)\n"),&ptr[8]);
572         }
573       else if(ascii_memcasecmp(ptr,"OPTION OUTOFBAND",16)==0)
574         outofband=1; /* Currently the only OPTION */
575     }
576
577   m_free(line);
578
579   if(!gotversion)
580     {
581       log_error(_("keyserver did not send VERSION\n"));
582       goto fail;
583     }
584
585   if(!outofband)
586     switch(action)
587       {
588       case GET:
589         {
590           void *stats_handle;
591
592           stats_handle=import_new_stats_handle();
593
594           /* Slurp up all the key data.  In the future, it might be nice
595              to look for KEY foo OUTOFBAND and FAILED indicators.  It's
596              harmless to ignore them, but ignoring them does make gpg
597              complain about "no valid OpenPGP data found".  One way to
598              do this could be to continue parsing this line-by-line and
599              make a temp iobuf for each key. */
600
601           import_keys_stream(spawn->fromchild,0,stats_handle,
602                              opt.keyserver_options.import_options);
603
604           import_print_stats(stats_handle);
605           import_release_stats_handle(stats_handle);
606
607           break;
608         }
609
610         /* Nothing to do here */
611       case SEND:
612         break;
613
614       case SEARCH:
615         {
616           line=NULL;
617           buflen = 0;
618           maxlen = 80;
619           /* Look for the COUNT line */
620           do
621             {
622               if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
623                 {
624                   ret=G10ERR_READ_FILE;
625                   goto fail; /* i.e. EOF */
626                 }
627             }
628           while(sscanf(line,"COUNT %d\n",&i)!=1);
629
630           keyserver_search_prompt(spawn->fromchild,i,searchstr);
631
632           break;
633         }
634
635       default:
636         log_fatal(_("no keyserver action!\n"));
637         break;
638       }
639
640  fail:
641   *prog=exec_finish(spawn);
642
643   return ret;
644 }
645
646 static int 
647 keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count)
648 {
649   int rc=0,ret=0;
650
651   if(opt.keyserver_scheme==NULL)
652     {
653       log_error(_("no keyserver known (use option --keyserver)\n"));
654       return G10ERR_BAD_URI;
655     }
656
657 #ifndef USE_EXTERNAL_HKP
658   /* Use the internal HKP code */
659   if(ascii_strcasecmp(opt.keyserver_scheme,"hkp")==0)
660     {
661       if(opt.keyserver_host==NULL)
662         {
663           log_error(_("no keyserver known (use option --keyserver)\n"));
664           return G10ERR_BAD_URI;
665         }
666       else
667         {
668           void *stats_handle = import_new_stats_handle ();
669
670           switch(action)
671             {
672             case GET:
673               for(count--;count>=0;count--)
674                 if(hkp_ask_import(&desc[count],stats_handle))
675                   log_inc_errorcount();
676               break;
677             case SEND:
678               return hkp_export(list);
679             case SEARCH:
680               return hkp_search(list);
681             }
682
683           import_print_stats (stats_handle);
684           import_release_stats_handle (stats_handle);
685
686           return 0;
687         }
688     }
689 #endif
690
691 #ifdef DISABLE_KEYSERVER_HELPERS
692   log_error(_("external keyserver calls are not supported in this build\n"));
693   return G10ERR_KEYSERVER;
694 #endif
695
696   /* It's not the internal HKP code, so try and spawn a handler for it */
697
698   rc=keyserver_spawn(action,list,desc,count,&ret);
699   if(ret)
700     {
701       switch(ret)
702         {
703         case KEYSERVER_SCHEME_NOT_FOUND:
704           log_error(_("no handler for keyserver scheme \"%s\"\n"),
705                     opt.keyserver_scheme);
706           break;
707
708         case KEYSERVER_NOT_SUPPORTED:
709           log_error(_("action \"%s\" not supported with keyserver "
710                       "scheme \"%s\"\n"),
711                     action==GET?"get":action==SEND?"send":
712                     action==SEARCH?"search":"unknown",
713                     opt.keyserver_scheme);
714
715         case KEYSERVER_INTERNAL_ERROR:
716         default:
717           log_error(_("keyserver internal error\n"));
718           break;
719         }
720
721       return G10ERR_KEYSERVER;
722     }
723
724   if(rc)
725     {
726       log_error(_("keyserver communications error: %s\n"),g10_errstr(rc));
727
728       return rc;
729     }
730
731   return 0;
732 }
733
734 int 
735 keyserver_export(STRLIST users)
736 {
737   /* We better ask for confirmation when the user entered --send-keys
738      without arguments.  Sending all keys might not be the thing he
739      intended to do */
740   if (users || opt.batch || opt.answer_yes)
741     ;
742   else if ( !cpr_get_answer_is_yes
743             ("keyserver_export.send_all",
744              _("Do you really want to send all your "
745                "public keys to the keyserver? (y/N) ")))
746     return -1;
747
748   return keyserver_work(SEND,users,NULL,0);
749 }
750
751 int 
752 keyserver_import(STRLIST users)
753 {
754   KEYDB_SEARCH_DESC *desc;
755   int num=100,count=0;
756   int rc=0;
757
758   /* Build a list of key ids */
759   desc=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num);
760
761   for(;users;users=users->next)
762     {
763       classify_user_id (users->d, &desc[count]);
764       if(desc[count].mode!=KEYDB_SEARCH_MODE_SHORT_KID &&
765          desc[count].mode!=KEYDB_SEARCH_MODE_LONG_KID &&
766          desc[count].mode!=KEYDB_SEARCH_MODE_FPR16 &&
767          desc[count].mode!=KEYDB_SEARCH_MODE_FPR20)
768         {
769           log_error(_("skipping invalid key ID \"%s\"\n"),users->d);
770           continue;
771         }
772
773       count++;
774       if(count==num)
775         {
776           num+=100;
777           desc=m_realloc(desc,sizeof(KEYDB_SEARCH_DESC)*num);
778         }
779     }
780
781   if(count>0)
782     rc=keyserver_work(GET,NULL,desc,count);
783
784   m_free(desc);
785
786   return rc;
787 }
788
789 int
790 keyserver_import_fprint(const byte *fprint,size_t fprint_len)
791 {
792   KEYDB_SEARCH_DESC desc;
793
794   memset(&desc,0,sizeof(desc));
795
796   if(fprint_len==16)
797     desc.mode=KEYDB_SEARCH_MODE_FPR16;
798   else if(fprint_len==20)
799     desc.mode=KEYDB_SEARCH_MODE_FPR20;
800   else
801     return -1;
802
803   memcpy(desc.u.fpr,fprint,fprint_len);
804
805   return keyserver_work(GET,NULL,&desc,1);
806 }
807
808 int 
809 keyserver_import_keyid(u32 *keyid)
810 {
811   KEYDB_SEARCH_DESC desc;
812
813   memset(&desc,0,sizeof(desc));
814
815   desc.mode=KEYDB_SEARCH_MODE_LONG_KID;
816   desc.u.kid[0]=keyid[0];
817   desc.u.kid[1]=keyid[1];
818
819   return keyserver_work(GET,NULL,&desc,1);
820 }
821
822 /* code mostly stolen from do_export_stream */
823 static int 
824 keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
825 {
826   int rc=0,ndesc,num=100;
827   KBNODE keyblock=NULL,node;
828   KEYDB_HANDLE kdbhd;
829   KEYDB_SEARCH_DESC *desc;
830   STRLIST sl;
831
832   *count=0;
833
834   *klist=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num);
835
836   kdbhd=keydb_new(0);
837
838   if(!users)
839     {
840       ndesc = 1;
841       desc = m_alloc_clear ( ndesc * sizeof *desc);
842       desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
843     }
844   else
845     {
846       for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) 
847         ;
848       desc = m_alloc ( ndesc * sizeof *desc);
849         
850       for (ndesc=0, sl=users; sl; sl = sl->next)
851         {
852           if(classify_user_id (sl->d, desc+ndesc))
853             ndesc++;
854           else
855             log_error (_("key `%s' not found: %s\n"),
856                        sl->d, g10_errstr (G10ERR_INV_USER_ID));
857         }
858     }
859
860   while (!(rc = keydb_search (kdbhd, desc, ndesc)))
861     {
862       if (!users) 
863         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
864
865       /* read the keyblock */
866       rc = keydb_get_keyblock (kdbhd, &keyblock );
867       if( rc )
868         {
869           log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
870           goto leave;
871         }
872
873       if((node=find_kbnode(keyblock,PKT_PUBLIC_KEY)))
874         {
875           /* This is to work around a bug in some keyservers (pksd and
876              OKS) that calculate v4 RSA keyids as if they were v3 RSA.
877              The answer is to refresh both the correct v4 keyid
878              (e.g. 99242560) and the fake v3 keyid (e.g. 68FDDBC7).
879              This only happens for key refresh using the HKP scheme
880              and if the refresh-add-fake-v3-keyids keyserver option is
881              set. */
882           if(fakev3 && is_RSA(node->pkt->pkt.public_key->pubkey_algo) &&
883              node->pkt->pkt.public_key->version>=4)
884             {
885               (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID;
886               mpi_get_keyid(node->pkt->pkt.public_key->pkey[0],
887                             (*klist)[*count].u.kid);
888               (*count)++;
889
890               if(*count==num)
891                 {
892                   num+=100;
893                   *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num);
894                 }
895             }
896
897           /* v4 keys get full fingerprints.  v3 keys get long keyids.
898              This is because it's easy to calculate any sort of key id
899              from a v4 fingerprint, but not a v3 fingerprint. */
900
901           if(node->pkt->pkt.public_key->version<4)
902             {
903               (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID;
904               keyid_from_pk(node->pkt->pkt.public_key,
905                             (*klist)[*count].u.kid);
906             }
907           else
908             {
909               size_t dummy;
910
911               (*klist)[*count].mode=KEYDB_SEARCH_MODE_FPR20;
912               fingerprint_from_pk(node->pkt->pkt.public_key,
913                                   (*klist)[*count].u.fpr,&dummy);
914             }
915
916           (*count)++;
917
918           if(*count==num)
919             {
920               num+=100;
921               *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num);
922             }
923         }
924     }
925
926   if(rc==-1)
927     rc=0;
928   
929  leave:
930   m_free(desc);
931   keydb_release(kdbhd);
932   release_kbnode(keyblock);
933
934   return rc;
935 }
936
937 /* Note this is different than the original HKP refresh.  It allows
938    usernames to refresh only part of the keyring. */
939
940 int 
941 keyserver_refresh(STRLIST users)
942 {
943   int rc,count,fakev3=0;
944   KEYDB_SEARCH_DESC *desc;
945
946   /* We switch merge_only on during a refresh, as 'refresh' should
947      never import new keys, even if their keyids match.  Is it worth
948      preserving the old merge_only value here? */
949   opt.merge_only=1;
950
951   /* If refresh_add_fake_v3_keyids is on and it's a HKP or MAILTO
952      scheme, then enable fake v3 keyid generation. */
953   if(opt.keyserver_options.fake_v3_keyids && opt.keyserver_scheme &&
954      (ascii_strcasecmp(opt.keyserver_scheme,"hkp")==0 ||
955       ascii_strcasecmp(opt.keyserver_scheme,"mailto")==0))
956     fakev3=1;
957
958   rc=keyidlist(users,&desc,&count,fakev3);
959   if(rc)
960     return rc;
961
962   if(count==1)
963     log_info(_("refreshing 1 key from %s\n"),opt.keyserver_uri);
964   else
965     log_info(_("refreshing %d keys from %s\n"),count,opt.keyserver_uri);
966
967   if(count>0)
968     rc=keyserver_work(GET,NULL,desc,count);
969
970   m_free(desc);
971
972   return 0;
973 }
974
975 int 
976 keyserver_search(STRLIST tokens)
977 {
978   if(tokens)
979     return keyserver_work(SEARCH,tokens,NULL,0);
980   else
981     return 0;
982 }
983
984 /* Count and searchstr are just for cosmetics.  If the count is too
985    small, it will grow safely.  If negative it disables the "Key x-y
986    of z" messages. */
987 void 
988 keyserver_search_prompt(IOBUF buffer,int count,const char *searchstr)
989 {
990   int i=0,validcount=1;
991   unsigned int maxlen=256,buflen=0;
992   KEYDB_SEARCH_DESC *desc;
993   byte *line=NULL;
994   char *answer;
995
996   if(count==0)
997     goto notfound;
998
999   if(count<0)
1000     {
1001       validcount=0;
1002       count=10;
1003     }
1004
1005   desc=m_alloc(count*sizeof(KEYDB_SEARCH_DESC));
1006
1007   /* Read each line and show it to the user */
1008
1009   for(;;)
1010     {
1011       int rl;
1012
1013       if(validcount && i%10==0)
1014         {
1015           printf("Keys %d-%d of %d",i+1,(i+10<count)?i+10:count,count);
1016           if(searchstr)
1017             printf(" for \"%s\"",searchstr);
1018           printf("\n");
1019         }
1020
1021       maxlen=1024;
1022       rl=iobuf_read_line(buffer,&line,&buflen,&maxlen);
1023       if(rl>0)
1024         {
1025           if(print_keyinfo(i+1,line,&desc[i])==0)
1026             {
1027               i++;
1028
1029               if(i==count)
1030                 {
1031                   count+=10;
1032                   desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC));
1033                   validcount=0;
1034                 }
1035             }
1036           else
1037             continue;
1038         }
1039
1040       if(rl==0 && i==0)
1041         {
1042           count=0;
1043           break;
1044         }
1045
1046       if(i%10==0 || rl==0)
1047         {
1048           answer=cpr_get_no_help("keysearch.prompt",
1049                                  _("Enter number(s), N)ext, or Q)uit > "));
1050           /* control-d */
1051           if(answer[0]=='\x04')
1052             {
1053               printf("Q\n");
1054               answer[0]='q';
1055             }
1056
1057           if(answer[0]=='q' || answer[0]=='Q')
1058             {
1059               m_free(answer);
1060               break;
1061             }
1062           else if(atoi(answer)>=1 && atoi(answer)<=i)
1063             {
1064               char *split=answer,*num;
1065
1066               while((num=strsep(&split," ,"))!=NULL)
1067                 if(atoi(num)>=1 && atoi(num)<=i)
1068                   keyserver_work(GET,NULL,&desc[atoi(num)-1],1);
1069
1070               m_free(answer);
1071               break;
1072             }
1073         }
1074     }
1075
1076   m_free(desc);
1077   m_free(line);
1078
1079  notfound:
1080   if(count==0)
1081     {
1082       if(searchstr)
1083         log_info(_("key \"%s\" not found on keyserver\n"),searchstr);
1084       else
1085         log_info(_("key not found on keyserver\n"));
1086       return;
1087     }
1088 }