| version 1.372, 2010/01/29 00:20:41 |
version 1.373, 2010/02/26 20:29:54 |
|
|
| Key *server_key; /* ephemeral server key */ |
Key *server_key; /* ephemeral server key */ |
| Key *ssh1_host_key; /* ssh1 host key */ |
Key *ssh1_host_key; /* ssh1 host key */ |
| Key **host_keys; /* all private host keys */ |
Key **host_keys; /* all private host keys */ |
| |
Key **host_certificates; /* all public host certificates */ |
| int have_ssh1_key; |
int have_ssh1_key; |
| int have_ssh2_key; |
int have_ssh2_key; |
| u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH]; |
u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH]; |
|
|
| key_free(sensitive_data.host_keys[i]); |
key_free(sensitive_data.host_keys[i]); |
| sensitive_data.host_keys[i] = NULL; |
sensitive_data.host_keys[i] = NULL; |
| } |
} |
| |
if (sensitive_data.host_certificates[i]) { |
| |
key_free(sensitive_data.host_certificates[i]); |
| |
sensitive_data.host_certificates[i] = NULL; |
| |
} |
| } |
} |
| sensitive_data.ssh1_host_key = NULL; |
sensitive_data.ssh1_host_key = NULL; |
| memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH); |
memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH); |
|
|
| if (tmp->type == KEY_RSA1) |
if (tmp->type == KEY_RSA1) |
| sensitive_data.ssh1_host_key = tmp; |
sensitive_data.ssh1_host_key = tmp; |
| } |
} |
| |
/* Certs do not need demotion */ |
| } |
} |
| |
|
| /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ |
/* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ |
|
|
| const char *p; |
const char *p; |
| char *ret; |
char *ret; |
| int i; |
int i; |
| |
Key *key; |
| |
|
| buffer_init(&b); |
buffer_init(&b); |
| for (i = 0; i < options.num_host_key_files; i++) { |
for (i = 0; i < options.num_host_key_files; i++) { |
| Key *key = sensitive_data.host_keys[i]; |
key = sensitive_data.host_keys[i]; |
| if (key == NULL) |
if (key == NULL) |
| continue; |
continue; |
| switch (key->type) { |
switch (key->type) { |
|
|
| buffer_append(&b, p, strlen(p)); |
buffer_append(&b, p, strlen(p)); |
| break; |
break; |
| } |
} |
| |
/* If the private key has a cert peer, then list that too */ |
| |
key = sensitive_data.host_certificates[i]; |
| |
if (key == NULL) |
| |
continue; |
| |
switch (key->type) { |
| |
case KEY_RSA_CERT: |
| |
case KEY_DSA_CERT: |
| |
if (buffer_len(&b) > 0) |
| |
buffer_append(&b, ",", 1); |
| |
p = key_ssh_name(key); |
| |
buffer_append(&b, p, strlen(p)); |
| |
break; |
| |
} |
| } |
} |
| buffer_append(&b, "\0", 1); |
buffer_append(&b, "\0", 1); |
| ret = xstrdup(buffer_ptr(&b)); |
ret = xstrdup(buffer_ptr(&b)); |
|
|
| return ret; |
return ret; |
| } |
} |
| |
|
| Key * |
static Key * |
| get_hostkey_by_type(int type) |
get_hostkey_by_type(int type, int need_private) |
| { |
{ |
| int i; |
int i; |
| |
Key *key; |
| |
|
| for (i = 0; i < options.num_host_key_files; i++) { |
for (i = 0; i < options.num_host_key_files; i++) { |
| Key *key = sensitive_data.host_keys[i]; |
if (type == KEY_RSA_CERT || type == KEY_DSA_CERT) |
| |
key = sensitive_data.host_certificates[i]; |
| |
else |
| |
key = sensitive_data.host_keys[i]; |
| if (key != NULL && key->type == type) |
if (key != NULL && key->type == type) |
| return key; |
return need_private ? |
| |
sensitive_data.host_keys[i] : key; |
| } |
} |
| return NULL; |
return NULL; |
| } |
} |
| |
|
| Key * |
Key * |
| |
get_hostkey_public_by_type(int type) |
| |
{ |
| |
return get_hostkey_by_type(type, 0); |
| |
} |
| |
|
| |
Key * |
| |
get_hostkey_private_by_type(int type) |
| |
{ |
| |
return get_hostkey_by_type(type, 1); |
| |
} |
| |
|
| |
Key * |
| get_hostkey_by_index(int ind) |
get_hostkey_by_index(int ind) |
| { |
{ |
| if (ind < 0 || ind >= options.num_host_key_files) |
if (ind < 0 || ind >= options.num_host_key_files) |
|
|
| int i; |
int i; |
| |
|
| for (i = 0; i < options.num_host_key_files; i++) { |
for (i = 0; i < options.num_host_key_files; i++) { |
| if (key == sensitive_data.host_keys[i]) |
if (key_is_cert(key)) { |
| return (i); |
if (key == sensitive_data.host_certificates[i]) |
| |
return (i); |
| |
} else { |
| |
if (key == sensitive_data.host_keys[i]) |
| |
return (i); |
| |
} |
| } |
} |
| return (-1); |
return (-1); |
| } |
} |
|
|
| fprintf(stderr, "%s, %s\n", |
fprintf(stderr, "%s, %s\n", |
| SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); |
SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); |
| fprintf(stderr, |
fprintf(stderr, |
| "usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-f config_file]\n" |
"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n" |
| " [-g login_grace_time] [-h host_key_file] [-k key_gen_time]\n" |
" [-f config_file] [-g login_grace_time] [-h host_key_file]\n" |
| " [-o option] [-p port] [-u len]\n" |
" [-k key_gen_time] [-o option] [-p port] [-u len]\n" |
| ); |
); |
| exit(1); |
exit(1); |
| } |
} |
|
|
| { |
{ |
| extern char *optarg; |
extern char *optarg; |
| extern int optind; |
extern int optind; |
| int opt, i, on = 1; |
int opt, i, j, on = 1; |
| int sock_in = -1, sock_out = -1, newsock = -1; |
int sock_in = -1, sock_out = -1, newsock = -1; |
| const char *remote_ip; |
const char *remote_ip; |
| char *test_user = NULL, *test_host = NULL, *test_addr = NULL; |
char *test_user = NULL, *test_host = NULL, *test_addr = NULL; |
|
|
| case 'f': |
case 'f': |
| config_file_name = optarg; |
config_file_name = optarg; |
| break; |
break; |
| |
case 'c': |
| |
if (options.num_host_cert_files >= MAX_HOSTCERTS) { |
| |
fprintf(stderr, "too many host certificates.\n"); |
| |
exit(1); |
| |
} |
| |
options.host_cert_files[options.num_host_cert_files++] = |
| |
derelativise_path(optarg); |
| |
break; |
| case 'd': |
case 'd': |
| if (debug_flag == 0) { |
if (debug_flag == 0) { |
| debug_flag = 1; |
debug_flag = 1; |
|
|
| exit(1); |
exit(1); |
| } |
} |
| |
|
| |
/* |
| |
* Load certificates. They are stored in an array at identical |
| |
* indices to the public keys that they relate to. |
| |
*/ |
| |
sensitive_data.host_certificates = xcalloc(options.num_host_key_files, |
| |
sizeof(Key *)); |
| |
for (i = 0; i < options.num_host_key_files; i++) |
| |
sensitive_data.host_certificates[i] = NULL; |
| |
|
| |
for (i = 0; i < options.num_host_cert_files; i++) { |
| |
key = key_load_public(options.host_cert_files[i], NULL); |
| |
if (key == NULL) { |
| |
error("Could not load host certificate: %s", |
| |
options.host_cert_files[i]); |
| |
continue; |
| |
} |
| |
if (!key_is_cert(key)) { |
| |
error("Certificate file is not a certificate: %s", |
| |
options.host_cert_files[i]); |
| |
key_free(key); |
| |
continue; |
| |
} |
| |
/* Find matching private key */ |
| |
for (j = 0; j < options.num_host_key_files; j++) { |
| |
if (key_equal_public(key, |
| |
sensitive_data.host_keys[j])) { |
| |
sensitive_data.host_certificates[j] = key; |
| |
break; |
| |
} |
| |
} |
| |
if (j >= options.num_host_key_files) { |
| |
error("No matching private key for certificate: %s", |
| |
options.host_cert_files[i]); |
| |
key_free(key); |
| |
continue; |
| |
} |
| |
sensitive_data.host_certificates[j] = key; |
| |
debug("host certificate: #%d type %d %s", j, key->type, |
| |
key_type(key)); |
| |
} |
| /* Check certain values for sanity. */ |
/* Check certain values for sanity. */ |
| if (options.protocol & SSH_PROTO_1) { |
if (options.protocol & SSH_PROTO_1) { |
| if (options.server_key_bits < 512 || |
if (options.server_key_bits < 512 || |
|
|
| kex->server = 1; |
kex->server = 1; |
| kex->client_version_string=client_version_string; |
kex->client_version_string=client_version_string; |
| kex->server_version_string=server_version_string; |
kex->server_version_string=server_version_string; |
| kex->load_host_key=&get_hostkey_by_type; |
kex->load_host_public_key=&get_hostkey_public_by_type; |
| |
kex->load_host_private_key=&get_hostkey_private_by_type; |
| kex->host_key_index=&get_hostkey_index; |
kex->host_key_index=&get_hostkey_index; |
| |
|
| xxx_kex = kex; |
xxx_kex = kex; |