[openssh-commits] [openssh] 03/06: upstream commit

git+noreply at mindrot.org git+noreply at mindrot.org
Fri Dec 5 09:31:30 EST 2014


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

djm pushed a commit to branch master
in repository openssh.

commit 5e39a49930d885aac9c76af3129332b6e772cd75
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Thu Dec 4 02:24:32 2014 +0000

    upstream commit
    
    add RevokedHostKeys option for the client
    
    Allow textfile or KRL-based revocation of hostkeys.
---
 auth.c         | 62 ++++++++++++++++++++++++++------------------------------
 auth2-pubkey.c |  6 +++---
 authfile.c     | 58 +++++++++++++++++++++++++++++++++++++++++++---------
 authfile.h     |  5 +++--
 readconf.c     | 12 +++++++++--
 readconf.h     |  4 +++-
 ssh_config.5   | 14 +++++++++++--
 sshconnect.c   | 64 ++++++++++++++++++++++++++++++++++++++++++----------------
 8 files changed, 155 insertions(+), 70 deletions(-)

diff --git a/auth.c b/auth.c
index 5e60682..348ddc3 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.106 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: auth.c,v 1.107 2014/12/04 02:24:32 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -71,7 +71,8 @@
 #endif
 #include "authfile.h"
 #include "monitor_wrap.h"
-#include "krl.h"
+#include "authfile.h"
+#include "ssherr.h"
 #include "compat.h"
 
 /* import */
@@ -673,43 +674,38 @@ getpwnamallow(const char *user)
 int
 auth_key_is_revoked(Key *key)
 {
-#ifdef WITH_OPENSSL
-	char *key_fp;
+	char *fp = NULL;
+	int r;
 
 	if (options.revoked_keys_file == NULL)
 		return 0;
-	switch (ssh_krl_file_contains_key(options.revoked_keys_file, key)) {
+	if ((fp = sshkey_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX)) == NULL) {
+		r = SSH_ERR_ALLOC_FAIL;
+		error("%s: fingerprint key: %s", __func__, ssh_err(r));
+		goto out;
+	}
+
+	r = sshkey_check_revoked(key, options.revoked_keys_file);
+	switch (r) {
 	case 0:
-		return 0;	/* Not revoked */
-	case -2:
-		break;		/* Not a KRL */
+		break; /* not revoked */
+	case SSH_ERR_KEY_REVOKED:
+		error("Authentication key %s %s revoked by file %s",
+		    sshkey_type(key), fp, options.revoked_keys_file);
+		goto out;
 	default:
-		goto revoked;
+		error("Error checking authentication key %s %s in "
+		    "revoked keys file %s: %s", sshkey_type(key), fp,
+		    options.revoked_keys_file, ssh_err(r));
+		goto out;
 	}
-#endif
-	debug3("%s: treating %s as a key list", __func__,
-	    options.revoked_keys_file);
-	switch (key_in_file(key, options.revoked_keys_file, 0)) {
-	case 0:
-		/* key not revoked */
-		return 0;
-	case -1:
-		/* Error opening revoked_keys_file: refuse all keys */
-		error("Revoked keys file is unreadable: refusing public key "
-		    "authentication");
-		return 1;
-#ifdef WITH_OPENSSL
-	case 1:
- revoked:
-		/* Key revoked */
-		key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
-		error("WARNING: authentication attempt with a revoked "
-		    "%s key %s ", key_type(key), key_fp);
-		free(key_fp);
-		return 1;
-#endif
-	}
-	fatal("key_in_file returned junk");
+
+	/* Success */
+	r = 0;
+
+ out:
+	free(fp);
+	return r == 0 ? 0 : 1;
 }
 
 void
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index f3ca965..0a3c1de 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.42 2014/12/04 02:24:32 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -434,8 +434,8 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
 	ca_fp = key_fingerprint(key->cert->signature_key,
 	    SSH_FP_MD5, SSH_FP_HEX);
 
-	if (key_in_file(key->cert->signature_key,
-	    options.trusted_user_ca_keys, 1) != 1) {
+	if (sshkey_in_file(key->cert->signature_key,
+	    options.trusted_user_ca_keys, 1, 0) != 0) {
 		debug2("%s: CA %s %s is not listed in %s", __func__,
 		    key_type(key->cert->signature_key), ca_fp,
 		    options.trusted_user_ca_keys);
diff --git a/authfile.c b/authfile.c
index e93d867..95877e1 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.c,v 1.107 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: authfile.c,v 1.108 2014/12/04 02:24:32 djm Exp $ */
 /*
  * Copyright (c) 2000, 2013 Markus Friedl.  All rights reserved.
  *
@@ -48,6 +48,7 @@
 #include "atomicio.h"
 #include "sshbuf.h"
 #include "ssherr.h"
+#include "krl.h"
 
 #define MAX_KEY_FILE_SIZE	(1024 * 1024)
 
@@ -494,11 +495,14 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
 /*
  * Returns success if the specified "key" is listed in the file "filename",
  * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
- * If strict_type is set then the key type must match exactly,
+ * If "strict_type" is set then the key type must match exactly,
  * otherwise a comparison that ignores certficiate data is performed.
+ * If "check_ca" is set and "key" is a certificate, then its CA key is
+ * also checked and sshkey_in_file() will return success if either is found.
  */
 int
-sshkey_in_file(struct sshkey *key, const char *filename, int strict_type)
+sshkey_in_file(struct sshkey *key, const char *filename, int strict_type,
+    int check_ca)
 {
 	FILE *f;
 	char line[SSH_MAX_PUBKEY_BYTES];
@@ -509,12 +513,8 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type)
 	int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
 	    strict_type ?  sshkey_equal : sshkey_equal_public;
 
-	if ((f = fopen(filename, "r")) == NULL) {
-		if (errno == ENOENT)
-			return SSH_ERR_KEY_NOT_FOUND;
-		else
-			return SSH_ERR_SYSTEM_ERROR;
-	}
+	if ((f = fopen(filename, "r")) == NULL)
+		return SSH_ERR_SYSTEM_ERROR;
 
 	while (read_keyfile_line(f, filename, line, sizeof(line),
 	    &linenum) != -1) {
@@ -538,7 +538,9 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type)
 		}
 		if ((r = sshkey_read(pub, &cp)) != 0)
 			goto out;
-		if (sshkey_compare(key, pub)) {
+		if (sshkey_compare(key, pub) ||
+		    (check_ca && sshkey_is_cert(key) &&
+		    sshkey_compare(key->cert->signature_key, pub))) {
 			r = 0;
 			goto out;
 		}
@@ -553,3 +555,39 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type)
 	return r;
 }
 
+/*
+ * Checks whether the specified key is revoked, returning 0 if not,
+ * SSH_ERR_KEY_REVOKED if it is or another error code if something
+ * unexpected happened.
+ * This will check both the key and, if it is a certificate, its CA key too.
+ * "revoked_keys_file" may be a KRL or a one-per-line list of public keys.
+ */
+int
+sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file)
+{
+	int r;
+
+#ifdef WITH_OPENSSL
+	r = ssh_krl_file_contains_key(revoked_keys_file, key);
+	/* If this was not a KRL to begin with then continue below */
+	if (r != SSH_ERR_KRL_BAD_MAGIC)
+		return r;
+#endif
+
+	/*
+	 * If the file is not a KRL or we can't handle KRLs then attempt to
+	 * parse the file as a flat list of keys.
+	 */
+	switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) {
+	case 0:
+		/* Key found => revoked */
+		return SSH_ERR_KEY_REVOKED;
+	case SSH_ERR_KEY_NOT_FOUND:
+		/* Key not found => not revoked */
+		return 0;
+	default:
+		/* Some other error occurred */
+		return r;
+	}
+}
+
diff --git a/authfile.h b/authfile.h
index 03bc395..645404e 100644
--- a/authfile.h
+++ b/authfile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.h,v 1.19 2014/07/03 23:18:35 djm Exp $ */
+/* $OpenBSD: authfile.h,v 1.20 2014/12/04 02:24:32 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2013 Markus Friedl.  All rights reserved.
@@ -42,6 +42,7 @@ int sshkey_load_private_type(int, const char *, const char *,
     struct sshkey **, char **, int *);
 int sshkey_load_private_pem(int, int, const char *, struct sshkey **, char **);
 int sshkey_perm_ok(int, const char *);
-int sshkey_in_file(struct sshkey *, const char *, int);
+int sshkey_in_file(struct sshkey *, const char *, int, int);
+int sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file);
 
 #endif
diff --git a/readconf.c b/readconf.c
index 922c574..e038693 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.222 2014/10/24 02:01:20 lteo Exp $ */
+/* $OpenBSD: readconf.c,v 1.223 2014/12/04 02:24:32 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -154,7 +154,7 @@ typedef enum {
 	oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
-	oStreamLocalBindMask, oStreamLocalBindUnlink,
+	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
 	oIgnoredUnknownOption, oDeprecated, oUnsupported
 } OpCodes;
 
@@ -269,6 +269,7 @@ static struct {
 	{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
 	{ "streamlocalbindmask", oStreamLocalBindMask },
 	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
+	{ "revokedhostkeys", oRevokedHostKeys },
 	{ "ignoreunknown", oIgnoreUnknown },
 
 	{ NULL, oBadOption }
@@ -1455,6 +1456,10 @@ parse_int:
 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
 		goto parse_flag;
 
+	case oRevokedHostKeys:
+		charptr = &options->revoked_host_keys;
+		goto parse_string;
+
 	case oDeprecated:
 		debug("%s line %d: Deprecated option \"%s\"",
 		    filename, linenum, keyword);
@@ -1631,6 +1636,7 @@ initialize_options(Options * options)
 	options->canonicalize_max_dots = -1;
 	options->canonicalize_fallback_local = -1;
 	options->canonicalize_hostname = -1;
+	options->revoked_host_keys = NULL;
 }
 
 /*
@@ -1818,6 +1824,7 @@ fill_default_options(Options * options)
 	CLEAR_ON_NONE(options->local_command);
 	CLEAR_ON_NONE(options->proxy_command);
 	CLEAR_ON_NONE(options->control_path);
+	CLEAR_ON_NONE(options->revoked_host_keys);
 	/* options->user will be set in the main program if appropriate */
 	/* options->hostname will be set in the main program if appropriate */
 	/* options->host_key_alias should not be set by default */
@@ -2251,6 +2258,7 @@ dump_client_config(Options *o, const char *host)
 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
 	dump_cfg_string(oProxyCommand, o->proxy_command);
 	dump_cfg_string(oXAuthLocation, o->xauth_location);
+	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
 
 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
diff --git a/readconf.h b/readconf.h
index 7b58d01..49858bf 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.103 2014/10/08 22:20:25 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.104 2014/12/04 02:24:32 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
@@ -144,6 +144,8 @@ typedef struct {
 	int	num_permitted_cnames;
 	struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS];
 
+	char	*revoked_host_keys;
+
 	char	*ignored_unknown; /* Pattern list of unknown tokens to ignore */
 }       Options;
 
diff --git a/ssh_config.5 b/ssh_config.5
index d8f980b..f0a4b29 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: ssh_config.5,v 1.195 2014/11/10 22:25:49 djm Exp $
-.Dd $Mdocdate: November 10 2014 $
+.\" $OpenBSD: ssh_config.5,v 1.196 2014/12/04 02:24:32 djm Exp $
+.Dd $Mdocdate: December 4 2014 $
 .Dt SSH_CONFIG 5
 .Os
 .Sh NAME
@@ -1253,6 +1253,16 @@ and
 .Fl T
 flags for
 .Xr ssh 1 .
+.It Cm RevokedHostKeys
+Specifies revoked host public keys.
+Keys listed in this file will be refused for host authentication.
+Note that if this file does not exist or is not readable,
+then host authentication will be refused for all hosts.
+Keys may be specified as a text file, listing one public key per line, or as
+an OpenSSH Key Revocation List (KRL) as generated by
+.Xr ssh-keygen 1 .
+For more information on KRLs, see the KEY REVOCATION LISTS section in
+.Xr ssh-keygen 1 .
 .It Cm RhostsRSAAuthentication
 Specifies whether to try rhosts based authentication with RSA host
 authentication.
diff --git a/sshconnect.c b/sshconnect.c
index ac09eae..f9a5937 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.252 2014/12/04 02:24:32 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -62,6 +62,8 @@
 #include "monitor_fdpass.h"
 #include "ssh2.h"
 #include "version.h"
+#include "authfile.h"
+#include "ssherr.h"
 
 char *client_version_string = NULL;
 char *server_version_string = NULL;
@@ -1219,16 +1221,44 @@ int
 verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
 {
 	int r = -1, flags = 0;
-	char *fp;
-	Key *plain = NULL;
+	char *fp = NULL;
+	struct sshkey *plain = NULL;
 
-	fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
-	debug("Server host key: %s %s", key_type(host_key), fp);
-	free(fp);
+	if ((fp = sshkey_fingerprint(host_key,
+	    SSH_FP_MD5, SSH_FP_HEX)) == NULL) {
+		error("%s: fingerprint host key: %s", __func__, ssh_err(r));
+		r = -1;
+		goto out;
+	}
 
-	if (key_equal(previous_host_key, host_key)) {
-		debug("%s: server host key matches cached key", __func__);
-		return 0;
+	debug("Server host key: %s %s", sshkey_type(host_key), fp);
+
+	if (sshkey_equal(previous_host_key, host_key)) {
+		debug2("%s: server host key %s %s matches cached key",
+		    __func__, sshkey_type(host_key), fp);
+		r = 0;
+		goto out;
+	}
+
+	/* Check in RevokedHostKeys file if specified */
+	if (options.revoked_host_keys != NULL) {
+		r = sshkey_check_revoked(host_key, options.revoked_host_keys);
+		switch (r) {
+		case 0:
+			break; /* not revoked */
+		case SSH_ERR_KEY_REVOKED:
+			error("Host key %s %s revoked by file %s",
+			    sshkey_type(host_key), fp,
+			    options.revoked_host_keys);
+			r = -1;
+			goto out;
+		default:
+			error("Error checking host key %s %s in "
+			    "revoked keys file %s: %s", sshkey_type(host_key),
+			    fp, options.revoked_host_keys, ssh_err(r));
+			r = -1;
+			goto out;
+		}
 	}
 
 	if (options.verify_host_key_dns) {
@@ -1236,17 +1266,17 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
 		 * XXX certs are not yet supported for DNS, so downgrade
 		 * them and try the plain key.
 		 */
-		plain = key_from_private(host_key);
-		if (key_is_cert(plain))
-			key_drop_cert(plain);
+		if ((r = sshkey_from_private(host_key, &plain)) != 0)
+			goto out;
+		if (sshkey_is_cert(plain))
+			sshkey_drop_cert(plain);
 		if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) {
 			if (flags & DNS_VERIFY_FOUND) {
 				if (options.verify_host_key_dns == 1 &&
 				    flags & DNS_VERIFY_MATCH &&
 				    flags & DNS_VERIFY_SECURE) {
-					key_free(plain);
 					r = 0;
-					goto done;
+					goto out;
 				}
 				if (flags & DNS_VERIFY_MATCH) {
 					matching_host_key_dns = 1;
@@ -1258,14 +1288,14 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
 				}
 			}
 		}
-		key_free(plain);
 	}
-
 	r = check_host_key(host, hostaddr, options.port, host_key, RDRW,
 	    options.user_hostfiles, options.num_user_hostfiles,
 	    options.system_hostfiles, options.num_system_hostfiles);
 
-done:
+out:
+	sshkey_free(plain);
+	free(fp);
 	if (r == 0 && host_key != NULL) {
 		key_free(previous_host_key);
 		previous_host_key = key_from_private(host_key);

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


More information about the openssh-commits mailing list