Mailing List Archive

[PATCH 2/2] engine: add "any" engine mechanism and make it the default
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@HansenPartnership.com>
---
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@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev