diff --git a/src/agent.c b/src/agent.c index cfab538a..65ac44a6 100644 --- a/src/agent.c +++ b/src/agent.c @@ -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; }