diff --git a/src/kex.c b/src/kex.c index a564226f77..cb1663937d 100644 --- a/src/kex.c +++ b/src/kex.c @@ -241,6 +241,9 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, if(exchange_state->state == libssh2_NB_state_sent1) { /* Wait for KEX reply */ + struct string_buf buf; + size_t host_key_len; + rc = _libssh2_packet_require(session, packet_type_reply, &exchange_state->s_packet, &exchange_state->s_packet_len, 0, NULL, @@ -261,31 +264,22 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, goto clean_exit; } - exchange_state->s = exchange_state->s_packet + 1; - - session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - - if(session->server_hostkey_len > exchange_state->s_packet_len - 5) { - ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, - "Host key length out of bounds"); - goto clean_exit; - } + buf.data = exchange_state->s_packet; + buf.len = exchange_state->s_packet_len; + buf.dataptr = buf.data; + buf.dataptr++; /* advance past type */ if(session->server_hostkey) LIBSSH2_FREE(session, session->server_hostkey); - session->server_hostkey = - LIBSSH2_ALLOC(session, session->server_hostkey_len); - if(!session->server_hostkey) { + if(_libssh2_copy_string(session, &buf, &(session->server_hostkey), + &host_key_len)) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for a copy " - "of the host key"); + "Could not copy host key"); goto clean_exit; } - memcpy(session->server_hostkey, exchange_state->s, - session->server_hostkey_len); - exchange_state->s += session->server_hostkey_len; + + session->server_hostkey_len = (uint32_t)host_key_len; #if LIBSSH2_MD5 { @@ -383,16 +377,22 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, goto clean_exit; } - exchange_state->f_value_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->f_value = exchange_state->s; - exchange_state->s += exchange_state->f_value_len; + if(_libssh2_get_string(&buf, &(exchange_state->f_value), + &(exchange_state->f_value_len))) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to get f value"); + goto clean_exit; + } + _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len, exchange_state->f_value); - exchange_state->h_sig_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->h_sig = exchange_state->s; + if(_libssh2_get_string(&buf, &(exchange_state->h_sig), + &(exchange_state->h_sig_len))) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to get h sig"); + goto clean_exit; + } /* Compute the shared secret */ libssh2_dh_secret(&exchange_state->x, exchange_state->k, @@ -932,6 +932,9 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, if(exchange_state->state == libssh2_NB_state_sent1) { /* Wait for KEX reply */ + struct string_buf buf; + size_t host_key_len; + rc = _libssh2_packet_require(session, packet_type_reply, &exchange_state->s_packet, &exchange_state->s_packet_len, 0, NULL, @@ -952,31 +955,22 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, goto clean_exit; } - exchange_state->s = exchange_state->s_packet + 1; - - session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - - if(session->server_hostkey_len > exchange_state->s_packet_len - 5) { - ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, - "Host key length out of bounds"); - goto clean_exit; - } + buf.data = exchange_state->s_packet; + buf.len = exchange_state->s_packet_len; + buf.dataptr = buf.data; + buf.dataptr++; /* advance past type */ if(session->server_hostkey) LIBSSH2_FREE(session, session->server_hostkey); - session->server_hostkey = - LIBSSH2_ALLOC(session, session->server_hostkey_len); - if(!session->server_hostkey) { + if(_libssh2_copy_string(session, &buf, &(session->server_hostkey), + &host_key_len)) { ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for a copy " - "of the host key"); + "Could not copy host key"); goto clean_exit; } - memcpy(session->server_hostkey, exchange_state->s, - session->server_hostkey_len); - exchange_state->s += session->server_hostkey_len; + + session->server_hostkey_len = (uint32_t)host_key_len; #if LIBSSH2_MD5 { @@ -1073,16 +1067,22 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session, goto clean_exit; } - exchange_state->f_value_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->f_value = exchange_state->s; - exchange_state->s += exchange_state->f_value_len; + if(_libssh2_get_string(&buf, &(exchange_state->f_value), + &(exchange_state->f_value_len))) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to get f value"); + goto clean_exit; + } + _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len, exchange_state->f_value); - exchange_state->h_sig_len = _libssh2_ntohu32(exchange_state->s); - exchange_state->s += 4; - exchange_state->h_sig = exchange_state->s; + if(_libssh2_get_string(&buf, &(exchange_state->h_sig), + &(exchange_state->h_sig_len))) { + ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT, + "Unable to get h sig"); + goto clean_exit; + } /* Compute the shared secret */ libssh2_dh_secret(&exchange_state->x, exchange_state->k, diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 13c848e30f..563e776b49 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -261,7 +261,6 @@ typedef struct kmdhgGPshakex_state_t _libssh2_bn *e; _libssh2_bn *f; _libssh2_bn *k; - unsigned char *s; unsigned char *f_value; unsigned char *k_value; unsigned char *h_sig; diff --git a/src/misc.c b/src/misc.c index 487a8df08d..bd084c854f 100644 --- a/src/misc.c +++ b/src/misc.c @@ -786,6 +786,30 @@ int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf, return 0; } +int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf, + unsigned char **outbuf, size_t *outlen) +{ + size_t str_len; + unsigned char *str; + + if(_libssh2_get_string(buf, &str, &str_len)) { + return -1; + } + + *outbuf = LIBSSH2_ALLOC(session, str_len); + if(*outbuf) { + memcpy(*outbuf, str, str_len); + } + else { + return -1; + } + + if(outlen) + *outlen = str_len; + + return 0; +} + int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf, size_t *outlen) { diff --git a/src/misc.h b/src/misc.h index 47d42ec16e..5481e666ca 100644 --- a/src/misc.h +++ b/src/misc.h @@ -96,6 +96,8 @@ int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out); int _libssh2_match_string(struct string_buf *buf, const char *match); int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf, size_t *outlen); +int _libssh2_copy_string(LIBSSH2_SESSION* session, struct string_buf *buf, + unsigned char **outbuf, size_t *outlen); int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf, size_t *outlen); int _libssh2_check_length(struct string_buf *buf, size_t requested_len);