version 1.266, 2015/01/20 23:14:00 |
version 1.267, 2015/01/26 03:04:45 |
|
|
#include "msg.h" |
#include "msg.h" |
#include "roaming.h" |
#include "roaming.h" |
#include "ssherr.h" |
#include "ssherr.h" |
|
#include "hostfile.h" |
|
|
/* import options */ |
/* import options */ |
extern Options options; |
extern Options options; |
|
|
quit_pending = 1; |
quit_pending = 1; |
return 0; |
return 0; |
} |
} |
|
|
static int |
static int |
client_input_agent_open(int type, u_int32_t seq, void *ctxt) |
client_input_agent_open(int type, u_int32_t seq, void *ctxt) |
{ |
{ |
|
|
free(ctype); |
free(ctype); |
return 0; |
return 0; |
} |
} |
|
|
static int |
static int |
client_input_channel_req(int type, u_int32_t seq, void *ctxt) |
client_input_channel_req(int type, u_int32_t seq, void *ctxt) |
{ |
{ |
|
|
free(rtype); |
free(rtype); |
return 0; |
return 0; |
} |
} |
|
|
|
/* |
|
* Handle hostkeys@openssh.com global request to inform the client of all |
|
* the server's hostkeys. The keys are checked against the user's |
|
* HostkeyAlgorithms preference before they are accepted. |
|
*/ |
static int |
static int |
|
client_input_hostkeys(void) |
|
{ |
|
const u_char *blob = NULL; |
|
u_int i, len = 0, nkeys = 0; |
|
struct sshbuf *buf = NULL; |
|
struct sshkey *key = NULL, **tmp, **keys = NULL; |
|
int r, success = 1; |
|
char *fp, *host_str = NULL; |
|
static int hostkeys_seen = 0; /* XXX use struct ssh */ |
|
|
|
/* |
|
* NB. Return success for all cases other than protocol error. The |
|
* server doesn't need to know what the client does with its hosts |
|
* file. |
|
*/ |
|
|
|
blob = packet_get_string_ptr(&len); |
|
packet_check_eom(); |
|
|
|
if (hostkeys_seen) |
|
fatal("%s: server already sent hostkeys", __func__); |
|
if (!options.update_hostkeys || options.num_user_hostfiles <= 0) |
|
return 1; |
|
if ((buf = sshbuf_from(blob, len)) == NULL) |
|
fatal("%s: sshbuf_from failed", __func__); |
|
while (sshbuf_len(buf) > 0) { |
|
sshkey_free(key); |
|
key = NULL; |
|
if ((r = sshkey_froms(buf, &key)) != 0) |
|
fatal("%s: parse key: %s", __func__, ssh_err(r)); |
|
fp = sshkey_fingerprint(key, options.fingerprint_hash, |
|
SSH_FP_DEFAULT); |
|
debug3("%s: received %s key %s", __func__, |
|
sshkey_type(key), fp); |
|
free(fp); |
|
/* Check that the key is accepted in HostkeyAlgorithms */ |
|
if (options.hostkeyalgorithms != NULL && |
|
match_pattern_list(sshkey_ssh_name(key), |
|
options.hostkeyalgorithms, |
|
strlen(options.hostkeyalgorithms), 0) != 1) { |
|
debug3("%s: %s key not permitted by HostkeyAlgorithms", |
|
__func__, sshkey_ssh_name(key)); |
|
continue; |
|
} |
|
if ((tmp = reallocarray(keys, nkeys + 1, |
|
sizeof(*keys))) == NULL) |
|
fatal("%s: reallocarray failed nkeys = %u", |
|
__func__, nkeys); |
|
keys = tmp; |
|
keys[nkeys++] = key; |
|
key = NULL; |
|
} |
|
|
|
debug3("%s: received %u keys from server", __func__, nkeys); |
|
if (nkeys == 0) { |
|
error("%s: server sent no hostkeys", __func__); |
|
goto out; |
|
} |
|
|
|
get_hostfile_hostname_ipaddr(host, NULL, options.port, &host_str, NULL); |
|
|
|
if ((r = hostfile_replace_entries(options.user_hostfiles[0], host_str, |
|
keys, nkeys, options.hash_known_hosts, 1)) != 0) { |
|
error("%s: hostfile_replace_entries failed: %s", |
|
__func__, ssh_err(r)); |
|
goto out; |
|
} |
|
|
|
/* Success */ |
|
out: |
|
free(host_str); |
|
sshkey_free(key); |
|
for (i = 0; i < nkeys; i++) |
|
sshkey_free(keys[i]); |
|
sshbuf_free(buf); |
|
return success; |
|
} |
|
|
|
static int |
client_input_global_request(int type, u_int32_t seq, void *ctxt) |
client_input_global_request(int type, u_int32_t seq, void *ctxt) |
{ |
{ |
char *rtype; |
char *rtype; |
int want_reply; |
int want_reply; |
int success = 0; |
int success = 0; |
|
|
rtype = packet_get_string(NULL); |
rtype = packet_get_cstring(NULL); |
want_reply = packet_get_char(); |
want_reply = packet_get_char(); |
debug("client_input_global_request: rtype %s want_reply %d", |
debug("client_input_global_request: rtype %s want_reply %d", |
rtype, want_reply); |
rtype, want_reply); |
|
if (strcmp(rtype, "hostkeys@openssh.com") == 0) |
|
success = client_input_hostkeys(); |
if (want_reply) { |
if (want_reply) { |
packet_start(success ? |
packet_start(success ? |
SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); |
SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); |