diff options
Diffstat (limited to 'g10/keyserver.c')
-rw-r--r-- | g10/keyserver.c | 741 |
1 files changed, 481 insertions, 260 deletions
diff --git a/g10/keyserver.c b/g10/keyserver.c index 60a117d2e..e560d4bfa 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> @@ -46,7 +49,7 @@ #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. @@ -66,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[]= @@ -94,6 +115,10 @@ 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); + /* Reasonable guess */ #define DEFAULT_MAX_CERT_SIZE 16384 @@ -556,6 +581,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; @@ -584,12 +611,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; @@ -665,7 +687,7 @@ parse_keyrec(char *keystring) case 'R': work->flags|=1; break; - + case 'd': case 'D': work->flags|=2; @@ -728,221 +750,245 @@ 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') + if (answer[0]=='q' || answer[0]=='Q') + err = gpg_error (GPG_ERR_CANCELED); + else if (atoi (answer) >= 1 && atoi (answer) <= numdesc) { - xfree(answer); - return 1; - } - 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); + 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; - xfree(answer); - return 1; + { + 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); + } } - return 0; + leave: + xfree (answer); + return err; } -/* 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)); +/* 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) +{ + struct search_line_handler_parm_s *parm = opaque; + gpg_error_t err = 0; + struct keyrec *keyrec; - for(;;) + if (parm->eof_seen && line) { - 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; - - 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; + log_debug ("ooops: unexpected data after EOF\n"); + line = NULL; + } - 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 the received line. */ + if (opt.with_colons && line) + { + log_debug ("%s\n",line); + } - print_keyrec(i+1,keyrec); - } + /* 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)) + { + char *str = line + 5; + char *tok; - numlines+=keyrec->lines; - iobuf_close(keyrec->uidbuf); - xfree(keyrec); + 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. */ + } - started=1; - i++; - } + again: + if (line) + keyrec = parse_keyrec (line); + else + { + /* 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; + } + } + } } - 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) + /* Save the key in the key array. */ + if (keyrec) { - if(localstr) - log_info(_("key \"%s\" not found on keyserver\n"),localstr); - else - log_info(_("key not found on keyserver\n")); + /* 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; } - xfree(localstr); - xfree(desc); - xfree(line); + return 0; } + /* We sometimes want to use a different gpgkeys_xxx for a given protocol (for example, ldaps is handled by gpgkeys_ldap). Map these here. */ @@ -978,7 +1024,7 @@ direct_uri_map(const char *scheme,unsigned int is_direct) #define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\"" #define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" -static int +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, @@ -1019,7 +1065,7 @@ keyserver_spawn (ctrl_t ctrl, 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. + anymore required. set_exec_path(libexecdir); */ #else @@ -1049,7 +1095,7 @@ keyserver_spawn (ctrl_t ctrl, fetcher that can speak that protocol (this is a problem for LDAP). */ - strcat(command,GPGKEYS_PREFIX); + strcat(command,GPGKEYS_PREFIX); strcat(command,scheme); /* This "_uri" thing is in case we need to call a direct handler @@ -1079,7 +1125,7 @@ keyserver_spawn (ctrl_t ctrl, { command=xrealloc(command,strlen(command)+ strlen(KEYSERVER_ARGS_NOKEEP)+1); - strcat(command,KEYSERVER_ARGS_NOKEEP); + strcat(command,KEYSERVER_ARGS_NOKEEP); } ret=exec_write(&spawn,NULL,command,NULL,0,0); @@ -1497,7 +1543,7 @@ keyserver_spawn (ctrl_t ctrl, 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); @@ -1513,7 +1559,7 @@ keyserver_spawn (ctrl_t ctrl, break; case KS_SEARCH: - keyserver_search_prompt (ctrl, spawn->fromchild,searchstr); + //keyserver_search_prompt (ctrl, spawn->fromchild,searchstr); break; default: @@ -1532,7 +1578,9 @@ keyserver_spawn (ctrl_t ctrl, } -static int + + +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, @@ -1596,7 +1644,11 @@ keyserver_work (ctrl_t ctrl, return 0; } -int + + + + +int keyserver_export (ctrl_t ctrl, strlist_t users) { gpg_error_t err; @@ -1629,7 +1681,7 @@ keyserver_export (ctrl_t ctrl, strlist_t users) return rc; } -int +int keyserver_import (ctrl_t ctrl, strlist_t users) { gpg_error_t err; @@ -1661,8 +1713,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); @@ -1688,10 +1739,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) { @@ -1703,11 +1754,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; @@ -1730,13 +1781,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 @@ -1747,7 +1798,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 */ @@ -1850,7 +1901,7 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) if(rc==-1) rc=0; - + leave: if(rc) xfree(*klist); @@ -1907,9 +1958,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]), @@ -1939,8 +1988,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); @@ -1955,16 +2003,18 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users) return rc; } + /* 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) { gpg_error_t err; - int rc=0,ret=0; char *searchstr; + struct search_line_handler_parm_s parm; + + memset (&parm, 0, sizeof parm); - /* FIXME: WORK IN PROGRESS */ if (!tokens) return 0; /* Return success if no patterns are given. */ @@ -1974,31 +2024,6 @@ keyserver_search (ctrl_t ctrl, strlist_t tokens) return gpg_error (GPG_ERR_NO_KEYSERVER); } - /* 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); */ - - /* Write global options */ /* for(temp=opt.keyserver_options.other;temp;temp=temp->next) */ @@ -2009,8 +2034,6 @@ keyserver_search (ctrl_t ctrl, strlist_t tokens) /* for(temp=keyserver->options;temp;temp=temp->next) */ /* fprintf(spawn->tochild,"OPTION %s\n",temp->d); */ - /* Which keys do we want? Remember that the gpgkeys_ program - is going to lump these together into a search string. */ { membuf_t mb; strlist_t item; @@ -2027,28 +2050,226 @@ keyserver_search (ctrl_t ctrl, strlist_t tokens) if (!searchstr) { err = gpg_error_from_syserror (); + goto leave; } } - log_info (_("searching for \"%s\" from %s\n"), searchstr, keyserver->uri); + /* 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); */ - { - estream_t fp; - err = gpg_dirmngr_ks_search (ctrl, searchstr, &fp); - - keyserver_search_prompt (ctrl, fp,searchstr); - } leave: - xfree(line); + xfree (parm.desc); + xfree (parm.searchstr_disp); xfree(searchstr); + return err; +} - *prog=exec_finish(spawn); - return ret; + +/* Called using: + +show_prompt: +import: +import_foo: +refresh: + rc=keyserver_work (ctrl, KS_GET, NULL, desc, count, + NULL, NULL, opt.keyserver); + + +fetch: + rc = keyserver_work (ctrl, KS_GET, NULL, &desc, 1, NULL, NULL, spec); + if(rc) + log_info (_("WARNING: unable to fetch URI %s: %s\n"), + sl->d,g10_errstr(rc)); + + +export: + rc = keyserver_work (ctrl, KS_SEND,sl,NULL,0,NULL,NULL,opt.keyserver); + + + +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; } + + + int keyserver_fetch (ctrl_t ctrl, strlist_t urilist) { @@ -2075,7 +2296,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)); @@ -2275,7 +2496,7 @@ keyserver_import_ldap (ctrl_t ctrl, snprintf(port,7,":%u",srvlist[i].port); strcat(keyserver->host,port); } - + strcat(keyserver->host," "); } @@ -2291,7 +2512,7 @@ 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); |