[RFC 2/2] engine: add "any" engine mechanism and make it the default

James Bottomley James.Bottomley at HansenPartnership.com
Thu Oct 26 18:45:13 AEDT 2017


If openssl cannot load the private key, chances are it's an engine key
(or a corrupt file), so try processing it via any engine first before
concluding corruption.

Signed-off-by: James Bottomley <James.Bottomley at HansenPartnership.com>
---
 ssh-add.c    |  6 ++++--
 ssh-engine.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/ssh-add.c b/ssh-add.c
index d85bcc7ec..b8706866a 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -459,8 +459,10 @@ do_file(int agent_fd, int deleting, int key_only, char *file, int qflag)
 		if (delete_file(agent_fd, file, key_only, qflag) == -1)
 			return -1;
 	} else {
-		if (add_file(agent_fd, file, key_only, qflag) == -1)
-			return -1;
+		if (add_file(agent_fd, file, key_only, qflag) == -1) {
+			if (add_engine_key(agent_fd, file, "any") < 0)
+				return -1;
+		}
 	}
 	return 0;
 }
diff --git a/ssh-engine.c b/ssh-engine.c
index f4673e4ee..53fd1a004 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.12.3


More information about the openssh-unix-dev mailing list