version 1.32, 2003/11/10 16:23:41 |
version 1.32.4.1, 2005/03/10 16:28:27 |
|
|
#include "includes.h" |
#include "includes.h" |
RCSID("$OpenBSD$"); |
RCSID("$OpenBSD$"); |
|
|
|
#include <resolv.h> |
|
#include <openssl/hmac.h> |
|
#include <openssl/sha.h> |
|
|
#include "packet.h" |
#include "packet.h" |
#include "match.h" |
#include "match.h" |
#include "key.h" |
#include "key.h" |
#include "hostfile.h" |
#include "hostfile.h" |
#include "log.h" |
#include "log.h" |
|
#include "xmalloc.h" |
|
|
|
static int |
|
extract_salt(const char *s, u_int l, char *salt, size_t salt_len) |
|
{ |
|
char *p, *b64salt; |
|
u_int b64len; |
|
int ret; |
|
|
|
if (l < sizeof(HASH_MAGIC) - 1) { |
|
debug2("extract_salt: string too short"); |
|
return (-1); |
|
} |
|
if (strncmp(s, HASH_MAGIC, sizeof(HASH_MAGIC) - 1) != 0) { |
|
debug2("extract_salt: invalid magic identifier"); |
|
return (-1); |
|
} |
|
s += sizeof(HASH_MAGIC) - 1; |
|
l -= sizeof(HASH_MAGIC) - 1; |
|
if ((p = memchr(s, HASH_DELIM, l)) == NULL) { |
|
debug2("extract_salt: missing salt termination character"); |
|
return (-1); |
|
} |
|
|
|
b64len = p - s; |
|
/* Sanity check */ |
|
if (b64len == 0 || b64len > 1024) { |
|
debug2("extract_salt: bad encoded salt length %u", b64len); |
|
return (-1); |
|
} |
|
b64salt = xmalloc(1 + b64len); |
|
memcpy(b64salt, s, b64len); |
|
b64salt[b64len] = '\0'; |
|
|
|
ret = __b64_pton(b64salt, salt, salt_len); |
|
xfree(b64salt); |
|
if (ret == -1) { |
|
debug2("extract_salt: salt decode error"); |
|
return (-1); |
|
} |
|
if (ret != SHA_DIGEST_LENGTH) { |
|
debug2("extract_salt: expected salt len %u, got %u", |
|
salt_len, ret); |
|
return (-1); |
|
} |
|
|
|
return (0); |
|
} |
|
|
|
char * |
|
host_hash(const char *host, const char *name_from_hostfile, u_int src_len) |
|
{ |
|
const EVP_MD *md = EVP_sha1(); |
|
HMAC_CTX mac_ctx; |
|
char salt[256], result[256], uu_salt[512], uu_result[512]; |
|
static char encoded[1024]; |
|
u_int i, len; |
|
|
|
len = EVP_MD_size(md); |
|
|
|
if (name_from_hostfile == NULL) { |
|
/* Create new salt */ |
|
for (i = 0; i < len; i++) |
|
salt[i] = arc4random(); |
|
} else { |
|
/* Extract salt from known host entry */ |
|
if (extract_salt(name_from_hostfile, src_len, salt, |
|
sizeof(salt)) == -1) |
|
return (NULL); |
|
} |
|
|
|
HMAC_Init(&mac_ctx, salt, len, md); |
|
HMAC_Update(&mac_ctx, host, strlen(host)); |
|
HMAC_Final(&mac_ctx, result, NULL); |
|
HMAC_cleanup(&mac_ctx); |
|
|
|
if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 || |
|
__b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1) |
|
fatal("host_hash: __b64_ntop failed"); |
|
|
|
snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt, |
|
HASH_DELIM, uu_result); |
|
|
|
return (encoded); |
|
} |
|
|
/* |
/* |
* Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the |
* Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the |
* pointer over the key. Skips any whitespace at the beginning and at end. |
* pointer over the key. Skips any whitespace at the beginning and at end. |
|
|
char line[8192]; |
char line[8192]; |
int linenum = 0; |
int linenum = 0; |
u_int kbits; |
u_int kbits; |
char *cp, *cp2; |
char *cp, *cp2, *hashed_host; |
HostStatus end_return; |
HostStatus end_return; |
|
|
debug3("check_host_in_hostfile: filename %s", filename); |
debug3("check_host_in_hostfile: filename %s", filename); |
|
|
; |
; |
|
|
/* Check if the host name matches. */ |
/* Check if the host name matches. */ |
if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1) |
if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1) { |
continue; |
if (*cp != HASH_DELIM) |
|
continue; |
|
hashed_host = host_hash(host, cp, (u_int) (cp2 - cp)); |
|
if (hashed_host == NULL) { |
|
debug("Invalid hashed host line %d of %s", |
|
linenum, filename); |
|
continue; |
|
} |
|
if (strncmp(hashed_host, cp, (u_int) (cp2 - cp)) != 0) |
|
continue; |
|
} |
|
|
/* Got a match. Skip host name. */ |
/* Got a match. Skip host name. */ |
cp = cp2; |
cp = cp2; |
|
|
*/ |
*/ |
|
|
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, const Key *key, |
|
int store_hash) |
{ |
{ |
FILE *f; |
FILE *f; |
int success = 0; |
int success = 0; |
|
char *hashed_host; |
|
|
if (key == NULL) |
if (key == NULL) |
return 1; /* XXX ? */ |
return 1; /* XXX ? */ |
f = fopen(filename, "a"); |
f = fopen(filename, "a"); |
if (!f) |
if (!f) |
return 0; |
return 0; |
fprintf(f, "%s ", host); |
|
|
if (store_hash) { |
|
if ((hashed_host = host_hash(host, NULL, 0)) == NULL) { |
|
error("add_host_to_hostfile: host_hash failed"); |
|
fclose(f); |
|
return 0; |
|
} |
|
} |
|
fprintf(f, "%s ", store_hash ? hashed_host : host); |
|
|
if (key_write(key, f)) { |
if (key_write(key, f)) { |
success = 1; |
success = 1; |
} else { |
} else { |