mirror of
https://github.com/libssh2/libssh2.git
synced 2025-08-05 20:55:47 +03:00
1.8 Security fixes (#314)
* fixed possible integer overflow in packet_length CVE https://www.libssh2.org/CVE-2019-3861.html * fixed possible interger overflow with userauth_keyboard_interactive CVE https://www.libssh2.org/CVE-2019-3856.html * fixed possible out zero byte/incorrect bounds allocation CVE https://www.libssh2.org/CVE-2019-3857.html * bounds checks for response packets * fixed integer overflow in userauth_keyboard_interactive CVE https://www.libssh2.org/CVE-2019-3863.html * 1.8.1 release notes
This commit is contained in:
@@ -1,31 +1,29 @@
|
|||||||
libssh2 1.8.0
|
libssh2 1.8.1
|
||||||
|
|
||||||
This release includes the following changes:
|
|
||||||
|
|
||||||
o added a basic dockerised test suite
|
|
||||||
o crypto: add support for the mbedTLS backend
|
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
o libgcrypt: fixed a NULL pointer dereference on OOM
|
o fixed possible integer overflow when reading a specially crafted packet
|
||||||
o VMS: can't use %zd for off_t format
|
(https://www.libssh2.org/CVE-2019-3855.html)
|
||||||
o VMS: update vms/libssh2_config.h
|
o fixed possible integer overflow in userauth_keyboard_interactive with a
|
||||||
o windows: link with crypt32.lib
|
number of extremely long prompt strings
|
||||||
o libssh2_channel_open: speeling error fixed in channel error message
|
(https://www.libssh2.org/CVE-2019-3863.html)
|
||||||
o msvc: fixed 14 compilation warnings
|
o fixed possible integer overflow if the server sent an extremely large number
|
||||||
o tests: HAVE_NETINET_IN_H was not defined correctly
|
of keyboard prompts (https://www.libssh2.org/CVE-2019-3856.html)
|
||||||
o openssl: add OpenSSL 1.1.0 compatibility
|
o fixed possible out of bounds read when processing a specially crafted packet
|
||||||
o cmake: Add CLEAR_MEMORY option, analogously to that for autoconf
|
(https://www.libssh2.org/CVE-2019-3861.html)
|
||||||
o configure: make the --with-* options override the OpenSSL default
|
o fixed possible integer overflow when receiving a specially crafted exit
|
||||||
o libssh2_wait_socket: set err_msg on errors
|
signal message channel packet (https://www.libssh2.org/CVE-2019-3857.html)
|
||||||
o libssh2_wait_socket: Fix comparison with api_timeout to use milliseconds
|
o fixed possible out of bounds read when receiving a specially crafted exit
|
||||||
|
status message channel packet (https://www.libssh2.org/CVE-2019-3862.html)
|
||||||
|
o fixed possible zero byte allocation when reading a specially crafted SFTP
|
||||||
|
packet (https://www.libssh2.org/CVE-2019-3858.html)
|
||||||
|
o fixed possible out of bounds reads when processing specially crafted SFTP
|
||||||
|
packets (https://www.libssh2.org/CVE-2019-3860.html)
|
||||||
|
o fixed possible out of bounds reads in _libssh2_packet_require(v)
|
||||||
|
(https://www.libssh2.org/CVE-2019-3859.html)
|
||||||
|
|
||||||
This release would not have looked like this without help, code, reports and
|
This release would not have looked like this without help, code, reports and
|
||||||
advice from friends like these:
|
advice from friends like these:
|
||||||
|
|
||||||
Alexander Lamaison, Antenore Gatta, Brad Harder, Charles Collicutt,
|
Chris Coulson, Michael Buckley, Will Cosgrove, Daniel Stenberg
|
||||||
Craig A. Berry, Dan Fandrich, Daniel Stenberg, Kamil Dudka, Keno Fischer,
|
(4 contributors)
|
||||||
Taylor Holberton, Viktor Szakats, Will Cosgrove, Zenju
|
|
||||||
(12 contributors)
|
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
|
||||||
|
@@ -145,6 +145,18 @@ typedef int libssh2_socket_t;
|
|||||||
#define LIBSSH2_INVALID_SOCKET -1
|
#define LIBSSH2_INVALID_SOCKET -1
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
#ifndef SIZE_MAX
|
||||||
|
#if _WIN64
|
||||||
|
#define SIZE_MAX 0xFFFFFFFFFFFFFFFF
|
||||||
|
#else
|
||||||
|
#define SIZE_MAX 0xFFFFFFFF
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef UINT_MAX
|
||||||
|
#define UINT_MAX 0xFFFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine whether there is small or large file support on windows.
|
* Determine whether there is small or large file support on windows.
|
||||||
*/
|
*/
|
||||||
|
@@ -238,7 +238,20 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
|
|||||||
goto channel_error;
|
goto channel_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(session->open_data_len < 1) {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Unexpected packet size");
|
||||||
|
goto channel_error;
|
||||||
|
}
|
||||||
|
|
||||||
if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
|
if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
|
||||||
|
|
||||||
|
if(session->open_data_len < 17) {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Unexpected packet size");
|
||||||
|
goto channel_error;
|
||||||
|
}
|
||||||
|
|
||||||
session->open_channel->remote.id =
|
session->open_channel->remote.id =
|
||||||
_libssh2_ntohu32(session->open_data + 5);
|
_libssh2_ntohu32(session->open_data + 5);
|
||||||
session->open_channel->local.window_size =
|
session->open_channel->local.window_size =
|
||||||
@@ -518,7 +531,7 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
|
|||||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
|
_libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (rc) {
|
} else if (rc || data_len < 1) {
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown");
|
_libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown");
|
||||||
session->fwdLstn_state = libssh2_NB_state_idle;
|
session->fwdLstn_state = libssh2_NB_state_idle;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -855,6 +868,11 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel,
|
|||||||
channel->setenv_state = libssh2_NB_state_idle;
|
channel->setenv_state = libssh2_NB_state_idle;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
else if(data_len < 1) {
|
||||||
|
channel->setenv_state = libssh2_NB_state_idle;
|
||||||
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Unexpected packet size");
|
||||||
|
}
|
||||||
|
|
||||||
if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
|
if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
|
||||||
LIBSSH2_FREE(session, data);
|
LIBSSH2_FREE(session, data);
|
||||||
@@ -971,7 +989,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
|
|||||||
&channel->reqPTY_packet_requirev_state);
|
&channel->reqPTY_packet_requirev_state);
|
||||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||||
return rc;
|
return rc;
|
||||||
} else if (rc) {
|
} else if (rc || data_len < 1) {
|
||||||
channel->reqPTY_state = libssh2_NB_state_idle;
|
channel->reqPTY_state = libssh2_NB_state_idle;
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
"Failed to require the PTY package");
|
"Failed to require the PTY package");
|
||||||
@@ -1197,7 +1215,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
|
|||||||
&channel->reqX11_packet_requirev_state);
|
&channel->reqX11_packet_requirev_state);
|
||||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||||
return rc;
|
return rc;
|
||||||
} else if (rc) {
|
} else if (rc || data_len < 1) {
|
||||||
channel->reqX11_state = libssh2_NB_state_idle;
|
channel->reqX11_state = libssh2_NB_state_idle;
|
||||||
return _libssh2_error(session, rc,
|
return _libssh2_error(session, rc,
|
||||||
"waiting for x11-req response packet");
|
"waiting for x11-req response packet");
|
||||||
@@ -1324,7 +1342,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
|
|||||||
&channel->process_packet_requirev_state);
|
&channel->process_packet_requirev_state);
|
||||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||||
return rc;
|
return rc;
|
||||||
} else if (rc) {
|
} else if (rc || data_len < 1) {
|
||||||
channel->process_state = libssh2_NB_state_end;
|
channel->process_state = libssh2_NB_state_end;
|
||||||
return _libssh2_error(session, rc,
|
return _libssh2_error(session, rc,
|
||||||
"Failed waiting for channel success");
|
"Failed waiting for channel success");
|
||||||
|
24
src/kex.c
24
src/kex.c
@@ -228,11 +228,23 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse KEXDH_REPLY */
|
/* Parse KEXDH_REPLY */
|
||||||
|
if(exchange_state->s_packet_len < 5) {
|
||||||
|
ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Unexpected packet length");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
exchange_state->s = exchange_state->s_packet + 1;
|
exchange_state->s = exchange_state->s_packet + 1;
|
||||||
|
|
||||||
session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
|
session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
|
||||||
exchange_state->s += 4;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if (session->server_hostkey)
|
if (session->server_hostkey)
|
||||||
LIBSSH2_FREE(session, session->server_hostkey);
|
LIBSSH2_FREE(session, session->server_hostkey);
|
||||||
|
|
||||||
@@ -848,11 +860,23 @@ static int diffie_hellman_sha256(LIBSSH2_SESSION *session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse KEXDH_REPLY */
|
/* Parse KEXDH_REPLY */
|
||||||
|
if(exchange_state->s_packet_len < 5) {
|
||||||
|
ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Unexpected packet length");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
exchange_state->s = exchange_state->s_packet + 1;
|
exchange_state->s = exchange_state->s_packet + 1;
|
||||||
|
|
||||||
session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
|
session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
|
||||||
exchange_state->s += 4;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if (session->server_hostkey)
|
if (session->server_hostkey)
|
||||||
LIBSSH2_FREE(session, session->server_hostkey);
|
LIBSSH2_FREE(session, session->server_hostkey);
|
||||||
|
|
||||||
|
11
src/packet.c
11
src/packet.c
@@ -815,8 +815,15 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
/* set signal name (without SIG prefix) */
|
/* set signal name (without SIG prefix) */
|
||||||
uint32_t namelen =
|
uint32_t namelen =
|
||||||
_libssh2_ntohu32(data + 9 + sizeof("exit-signal"));
|
_libssh2_ntohu32(data + 9 + sizeof("exit-signal"));
|
||||||
channelp->exit_signal =
|
|
||||||
LIBSSH2_ALLOC(session, namelen + 1);
|
if(namelen <= UINT_MAX - 1) {
|
||||||
|
channelp->exit_signal =
|
||||||
|
LIBSSH2_ALLOC(session, namelen + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
channelp->exit_signal = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!channelp->exit_signal)
|
if (!channelp->exit_signal)
|
||||||
rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"memory for signal name");
|
"memory for signal name");
|
||||||
|
@@ -765,6 +765,11 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
if(session->startup_data_len < 5) {
|
||||||
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Unexpected packet length");
|
||||||
|
}
|
||||||
|
|
||||||
session->startup_service_length =
|
session->startup_service_length =
|
||||||
_libssh2_ntohu32(session->startup_data + 1);
|
_libssh2_ntohu32(session->startup_data + 1);
|
||||||
|
|
||||||
|
@@ -438,6 +438,12 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
|||||||
return LIBSSH2_ERROR_DECRYPT;
|
return LIBSSH2_ERROR_DECRYPT;
|
||||||
|
|
||||||
p->padding_length = block[4];
|
p->padding_length = block[4];
|
||||||
|
if(p->packet_length < 1) {
|
||||||
|
return LIBSSH2_ERROR_DECRYPT;
|
||||||
|
}
|
||||||
|
else if(p->packet_length > LIBSSH2_PACKET_MAXPAYLOAD) {
|
||||||
|
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
|
||||||
|
}
|
||||||
|
|
||||||
/* total_num is the number of bytes following the initial
|
/* total_num is the number of bytes following the initial
|
||||||
(5 bytes) packet length and padding length fields */
|
(5 bytes) packet length and padding length fields */
|
||||||
|
@@ -107,7 +107,7 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
|
|||||||
LIBSSH2_FREE(session, session->userauth_list_data);
|
LIBSSH2_FREE(session, session->userauth_list_data);
|
||||||
session->userauth_list_data = NULL;
|
session->userauth_list_data = NULL;
|
||||||
|
|
||||||
if (rc) {
|
if (rc || (session->userauth_list_data_len < 1)) {
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
_libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
"Unable to send userauth-none request");
|
"Unable to send userauth-none request");
|
||||||
session->userauth_list_state = libssh2_NB_state_idle;
|
session->userauth_list_state = libssh2_NB_state_idle;
|
||||||
@@ -143,8 +143,20 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
methods_len = _libssh2_ntohu32(session->userauth_list_data + 1);
|
if(session->userauth_list_data_len < 5) {
|
||||||
|
LIBSSH2_FREE(session, session->userauth_list_data);
|
||||||
|
session->userauth_list_data = NULL;
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Unexpected packet size");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
methods_len = _libssh2_ntohu32(session->userauth_list_data + 1);
|
||||||
|
if(methods_len >= session->userauth_list_data_len - 5) {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
|
||||||
|
"Unexpected userauth list size");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
/* Do note that the memory areas overlap! */
|
/* Do note that the memory areas overlap! */
|
||||||
memmove(session->userauth_list_data, session->userauth_list_data + 5,
|
memmove(session->userauth_list_data, session->userauth_list_data + 5,
|
||||||
methods_len);
|
methods_len);
|
||||||
@@ -285,6 +297,11 @@ userauth_password(LIBSSH2_SESSION *session,
|
|||||||
return _libssh2_error(session, rc,
|
return _libssh2_error(session, rc,
|
||||||
"Waiting for password response");
|
"Waiting for password response");
|
||||||
}
|
}
|
||||||
|
else if(session->userauth_pswd_data_len < 1) {
|
||||||
|
session->userauth_pswd_state = libssh2_NB_state_idle;
|
||||||
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Unexpected packet size");
|
||||||
|
}
|
||||||
|
|
||||||
if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
|
||||||
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
_libssh2_debug(session, LIBSSH2_TRACE_AUTH,
|
||||||
@@ -312,6 +329,12 @@ userauth_password(LIBSSH2_SESSION *session,
|
|||||||
session->userauth_pswd_state = libssh2_NB_state_sent1;
|
session->userauth_pswd_state = libssh2_NB_state_sent1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(session->userauth_pswd_data_len < 1) {
|
||||||
|
session->userauth_pswd_state = libssh2_NB_state_idle;
|
||||||
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Unexpected packet size");
|
||||||
|
}
|
||||||
|
|
||||||
if ((session->userauth_pswd_data[0] ==
|
if ((session->userauth_pswd_data[0] ==
|
||||||
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)
|
SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)
|
||||||
|| (session->userauth_pswd_data0 ==
|
|| (session->userauth_pswd_data0 ==
|
||||||
@@ -976,7 +999,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
session->userauth_host_state = libssh2_NB_state_idle;
|
session->userauth_host_state = libssh2_NB_state_idle;
|
||||||
if (rc) {
|
if (rc || data_len < 1) {
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||||
"Auth failed");
|
"Auth failed");
|
||||||
}
|
}
|
||||||
@@ -1149,7 +1172,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
|||||||
NULL, 0);
|
NULL, 0);
|
||||||
if (rc == LIBSSH2_ERROR_EAGAIN)
|
if (rc == LIBSSH2_ERROR_EAGAIN)
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
|
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
|
||||||
else if (rc) {
|
else if (rc || (session->userauth_pblc_data_len < 1)) {
|
||||||
LIBSSH2_FREE(session, session->userauth_pblc_packet);
|
LIBSSH2_FREE(session, session->userauth_pblc_packet);
|
||||||
session->userauth_pblc_packet = NULL;
|
session->userauth_pblc_packet = NULL;
|
||||||
LIBSSH2_FREE(session, session->userauth_pblc_method);
|
LIBSSH2_FREE(session, session->userauth_pblc_method);
|
||||||
@@ -1332,7 +1355,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
|||||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||||
"Would block requesting userauth list");
|
"Would block requesting userauth list");
|
||||||
} else if (rc) {
|
} else if (rc || session->userauth_pblc_data_len < 1) {
|
||||||
session->userauth_pblc_state = libssh2_NB_state_idle;
|
session->userauth_pblc_state = libssh2_NB_state_idle;
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
|
||||||
"Waiting for publickey USERAUTH response");
|
"Waiting for publickey USERAUTH response");
|
||||||
@@ -1654,7 +1677,7 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
|||||||
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
if (rc == LIBSSH2_ERROR_EAGAIN) {
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
|
||||||
"Would block");
|
"Would block");
|
||||||
} else if (rc) {
|
} else if (rc || session->userauth_kybd_data_len < 1) {
|
||||||
session->userauth_kybd_state = libssh2_NB_state_idle;
|
session->userauth_kybd_state = libssh2_NB_state_idle;
|
||||||
return _libssh2_error(session,
|
return _libssh2_error(session,
|
||||||
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
|
LIBSSH2_ERROR_AUTHENTICATION_FAILED,
|
||||||
@@ -1734,6 +1757,13 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
|||||||
/* int num-prompts */
|
/* int num-prompts */
|
||||||
session->userauth_kybd_num_prompts = _libssh2_ntohu32(s);
|
session->userauth_kybd_num_prompts = _libssh2_ntohu32(s);
|
||||||
s += 4;
|
s += 4;
|
||||||
|
if(session->userauth_kybd_num_prompts &&
|
||||||
|
session->userauth_kybd_num_prompts > 100) {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
|
||||||
|
"Too many replies for "
|
||||||
|
"keyboard-interactive prompts");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if(session->userauth_kybd_num_prompts) {
|
if(session->userauth_kybd_num_prompts) {
|
||||||
session->userauth_kybd_prompts =
|
session->userauth_kybd_prompts =
|
||||||
@@ -1801,8 +1831,17 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
|
|||||||
|
|
||||||
for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
|
for(i = 0; i < session->userauth_kybd_num_prompts; i++) {
|
||||||
/* string response[1] (ISO-10646 UTF-8) */
|
/* string response[1] (ISO-10646 UTF-8) */
|
||||||
session->userauth_kybd_packet_len +=
|
if(session->userauth_kybd_responses[i].length <=
|
||||||
4 + session->userauth_kybd_responses[i].length;
|
(SIZE_MAX - 4 - session->userauth_kybd_packet_len) ) {
|
||||||
|
session->userauth_kybd_packet_len +=
|
||||||
|
4 + session->userauth_kybd_responses[i].length;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"Unable to allocate memory for keyboard-"
|
||||||
|
"interactive response packet");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A new userauth_kybd_data area is to be allocated, free the
|
/* A new userauth_kybd_data area is to be allocated, free the
|
||||||
|
Reference in New Issue
Block a user