aboutsummaryrefslogtreecommitdiffstats
path: root/g10/keyserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/keyserver.c')
-rw-r--r--g10/keyserver.c63
1 files changed, 55 insertions, 8 deletions
diff --git a/g10/keyserver.c b/g10/keyserver.c
index af00401f9..dc49e1b14 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -1062,6 +1062,30 @@ keyserver_retrieval_filter (kbnode_t keyblock, void *opaque)
}
+static const char *
+keyserver_errstr (int code)
+{
+ const char *s;
+
+ switch (code)
+ {
+ case KEYSERVER_OK: s = "success"; break;
+ case KEYSERVER_INTERNAL_ERROR:s = "keyserver helper internal error"; break;
+ case KEYSERVER_NOT_SUPPORTED: s =gpg_strerror (GPG_ERR_NOT_SUPPORTED);break;
+ case KEYSERVER_VERSION_ERROR: s = "keyserver helper version mismatch";break;
+ case KEYSERVER_GENERAL_ERROR: s = "keyserver helper general error"; break;
+ case KEYSERVER_NO_MEMORY: s = "keyserver helper is out of core"; break;
+ case KEYSERVER_KEY_NOT_FOUND: s =gpg_strerror (GPG_ERR_NOT_FOUND); break;
+ case KEYSERVER_KEY_EXISTS: s = "key exists"; break;
+ case KEYSERVER_KEY_INCOMPLETE:s = "key incomplete (EOF)"; break;
+ case KEYSERVER_UNREACHABLE: s =gpg_strerror (GPG_ERR_UNKNOWN_HOST);break;
+ case KEYSERVER_TIMEOUT: s =gpg_strerror (GPG_ERR_TIMEOUT); break;
+ default: s = "?"; break;
+ }
+ return s;
+}
+
+
static int
keyserver_spawn (enum ks_action action, strlist_t list, KEYDB_SEARCH_DESC *desc,
int count, int *prog, unsigned char **fpr, size_t *fpr_len,
@@ -1534,8 +1558,11 @@ keyserver_spawn (enum ks_action action, strlist_t list, KEYDB_SEARCH_DESC *desc,
plen--;
plen[ptr]='\0';
- if(*ptr=='\0')
- break;
+ /* Stop at the first empty line but not if we are sending keys.
+ In the latter case we won't continue reading later and thus
+ we need to watch out for errors right in this loop. */
+ if(*ptr=='\0' && action != KS_SEND)
+ break;
if(ascii_strncasecmp(ptr,"VERSION ",8)==0)
{
@@ -1556,6 +1583,14 @@ keyserver_spawn (enum ks_action action, strlist_t list, KEYDB_SEARCH_DESC *desc,
}
else if(ascii_strncasecmp(ptr,"OPTION OUTOFBAND",16)==0)
outofband=1; /* Currently the only OPTION */
+ else if (action == KS_SEND
+ && ascii_strncasecmp(ptr,"KEY ",4)==0)
+ {
+ ret = parse_key_failed_line (ptr+4, strlen (ptr+4));
+ break; /* We stop at the first KEY line so that we won't
+ run into an EOF which would return an unspecified
+ error message (due to iobuf_read_line). */
+ }
}
if(!gotversion)
@@ -1572,6 +1607,7 @@ keyserver_spawn (enum ks_action action, strlist_t list, KEYDB_SEARCH_DESC *desc,
{
void *stats_handle;
struct ks_retrieval_filter_arg_s filterarg;
+ int gpgkeys_err;
stats_handle=import_new_stats_handle();
@@ -1586,14 +1622,21 @@ keyserver_spawn (enum ks_action action, strlist_t list, KEYDB_SEARCH_DESC *desc,
but we better protect against rogue keyservers. */
filterarg.desc = desc;
filterarg.ndesc = count;
+ gpgkeys_err = 0;
import_keys_stream (spawn->fromchild, stats_handle, fpr, fpr_len,
(opt.keyserver_options.import_options
| IMPORT_NO_SECKEY),
- keyserver_retrieval_filter, &filterarg);
+ keyserver_retrieval_filter, &filterarg,
+ &gpgkeys_err);
import_print_stats(stats_handle);
import_release_stats_handle(stats_handle);
-
+ if (gpgkeys_err)
+ {
+ log_error (_("keyserver communications error: %s\n"),
+ keyserver_errstr (gpgkeys_err));
+ ret = gpgkeys_err;
+ }
break;
}
@@ -1614,7 +1657,6 @@ keyserver_spawn (enum ks_action action, strlist_t list, KEYDB_SEARCH_DESC *desc,
xfree(line);
xfree(searchstr);
-
*prog=exec_finish(spawn);
return ret;
@@ -1641,9 +1683,11 @@ keyserver_work (enum ks_action action, strlist_t list, KEYDB_SEARCH_DESC *desc,
return G10ERR_KEYSERVER;
#else
- /* Spawn a handler */
-
+ /* Spawn a handler. The use of RC and RET is a mess. We use a
+ kludge to return a suitable error message. */
rc=keyserver_spawn(action,list,desc,count,&ret,fpr,fpr_len,keyserver);
+ if (ret == KEYSERVER_INTERNAL_ERROR && rc)
+ ret = rc;
if(ret)
{
switch(ret)
@@ -1672,6 +1716,9 @@ keyserver_work (enum ks_action action, strlist_t list, KEYDB_SEARCH_DESC *desc,
log_error(_("keyserver timed out\n"));
break;
+ case KEYSERVER_UNREACHABLE:
+ return gpg_error (GPG_ERR_UNKNOWN_HOST);
+
case KEYSERVER_INTERNAL_ERROR:
default:
log_error(_("keyserver internal error\n"));
@@ -2136,7 +2183,7 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len)
rc=import_keys_stream (key, NULL, fpr, fpr_len,
(opt.keyserver_options.import_options
- | IMPORT_NO_SECKEY), NULL, NULL);
+ | IMPORT_NO_SECKEY), NULL, NULL, NULL);
opt.no_armor=armor_status;