summaryrefslogtreecommitdiffstats
path: root/hostfile.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-03-04 21:53:35 +1100
committerDamien Miller <djm@mindrot.org>2010-03-04 21:53:35 +1100
commit1aed65eb27feec505997c98621bdf158f9ab8b99 (patch)
tree81c2d0b9aff3c2211388ba00cde544e0618750d2 /hostfile.c
parent2befbad9b3c8fc6e4e564c062870229bc722734c (diff)
- 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@
Diffstat (limited to 'hostfile.c')
-rw-r--r--hostfile.c102
1 files changed, 81 insertions, 21 deletions
diff --git a/hostfile.c b/hostfile.c
index fc7f84c7..afab6dad 100644
--- a/hostfile.c
+++ b/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
@@ -183,6 +183,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
@@ -195,17 +230,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)
@@ -229,21 +268,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. */
@@ -267,6 +303,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.
@@ -289,6 +328,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 */
@@ -325,8 +382,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
@@ -334,7 +394,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);
}
/*