If openssl cannot load the private key, chances are it's an engine key (or a corrupt file), so try processing it via all the available openssl engines first before concluding corruption. The reason for doing this is to make the -o <engine> specifier optional, which means that gnome-keyring-daemon can treat engine based openssh keys in exactly the same way as it does ordinary ones. Not specifying the engine does incur some overhead in finding exactly which engine handles the key, but most installations only have a small number of engines available, so it's not really noticeable. Signed-off-by: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> --- ssh-add.c | 8 ++++++++ ssh-engine.c | 51 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/ssh-add.c b/ssh-add.c index e988023a7..92c324740 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -259,6 +259,14 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, /* At first, try empty passphrase */ if ((r = sshkey_parse_private_fileblob(keyblob, "", &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) { + int n_r = add_engine_key(agent_fd, filename, "any"); + if (n_r == SSH_AGENT_SUCCESS) { + clear_pass(); + sshbuf_free(keyblob); + return 0; + } else if (n_r != SSH_ERR_INTERNAL_ERROR) { + r = n_r; + } fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); goto fail_load; diff --git a/ssh-engine.c b/ssh-engine.c index 90150c543..b13f9e298 100644 --- a/ssh-engine.c +++ b/ssh-engine.c @@ -37,29 +37,23 @@ ui_read(UI *ui, UI_STRING *uis) return d->ret; } -int -engine_process_add(char *engine, char *file, char *pin, - struct sshkey **k) +static int +engine_process_add_internal(ENGINE *e, char *file, char *pin, + struct sshkey **k) { EVP_PKEY *pk; - ENGINE *e; struct sshkey *key; int ret; UI_METHOD *ui; EVP_PKEY_CTX *ctx; char hash[SHA256_DIGEST_LENGTH], result[1024]; size_t siglen; + const char *engine = ENGINE_get_name(e); struct ui_data d; verbose("%s: add provider=%s, key=%s", __func__, engine, file); ret = SSH_ERR_INTERNAL_ERROR; - e = ENGINE_by_id(engine); - if (!e) { - verbose("%s: failed to get engine %s", __func__, engine); - ERR_print_errors_fp(stderr); - return ret; - } ui = UI_create_method("ssh-agent password writer"); if (!ui) { @@ -152,3 +146,40 @@ engine_process_add(char *engine, char *file, char *pin, verbose("%s: returning %d", __func__, ret); return ret; } + +int +engine_process_add(char *engine, char *file, char *pin, + struct sshkey **k) +{ + ENGINE *e; + + if (strcmp(engine, "any") != 0) { + int ret; + + e = ENGINE_by_id(engine); + if (!e) { + verbose("%s: failed to get engine %s", __func__, engine); + ERR_print_errors_fp(stderr); + return SSH_ERR_INTERNAL_ERROR; + } + ret = engine_process_add_internal(e, file, pin, k); + ENGINE_free(e); + return ret; + } + + /* this is the any engine case */ + + for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { + int ret; + + if (!ENGINE_get_load_privkey_function(e)) + continue; + + ret = engine_process_add_internal(e, file, pin, k); + + if (ret == 1 || ret == SSH_ERR_KEY_WRONG_PASSPHRASE) + return ret; + } + + return SSH_ERR_INTERNAL_ERROR; +} -- 2.16.4 _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev