version 1.58, 2014/10/20 03:43:01 |
version 1.59, 2015/01/15 09:40:00 |
|
|
|
|
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "match.h" |
#include "match.h" |
#include "key.h" |
#include "sshkey.h" |
#include "hostfile.h" |
#include "hostfile.h" |
#include "log.h" |
#include "log.h" |
#include "misc.h" |
#include "misc.h" |
|
#include "ssherr.h" |
#include "digest.h" |
#include "digest.h" |
#include "hmac.h" |
#include "hmac.h" |
|
|
|
|
*/ |
*/ |
|
|
int |
int |
hostfile_read_key(char **cpp, int *bitsp, Key *ret) |
hostfile_read_key(char **cpp, u_int *bitsp, struct sshkey *ret) |
{ |
{ |
char *cp; |
char *cp; |
|
int r; |
|
|
/* Skip leading whitespace. */ |
/* Skip leading whitespace. */ |
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) |
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) |
; |
; |
|
|
if (key_read(ret, &cp) != 1) |
if ((r = sshkey_read(ret, &cp)) != 0) |
return 0; |
return 0; |
|
|
/* Skip trailing whitespace. */ |
/* Skip trailing whitespace. */ |
|
|
|
|
/* Return results. */ |
/* Return results. */ |
*cpp = cp; |
*cpp = cp; |
if (bitsp != NULL) { |
if (bitsp != NULL) |
if ((*bitsp = key_size(ret)) <= 0) |
*bitsp = sshkey_size(ret); |
return 0; |
|
} |
|
return 1; |
return 1; |
} |
} |
|
|
static int |
static int |
hostfile_check_key(int bits, const Key *key, const char *host, |
hostfile_check_key(int bits, const struct sshkey *key, const char *host, |
const char *filename, u_long linenum) |
const char *filename, u_long linenum) |
{ |
{ |
#ifdef WITH_SSH1 |
#ifdef WITH_SSH1 |
|
|
u_long linenum = 0, num_loaded = 0; |
u_long linenum = 0, num_loaded = 0; |
char *cp, *cp2, *hashed_host; |
char *cp, *cp2, *hashed_host; |
HostkeyMarker marker; |
HostkeyMarker marker; |
Key *key; |
struct sshkey *key; |
int kbits; |
u_int kbits; |
|
|
if ((f = fopen(path, "r")) == NULL) |
if ((f = fopen(path, "r")) == NULL) |
return; |
return; |
|
|
* 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. |
*/ |
*/ |
key = key_new(KEY_UNSPEC); |
if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { |
|
error("%s: sshkey_new failed", __func__); |
|
break; |
|
} |
if (!hostfile_read_key(&cp, &kbits, key)) { |
if (!hostfile_read_key(&cp, &kbits, key)) { |
key_free(key); |
sshkey_free(key); |
#ifdef WITH_SSH1 |
#ifdef WITH_SSH1 |
key = key_new(KEY_RSA1); |
if ((key = sshkey_new(KEY_RSA1)) == NULL) { |
|
error("%s: sshkey_new failed", __func__); |
|
break; |
|
} |
if (!hostfile_read_key(&cp, &kbits, key)) { |
if (!hostfile_read_key(&cp, &kbits, key)) { |
key_free(key); |
sshkey_free(key); |
continue; |
continue; |
} |
} |
#else |
#else |
|
|
debug3("%s: found %skey type %s in file %s:%lu", __func__, |
debug3("%s: found %skey type %s in file %s:%lu", __func__, |
marker == MRK_NONE ? "" : |
marker == MRK_NONE ? "" : |
(marker == MRK_CA ? "ca " : "revoked "), |
(marker == MRK_CA ? "ca " : "revoked "), |
key_type(key), path, linenum); |
sshkey_type(key), path, linenum); |
hostkeys->entries = xrealloc(hostkeys->entries, |
hostkeys->entries = xrealloc(hostkeys->entries, |
hostkeys->num_entries + 1, sizeof(*hostkeys->entries)); |
hostkeys->num_entries + 1, sizeof(*hostkeys->entries)); |
hostkeys->entries[hostkeys->num_entries].host = xstrdup(host); |
hostkeys->entries[hostkeys->num_entries].host = xstrdup(host); |
|
|
for (i = 0; i < hostkeys->num_entries; i++) { |
for (i = 0; i < hostkeys->num_entries; i++) { |
free(hostkeys->entries[i].host); |
free(hostkeys->entries[i].host); |
free(hostkeys->entries[i].file); |
free(hostkeys->entries[i].file); |
key_free(hostkeys->entries[i].key); |
sshkey_free(hostkeys->entries[i].key); |
explicit_bzero(hostkeys->entries + i, sizeof(*hostkeys->entries)); |
explicit_bzero(hostkeys->entries + i, sizeof(*hostkeys->entries)); |
} |
} |
free(hostkeys->entries); |
free(hostkeys->entries); |
|
|
} |
} |
|
|
static int |
static int |
check_key_not_revoked(struct hostkeys *hostkeys, Key *k) |
check_key_not_revoked(struct hostkeys *hostkeys, struct sshkey *k) |
{ |
{ |
int is_cert = key_is_cert(k); |
int is_cert = sshkey_is_cert(k); |
u_int i; |
u_int i; |
|
|
for (i = 0; i < hostkeys->num_entries; i++) { |
for (i = 0; i < hostkeys->num_entries; i++) { |
if (hostkeys->entries[i].marker != MRK_REVOKE) |
if (hostkeys->entries[i].marker != MRK_REVOKE) |
continue; |
continue; |
if (key_equal_public(k, hostkeys->entries[i].key)) |
if (sshkey_equal_public(k, hostkeys->entries[i].key)) |
return -1; |
return -1; |
if (is_cert && |
if (is_cert && |
key_equal_public(k->cert->signature_key, |
sshkey_equal_public(k->cert->signature_key, |
hostkeys->entries[i].key)) |
hostkeys->entries[i].key)) |
return -1; |
return -1; |
} |
} |
|
|
*/ |
*/ |
static HostStatus |
static HostStatus |
check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, |
check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, |
Key *k, int keytype, const struct hostkey_entry **found) |
struct sshkey *k, int keytype, const struct hostkey_entry **found) |
{ |
{ |
u_int i; |
u_int i; |
HostStatus end_return = HOST_NEW; |
HostStatus end_return = HOST_NEW; |
int want_cert = key_is_cert(k); |
int want_cert = sshkey_is_cert(k); |
HostkeyMarker want_marker = want_cert ? MRK_CA : MRK_NONE; |
HostkeyMarker want_marker = want_cert ? MRK_CA : MRK_NONE; |
int proto = (k ? k->type : keytype) == KEY_RSA1 ? 1 : 2; |
int proto = (k ? k->type : keytype) == KEY_RSA1 ? 1 : 2; |
|
|
|
|
break; |
break; |
} |
} |
if (want_cert) { |
if (want_cert) { |
if (key_equal_public(k->cert->signature_key, |
if (sshkey_equal_public(k->cert->signature_key, |
hostkeys->entries[i].key)) { |
hostkeys->entries[i].key)) { |
/* A matching CA exists */ |
/* A matching CA exists */ |
end_return = HOST_OK; |
end_return = HOST_OK; |
|
|
break; |
break; |
} |
} |
} else { |
} else { |
if (key_equal(k, hostkeys->entries[i].key)) { |
if (sshkey_equal(k, hostkeys->entries[i].key)) { |
end_return = HOST_OK; |
end_return = HOST_OK; |
if (found != NULL) |
if (found != NULL) |
*found = hostkeys->entries + i; |
*found = hostkeys->entries + i; |
|
|
} |
} |
|
|
HostStatus |
HostStatus |
check_key_in_hostkeys(struct hostkeys *hostkeys, Key *key, |
check_key_in_hostkeys(struct hostkeys *hostkeys, struct sshkey *key, |
const struct hostkey_entry **found) |
const struct hostkey_entry **found) |
{ |
{ |
if (key == NULL) |
if (key == NULL) |
|
|
*/ |
*/ |
|
|
int |
int |
add_host_to_hostfile(const char *filename, const char *host, const Key *key, |
add_host_to_hostfile(const char *filename, const char *host, |
int store_hash) |
const struct sshkey *key, int store_hash) |
{ |
{ |
FILE *f; |
FILE *f; |
int success = 0; |
int r, success = 0; |
char *hashed_host = NULL; |
char *hashed_host = NULL; |
|
|
if (key == NULL) |
if (key == NULL) |
|
|
} |
} |
fprintf(f, "%s ", store_hash ? hashed_host : host); |
fprintf(f, "%s ", store_hash ? hashed_host : host); |
|
|
if (key_write(key, f)) { |
if ((r = sshkey_write(key, f)) != 0) { |
|
error("%s: saving key in %s failed: %s", |
|
__func__, filename, ssh_err(r)); |
|
} else |
success = 1; |
success = 1; |
} else { |
fputs("\n", f); |
error("add_host_to_hostfile: saving key in %s failed", filename); |
|
} |
|
fprintf(f, "\n"); |
|
fclose(f); |
fclose(f); |
return success; |
return success; |
} |
} |