summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2010-03-04 10:36:04 +0000
committerDamien Miller <djm@cvs.openbsd.org>2010-03-04 10:36:04 +0000
commitc8134fe1bb941fca921afd4b74baf29d690607e8 (patch)
treede00bd5b87eafad54b43aad75afc3262b894094d
parent17325e7478933056d32437401903f5e253bb92a7 (diff)
Add a TrustedUserCAKeys option to sshd_config to specify CA keys that
are trusted to authenticate users (in addition than doing it per-user in authorized_keys). Add a RevokedKeys option to sshd_config and a @revoked marker to known_hosts to allow keys to me revoked and banned for user or host authentication. feedback and ok markus@
-rw-r--r--usr.bin/ssh/auth-rh-rsa.c5
-rw-r--r--usr.bin/ssh/auth-rsa.c5
-rw-r--r--usr.bin/ssh/auth.c31
-rw-r--r--usr.bin/ssh/auth.h3
-rw-r--r--usr.bin/ssh/auth2-hostbased.c5
-rw-r--r--usr.bin/ssh/auth2-pubkey.c53
-rw-r--r--usr.bin/ssh/authfile.c64
-rw-r--r--usr.bin/ssh/authfile.h3
-rw-r--r--usr.bin/ssh/hostfile.c102
-rw-r--r--usr.bin/ssh/hostfile.h5
-rw-r--r--usr.bin/ssh/servconf.c19
-rw-r--r--usr.bin/ssh/servconf.h4
-rw-r--r--usr.bin/ssh/ssh-keygen.c4
-rw-r--r--usr.bin/ssh/ssh.120
-rw-r--r--usr.bin/ssh/sshconnect.c24
-rw-r--r--usr.bin/ssh/sshd_config.525
16 files changed, 331 insertions, 41 deletions
diff --git a/usr.bin/ssh/auth-rh-rsa.c b/usr.bin/ssh/auth-rh-rsa.c
index c5ac7b20a8f..d233e493a46 100644
--- a/usr.bin/ssh/auth-rh-rsa.c
+++ b/usr.bin/ssh/auth-rh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rh-rsa.c,v 1.42 2006/08/03 03:34:41 deraadt Exp $ */
+/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,6 +42,9 @@ auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
{
HostStatus host_status;
+ if (auth_key_is_revoked(client_host_key))
+ return 0;
+
/* Check if we would accept it using rhosts authentication. */
if (!auth_rhosts(pw, cuser))
return 0;
diff --git a/usr.bin/ssh/auth-rsa.c b/usr.bin/ssh/auth-rsa.c
index 338ae7d5b68..f136e65961c 100644
--- a/usr.bin/ssh/auth-rsa.c
+++ b/usr.bin/ssh/auth-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rsa.c,v 1.73 2008/07/02 12:03:51 dtucker Exp $ */
+/* $OpenBSD: auth-rsa.c,v 1.74 2010/03/04 10:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -91,6 +91,9 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
MD5_CTX md;
int len;
+ if (auth_key_is_revoked(key))
+ return 0;
+
/* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
diff --git a/usr.bin/ssh/auth.c b/usr.bin/ssh/auth.c
index 9a745e19dff..19002a6def1 100644
--- a/usr.bin/ssh/auth.c
+++ b/usr.bin/ssh/auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.84 2010/02/09 06:18:46 djm Exp $ */
+/* $OpenBSD: auth.c,v 1.85 2010/03/04 10:36:03 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -55,6 +55,7 @@
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
+#include "authfile.h"
#include "monitor_wrap.h"
/* import */
@@ -464,6 +465,34 @@ getpwnamallow(const char *user)
return (NULL);
}
+/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
+int
+auth_key_is_revoked(Key *key)
+{
+ char *key_fp;
+
+ if (options.revoked_keys_file == NULL)
+ return 0;
+
+ 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;
+ case 1:
+ /* Key revoked */
+ key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ error("%s key %s is revoked", key_type(key), key_fp);
+ xfree(key_fp);
+ return 1;
+ }
+ fatal("key_in_file returned junk");
+}
+
void
auth_debug_add(const char *fmt,...)
{
diff --git a/usr.bin/ssh/auth.h b/usr.bin/ssh/auth.h
index bcadcba159f..d7fbdfba620 100644
--- a/usr.bin/ssh/auth.h
+++ b/usr.bin/ssh/auth.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.h,v 1.64 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: auth.h,v 1.65 2010/03/04 10:36:03 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -148,6 +148,7 @@ char *authorized_keys_file(struct passwd *);
char *authorized_keys_file2(struct passwd *);
FILE *auth_openkeyfile(const char *, struct passwd *, int);
+int auth_key_is_revoked(Key *);
HostStatus
check_key_in_hostfiles(struct passwd *, Key *, const char *,
diff --git a/usr.bin/ssh/auth2-hostbased.c b/usr.bin/ssh/auth2-hostbased.c
index 2c0c375631b..882651cfcc5 100644
--- a/usr.bin/ssh/auth2-hostbased.c
+++ b/usr.bin/ssh/auth2-hostbased.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.12 2008/07/17 08:51:07 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.13 2010/03/04 10:36:03 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -144,6 +144,9 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
HostStatus host_status;
int len;
+ if (auth_key_is_revoked(key))
+ return 0;
+
resolvedname = get_canonical_hostname(options.use_dns);
ipaddr = get_remote_ipaddr();
diff --git a/usr.bin/ssh/auth2-pubkey.c b/usr.bin/ssh/auth2-pubkey.c
index 9b90c39e2e0..bd7df66db03 100644
--- a/usr.bin/ssh/auth2-pubkey.c
+++ b/usr.bin/ssh/auth2-pubkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.20 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.21 2010/03/04 10:36:03 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -55,6 +55,7 @@
#endif
#include "monitor_wrap.h"
#include "misc.h"
+#include "authfile.h"
/* import */
extern ServerOptions options;
@@ -275,6 +276,47 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
return found_key;
}
+/* Authenticate a certificate key against TrustedUserCAKeys */
+static int
+user_cert_trusted_ca(struct passwd *pw, Key *key)
+{
+ char *key_fp, *ca_fp;
+ const char *reason;
+ int ret = 0;
+
+ if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
+ return 0;
+
+ key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ ca_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+
+ if (key_in_file(key->cert->signature_key,
+ options.trusted_user_ca_keys, 1) != 1) {
+ debug2("%s: CA %s %s is not listed in %s", __func__,
+ key_type(key->cert->signature_key), ca_fp,
+ options.trusted_user_ca_keys);
+ goto out;
+ }
+ if (key_cert_check_authority(key, 0, 1, pw->pw_name, &reason) != 0) {
+ error("%s", reason);
+ auth_debug_add("%s", reason);
+ goto out;
+ }
+ if (auth_cert_constraints(&key->cert->constraints, pw) != 0)
+ goto out;
+
+ verbose("%s certificate %s allowed by trusted %s key %s",
+ key_type(key), key_fp, key_type(key->cert->signature_key), ca_fp);
+ ret = 1;
+
+ out:
+ if (key_fp != NULL)
+ xfree(key_fp);
+ if (ca_fp != NULL)
+ xfree(ca_fp);
+ return ret;
+}
+
/* check whether given key is in .ssh/authorized_keys* */
int
user_key_allowed(struct passwd *pw, Key *key)
@@ -282,6 +324,15 @@ user_key_allowed(struct passwd *pw, Key *key)
int success;
char *file;
+ if (auth_key_is_revoked(key))
+ return 0;
+ if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
+ return 0;
+
+ success = user_cert_trusted_ca(pw, key);
+ if (success)
+ return success;
+
file = authorized_keys_file(pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
diff --git a/usr.bin/ssh/authfile.c b/usr.bin/ssh/authfile.c
index 17ca4e809d8..3726f51042f 100644
--- a/usr.bin/ssh/authfile.c
+++ b/usr.bin/ssh/authfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.c,v 1.79 2010/01/12 00:16:47 dtucker Exp $ */
+/* $OpenBSD: authfile.c,v 1.80 2010/03/04 10:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -680,3 +680,65 @@ key_load_public(const char *filename, char **commentp)
key_free(pub);
return NULL;
}
+
+/*
+ * Returns 1 if the specified "key" is listed in the file "filename",
+ * 0 if the key is not listed or -1 on error.
+ * If strict_type is set then the key type must match exactly,
+ * otherwise a comparison that ignores certficiate data is performed.
+ */
+int
+key_in_file(Key *key, const char *filename, int strict_type)
+{
+ FILE *f;
+ char line[SSH_MAX_PUBKEY_BYTES];
+ char *cp;
+ u_long linenum = 0;
+ int ret = 0;
+ Key *pub;
+ int (*key_compare)(const Key *, const Key *) = strict_type ?
+ key_equal : key_equal_public;
+
+ if ((f = fopen(filename, "r")) == NULL) {
+ if (errno == ENOENT) {
+ debug("%s: keyfile \"%s\" missing", __func__, filename);
+ return 0;
+ } else {
+ error("%s: could not open keyfile \"%s\": %s", __func__,
+ filename, strerror(errno));
+ return -1;
+ }
+ }
+
+ while (read_keyfile_line(f, filename, line, sizeof(line),
+ &linenum) != -1) {
+ cp = line;
+
+ /* Skip leading whitespace. */
+ for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
+ ;
+
+ /* Skip comments and empty lines */
+ switch (*cp) {
+ case '#':
+ case '\n':
+ case '\0':
+ continue;
+ }
+
+ pub = key_new(KEY_UNSPEC);
+ if (key_read(pub, &cp) != 1) {
+ key_free(pub);
+ continue;
+ }
+ if (key_compare(key, pub)) {
+ ret = 1;
+ key_free(pub);
+ break;
+ }
+ key_free(pub);
+ }
+ fclose(f);
+ return ret;
+}
+
diff --git a/usr.bin/ssh/authfile.h b/usr.bin/ssh/authfile.h
index a6c74934d69..6dfa478e76e 100644
--- a/usr.bin/ssh/authfile.h
+++ b/usr.bin/ssh/authfile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.h,v 1.13 2006/04/25 08:02:27 dtucker Exp $ */
+/* $OpenBSD: authfile.h,v 1.14 2010/03/04 10:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -22,5 +22,6 @@ Key *key_load_private(const char *, const char *, char **);
Key *key_load_private_type(int, const char *, const char *, char **, int *);
Key *key_load_private_pem(int, int, const char *, char **);
int key_perm_ok(int, const char *);
+int key_in_file(Key *, const char *, int);
#endif
diff --git a/usr.bin/ssh/hostfile.c b/usr.bin/ssh/hostfile.c
index ad52439d54b..4ad5557fede 100644
--- a/usr.bin/ssh/hostfile.c
+++ b/usr.bin/ssh/hostfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.c,v 1.47 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: hostfile.c,v 1.48 2010/03/04 10:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -180,6 +180,41 @@ hostfile_check_key(int bits, const Key *key, const char *host, const char *filen
return 1;
}
+static enum { MRK_ERROR, MRK_NONE, MRK_REVOKE, MRK_CA }
+check_markers(char **cpp)
+{
+ char marker[32], *sp, *cp = *cpp;
+ int ret = MRK_NONE;
+
+ while (*cp == '@') {
+ /* Only one marker is allowed */
+ if (ret != MRK_NONE)
+ return MRK_ERROR;
+ /* Markers are terminated by whitespace */
+ if ((sp = strchr(cp, ' ')) == NULL &&
+ (sp = strchr(cp, '\t')) == NULL)
+ return MRK_ERROR;
+ /* Extract marker for comparison */
+ if (sp <= cp + 1 || sp >= cp + sizeof(marker))
+ return MRK_ERROR;
+ memcpy(marker, cp, sp - cp);
+ marker[sp - cp] = '\0';
+ if (strcmp(marker, CA_MARKER) == 0)
+ ret = MRK_CA;
+ else if (strcmp(marker, REVOKE_MARKER) == 0)
+ ret = MRK_REVOKE;
+ else
+ return MRK_ERROR;
+
+ /* Skip past marker and any whitespace that follows it */
+ cp = sp;
+ for (; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ }
+ *cpp = cp;
+ return ret;
+}
+
/*
* Checks whether the given host (which must be in all lowercase) is already
* in the list of our known hosts. Returns HOST_OK if the host is known and
@@ -192,17 +227,21 @@ hostfile_check_key(int bits, const Key *key, const char *host, const char *filen
static HostStatus
check_host_in_hostfile_by_key_or_type(const char *filename,
- const char *host, const Key *key, int keytype, Key *found, int *numret)
+ const char *host, const Key *key, int keytype, Key *found,
+ int want_revocation, int *numret)
{
FILE *f;
char line[8192];
- int linenum = 0, want_cert = key_is_cert(key);
+ int want, have, linenum = 0, want_cert = key_is_cert(key);
u_int kbits;
char *cp, *cp2, *hashed_host;
HostStatus end_return;
debug3("check_host_in_hostfile: host %s filename %s", host, filename);
+ if (want_revocation && (key == NULL || keytype != 0 || found != NULL))
+ fatal("%s: invalid arguments", __func__);
+
/* Open the file containing the list of known hosts. */
f = fopen(filename, "r");
if (!f)
@@ -226,21 +265,18 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
if (!*cp || *cp == '#' || *cp == '\n')
continue;
- /*
- * Ignore CA keys when looking for raw keys.
- * Ignore raw keys when looking for CA keys.
- */
- if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 &&
- (cp[sizeof(CA_MARKER) - 1] == ' ' ||
- cp[sizeof(CA_MARKER) - 1] == '\t')) {
- if (want_cert) {
- /* Skip the marker and following whitespace */
- cp += sizeof(CA_MARKER);
- for (; *cp == ' ' || *cp == '\t'; cp++)
- ;
- } else
- continue;
- } else if (want_cert)
+ if (want_revocation)
+ want = MRK_REVOKE;
+ else if (want_cert)
+ want = MRK_CA;
+ else
+ want = MRK_NONE;
+
+ if ((have = check_markers(&cp)) == MRK_ERROR) {
+ verbose("%s: invalid marker at %s:%d",
+ __func__, filename, linenum);
+ continue;
+ } else if (want != have)
continue;
/* Find the end of the host name portion. */
@@ -264,6 +300,9 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
/* Got a match. Skip host name. */
cp = cp2;
+ if (want_revocation)
+ found = key_new(KEY_UNSPEC);
+
/*
* Extract the key from the line. This will skip any leading
* whitespace. Ignore badly formatted lines.
@@ -286,6 +325,24 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
if (!hostfile_check_key(kbits, found, host, filename, linenum))
continue;
+ if (want_revocation) {
+ if (key_is_cert(key) &&
+ key_equal_public(key->cert->signature_key, found)) {
+ verbose("check_host_in_hostfile: revoked CA "
+ "line %d", linenum);
+ key_free(found);
+ return HOST_REVOKED;
+ }
+ if (key_equal_public(key, found)) {
+ verbose("check_host_in_hostfile: revoked key "
+ "line %d", linenum);
+ key_free(found);
+ return HOST_REVOKED;
+ }
+ key_free(found);
+ continue;
+ }
+
/* Check if the current key is the same as the given key. */
if (want_cert && key_equal(key->cert->signature_key, found)) {
/* Found CA cert for key */
@@ -322,8 +379,11 @@ check_host_in_hostfile(const char *filename, const char *host, const Key *key,
{
if (key == NULL)
fatal("no key to look up");
- return (check_host_in_hostfile_by_key_or_type(filename, host, key, 0,
- found, numret));
+ if (check_host_in_hostfile_by_key_or_type(filename, host,
+ key, 0, NULL, 1, NULL) == HOST_REVOKED)
+ return HOST_REVOKED;
+ return check_host_in_hostfile_by_key_or_type(filename, host, key, 0,
+ found, 0, numret);
}
int
@@ -331,7 +391,7 @@ lookup_key_in_hostfile_by_type(const char *filename, const char *host,
int keytype, Key *found, int *numret)
{
return (check_host_in_hostfile_by_key_or_type(filename, host, NULL,
- keytype, found, numret) == HOST_FOUND);
+ keytype, found, 0, numret) == HOST_FOUND);
}
/*
diff --git a/usr.bin/ssh/hostfile.h b/usr.bin/ssh/hostfile.h
index ebac1e4f141..1d460c1a915 100644
--- a/usr.bin/ssh/hostfile.h
+++ b/usr.bin/ssh/hostfile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.h,v 1.17 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: hostfile.h,v 1.18 2010/03/04 10:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -15,7 +15,7 @@
#define HOSTFILE_H
typedef enum {
- HOST_OK, HOST_NEW, HOST_CHANGED, HOST_FOUND
+ HOST_OK, HOST_NEW, HOST_CHANGED, HOST_REVOKED, HOST_FOUND
} HostStatus;
int hostfile_read_key(char **, u_int *, Key *);
@@ -29,6 +29,7 @@ int lookup_key_in_hostfile_by_type(const char *, const char *,
#define HASH_DELIM '|'
#define CA_MARKER "@cert-authority"
+#define REVOKE_MARKER "@revoked"
char *host_hash(const char *, const char *, u_int);
diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c
index 941990f7fcc..4b2870ae063 100644
--- a/usr.bin/ssh/servconf.c
+++ b/usr.bin/ssh/servconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.203 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.204 2010/03/04 10:36:03 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -122,6 +122,8 @@ initialize_server_options(ServerOptions *options)
options->adm_forced_command = NULL;
options->chroot_directory = NULL;
options->zero_knowledge_password_authentication = -1;
+ options->revoked_keys_file = NULL;
+ options->trusted_user_ca_keys = NULL;
}
void
@@ -283,6 +285,7 @@ typedef enum {
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
sZeroKnowledgePasswordAuthentication, sHostCertificate,
+ sRevokedKeys, sTrustedUserCAKeys,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -390,6 +393,8 @@ static struct {
{ "forcecommand", sForceCommand, SSHCFG_ALL },
{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
+ { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
+ { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
@@ -1280,6 +1285,14 @@ process_server_config_line(ServerOptions *options, char *line,
*charptr = xstrdup(arg);
break;
+ case sTrustedUserCAKeys:
+ charptr = &options->trusted_user_ca_keys;
+ goto parse_filename;
+
+ case sRevokedKeys:
+ charptr = &options->revoked_keys_file;
+ goto parse_filename;
+
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@@ -1394,6 +1407,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
return;
M_CP_STROPT(adm_forced_command);
M_CP_STROPT(chroot_directory);
+ M_CP_STROPT(trusted_user_ca_keys);
+ M_CP_STROPT(revoked_keys_file);
}
#undef M_CP_INTOPT
@@ -1608,6 +1623,8 @@ dump_config(ServerOptions *o)
dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory);
+ dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
+ dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
diff --git a/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h
index 137da2ac2f2..7c53dec6de2 100644
--- a/usr.bin/ssh/servconf.h
+++ b/usr.bin/ssh/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.91 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.92 2010/03/04 10:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -152,6 +152,8 @@ typedef struct {
int num_permitted_opens;
char *chroot_directory;
+ char *revoked_keys_file;
+ char *trusted_user_ca_keys;
} ServerOptions;
void initialize_server_options(ServerOptions *);
diff --git a/usr.bin/ssh/ssh-keygen.c b/usr.bin/ssh/ssh-keygen.c
index a6ffd83a50d..ce63cc33373 100644
--- a/usr.bin/ssh/ssh-keygen.c
+++ b/usr.bin/ssh/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.180 2010/03/02 23:20:57 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.181 2010/03/04 10:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1292,7 +1292,7 @@ parse_cert_times(char *timespec)
from = xstrdup(timespec);
to = strchr(from, ':');
if (to == NULL || from == to || *(to + 1) == '\0')
- fatal("Invalid certificate life specification %s", optarg);
+ fatal("Invalid certificate life specification %s", timespec);
*to++ = '\0';
if (*from == '-' || *from == '+')
diff --git a/usr.bin/ssh/ssh.1 b/usr.bin/ssh/ssh.1
index 183dc277fc5..e8a4e5953a5 100644
--- a/usr.bin/ssh/ssh.1
+++ b/usr.bin/ssh/ssh.1
@@ -34,8 +34,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.1,v 1.296 2010/02/26 22:09:28 jmc Exp $
-.Dd $Mdocdate: February 26 2010 $
+.\" $OpenBSD: ssh.1,v 1.297 2010/03/04 10:36:03 djm Exp $
+.Dd $Mdocdate: March 4 2010 $
.Dt SSH 1
.Os
.Sh NAME
@@ -1121,6 +1121,22 @@ See the
section of
.Xr ssh-keygen 1
for more details.
+.Pp
+Keys may be also be marked as revoked using the
+.Dq @revoked
+marker.
+Revoked keys will always trigger a warning when encountered and the host
+that presented them will be treated as untrusted.
+For example:
+.Pp
+.Dl @revoked * ssh-rsa AAAAB5W...
+.Pp
+Revoking a key revokes it for direct use and as a certification authority.
+Do not use both the
+.Dq @cert-authority and
+.Dq @revoked
+markers on the same line.
+.Pp
.Sh SSH-BASED VIRTUAL PRIVATE NETWORKS
.Nm
contains support for Virtual Private Network (VPN) tunnelling
diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c
index df5a9bdcb5a..7bf8fbec832 100644
--- a/usr.bin/ssh/sshconnect.c
+++ b/usr.bin/ssh/sshconnect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.c,v 1.219 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.220 2010/03/04 10:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -846,6 +846,25 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
logit("Warning: Permanently added '%.200s' (%s) to the "
"list of known hosts.", hostp, type);
break;
+ case HOST_REVOKED:
+ error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ error("@ WARNING: REVOKED HOST KEY DETECTED! @");
+ error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ error("The %s host key for %s is marked as revoked.", type, host);
+ error("This could mean that a stolen key is being used to");
+ error("impersonate this host.");
+
+ /*
+ * If strict host key checking is in use, the user will have
+ * to edit the key manually and we can only abort.
+ */
+ if (options.strict_host_key_checking) {
+ error("%s host key for %.200s was revoked and you have "
+ "requested strict checking.", type, host);
+ goto fail;
+ }
+ goto continue_unsafe;
+
case HOST_CHANGED:
if (want_cert) {
/*
@@ -895,6 +914,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
goto fail;
}
+ continue_unsafe:
/*
* If strict host key checking has not been requested, allow
* the connection but without MITM-able authentication or
@@ -994,7 +1014,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
return 0;
fail:
- if (want_cert) {
+ if (want_cert && host_status != HOST_REVOKED) {
/*
* No matching certificate. Downgrade cert to raw key and
* search normally.
diff --git a/usr.bin/ssh/sshd_config.5 b/usr.bin/ssh/sshd_config.5
index 3b492a3dbc2..80ce110d3b9 100644
--- a/usr.bin/ssh/sshd_config.5
+++ b/usr.bin/ssh/sshd_config.5
@@ -34,8 +34,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: sshd_config.5,v 1.117 2010/02/26 20:29:54 djm Exp $
-.Dd $Mdocdate: February 26 2010 $
+.\" $OpenBSD: sshd_config.5,v 1.118 2010/03/04 10:36:03 djm Exp $
+.Dd $Mdocdate: March 4 2010 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@@ -815,6 +815,11 @@ Specifies whether public key authentication is allowed.
The default is
.Dq yes .
Note that this option applies to protocol version 2 only.
+.It Cm RevokedKeys
+Specifies a list of revoked public keys.
+Keys listed in this file will be refused for public key authentication.
+Note that if this file is not readable, then public key authentication will
+be refused for all users.
.It Cm RhostsRSAAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication together
with successful RSA host authentication is allowed.
@@ -890,6 +895,22 @@ This avoids infinitely hanging sessions.
.Pp
To disable TCP keepalive messages, the value should be set to
.Dq no .
+.It Cm TrustedUserCAKeys
+Specifies a file containing public keys of certificate authorities that are
+trusted sign user certificates for authentication.
+Keys are listed one per line, empty lines and comments starting with
+.Ql #
+are allowed.
+If a certificate is presented for authentication and has its signing CA key
+listed in this file, then it may be used for authentication for any user
+listed in the certificate's principals list.
+Note that certificates that lack a list of principals will not be permitted
+for authentication using
+.Cm TrustedUserCAKeys .
+For more details in certificates, please see the
+.Sx CERTIFICATES
+section in
+.Xr ssh-keygen 1 .
.It Cm UseDNS
Specifies whether
.Xr sshd 8