aboutsummaryrefslogtreecommitdiffstats
path: root/g10/keyserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/keyserver.c')
-rw-r--r--g10/keyserver.c1438
1 files changed, 556 insertions, 882 deletions
diff --git a/g10/keyserver.c b/g10/keyserver.c
index 422e62e78..2f055ada5 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -1,6 +1,6 @@
/* keyserver.c - generic keyserver code
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- * 2009 Free Software Foundation, Inc.
+ * 2009, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -18,6 +18,9 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+/* !!! FIXME: Replace all printf by es_printf. FIXME !!! */
+
+
#include <config.h>
#include <ctype.h>
#include <stdio.h>
@@ -45,7 +48,8 @@
#ifdef USE_DNS_SRV
#include "srv.h"
#endif
-
+#include "membuf.h"
+#include "call-dirmngr.h"
#ifdef HAVE_W32_SYSTEM
/* It seems Vista doesn't grok X_OK and so fails access() tests.
@@ -65,6 +69,24 @@ struct keyrec
unsigned int lines;
};
+/* Parameters for the search line handler. */
+struct search_line_handler_parm_s
+{
+ ctrl_t ctrl; /* The session control structure. */
+ char *searchstr_disp; /* Native encoded search string or NULL. */
+ KEYDB_SEARCH_DESC *desc; /* Array with search descriptions. */
+ int count; /* Number of keys we are currently prepared to
+ handle. This is the size of the DESC array. If
+ it is too small, it will grow safely. */
+ int validcount; /* Enable the "Key x-y of z" messages. */
+ int nkeys; /* Number of processed records. */
+ int any_lines; /* At least one line has been processed. */
+ unsigned int numlines; /* Counter for displayed lines. */
+ int eof_seen; /* EOF encountered. */
+ int not_found; /* Set if no keys have been found. */
+};
+
+
enum ks_action {KS_UNKNOWN=0,KS_GET,KS_GETNAME,KS_SEND,KS_SEARCH};
static struct parse_options keyserver_opts[]=
@@ -89,10 +111,12 @@ static struct parse_options keyserver_opts[]=
{NULL,0,NULL,NULL}
};
-static int keyserver_work (ctrl_t ctrl, enum ks_action action,strlist_t list,
- KEYDB_SEARCH_DESC *desc,int count,
- unsigned char **fpr,size_t *fpr_len,
- struct keyserver_spec *keyserver);
+static gpg_error_t keyserver_get (ctrl_t ctrl,
+ KEYDB_SEARCH_DESC *desc, int ndesc,
+ struct keyserver_spec *keyserver);
+static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs,
+ struct keyserver_spec *keyserver);
+
/* Reasonable guess */
#define DEFAULT_MAX_CERT_SIZE 16384
@@ -236,9 +260,9 @@ keyserver_match(struct keyserver_spec *spec)
parser any longer so it can be removed, or at least moved to
keyserver/ksutil.c for limited use in gpgkeys_ldap or the like. */
-struct keyserver_spec *
-parse_keyserver_uri(const char *string,int require_scheme,
- const char *configname,unsigned int configlineno)
+keyserver_spec_t
+parse_keyserver_uri (const char *string,int require_scheme,
+ const char *configname,unsigned int configlineno)
{
int assume_hkp=0;
struct keyserver_spec *keyserver;
@@ -555,6 +579,8 @@ print_keyrec(int number,struct keyrec *keyrec)
static struct keyrec *
parse_keyrec(char *keystring)
{
+ /* FIXME: Remove the static and put the data into the parms we use
+ for the caller anyway. */
static struct keyrec *work=NULL;
struct keyrec *ret=NULL;
char *record;
@@ -583,12 +609,7 @@ parse_keyrec(char *keystring)
work->uidbuf=iobuf_temp();
}
- /* Remove trailing whitespace */
- for(i=strlen(keystring);i>0;i--)
- if(ascii_isspace(keystring[i-1]))
- keystring[i-1]='\0';
- else
- break;
+ trim_trailing_ws (keystring, strlen (keystring));
if((record=strsep(&keystring,":"))==NULL)
return ret;
@@ -664,7 +685,7 @@ parse_keyrec(char *keystring)
case 'R':
work->flags|=1;
break;
-
+
case 'd':
case 'D':
work->flags|=2;
@@ -727,882 +748,247 @@ parse_keyrec(char *keystring)
return ret;
}
-/* TODO: do this as a list sent to keyserver_work rather than calling
- it once for each key to get the correct counts after the import
- (cosmetics, really) and to better take advantage of the keyservers
- that can do multiple fetches in one go (LDAP). */
-static int
-show_prompt (ctrl_t ctrl,
- KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search)
+/* Show a prompt and allow the user to select keys for retrieval. */
+static gpg_error_t
+show_prompt (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int numdesc,
+ int count, const char *search)
{
- char *answer;
+ gpg_error_t err;
+ char *answer = NULL;
fflush (stdout);
- if(count && opt.command_fd==-1)
+ if (count && opt.command_fd == -1)
{
- static int from=1;
- tty_printf("Keys %d-%d of %d for \"%s\". ",from,numdesc,count,search);
- from=numdesc+1;
+ static int from = 1;
+ tty_printf ("Keys %d-%d of %d for \"%s\". ",
+ from, numdesc, count, search);
+ from = numdesc + 1;
}
- answer=cpr_get_no_help("keysearch.prompt",
- _("Enter number(s), N)ext, or Q)uit > "));
+ again:
+ err = 0;
+ xfree (answer);
+ answer = cpr_get_no_help ("keysearch.prompt",
+ _("Enter number(s), N)ext, or Q)uit > "));
/* control-d */
- if(answer[0]=='\x04')
+ if (answer[0]=='\x04')
{
- printf("Q\n");
- answer[0]='q';
+ tty_printf ("Q\n");
+ answer[0] = 'q';
}
- if(answer[0]=='q' || answer[0]=='Q')
- {
- xfree(answer);
- return 1;
- }
- else if(atoi(answer)>=1 && atoi(answer)<=numdesc)
+ if (answer[0]=='q' || answer[0]=='Q')
+ err = gpg_error (GPG_ERR_CANCELED);
+ else if (atoi (answer) >= 1 && atoi (answer) <= numdesc)
{
- char *split=answer,*num;
-
- while((num=strsep(&split," ,"))!=NULL)
- if(atoi(num)>=1 && atoi(num)<=numdesc)
- keyserver_work (ctrl, KS_GET,NULL,&desc[atoi(num)-1],1,
- NULL,NULL,opt.keyserver);
-
- xfree(answer);
- return 1;
- }
-
- return 0;
-}
-
-/* Count and searchstr are just for cosmetics. If the count is too
- small, it will grow safely. If negative it disables the "Key x-y
- of z" messages. searchstr should be UTF-8 (rather than native). */
-static void
-keyserver_search_prompt (ctrl_t ctrl, IOBUF buffer,const char *searchstr)
-{
- int i=0,validcount=0,started=0,header=0,count=1;
- unsigned int maxlen,buflen,numlines=0;
- KEYDB_SEARCH_DESC *desc;
- byte *line=NULL;
- char *localstr=NULL;
-
- if(searchstr)
- localstr=utf8_to_native(searchstr,strlen(searchstr),0);
-
- desc=xmalloc(count*sizeof(KEYDB_SEARCH_DESC));
-
- for(;;)
- {
- struct keyrec *keyrec;
- int rl;
-
- maxlen=1024;
- rl=iobuf_read_line(buffer,&line,&buflen,&maxlen);
-
- if(opt.with_colons)
- {
- if(!header && ascii_strncasecmp("SEARCH ",line,7)==0
- && ascii_strncasecmp(" BEGIN",&line[strlen(line)-7],6)==0)
- {
- header=1;
- continue;
- }
- else if(ascii_strncasecmp("SEARCH ",line,7)==0
- && ascii_strncasecmp(" END",&line[strlen(line)-5],4)==0)
- continue;
-
- printf("%s",line);
- }
-
- /* Look for an info: line. The only current info: values
- defined are the version and key count. */
- if(!started && rl>0 && ascii_strncasecmp("info:",line,5)==0)
- {
- char *tok,*str=&line[5];
-
- if((tok=strsep(&str,":"))!=NULL)
- {
- int version;
-
- if(sscanf(tok,"%d",&version)!=1)
- version=1;
-
- if(version!=1)
- {
- log_error(_("invalid keyserver protocol "
- "(us %d!=handler %d)\n"),1,version);
- break;
- }
- }
-
- if((tok=strsep(&str,":"))!=NULL && sscanf(tok,"%d",&count)==1)
- {
- if(count==0)
- goto notfound;
- else if(count<0)
- count=10;
- else
- validcount=1;
-
- desc=xrealloc(desc,count*sizeof(KEYDB_SEARCH_DESC));
- }
-
- started=1;
- continue;
- }
-
- if(rl==0)
- {
- keyrec=parse_keyrec(NULL);
-
- if(keyrec==NULL)
- {
- if(i==0)
- {
- count=0;
- break;
- }
-
- if(i!=count)
- validcount=0;
+ char *split = answer;
+ char *num;
+ int numarray[50];
+ int numidx = 0;
+ int idx;
+
+ while ((num = strsep (&split, " ,")))
+ if (atoi (num) >= 1 && atoi (num) <= numdesc)
+ {
+ if (numidx >= DIM (numarray))
+ {
+ tty_printf ("Too many keys selected\n");
+ goto again;
+ }
+ numarray[numidx++] = atoi (num);
+ }
+
+ if (!numidx)
+ goto again;
- if (opt.with_colons && opt.batch)
- break;
-
- for(;;)
- {
- if (show_prompt (ctrl, desc, i, validcount?count:0, localstr))
- break;
- validcount=0;
- }
-
- break;
- }
- }
- else
- keyrec=parse_keyrec(line);
-
- if(i==count)
- {
- /* keyserver helper sent more keys than they claimed in the
- info: line. */
- count+=10;
- desc=xrealloc(desc,count*sizeof(KEYDB_SEARCH_DESC));
- validcount=0;
- }
-
- if(keyrec)
- {
- desc[i]=keyrec->desc;
-
- if(!opt.with_colons)
- {
- /* screen_lines - 1 for the prompt. */
- if(numlines+keyrec->lines>opt.screen_lines-1)
- {
- if (show_prompt (ctrl, desc, i, validcount?count:0, localstr))
- break;
- else
- numlines=0;
- }
-
- print_keyrec(i+1,keyrec);
- }
-
- numlines+=keyrec->lines;
- iobuf_close(keyrec->uidbuf);
- xfree(keyrec);
-
- started=1;
- i++;
- }
- }
-
- notfound:
- /* Leave this commented out or now, and perhaps for a very long
- time. All HKPish servers return HTML error messages for
- no-key-found. */
- /*
- if(!started)
- log_info(_("keyserver does not support searching\n"));
- else
- */
- if(count==0)
- {
- if(localstr)
- log_info(_("key \"%s\" not found on keyserver\n"),localstr);
- else
- log_info(_("key not found on keyserver\n"));
+ {
+ KEYDB_SEARCH_DESC *selarray;
+
+ selarray = xtrymalloc (numidx * sizeof *selarray);
+ if (!selarray)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ for (idx = 0; idx < numidx; idx++)
+ selarray[idx] = desc[numarray[idx]-1];
+ err = keyserver_get (ctrl, selarray, numidx, NULL);
+ xfree (selarray);
+ }
}
- xfree(localstr);
- xfree(desc);
- xfree(line);
-}
-
-/* We sometimes want to use a different gpgkeys_xxx for a given
- protocol (for example, ldaps is handled by gpgkeys_ldap). Map
- these here. */
-static const char *
-keyserver_typemap(const char *type)
-{
- if(strcmp(type,"ldaps")==0)
- return "ldap";
- else if(strcmp(type,"hkps")==0)
- return "hkp";
- else
- return type;
+ leave:
+ xfree (answer);
+ return err;
}
-/* The PGP LDAP and the curl fetch-a-LDAP-object methodologies are
- sufficiently different that we can't use curl to do LDAP. */
-static int
-direct_uri_map(const char *scheme,unsigned int is_direct)
-{
- if(is_direct && strcmp(scheme,"ldap")==0)
- return 1;
-
- return 0;
-}
-#if GNUPG_MAJOR_VERSION == 2
-#define GPGKEYS_PREFIX "gpg2keys_"
-#else
-#define GPGKEYS_PREFIX "gpgkeys_"
-#endif
-#define GPGKEYS_CURL GPGKEYS_PREFIX "curl" EXEEXT
-#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_CURL))
-#define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\""
-#define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\""
-
-static int
-keyserver_spawn (ctrl_t ctrl,
- enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
- int count,int *prog,unsigned char **fpr,size_t *fpr_len,
- struct keyserver_spec *keyserver)
+/* This is a callback used by call-dirmngr.c to process the result of
+ KS_SEARCH command. LINE is the actual data line received with all
+ escaping removed and guaranteed to be exactly one line with
+ stripped LF; an EOF is indicated by LINE passed as NULL. LINE may
+ be modified after return. */
+static gpg_error_t
+search_line_handler (void *opaque, char *line)
{
- int ret=0,i,gotversion=0,outofband=0;
- strlist_t temp;
- unsigned int maxlen,buflen;
- char *command,*end,*searchstr=NULL;
- byte *line=NULL;
- struct exec_info *spawn;
- const char *scheme;
- const char *libexecdir = gnupg_libexecdir ();
+ struct search_line_handler_parm_s *parm = opaque;
+ gpg_error_t err = 0;
+ struct keyrec *keyrec;
- assert(keyserver);
-
-#ifdef EXEC_TEMPFILE_ONLY
- opt.keyserver_options.options|=KEYSERVER_USE_TEMP_FILES;
-#endif
-
- /* Build the filename for the helper to execute */
- scheme=keyserver_typemap(keyserver->scheme);
-
-#ifdef DISABLE_KEYSERVER_PATH
- /* Destroy any path we might have. This is a little tricky,
- portability-wise. It's not correct to delete the PATH
- environment variable, as that may fall back to a system built-in
- PATH. Similarly, it is not correct to set PATH to the null
- string (PATH="") since this actually deletes the PATH environment
- variable under MinGW. The safest thing to do here is to force
- PATH to be GNUPG_LIBEXECDIR. All this is not that meaningful on
- Unix-like systems (since we're going to give a full path to
- gpgkeys_foo), but on W32 it prevents loading any DLLs from
- directories in %PATH%.
-
- After some more thinking about this we came to the conclusion
- that it is better to load the helpers from the directory where
- the program of this process lives. Fortunately Windows provides
- a way to retrieve this and our gnupg_libexecdir function has been
- modified to return just this. Setting the exec-path is not
- anymore required.
- set_exec_path(libexecdir);
- */
-#else
- if(opt.exec_path_set)
+ if (parm->eof_seen && line)
{
- /* If exec-path was set, and DISABLE_KEYSERVER_PATH is
- undefined, then don't specify a full path to gpgkeys_foo, so
- that the PATH can work. */
- command=xmalloc(GPGKEYS_PREFIX_LEN+strlen(scheme)+3+strlen(EXEEXT)+1);
- command[0]='\0';
+ log_debug ("ooops: unexpected data after EOF\n");
+ line = NULL;
}
- else
-#endif
- {
- /* Specify a full path to gpgkeys_foo. */
- command=xmalloc(strlen(libexecdir)+strlen(DIRSEP_S)+
- GPGKEYS_PREFIX_LEN+strlen(scheme)+3+strlen(EXEEXT)+1);
- strcpy(command,libexecdir);
- strcat(command,DIRSEP_S);
- }
-
- end=command+strlen(command);
-
- /* Build a path for the keyserver helper. If it is direct_uri
- (i.e. an object fetch and not a keyserver), then add "_uri" to
- the end to distinguish the keyserver helper from an object
- fetcher that can speak that protocol (this is a problem for
- LDAP). */
-
- strcat(command,GPGKEYS_PREFIX);
- strcat(command,scheme);
-
- /* This "_uri" thing is in case we need to call a direct handler
- instead of the keyserver handler. This lets us use gpgkeys_curl
- or gpgkeys_ldap_uri (we don't provide it, but a user might)
- instead of gpgkeys_ldap to fetch things like
- ldap://keyserver.pgp.com/o=PGP%20keys?pgpkey?sub?pgpkeyid=99242560 */
- if(direct_uri_map(scheme,keyserver->flags.direct_uri))
- strcat(command,"_uri");
-
- strcat(command,EXEEXT);
-
- /* Can we execute it? If not, try curl as our catchall. */
- if(path_access(command,X_OK)!=0)
- strcpy(end,GPGKEYS_CURL);
-
- if(opt.keyserver_options.options&KEYSERVER_USE_TEMP_FILES)
+ /* Print the received line. */
+ if (opt.with_colons && line)
{
- if(opt.keyserver_options.options&KEYSERVER_KEEP_TEMP_FILES)
- {
- command=xrealloc(command,strlen(command)+
- strlen(KEYSERVER_ARGS_KEEP)+1);
- strcat(command,KEYSERVER_ARGS_KEEP);
- }
- else
- {
- command=xrealloc(command,strlen(command)+
- strlen(KEYSERVER_ARGS_NOKEEP)+1);
- strcat(command,KEYSERVER_ARGS_NOKEEP);
- }
-
- ret=exec_write(&spawn,NULL,command,NULL,0,0);
+ log_debug ("%s\n",line);
}
- else
- ret=exec_write(&spawn,command,NULL,NULL,0,0);
- xfree(command);
-
- if(ret)
- return ret;
-
- fprintf(spawn->tochild,
- "# This is a GnuPG %s keyserver communications file\n",VERSION);
- fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
- fprintf(spawn->tochild,"PROGRAM %s\n",VERSION);
- fprintf(spawn->tochild,"SCHEME %s\n",keyserver->scheme);
-
- if(keyserver->opaque)
- fprintf(spawn->tochild,"OPAQUE %s\n",keyserver->opaque);
- else
+ /* Look for an info: line. The only current info: values defined
+ are the version and key count. */
+ if (line && !parm->any_lines && !ascii_strncasecmp ("info:", line, 5))
{
- if(keyserver->auth)
- fprintf(spawn->tochild,"AUTH %s\n",keyserver->auth);
-
- if(keyserver->host)
- fprintf(spawn->tochild,"HOST %s\n",keyserver->host);
-
- if(keyserver->port)
- fprintf(spawn->tochild,"PORT %s\n",keyserver->port);
-
- if(keyserver->path)
- fprintf(spawn->tochild,"PATH %s\n",keyserver->path);
- }
-
- /* Write global options */
-
- for(temp=opt.keyserver_options.other;temp;temp=temp->next)
- fprintf(spawn->tochild,"OPTION %s\n",temp->d);
-
- /* Write per-keyserver options */
-
- for(temp=keyserver->options;temp;temp=temp->next)
- fprintf(spawn->tochild,"OPTION %s\n",temp->d);
-
- switch(action)
- {
- case KS_GET:
- {
- fprintf(spawn->tochild,"COMMAND GET\n\n");
-
- /* Which keys do we want? */
-
- for(i=0;i<count;i++)
- {
- int quiet=0;
-
- if(desc[i].mode==KEYDB_SEARCH_MODE_FPR20)
- {
- int f;
-
- fprintf(spawn->tochild,"0x");
-
- for(f=0;f<MAX_FINGERPRINT_LEN;f++)
- fprintf(spawn->tochild,"%02X",desc[i].u.fpr[f]);
-
- fprintf(spawn->tochild,"\n");
- }
- else if(desc[i].mode==KEYDB_SEARCH_MODE_FPR16)
- {
- int f;
-
- fprintf(spawn->tochild,"0x");
-
- for(f=0;f<16;f++)
- fprintf(spawn->tochild,"%02X",desc[i].u.fpr[f]);
-
- fprintf(spawn->tochild,"\n");
- }
- else if(desc[i].mode==KEYDB_SEARCH_MODE_LONG_KID)
- fprintf(spawn->tochild,"0x%08lX%08lX\n",
- (ulong)desc[i].u.kid[0],
- (ulong)desc[i].u.kid[1]);
- else if(desc[i].mode==KEYDB_SEARCH_MODE_SHORT_KID)
- fprintf(spawn->tochild,"0x%08lX\n",
- (ulong)desc[i].u.kid[1]);
- else if(desc[i].mode==KEYDB_SEARCH_MODE_EXACT)
- {
- fprintf(spawn->tochild,"0x0000000000000000\n");
- quiet=1;
- }
- else if(desc[i].mode==KEYDB_SEARCH_MODE_NONE)
- continue;
- else
- BUG();
-
- if(!quiet)
- {
- if(keyserver->host)
- log_info(_("requesting key %s from %s server %s\n"),
- keystr_from_desc(&desc[i]),
- keyserver->scheme,keyserver->host);
- else
- log_info(_("requesting key %s from %s\n"),
- keystr_from_desc(&desc[i]),keyserver->uri);
- }
- }
-
- fprintf(spawn->tochild,"\n");
-
- break;
- }
-
- case KS_GETNAME:
- {
- strlist_t key;
-
- fprintf(spawn->tochild,"COMMAND GETNAME\n\n");
-
- /* Which names do we want? */
-
- for(key=list;key!=NULL;key=key->next)
- fprintf(spawn->tochild,"%s\n",key->d);
-
- fprintf(spawn->tochild,"\n");
-
- if(keyserver->host)
- log_info(_("searching for names from %s server %s\n"),
- keyserver->scheme,keyserver->host);
- else
- log_info(_("searching for names from %s\n"),keyserver->uri);
-
- break;
- }
-
- case KS_SEND:
- {
- strlist_t key;
-
- /* Note the extra \n here to send an empty keylist block */
- fprintf(spawn->tochild,"COMMAND SEND\n\n\n");
-
- for(key=list;key!=NULL;key=key->next)
- {
- armor_filter_context_t *afx;
- IOBUF buffer = iobuf_temp ();
- KBNODE block;
-
- temp=NULL;
- add_to_strlist(&temp,key->d);
-
- afx = new_armor_context ();
- afx->what = 1;
- /* Tell the armor filter to use Unix-style \n line
- endings, since we're going to fprintf this to a file
- that (on Win32) is open in text mode. The win32 stdio
- will transform the \n to \r\n and we'll end up with the
- proper line endings on win32. This is a no-op on
- Unix. */
- afx->eol[0] = '\n';
- push_armor_filter (afx, buffer);
- release_armor_context (afx);
-
- /* TODO: Remove Comment: lines from keys exported this
- way? */
-
- if(export_pubkeys_stream (ctrl, buffer,temp,&block,
- opt.keyserver_options.export_options)==-1)
- iobuf_close(buffer);
- else
- {
- KBNODE node;
-
- iobuf_flush_temp(buffer);
-
- merge_keys_and_selfsig(block);
-
- fprintf(spawn->tochild,"INFO %08lX%08lX BEGIN\n",
- (ulong)block->pkt->pkt.public_key->keyid[0],
- (ulong)block->pkt->pkt.public_key->keyid[1]);
-
- for(node=block;node;node=node->next)
- {
- switch(node->pkt->pkttype)
- {
- default:
- continue;
-
- case PKT_PUBLIC_KEY:
- case PKT_PUBLIC_SUBKEY:
- {
- PKT_public_key *pk=node->pkt->pkt.public_key;
-
- keyid_from_pk(pk,NULL);
-
- fprintf(spawn->tochild,"%sb:%08lX%08lX:%u:%u:%u:%u:",
- node->pkt->pkttype==PKT_PUBLIC_KEY?"pu":"su",
- (ulong)pk->keyid[0],(ulong)pk->keyid[1],
- pk->pubkey_algo,
- nbits_from_pk(pk),
- pk->timestamp,
- pk->expiredate);
-
- if(pk->flags.revoked)
- fprintf(spawn->tochild,"r");
- if(pk->has_expired)
- fprintf(spawn->tochild,"e");
-
- fprintf(spawn->tochild,"\n");
- }
- break;
-
- case PKT_USER_ID:
- {
- PKT_user_id *uid=node->pkt->pkt.user_id;
- int r;
-
- if(uid->attrib_data)
- continue;
-
- fprintf(spawn->tochild,"uid:");
-
- /* Quote ':', '%', and any 8-bit
- characters */
- for(r=0;r<uid->len;r++)
- {
- if(uid->name[r]==':' || uid->name[r]=='%'
- || uid->name[r]&0x80)
- fprintf(spawn->tochild,"%%%02X",
- (byte)uid->name[r]);
- else
- fprintf(spawn->tochild,"%c",uid->name[r]);
- }
-
- fprintf(spawn->tochild,":%u:%u:",
- uid->created,uid->expiredate);
-
- if(uid->is_revoked)
- fprintf(spawn->tochild,"r");
- if(uid->is_expired)
- fprintf(spawn->tochild,"e");
-
- fprintf(spawn->tochild,"\n");
- }
- break;
-
- /* This bit is really for the benefit of
- people who store their keys in LDAP
- servers. It makes it easy to do queries
- for things like "all keys signed by
- Isabella". */
- case PKT_SIGNATURE:
- {
- PKT_signature *sig=node->pkt->pkt.signature;
-
- if(!IS_UID_SIG(sig))
- continue;
-
- fprintf(spawn->tochild,"sig:%08lX%08lX:%X:%u:%u\n",
- (ulong)sig->keyid[0],(ulong)sig->keyid[1],
- sig->sig_class,sig->timestamp,
- sig->expiredate);
- }
- break;
- }
- }
-
- fprintf(spawn->tochild,"INFO %08lX%08lX END\n",
- (ulong)block->pkt->pkt.public_key->keyid[0],
- (ulong)block->pkt->pkt.public_key->keyid[1]);
-
- fprintf(spawn->tochild,"KEY %08lX%08lX BEGIN\n",
- (ulong)block->pkt->pkt.public_key->keyid[0],
- (ulong)block->pkt->pkt.public_key->keyid[1]);
- fwrite(iobuf_get_temp_buffer(buffer),
- iobuf_get_temp_length(buffer),1,spawn->tochild);
- fprintf(spawn->tochild,"KEY %08lX%08lX END\n",
- (ulong)block->pkt->pkt.public_key->keyid[0],
- (ulong)block->pkt->pkt.public_key->keyid[1]);
-
- iobuf_close(buffer);
-
- if(keyserver->host)
- log_info(_("sending key %s to %s server %s\n"),
- keystr(block->pkt->pkt.public_key->keyid),
- keyserver->scheme,keyserver->host);
- else
- log_info(_("sending key %s to %s\n"),
- keystr(block->pkt->pkt.public_key->keyid),
- keyserver->uri);
-
- release_kbnode(block);
- }
-
- free_strlist(temp);
- }
-
- break;
- }
-
- case KS_SEARCH:
- {
- strlist_t key;
-
- fprintf(spawn->tochild,"COMMAND SEARCH\n\n");
-
- /* Which keys do we want? Remember that the gpgkeys_ program
- is going to lump these together into a search string. */
-
- for(key=list;key!=NULL;key=key->next)
- {
- fprintf(spawn->tochild,"%s\n",key->d);
- if(key!=list)
- {
- searchstr=xrealloc(searchstr,
- strlen(searchstr)+strlen(key->d)+2);
- strcat(searchstr," ");
- }
- else
- {
- searchstr=xmalloc(strlen(key->d)+1);
- searchstr[0]='\0';
- }
-
- strcat(searchstr,key->d);
- }
-
- fprintf(spawn->tochild,"\n");
-
- if(keyserver->host)
- log_info(_("searching for \"%s\" from %s server %s\n"),
- searchstr,keyserver->scheme,keyserver->host);
- else
- log_info(_("searching for \"%s\" from %s\n"),
- searchstr,keyserver->uri);
-
- break;
- }
+ char *str = line + 5;
+ char *tok;
- default:
- log_fatal(_("no keyserver action!\n"));
- break;
+ if ((tok = strsep (&str, ":")))
+ {
+ int version;
+
+ if (sscanf (tok, "%d", &version) !=1 )
+ version = 1;
+
+ if (version !=1 )
+ {
+ log_error (_("invalid keyserver protocol "
+ "(us %d!=handler %d)\n"), 1, version);
+ return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
+ }
+ }
+
+ if ((tok = strsep (&str, ":"))
+ && sscanf (tok, "%d", &parm->count) == 1)
+ {
+ if (!parm->count)
+ parm->not_found = 1;/* Server indicated that no items follow. */
+ else if (parm->count < 0)
+ parm->count = 10; /* Bad value - assume something reasonable. */
+ else
+ parm->validcount = 1; /* COUNT seems to be okay. */
+ }
+
+ parm->any_lines = 1;
+ return 0; /* Line processing finished. */
}
- /* Done sending, so start reading. */
- ret=exec_read(spawn);
- if(ret)
- goto fail;
-
- /* Now handle the response */
-
- for(;;)
+ again:
+ if (line)
+ keyrec = parse_keyrec (line);
+ else
{
- int plen;
- char *ptr;
-
- maxlen=1024;
- if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
- {
- ret = gpg_error_from_syserror ();
- goto fail; /* i.e. EOF */
- }
-
- ptr=line;
-
- /* remove trailing whitespace */
- plen=strlen(ptr);
- while(plen>0 && ascii_isspace(ptr[plen-1]))
- plen--;
- plen[ptr]='\0';
-
- if(*ptr=='\0')
- break;
-
- if(ascii_strncasecmp(ptr,"VERSION ",8)==0)
- {
- gotversion=1;
-
- if(atoi(&ptr[8])!=KEYSERVER_PROTO_VERSION)
- {
- log_error(_("invalid keyserver protocol (us %d!=handler %d)\n"),
- KEYSERVER_PROTO_VERSION,atoi(&ptr[8]));
- goto fail;
- }
- }
- else if(ascii_strncasecmp(ptr,"PROGRAM ",8)==0)
- {
- if(ascii_strncasecmp(&ptr[8],VERSION,strlen(VERSION))!=0)
- log_info(_("WARNING: keyserver handler from a different"
- " version of GnuPG (%s)\n"),&ptr[8]);
- }
- else if(ascii_strncasecmp(ptr,"OPTION OUTOFBAND",16)==0)
- outofband=1; /* Currently the only OPTION */
+ /* Received EOF - flush data */
+ parm->eof_seen = 1;
+ keyrec = parse_keyrec (NULL);
+ if (!keyrec)
+ {
+ if (!parm->nkeys)
+ parm->not_found = 1; /* No keys at all. */
+ else
+ {
+ if (parm->nkeys != parm->count)
+ parm->validcount = 0;
+
+ if (!(opt.with_colons && opt.batch))
+ {
+ err = show_prompt (parm->ctrl, parm->desc, parm->nkeys,
+ parm->validcount? parm->count : 0,
+ parm->searchstr_disp);
+ return err;
+ }
+ }
+ }
}
- if(!gotversion)
+ /* Save the key in the key array. */
+ if (keyrec)
{
- log_error(_("keyserver did not send VERSION\n"));
- goto fail;
+ /* Allocate or enlarge the key array if needed. */
+ if (!parm->desc)
+ {
+ if (parm->count < 1)
+ {
+ parm->count = 10;
+ parm->validcount = 0;
+ }
+ parm->desc = xtrymalloc (parm->count * sizeof *parm->desc);
+ if (!parm->desc)
+ {
+ err = gpg_error_from_syserror ();
+ iobuf_close (keyrec->uidbuf);
+ xfree (keyrec);
+ return err;
+ }
+ }
+ else if (parm->nkeys == parm->count)
+ {
+ /* Keyserver sent more keys than claimed in the info: line. */
+ KEYDB_SEARCH_DESC *tmp;
+ int newcount = parm->count + 10;
+
+ tmp = xtryrealloc (parm->desc, newcount * sizeof *parm->desc);
+ if (!tmp)
+ {
+ err = gpg_error_from_syserror ();
+ iobuf_close (keyrec->uidbuf);
+ xfree (keyrec);
+ return err;
+ }
+ parm->count = newcount;
+ parm->desc = tmp;
+ parm->validcount = 0;
+ }
+
+ parm->desc[parm->nkeys] = keyrec->desc;
+
+ if (!opt.with_colons)
+ {
+ /* SCREEN_LINES - 1 for the prompt. */
+ if (parm->numlines + keyrec->lines > opt.screen_lines - 1)
+ {
+ err = show_prompt (parm->ctrl, parm->desc, parm->nkeys,
+ parm->validcount ? parm->count:0,
+ parm->searchstr_disp);
+ if (err)
+ return err;
+ parm->numlines = 0;
+ }
+
+ print_keyrec (parm->nkeys+1, keyrec);
+ }
+
+ parm->numlines += keyrec->lines;
+ iobuf_close (keyrec->uidbuf);
+ xfree (keyrec);
+
+ parm->any_lines = 1;
+ parm->nkeys++;
+
+ /* If we are here due to a flush after the EOF, run again for
+ the last prompt. Fixme: Make this code better readable. */
+ if (parm->eof_seen)
+ goto again;
}
- if(!outofband)
- switch(action)
- {
- case KS_GET:
- case KS_GETNAME:
- {
- void *stats_handle;
-
- stats_handle=import_new_stats_handle();
-
- /* Slurp up all the key data. In the future, it might be
- nice to look for KEY foo OUTOFBAND and FAILED indicators.
- It's harmless to ignore them, but ignoring them does make
- gpg complain about "no valid OpenPGP data found". One
- way to do this could be to continue parsing this
- line-by-line and make a temp iobuf for each key. */
-
- /* FIXME: Pass CTRL. */
- import_keys_stream (NULL, spawn->fromchild,stats_handle,fpr,fpr_len,
- opt.keyserver_options.import_options);
-
- import_print_stats(stats_handle);
- import_release_stats_handle(stats_handle);
-
- break;
- }
-
- /* Nothing to do here */
- case KS_SEND:
- break;
-
- case KS_SEARCH:
- keyserver_search_prompt (ctrl, spawn->fromchild,searchstr);
- break;
-
- default:
- log_fatal(_("no keyserver action!\n"));
- break;
- }
-
- fail:
- xfree(line);
- xfree(searchstr);
-
-
- *prog=exec_finish(spawn);
-
- return ret;
+ return 0;
}
-static int
-keyserver_work (ctrl_t ctrl,
- enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
- int count,unsigned char **fpr,size_t *fpr_len,
- struct keyserver_spec *keyserver)
-{
- int rc=0,ret=0;
-
- if(!keyserver)
- {
- log_error(_("no keyserver known (use option --keyserver)\n"));
- return G10ERR_BAD_URI;
- }
-
-#ifdef DISABLE_KEYSERVER_HELPERS
-
- log_error(_("external keyserver calls are not supported in this build\n"));
- return G10ERR_KEYSERVER;
-
-#else
- /* Spawn a handler */
-
- rc = keyserver_spawn (ctrl, action, list, desc, count,
- &ret, fpr, fpr_len, keyserver);
- if(ret)
- {
- switch(ret)
- {
- case KEYSERVER_SCHEME_NOT_FOUND:
- log_error(_("no handler for keyserver scheme `%s'\n"),
- keyserver->scheme);
- break;
-
- case KEYSERVER_NOT_SUPPORTED:
- log_error(_("action `%s' not supported with keyserver "
- "scheme `%s'\n"),
- action==KS_GET?"get":action==KS_SEND?"send":
- action==KS_SEARCH?"search":"unknown",
- keyserver->scheme);
- break;
-
- case KEYSERVER_VERSION_ERROR:
- log_error(_(GPGKEYS_PREFIX "%s does not support"
- " handler version %d\n"),
- keyserver_typemap(keyserver->scheme),
- KEYSERVER_PROTO_VERSION);
- break;
-
- case KEYSERVER_TIMEOUT:
- log_error(_("keyserver timed out\n"));
- break;
-
- case KEYSERVER_INTERNAL_ERROR:
- default:
- log_error(_("keyserver internal error\n"));
- break;
- }
-
- return G10ERR_KEYSERVER;
- }
-
- if(rc)
- {
- log_error(_("keyserver communications error: %s\n"),g10_errstr(rc));
-
- return rc;
- }
- return 0;
-#endif /* ! DISABLE_KEYSERVER_HELPERS*/
-}
-int
+int
keyserver_export (ctrl_t ctrl, strlist_t users)
{
gpg_error_t err;
@@ -1628,14 +1014,14 @@ keyserver_export (ctrl_t ctrl, strlist_t users)
if(sl)
{
- rc = keyserver_work (ctrl, KS_SEND,sl,NULL,0,NULL,NULL,opt.keyserver);
+ rc = keyserver_put (ctrl, sl, opt.keyserver);
free_strlist(sl);
}
return rc;
}
-int
+int
keyserver_import (ctrl_t ctrl, strlist_t users)
{
gpg_error_t err;
@@ -1667,8 +1053,7 @@ keyserver_import (ctrl_t ctrl, strlist_t users)
}
if(count>0)
- rc=keyserver_work (ctrl, KS_GET, NULL, desc, count,
- NULL, NULL, opt.keyserver);
+ rc=keyserver_get (ctrl, desc, count, NULL);
xfree(desc);
@@ -1694,10 +1079,10 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
/* TODO: Warn here if the fingerprint we got doesn't match the one
we asked for? */
- return keyserver_work (ctrl, KS_GET, NULL, &desc, 1, NULL, NULL, keyserver);
+ return keyserver_get (ctrl, &desc, 1, keyserver);
}
-int
+int
keyserver_import_keyid (ctrl_t ctrl,
u32 *keyid,struct keyserver_spec *keyserver)
{
@@ -1709,11 +1094,11 @@ keyserver_import_keyid (ctrl_t ctrl,
desc.u.kid[0]=keyid[0];
desc.u.kid[1]=keyid[1];
- return keyserver_work (ctrl, KS_GET,NULL,&desc,1,NULL,NULL,keyserver);
+ return keyserver_get (ctrl, &desc,1, keyserver);
}
/* code mostly stolen from do_export_stream */
-static int
+static int
keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
{
int rc=0,ndesc,num=100;
@@ -1736,13 +1121,13 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
}
else
{
- for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
+ for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
;
desc = xmalloc ( ndesc * sizeof *desc);
-
+
for (ndesc=0, sl=users; sl; sl = sl->next)
{
- gpg_error_t err;
+ gpg_error_t err;
if (!(err = classify_user_id (sl->d, desc+ndesc)))
ndesc++;
else
@@ -1753,7 +1138,7 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
while (!(rc = keydb_search (kdbhd, desc, ndesc)))
{
- if (!users)
+ if (!users)
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
/* read the keyblock */
@@ -1856,7 +1241,7 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
if(rc==-1)
rc=0;
-
+
leave:
if(rc)
xfree(*klist);
@@ -1913,9 +1298,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
/* We use the keyserver structure we parsed out before.
Note that a preferred keyserver without a scheme://
will be interpreted as hkp:// */
-
- rc = keyserver_work (ctrl, KS_GET, NULL, &desc[i], 1,
- NULL, NULL, keyserver);
+ rc = keyserver_get (ctrl, &desc[i], 1, keyserver);
if(rc)
log_info(_("WARNING: unable to refresh key %s"
" via %s: %s\n"),keystr_from_desc(&desc[i]),
@@ -1945,8 +1328,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
count,opt.keyserver->uri);
}
- rc=keyserver_work (ctrl, KS_GET, NULL, desc, numdesc,
- NULL, NULL, opt.keyserver);
+ rc=keyserver_get (ctrl, desc, numdesc, NULL);
}
xfree(desc);
@@ -1961,15 +1343,305 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
return rc;
}
-int
+
+/* Search for keys on the keyservers. The patterns are given in the
+ string list TOKENS. */
+gpg_error_t
keyserver_search (ctrl_t ctrl, strlist_t tokens)
{
- if (tokens)
- return keyserver_work (ctrl, KS_SEARCH, tokens, NULL, 0,
- NULL, NULL, opt.keyserver);
- return 0;
+ gpg_error_t err;
+ char *searchstr;
+ struct search_line_handler_parm_s parm;
+
+ memset (&parm, 0, sizeof parm);
+
+ if (!tokens)
+ return 0; /* Return success if no patterns are given. */
+
+ if (!opt.keyserver)
+ {
+ log_error (_("no keyserver known (use option --keyserver)\n"));
+ return gpg_error (GPG_ERR_NO_KEYSERVER);
+ }
+
+ /* Write global options */
+
+ /* for(temp=opt.keyserver_options.other;temp;temp=temp->next) */
+ /* fprintf(spawn->tochild,"OPTION %s\n",temp->d); */
+
+ /* Write per-keyserver options */
+
+ /* for(temp=keyserver->options;temp;temp=temp->next) */
+ /* fprintf(spawn->tochild,"OPTION %s\n",temp->d); */
+
+ {
+ membuf_t mb;
+ strlist_t item;
+
+ init_membuf (&mb, 1024);
+ for (item = tokens; item; item = item->next)
+ {
+ if (item != tokens)
+ put_membuf (&mb, " ", 1);
+ put_membuf_str (&mb, item->d);
+ }
+ put_membuf (&mb, "", 1); /* Append Nul. */
+ searchstr = get_membuf (&mb, NULL);
+ if (!searchstr)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ }
+ /* FIXME: Enable the next line */
+ /* log_info (_("searching for \"%s\" from %s\n"), searchstr, keyserver->uri); */
+
+ parm.ctrl = ctrl;
+ if (searchstr)
+ parm.searchstr_disp = utf8_to_native (searchstr, strlen (searchstr), 0);
+
+ err = gpg_dirmngr_ks_search (ctrl, searchstr, search_line_handler, &parm);
+
+ if (parm.not_found)
+ {
+ if (parm.searchstr_disp)
+ log_info (_("key \"%s\" not found on keyserver\n"),
+ parm.searchstr_disp);
+ else
+ log_info (_("key not found on keyserver\n"));
+ }
+
+ if (gpg_err_code (err) == GPG_ERR_NO_KEYSERVER)
+ log_error (_("no keyserver known (use option --keyserver)\n"));
+ else if (err)
+ log_error ("error searching keyserver: %s\n", gpg_strerror (err));
+
+ /* switch(ret) */
+ /* { */
+ /* case KEYSERVER_SCHEME_NOT_FOUND: */
+ /* log_error(_("no handler for keyserver scheme `%s'\n"), */
+ /* opt.keyserver->scheme); */
+ /* break; */
+
+ /* case KEYSERVER_NOT_SUPPORTED: */
+ /* log_error(_("action `%s' not supported with keyserver " */
+ /* "scheme `%s'\n"), "search", opt.keyserver->scheme); */
+ /* break; */
+
+ /* case KEYSERVER_TIMEOUT: */
+ /* log_error(_("keyserver timed out\n")); */
+ /* break; */
+
+ /* case KEYSERVER_INTERNAL_ERROR: */
+ /* default: */
+ /* log_error(_("keyserver internal error\n")); */
+ /* break; */
+ /* } */
+
+ /* return gpg_error (GPG_ERR_KEYSERVER); */
+
+
+ leave:
+ xfree (parm.desc);
+ xfree (parm.searchstr_disp);
+ xfree(searchstr);
+
+ return err;
}
+
+
+/* Called using:
+
+import_name:
+ rc = keyserver_work (ctrl, KS_GETNAME, list, NULL,
+ 0, fpr, fpr_len, keyserver);
+
+import_ldap:
+ rc = keyserver_work (ctrl, KS_GETNAME, list, NULL,
+ 0, fpr, fpr_len, keyserver);
+
+ */
+
+static gpg_error_t
+keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
+ struct keyserver_spec *keyserver)
+
+{
+ gpg_error_t err = 0;
+ char **pattern;
+ int idx, npat;
+ estream_t datastream;
+
+ /* Create an array filled with a search pattern for each key. The
+ array is delimited by a NULL entry. */
+ pattern = xtrycalloc (ndesc+1, sizeof *pattern);
+ if (!pattern)
+ return gpg_error_from_syserror ();
+ for (npat=idx=0; idx < ndesc; idx++)
+ {
+ int quiet = 0;
+
+ if (desc[idx].mode == KEYDB_SEARCH_MODE_FPR20
+ || desc[idx].mode == KEYDB_SEARCH_MODE_FPR16)
+ {
+ pattern[npat] = xtrymalloc (2+2*20+1);
+ if (!pattern[npat])
+ err = gpg_error_from_syserror ();
+ else
+ {
+ strcpy (pattern[npat], "0x");
+ bin2hex (desc[idx].u.fpr,
+ desc[idx].mode == KEYDB_SEARCH_MODE_FPR20? 20 : 16,
+ pattern[npat]+2);
+ npat++;
+ }
+ }
+ else if(desc[idx].mode == KEYDB_SEARCH_MODE_LONG_KID)
+ {
+ pattern[npat] = xtryasprintf ("0x%08lX%08lX",
+ (ulong)desc[idx].u.kid[0],
+ (ulong)desc[idx].u.kid[1]);
+ if (!pattern[npat])
+ err = gpg_error_from_syserror ();
+ else
+ npat++;
+ }
+ else if(desc[idx].mode == KEYDB_SEARCH_MODE_SHORT_KID)
+ {
+ pattern[npat] = xtryasprintf ("0x%08lX", (ulong)desc[idx].u.kid[1]);
+ if (!pattern[npat])
+ err = gpg_error_from_syserror ();
+ else
+ npat++;
+ }
+ else if(desc[idx].mode == KEYDB_SEARCH_MODE_EXACT)
+ {
+ /* FIXME: We don't need this. It is used as a dummy by
+ keyserver_fetch which passes an entire URL. Better use a
+ separate function here. */
+ pattern[npat] = xtrystrdup ("0x0000000000000000");
+ if (!pattern[npat])
+ err = gpg_error_from_syserror ();
+ else
+ {
+ npat++;
+ quiet = 1;
+ }
+ }
+ else if (desc[idx].mode == KEYDB_SEARCH_MODE_NONE)
+ continue;
+ else
+ BUG();
+
+ if (err)
+ {
+ for (idx=0; idx < npat; idx++)
+ xfree (pattern[idx]);
+ xfree (pattern);
+ return err;
+ }
+
+ if (!quiet && keyserver)
+ {
+ if (keyserver->host)
+ log_info (_("requesting key %s from %s server %s\n"),
+ keystr_from_desc (&desc[idx]),
+ keyserver->scheme, keyserver->host);
+ else
+ log_info (_("requesting key %s from %s\n"),
+ keystr_from_desc (&desc[idx]), keyserver->uri);
+ }
+ }
+
+
+ err = gpg_dirmngr_ks_get (ctrl, pattern, &datastream);
+ for (idx=0; idx < npat; idx++)
+ xfree (pattern[idx]);
+ xfree (pattern);
+ if (!err)
+ {
+ void *stats_handle;
+
+ stats_handle = import_new_stats_handle();
+
+ /* FIXME: Check whether this comment should be moved to dirmngr.
+
+ Slurp up all the key data. In the future, it might be nice
+ to look for KEY foo OUTOFBAND and FAILED indicators. It's
+ harmless to ignore them, but ignoring them does make gpg
+ complain about "no valid OpenPGP data found". One way to do
+ this could be to continue parsing this line-by-line and make
+ a temp iobuf for each key. */
+
+ import_keys_es_stream (ctrl, datastream, stats_handle, NULL, NULL,
+ opt.keyserver_options.import_options);
+
+ import_print_stats (stats_handle);
+ import_release_stats_handle (stats_handle);
+ }
+ es_fclose (datastream);
+
+
+ return err;
+}
+
+
+/* Send all keys specified by KEYSPECS to the KEYSERVERS. */
+static gpg_error_t
+keyserver_put (ctrl_t ctrl, strlist_t keyspecs,
+ struct keyserver_spec *keyserver)
+
+{
+ gpg_error_t err;
+ strlist_t kspec;
+
+ if (!keyspecs)
+ return 0; /* Return success if the list is empty. */
+
+ if (!opt.keyserver)
+ {
+ log_error (_("no keyserver known (use option --keyserver)\n"));
+ return gpg_error (GPG_ERR_NO_KEYSERVER);
+ }
+
+ for (kspec = keyspecs; kspec; kspec = kspec->next)
+ {
+ void *data;
+ size_t datalen;
+ kbnode_t keyblock;
+
+ err = export_pubkey_buffer (ctrl, kspec->d,
+ opt.keyserver_options.export_options,
+ &keyblock, &data, &datalen);
+ if (err)
+ log_error (_("skipped \"%s\": %s\n"), kspec->d, gpg_strerror (err));
+ else
+ {
+ if (keyserver->host)
+ log_info (_("sending key %s to %s server %s\n"),
+ keystr (keyblock->pkt->pkt.public_key->keyid),
+ keyserver->scheme, keyserver->host);
+ else
+ log_info (_("sending key %s to %s\n"),
+ keystr (keyblock->pkt->pkt.public_key->keyid),
+ keyserver->uri);
+
+ err = gpg_dirmngr_ks_put (ctrl, data, datalen, keyblock);
+ release_kbnode (keyblock);
+ xfree (data);
+ if (err)
+ log_error (_("keyserver send failed: %s\n"), gpg_strerror (err));
+ }
+ }
+
+
+ return err;
+
+}
+
+
+
int
keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
{
@@ -1996,7 +1668,7 @@ keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
{
int rc;
- rc = keyserver_work (ctrl, KS_GET, NULL, &desc, 1, NULL, NULL, spec);
+ rc = keyserver_get (ctrl, &desc, 1, spec);
if(rc)
log_info (_("WARNING: unable to fetch URI %s: %s\n"),
sl->d,g10_errstr(rc));
@@ -2139,8 +1811,9 @@ keyserver_import_name (ctrl_t ctrl, const char *name,
append_to_strlist(&list,name);
- rc = keyserver_work (ctrl, KS_GETNAME, list, NULL,
- 0, fpr, fpr_len, keyserver);
+ rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED); /* FIXME */
+ /* keyserver_work (ctrl, KS_GETNAME, list, NULL, */
+ /* 0, fpr, fpr_len, keyserver); */
free_strlist(list);
@@ -2196,7 +1869,7 @@ keyserver_import_ldap (ctrl_t ctrl,
snprintf(port,7,":%u",srvlist[i].port);
strcat(keyserver->host,port);
}
-
+
strcat(keyserver->host," ");
}
@@ -2212,9 +1885,10 @@ keyserver_import_ldap (ctrl_t ctrl,
strcat(keyserver->host,domain);
append_to_strlist(&list,name);
-
- rc = keyserver_work (ctrl, KS_GETNAME, list, NULL,
- 0, fpr, fpr_len, keyserver);
+
+ rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED); /*FIXME*/
+ /* keyserver_work (ctrl, KS_GETNAME, list, NULL, */
+ /* 0, fpr, fpr_len, keyserver); */
free_strlist(list);