1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-11-23 01:22:37 +03:00

Guard against out-of-bounds reads in userauth.c

This commit is contained in:
Michael Buckley
2018-12-06 12:18:13 -08:00
parent 959b8e5fa0
commit 8031a60518

View File

@@ -1743,28 +1743,58 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
/* server requested PAM-like conversation */ /* server requested PAM-like conversation */
s = session->userauth_kybd_data + 1; s = session->userauth_kybd_data + 1;
/* string name (ISO-10646 UTF-8) */ if(session->userauth_kybd_data_len >= 5) {
session->userauth_kybd_auth_name_len = _libssh2_ntohu32(s); /* string name (ISO-10646 UTF-8) */
s += 4; session->userauth_kybd_auth_name_len = _libssh2_ntohu32(s);
if(session->userauth_kybd_auth_name_len) { s += 4;
session->userauth_kybd_auth_name = }
LIBSSH2_ALLOC(session, else {
session->userauth_kybd_auth_name_len); _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
if(!session->userauth_kybd_auth_name) { "userauth keyboard data buffer too small"
_libssh2_error(session, LIBSSH2_ERROR_ALLOC, "to get length");
"Unable to allocate memory for " goto cleanup;
"keyboard-interactive 'name' " }
"request field");
if(session->userauth_kybd_auth_name_len) {
session->userauth_kybd_auth_name =
LIBSSH2_ALLOC(session,
session->userauth_kybd_auth_name_len);
if(!session->userauth_kybd_auth_name) {
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for "
"keyboard-interactive 'name' "
"request field");
goto cleanup;
}
if (s + session->userauth_list_data_len <=
session->userauth_kybd_data +
session->userauth_kybd_data_len) {
memcpy(session->userauth_kybd_auth_name, s,
session->userauth_kybd_auth_name_len);
s += session->userauth_kybd_auth_name_len;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"userauth keyboard data buffer too small"
"for auth name");
goto cleanup; goto cleanup;
} }
memcpy(session->userauth_kybd_auth_name, s, }
session->userauth_kybd_auth_name_len);
s += session->userauth_kybd_auth_name_len; if (s + 4 <= session->userauth_kybd_data +
session->userauth_kybd_data_len) {
/* string instruction (ISO-10646 UTF-8) */
session->userauth_kybd_auth_instruction_len =
_libssh2_ntohu32(s);
s += 4;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"userauth keyboard data buffer too small"
"for auth instruction length");
goto cleanup;
} }
/* string instruction (ISO-10646 UTF-8) */
session->userauth_kybd_auth_instruction_len = _libssh2_ntohu32(s);
s += 4;
if(session->userauth_kybd_auth_instruction_len) { if(session->userauth_kybd_auth_instruction_len) {
session->userauth_kybd_auth_instruction = session->userauth_kybd_auth_instruction =
LIBSSH2_ALLOC(session, LIBSSH2_ALLOC(session,
@@ -1776,21 +1806,58 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
"request field"); "request field");
goto cleanup; goto cleanup;
} }
memcpy(session->userauth_kybd_auth_instruction, s, if(s + session->userauth_kybd_auth_instruction_len <=
session->userauth_kybd_auth_instruction_len); session->userauth_kybd_data +
s += session->userauth_kybd_auth_instruction_len; session->userauth_kybd_data_len) {
memcpy(session->userauth_kybd_auth_instruction, s,
session->userauth_kybd_auth_instruction_len);
s += session->userauth_kybd_auth_instruction_len;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"userauth keyboard data buffer too small"
"for auth instruction");
goto cleanup;
}
} }
/* string language tag (as defined in [RFC-3066]) */ if(s + 4 <= session->userauth_kybd_data +
language_tag_len = _libssh2_ntohu32(s); session->userauth_kybd_data_len) {
s += 4; /* string language tag (as defined in [RFC-3066]) */
language_tag_len = _libssh2_ntohu32(s);
s += 4;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"userauth keyboard data buffer too small"
"for auth language tag length");
goto cleanup;
}
/* ignoring this field as deprecated */ if(s + language_tag_len <= session->userauth_kybd_data +
s += language_tag_len; session->userauth_kybd_data_len) {
/* ignoring this field as deprecated */
s += language_tag_len;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"userauth keyboard data buffer too small"
"for auth language tag");
goto cleanup;
}
/* int num-prompts */ if(s + 4 <= session->userauth_kybd_data +
session->userauth_kybd_num_prompts = _libssh2_ntohu32(s); session->userauth_kybd_data_len) {
s += 4; /* int num-prompts */
session->userauth_kybd_num_prompts = _libssh2_ntohu32(s);
s += 4;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"userauth keyboard data buffer too small"
"for auth num keyboard prompts");
goto cleanup;
}
if(session->userauth_kybd_num_prompts && if(session->userauth_kybd_num_prompts &&
session->userauth_kybd_num_prompts > 100) { session->userauth_kybd_num_prompts > 100) {
@@ -1824,10 +1891,20 @@ 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 prompt[1] (ISO-10646 UTF-8) */ if(s + 4 <= session->userauth_kybd_data +
session->userauth_kybd_prompts[i].length = session->userauth_kybd_data_len) {
_libssh2_ntohu32(s); /* string prompt[1] (ISO-10646 UTF-8) */
s += 4; session->userauth_kybd_prompts[i].length =
_libssh2_ntohu32(s);
s += 4;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"userauth keyboard data buffer too small"
"for auth keyboard prompt length");
goto cleanup;
}
session->userauth_kybd_prompts[i].text = session->userauth_kybd_prompts[i].text =
LIBSSH2_CALLOC(session, LIBSSH2_CALLOC(session,
session->userauth_kybd_prompts[i].length); session->userauth_kybd_prompts[i].length);
@@ -1837,12 +1914,31 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session,
"keyboard-interactive prompt message"); "keyboard-interactive prompt message");
goto cleanup; goto cleanup;
} }
memcpy(session->userauth_kybd_prompts[i].text, s,
session->userauth_kybd_prompts[i].length); if(s + session->userauth_kybd_prompts[i].length <=
s += session->userauth_kybd_prompts[i].length; session->userauth_kybd_data +
session->userauth_kybd_data_len) {
/* boolean echo[1] */ memcpy(session->userauth_kybd_prompts[i].text, s,
session->userauth_kybd_prompts[i].echo = *s++; session->userauth_kybd_prompts[i].length);
s += session->userauth_kybd_prompts[i].length;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"userauth keyboard data buffer too small"
"for auth keyboard prompt");
goto cleanup;
}
if(s < session->userauth_kybd_data +
session->userauth_kybd_data_len) {
/* boolean echo[1] */
session->userauth_kybd_prompts[i].echo = *s++;
}
else {
_libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
"userauth keyboard data buffer too small"
"for auth keyboard prompt echo");
goto cleanup;
}
} }
} }