version 1.47, 2010/02/26 20:29:54 |
version 1.48, 2010/03/04 10:36:03 |
|
|
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 |
|
|
|
|
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) |
|
|
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++) |
|
; |
|
} else |
|
continue; |
|
} else if (want_cert) |
|
continue; |
continue; |
|
} else if (want != have) |
|
continue; |
|
|
/* Find the end of the host name portion. */ |
/* Find the end of the host name portion. */ |
for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) |
for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) |
|
|
/* 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. |
|
|
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 */ |
|
|
{ |
{ |
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 |
|
|
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); |
} |
} |
|
|
/* |
/* |