[openssh-commits] [openssh] 04/05: upstream commit

git+noreply at mindrot.org git+noreply at mindrot.org
Sun Mar 12 10:51:08 AEDT 2017


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit 1e24552716194db8f2f620587b876158a9ef56ad
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Sat Mar 11 23:40:26 2017 +0000

    upstream commit
    
    allow ssh to use certificates accompanied by a private
    key file but no corresponding plain *.pub public key. bz#2617 based on patch
    from Adam Eijdenberg; ok dtucker@ markus@
    
    Upstream-ID: 295668dca2c39505281577217583ddd2bd4b00b9
---
 sshconnect2.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 52 insertions(+), 15 deletions(-)

diff --git a/sshconnect2.c b/sshconnect2.c
index 2abb866..f8a54be 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.254 2017/02/03 02:56:00 dtucker Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.255 2017/03/11 23:40:26 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Damien Miller.  All rights reserved.
@@ -996,11 +996,11 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
 }
 
 static const char *
-identity_sign_encode(struct identity *id)
+key_sign_encode(const struct sshkey *key)
 {
 	struct ssh *ssh = active_state;
 
-	if (id->key->type == KEY_RSA) {
+	if (key->type == KEY_RSA) {
 		switch (ssh->kex->rsa_sha2) {
 		case 256:
 			return "rsa-sha2-256";
@@ -1008,7 +1008,7 @@ identity_sign_encode(struct identity *id)
 			return "rsa-sha2-512";
 		}
 	}
-	return key_ssh_name(id->key);
+	return key_ssh_name(key);
 }
 
 static int
@@ -1017,31 +1017,50 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
 {
 	Key *prv;
 	int ret;
-	const char *alg;
-
-	alg = identity_sign_encode(id);
 
 	/* the agent supports this key */
-	if (id->agent_fd != -1)
+	if (id->key != NULL && id->agent_fd != -1)
 		return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
-		    data, datalen, alg, compat);
+		    data, datalen, key_sign_encode(id->key), compat);
 
 	/*
 	 * we have already loaded the private key or
 	 * the private key is stored in external hardware
 	 */
-	if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
-		return (sshkey_sign(id->key, sigp, lenp, data, datalen, alg,
-		    compat));
+	if (id->key != NULL &&
+	    (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)))
+		return (sshkey_sign(id->key, sigp, lenp, data, datalen,
+		    key_sign_encode(id->key), compat));
+
 	/* load the private key from the file */
 	if ((prv = load_identity_file(id)) == NULL)
 		return SSH_ERR_KEY_NOT_FOUND;
-	ret = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat);
+	ret = sshkey_sign(prv, sigp, lenp, data, datalen,
+	    key_sign_encode(prv), compat);
 	sshkey_free(prv);
 	return (ret);
 }
 
 static int
+id_filename_matches(Identity *id, Identity *private_id)
+{
+	const char *suffixes[] = { ".pub", "-cert.pub", NULL };
+	size_t len = strlen(id->filename), plen = strlen(private_id->filename);
+	size_t i, slen;
+
+	if (strcmp(id->filename, private_id->filename) == 0)
+		return 1;
+	for (i = 0; suffixes[i]; i++) {
+		slen = strlen(suffixes[i]);
+		if (len > slen && plen == len - slen &&
+		    strcmp(id->filename + (len - slen), suffixes[i]) == 0 &&
+		    memcmp(id->filename, private_id->filename, plen) == 0)
+			return 1;
+	}
+	return 0;
+}
+
+static int
 sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
 {
 	Buffer b;
@@ -1083,7 +1102,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
 	} else {
 		buffer_put_cstring(&b, authctxt->method->name);
 		buffer_put_char(&b, have_sig);
-		buffer_put_cstring(&b, identity_sign_encode(id));
+		buffer_put_cstring(&b, key_sign_encode(id->key));
 	}
 	buffer_put_string(&b, blob, bloblen);
 
@@ -1103,6 +1122,24 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
 				break;
 			}
 		}
+		/*
+		 * Exact key matches are preferred, but also allow
+		 * filename matches for non-PKCS#11/agent keys that
+		 * didn't load public keys. This supports the case
+		 * of keeping just a private key file and public
+		 * certificate on disk.
+		 */
+		if (!matched && !id->isprivate && id->agent_fd == -1 &&
+		    (id->key->flags & SSHKEY_FLAG_EXT) == 0) {
+			TAILQ_FOREACH(private_id, &authctxt->keys, next) {
+				if (private_id->key == NULL &&
+				    id_filename_matches(id, private_id)) {
+					id = private_id;
+					matched = 1;
+					break;
+				}
+			}
+		}
 		if (matched) {
 			debug2("%s: using private key \"%s\"%s for "
 			    "certificate", __func__, id->filename,
@@ -1181,7 +1218,7 @@ send_pubkey_test(Authctxt *authctxt, Identity *id)
 	packet_put_cstring(authctxt->method->name);
 	packet_put_char(have_sig);
 	if (!(datafellows & SSH_BUG_PKAUTH))
-		packet_put_cstring(identity_sign_encode(id));
+		packet_put_cstring(key_sign_encode(id->key));
 	packet_put_string(blob, bloblen);
 	free(blob);
 	packet_send();

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list