- djm@cvs.openbsd.org 2010/03/04 10:36:03

[auth-rh-rsa.c auth-rsa.c auth.c auth.h auth2-hostbased.c auth2-pubkey.c]
     [authfile.c authfile.h hostfile.c hostfile.h servconf.c servconf.h]
     [ssh-keygen.c ssh.1 sshconnect.c sshd_config.5]
     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@
This commit is contained in:
Damien Miller 2010-03-04 21:53:35 +11:00
parent 2befbad9b3
commit 1aed65eb27
17 changed files with 343 additions and 40 deletions

View File

@ -22,6 +22,19 @@
[key.c] [key.c]
use buffer_get_string_ptr_ret() where we are checking the return use buffer_get_string_ptr_ret() where we are checking the return
value explicitly instead of the fatal()-causing buffer_get_string_ptr() value explicitly instead of the fatal()-causing buffer_get_string_ptr()
- djm@cvs.openbsd.org 2010/03/04 10:36:03
[auth-rh-rsa.c auth-rsa.c auth.c auth.h auth2-hostbased.c auth2-pubkey.c]
[authfile.c authfile.h hostfile.c hostfile.h servconf.c servconf.h]
[ssh-keygen.c ssh.1 sshconnect.c sshd_config.5]
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@
20100303 20100303
- (djm) [PROTOCOL.certkeys] Add RCS Ident - (djm) [PROTOCOL.certkeys] Add RCS Ident

View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -44,6 +44,9 @@ auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
{ {
HostStatus host_status; HostStatus host_status;
if (auth_key_is_revoked(client_host_key))
return 0;
/* Check if we would accept it using rhosts authentication. */ /* Check if we would accept it using rhosts authentication. */
if (!auth_rhosts(pw, cuser)) if (!auth_rhosts(pw, cuser))
return 0; return 0;

View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -94,6 +94,9 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
MD5_CTX md; MD5_CTX md;
int len; int len;
if (auth_key_is_revoked(key))
return 0;
/* don't allow short keys */ /* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { 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", error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",

31
auth.c
View File

@ -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. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -69,6 +69,7 @@
#ifdef GSSAPI #ifdef GSSAPI
#include "ssh-gss.h" #include "ssh-gss.h"
#endif #endif
#include "authfile.h"
#include "monitor_wrap.h" #include "monitor_wrap.h"
/* import */ /* import */
@ -582,6 +583,34 @@ getpwnamallow(const char *user)
return (NULL); 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 void
auth_debug_add(const char *fmt,...) auth_debug_add(const char *fmt,...)
{ {

3
auth.h
View File

@ -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. * Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -171,6 +171,7 @@ char *authorized_keys_file(struct passwd *);
char *authorized_keys_file2(struct passwd *); char *authorized_keys_file2(struct passwd *);
FILE *auth_openkeyfile(const char *, struct passwd *, int); FILE *auth_openkeyfile(const char *, struct passwd *, int);
int auth_key_is_revoked(Key *);
HostStatus HostStatus
check_key_in_hostfiles(struct passwd *, Key *, const char *, check_key_in_hostfiles(struct passwd *, Key *, const char *,

View File

@ -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. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -145,6 +145,9 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
HostStatus host_status; HostStatus host_status;
int len; int len;
if (auth_key_is_revoked(key))
return 0;
resolvedname = get_canonical_hostname(options.use_dns); resolvedname = get_canonical_hostname(options.use_dns);
ipaddr = get_remote_ipaddr(); ipaddr = get_remote_ipaddr();

View File

@ -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. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -56,6 +56,7 @@
#endif #endif
#include "monitor_wrap.h" #include "monitor_wrap.h"
#include "misc.h" #include "misc.h"
#include "authfile.h"
/* import */ /* import */
extern ServerOptions options; extern ServerOptions options;
@ -276,6 +277,47 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
return found_key; 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* */ /* check whether given key is in .ssh/authorized_keys* */
int int
user_key_allowed(struct passwd *pw, Key *key) user_key_allowed(struct passwd *pw, Key *key)
@ -283,6 +325,15 @@ user_key_allowed(struct passwd *pw, Key *key)
int success; int success;
char *file; 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); file = authorized_keys_file(pw);
success = user_key_allowed2(pw, key, file); success = user_key_allowed2(pw, key, file);
xfree(file); xfree(file);

View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -692,3 +692,65 @@ key_load_public(const char *filename, char **commentp)
key_free(pub); key_free(pub);
return NULL; 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;
}

View File

@ -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> * 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_type(int, const char *, const char *, char **, int *);
Key *key_load_private_pem(int, int, const char *, char **); Key *key_load_private_pem(int, int, const char *, char **);
int key_perm_ok(int, const char *); int key_perm_ok(int, const char *);
int key_in_file(Key *, const char *, int);
#endif #endif

View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -183,6 +183,41 @@ hostfile_check_key(int bits, const Key *key, const char *host, const char *filen
return 1; 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 * 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 * in the list of our known hosts. Returns HOST_OK if the host is known and
@ -195,17 +230,21 @@ hostfile_check_key(int bits, const Key *key, const char *host, const char *filen
static HostStatus static HostStatus
check_host_in_hostfile_by_key_or_type(const char *filename, 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; FILE *f;
char line[8192]; 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; u_int kbits;
char *cp, *cp2, *hashed_host; char *cp, *cp2, *hashed_host;
HostStatus end_return; HostStatus end_return;
debug3("check_host_in_hostfile: host %s filename %s", host, filename); 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. */ /* Open the file containing the list of known hosts. */
f = fopen(filename, "r"); f = fopen(filename, "r");
if (!f) if (!f)
@ -229,21 +268,18 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
if (!*cp || *cp == '#' || *cp == '\n') if (!*cp || *cp == '#' || *cp == '\n')
continue; continue;
/* if (want_revocation)
* Ignore CA keys when looking for raw keys. want = MRK_REVOKE;
* Ignore raw keys when looking for CA keys. else if (want_cert)
*/ want = MRK_CA;
if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 && else
(cp[sizeof(CA_MARKER) - 1] == ' ' || want = MRK_NONE;
cp[sizeof(CA_MARKER) - 1] == '\t')) {
if (want_cert) { if ((have = check_markers(&cp)) == MRK_ERROR) {
/* Skip the marker and following whitespace */ verbose("%s: invalid marker at %s:%d",
cp += sizeof(CA_MARKER); __func__, filename, linenum);
for (; *cp == ' ' || *cp == '\t'; cp++) continue;
; } else if (want != have)
} else
continue;
} else if (want_cert)
continue; continue;
/* Find the end of the host name portion. */ /* Find the end of the host name portion. */
@ -267,6 +303,9 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
/* Got a match. Skip host name. */ /* Got a match. Skip host name. */
cp = cp2; cp = cp2;
if (want_revocation)
found = key_new(KEY_UNSPEC);
/* /*
* Extract the key from the line. This will skip any leading * Extract the key from the line. This will skip any leading
* whitespace. Ignore badly formatted lines. * whitespace. Ignore badly formatted lines.
@ -289,6 +328,24 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
if (!hostfile_check_key(kbits, found, host, filename, linenum)) if (!hostfile_check_key(kbits, found, host, filename, linenum))
continue; 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. */ /* Check if the current key is the same as the given key. */
if (want_cert && key_equal(key->cert->signature_key, found)) { if (want_cert && key_equal(key->cert->signature_key, found)) {
/* Found CA cert for key */ /* Found CA cert for key */
@ -325,8 +382,11 @@ check_host_in_hostfile(const char *filename, const char *host, const Key *key,
{ {
if (key == NULL) if (key == NULL)
fatal("no key to look up"); fatal("no key to look up");
return (check_host_in_hostfile_by_key_or_type(filename, host, key, 0, if (check_host_in_hostfile_by_key_or_type(filename, host,
found, numret)); 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 int
@ -334,7 +394,7 @@ lookup_key_in_hostfile_by_type(const char *filename, const char *host,
int keytype, Key *found, int *numret) int keytype, Key *found, int *numret)
{ {
return (check_host_in_hostfile_by_key_or_type(filename, host, NULL, return (check_host_in_hostfile_by_key_or_type(filename, host, NULL,
keytype, found, numret) == HOST_FOUND); keytype, found, 0, numret) == HOST_FOUND);
} }
/* /*

View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -15,7 +15,7 @@
#define HOSTFILE_H #define HOSTFILE_H
typedef enum { typedef enum {
HOST_OK, HOST_NEW, HOST_CHANGED, HOST_FOUND HOST_OK, HOST_NEW, HOST_CHANGED, HOST_REVOKED, HOST_FOUND
} HostStatus; } HostStatus;
int hostfile_read_key(char **, u_int *, Key *); 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 HASH_DELIM '|'
#define CA_MARKER "@cert-authority" #define CA_MARKER "@cert-authority"
#define REVOKE_MARKER "@revoked"
char *host_hash(const char *, const char *, u_int); char *host_hash(const char *, const char *, u_int);

View File

@ -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 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -129,6 +129,8 @@ initialize_server_options(ServerOptions *options)
options->adm_forced_command = NULL; options->adm_forced_command = NULL;
options->chroot_directory = NULL; options->chroot_directory = NULL;
options->zero_knowledge_password_authentication = -1; options->zero_knowledge_password_authentication = -1;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
} }
void void
@ -308,6 +310,7 @@ typedef enum {
sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding, sUsePrivilegeSeparation, sAllowAgentForwarding,
sZeroKnowledgePasswordAuthentication, sHostCertificate, sZeroKnowledgePasswordAuthentication, sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys,
sDeprecated, sUnsupported sDeprecated, sUnsupported
} ServerOpCodes; } ServerOpCodes;
@ -427,6 +430,8 @@ static struct {
{ "forcecommand", sForceCommand, SSHCFG_ALL }, { "forcecommand", sForceCommand, SSHCFG_ALL },
{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ NULL, sBadOption, 0 } { NULL, sBadOption, 0 }
}; };
@ -1323,6 +1328,14 @@ process_server_config_line(ServerOptions *options, char *line,
*charptr = xstrdup(arg); *charptr = xstrdup(arg);
break; break;
case sTrustedUserCAKeys:
charptr = &options->trusted_user_ca_keys;
goto parse_filename;
case sRevokedKeys:
charptr = &options->revoked_keys_file;
goto parse_filename;
case sDeprecated: case sDeprecated:
logit("%s line %d: Deprecated option %s", logit("%s line %d: Deprecated option %s",
filename, linenum, arg); filename, linenum, arg);
@ -1437,6 +1450,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
return; return;
M_CP_STROPT(adm_forced_command); M_CP_STROPT(adm_forced_command);
M_CP_STROPT(chroot_directory); M_CP_STROPT(chroot_directory);
M_CP_STROPT(trusted_user_ca_keys);
M_CP_STROPT(revoked_keys_file);
} }
#undef M_CP_INTOPT #undef M_CP_INTOPT
@ -1656,6 +1671,8 @@ dump_config(ServerOptions *o)
dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2); dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
dump_cfg_string(sForceCommand, o->adm_forced_command); dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory); 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 */ /* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level)); dump_cfg_string(sLogLevel, log_level_name(o->log_level));

View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -154,6 +154,8 @@ typedef struct {
int num_permitted_opens; int num_permitted_opens;
char *chroot_directory; char *chroot_directory;
char *revoked_keys_file;
char *trusted_user_ca_keys;
} ServerOptions; } ServerOptions;
void initialize_server_options(ServerOptions *); void initialize_server_options(ServerOptions *);

View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland

20
ssh.1
View File

@ -34,8 +34,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" 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 $ .\" $OpenBSD: ssh.1,v 1.297 2010/03/04 10:36:03 djm Exp $
.Dd $Mdocdate: February 26 2010 $ .Dd $Mdocdate: March 4 2010 $
.Dt SSH 1 .Dt SSH 1
.Os .Os
.Sh NAME .Sh NAME
@ -1121,6 +1121,22 @@ See the
section of section of
.Xr ssh-keygen 1 .Xr ssh-keygen 1
for more details. 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 .Sh SSH-BASED VIRTUAL PRIVATE NETWORKS
.Nm .Nm
contains support for Virtual Private Network (VPN) tunnelling contains support for Virtual Private Network (VPN) tunnelling

View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -859,6 +859,25 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
logit("Warning: Permanently added '%.200s' (%s) to the " logit("Warning: Permanently added '%.200s' (%s) to the "
"list of known hosts.", hostp, type); "list of known hosts.", hostp, type);
break; 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: case HOST_CHANGED:
if (want_cert) { if (want_cert) {
/* /*
@ -908,6 +927,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
goto fail; goto fail;
} }
continue_unsafe:
/* /*
* If strict host key checking has not been requested, allow * If strict host key checking has not been requested, allow
* the connection but without MITM-able authentication or * the connection but without MITM-able authentication or
@ -1007,7 +1027,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
return 0; return 0;
fail: fail:
if (want_cert) { if (want_cert && host_status != HOST_REVOKED) {
/* /*
* No matching certificate. Downgrade cert to raw key and * No matching certificate. Downgrade cert to raw key and
* search normally. * search normally.

View File

@ -34,8 +34,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" 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 $ .\" $OpenBSD: sshd_config.5,v 1.118 2010/03/04 10:36:03 djm Exp $
.Dd $Mdocdate: February 26 2010 $ .Dd $Mdocdate: March 4 2010 $
.Dt SSHD_CONFIG 5 .Dt SSHD_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -814,6 +814,11 @@ Specifies whether public key authentication is allowed.
The default is The default is
.Dq yes . .Dq yes .
Note that this option applies to protocol version 2 only. 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 .It Cm RhostsRSAAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication together Specifies whether rhosts or /etc/hosts.equiv authentication together
with successful RSA host authentication is allowed. with successful RSA host authentication is allowed.
@ -889,6 +894,22 @@ This avoids infinitely hanging sessions.
.Pp .Pp
To disable TCP keepalive messages, the value should be set to To disable TCP keepalive messages, the value should be set to
.Dq no . .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 .It Cm UseDNS
Specifies whether Specifies whether
.Xr sshd 8 .Xr sshd 8