1
0
mirror of https://github.com/libssh2/libssh2.git synced 2026-10-24 03:48:58 +03:00

agent: fix bounds checks, and potential OOB access on 32-bit platforms in agent_sign()

Also limit payload to `UINT32_MAX`, since the protocol uses 32-bit value
to store the size. (I'd guess a lower, sane limit may be even better.)

Reported-by: afldl on github
Fixes #2021

Closes #2046
This commit is contained in:
Viktor Szakats
2026-06-12 01:24:36 +02:00
parent bf33b9439d
commit a6e07bc5a3

View File

@@ -745,13 +745,19 @@ static int agent_sign(LIBSSH2_SESSION *session,
LIBSSH2_AGENT *agent = (LIBSSH2_AGENT *)(*abstract);
struct agent_transaction_ctx *transctx = &agent->transctx;
struct agent_publickey *identity = agent->identity;
ssize_t len = 1 + 4 + identity->external.blob_len + 4 + data_len + 4;
ssize_t method_len;
size_t len, method_len, plain_len;
unsigned char *s;
int rc;
unsigned char *method_name = NULL;
uint32_t sign_flags = 0;
ssize_t plain_len;
len = 1 + 4 + 4 + 4; /* fixed parts */
if(identity->external.blob_len > UINT32_MAX - len ||
data_len > UINT32_MAX - len - identity->external.blob_len) {
return ssh2_err(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
"Agent sign request too large");
}
len += identity->external.blob_len + data_len;
/* Create a request to sign the data */
if(transctx->state == agent_NB_state_init) {
@@ -790,8 +796,8 @@ static int agent_sign(LIBSSH2_SESSION *session,
if(*transctx->request != SSH2_AGENTC_SIGN_REQUEST)
return ssh2_err(session, LIBSSH2_ERROR_BAD_USE, "illegal request");
/* if no agent has been connected, bail out */
if(!agent->ops)
/* if no agent has been connected, bail out */
return ssh2_err(session, LIBSSH2_ERROR_BAD_USE, "agent not connected");
rc = agent->ops->transact(agent, transctx);
@@ -803,8 +809,7 @@ static int agent_sign(LIBSSH2_SESSION *session,
len = transctx->response_len;
s = transctx->response;
len--;
if(len < 0) {
if(len < 1) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
@@ -812,26 +817,29 @@ static int agent_sign(LIBSSH2_SESSION *session,
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
len--;
s++;
/* Skip the entire length of the signature */
len -= 4;
if(len < 0) {
if(len < 4) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
len -= 4;
s += 4;
/* Skip signing method */
len -= 4;
if(len < 0) {
if(len < 4) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
/* method length */
method_len = ssh2_ntohu32(s);
len -= 4;
s += 4;
len -= method_len;
if(len < 0) {
if(len < method_len) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
@@ -843,13 +851,14 @@ static int agent_sign(LIBSSH2_SESSION *session,
goto error;
}
memcpy(method_name, s, method_len);
len -= method_len;
s += method_len;
plain_len = plain_method((char *)session->userauth_pblc_method,
session->userauth_pblc_method_len);
/* check to see if we match requested */
if(((size_t)method_len != session->userauth_pblc_method_len &&
if((method_len != session->userauth_pblc_method_len &&
method_len != plain_len) ||
memcmp(method_name, session->userauth_pblc_method, method_len)) {
ssh2_deb((session, LIBSSH2_TRACE_KEX, "Agent sign method %.*s",
@@ -860,15 +869,16 @@ static int agent_sign(LIBSSH2_SESSION *session,
}
/* Read the signature */
len -= 4;
if(len < 0) {
if(len < 4) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
*sig_len = ssh2_ntohu32(s);
len -= 4;
s += 4;
len -= *sig_len;
if(len < 0) {
if(len < *sig_len) {
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}