mirror of
https://github.com/samba-team/samba.git
synced 2025-09-18 09:44:19 +03:00
smb2_server: Add range checking to nbt_length
Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
committed by
Jeremy Allison
parent
d6f70d3346
commit
1c2562e691
@@ -237,16 +237,22 @@ static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
|
|||||||
buf[3] = (len)&0xFF; \
|
buf[3] = (len)&0xFF; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static void smb2_setup_nbt_length(struct iovec *vector, int count)
|
static bool smb2_setup_nbt_length(struct iovec *vector, int count)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
ssize_t len;
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=1; i < count; i++) {
|
if (count == 0) {
|
||||||
len += vector[i].iov_len;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = iov_buflen(vector+1, count-1);
|
||||||
|
|
||||||
|
if ((len == -1) || (len > 0xFFFFFF)) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_smb2_setlen(vector[0].iov_base, len);
|
_smb2_setlen(vector[0].iov_base, len);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
|
static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
|
||||||
@@ -944,6 +950,7 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
|
|||||||
struct iovec *vector;
|
struct iovec *vector;
|
||||||
int count;
|
int count;
|
||||||
int idx;
|
int idx;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
count = req->in.vector_count;
|
count = req->in.vector_count;
|
||||||
if (count <= ARRAY_SIZE(req->out._vector)) {
|
if (count <= ARRAY_SIZE(req->out._vector)) {
|
||||||
@@ -1035,7 +1042,10 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
|
|||||||
req->out.vector_count = count;
|
req->out.vector_count = count;
|
||||||
|
|
||||||
/* setup the length of the NBT packet */
|
/* setup the length of the NBT packet */
|
||||||
smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
|
ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
|
||||||
|
if (!ok) {
|
||||||
|
return NT_STATUS_INVALID_PARAMETER_MIX;
|
||||||
|
}
|
||||||
|
|
||||||
DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
|
DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
|
||||||
|
|
||||||
@@ -1156,6 +1166,7 @@ static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *re
|
|||||||
struct iovec *outvec = NULL;
|
struct iovec *outvec = NULL;
|
||||||
int count = req->out.vector_count;
|
int count = req->out.vector_count;
|
||||||
int i;
|
int i;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
newreq = smbd_smb2_request_allocate(req->xconn);
|
newreq = smbd_smb2_request_allocate(req->xconn);
|
||||||
if (!newreq) {
|
if (!newreq) {
|
||||||
@@ -1195,8 +1206,12 @@ static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *re
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
smb2_setup_nbt_length(newreq->out.vector,
|
ok = smb2_setup_nbt_length(newreq->out.vector,
|
||||||
newreq->out.vector_count);
|
newreq->out.vector_count);
|
||||||
|
if (!ok) {
|
||||||
|
TALLOC_FREE(newreq);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return newreq;
|
return newreq;
|
||||||
}
|
}
|
||||||
@@ -1210,6 +1225,7 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request
|
|||||||
uint8_t *outhdr = NULL;
|
uint8_t *outhdr = NULL;
|
||||||
struct smbd_smb2_request *nreq = NULL;
|
struct smbd_smb2_request *nreq = NULL;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
/* Create a new smb2 request we'll use
|
/* Create a new smb2 request we'll use
|
||||||
for the interim return. */
|
for the interim return. */
|
||||||
@@ -1222,8 +1238,11 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request
|
|||||||
ones we'll be using for the async reply. */
|
ones we'll be using for the async reply. */
|
||||||
nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
|
nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
|
||||||
|
|
||||||
smb2_setup_nbt_length(nreq->out.vector,
|
ok = smb2_setup_nbt_length(nreq->out.vector,
|
||||||
nreq->out.vector_count);
|
nreq->out.vector_count);
|
||||||
|
if (!ok) {
|
||||||
|
return NT_STATUS_INVALID_PARAMETER_MIX;
|
||||||
|
}
|
||||||
|
|
||||||
/* Step back to the previous reply. */
|
/* Step back to the previous reply. */
|
||||||
nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
|
nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
|
||||||
@@ -1463,6 +1482,7 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
|
|||||||
uint64_t nonce_low = 0;
|
uint64_t nonce_low = 0;
|
||||||
uint64_t async_id = 0;
|
uint64_t async_id = 0;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
TALLOC_FREE(req->async_te);
|
TALLOC_FREE(req->async_te);
|
||||||
|
|
||||||
@@ -1564,7 +1584,13 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
|
|||||||
state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
|
state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base = dyn;
|
||||||
state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
|
state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len = 1;
|
||||||
|
|
||||||
smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
|
ok = smb2_setup_nbt_length(state->vector,
|
||||||
|
1 + SMBD_SMB2_NUM_IOV_PER_REQ);
|
||||||
|
if (!ok) {
|
||||||
|
smbd_server_connection_terminate(
|
||||||
|
xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure we correctly go through crediting. Grant
|
/* Ensure we correctly go through crediting. Grant
|
||||||
the credits now, and zero credits on the final
|
the credits now, and zero credits on the final
|
||||||
@@ -2326,6 +2352,7 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
|
|||||||
struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
|
struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
|
||||||
struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
|
struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
req->subreq = NULL;
|
req->subreq = NULL;
|
||||||
TALLOC_FREE(req->async_te);
|
TALLOC_FREE(req->async_te);
|
||||||
@@ -2453,7 +2480,10 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
|
|||||||
req->compound_related = false;
|
req->compound_related = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
|
ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
|
||||||
|
if (!ok) {
|
||||||
|
return NT_STATUS_INVALID_PARAMETER_MIX;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set credit for these operations (zero credits if this
|
/* Set credit for these operations (zero credits if this
|
||||||
is a final reply for an async operation). */
|
is a final reply for an async operation). */
|
||||||
@@ -2736,6 +2766,7 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
|
|||||||
uint64_t nonce_low = 0;
|
uint64_t nonce_low = 0;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
size_t statelen;
|
size_t statelen;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
if (session != NULL) {
|
if (session != NULL) {
|
||||||
session_wire_id = session->global->session_wire_id;
|
session_wire_id = session->global->session_wire_id;
|
||||||
@@ -2817,7 +2848,11 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
|
|||||||
* state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
|
* state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
|
||||||
*/
|
*/
|
||||||
|
|
||||||
smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
|
ok = smb2_setup_nbt_length(state->vector,
|
||||||
|
1 + SMBD_SMB2_NUM_IOV_PER_REQ);
|
||||||
|
if (!ok) {
|
||||||
|
return NT_STATUS_INVALID_PARAMETER_MIX;
|
||||||
|
}
|
||||||
|
|
||||||
if (do_encryption) {
|
if (do_encryption) {
|
||||||
DATA_BLOB encryption_key = session->global->encryption_key;
|
DATA_BLOB encryption_key = session->global->encryption_key;
|
||||||
|
Reference in New Issue
Block a user