diff options
-rw-r--r-- | source3/smbd/smb2_server.c | 94 |
1 files changed, 52 insertions, 42 deletions
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index e3b6faaf2f..42f772652a 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -934,68 +934,78 @@ static bool dup_smb2_vec3(TALLOC_CTX *ctx, struct iovec *outvec, const struct iovec *srcvec) { - /* vec[0] is always boilerplate and must + const uint8_t *srchdr; + size_t srchdr_len; + const uint8_t *srcbody; + size_t srcbody_len; + const uint8_t *expected_srcbody; + const uint8_t *srcdyn; + size_t srcdyn_len; + const uint8_t *expected_srcdyn; + uint8_t *dsthdr; + uint8_t *dstbody; + uint8_t *dstdyn; + + srchdr = (const uint8_t *)srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base; + srchdr_len = srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_len; + srcbody = (const uint8_t *)srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_base; + srcbody_len = srcvec[SMBD_SMB2_BODY_IOV_OFS].iov_len; + expected_srcbody = srchdr + SMB2_HDR_BODY; + srcdyn = (const uint8_t *)srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_base; + srcdyn_len = srcvec[SMBD_SMB2_DYN_IOV_OFS].iov_len; + expected_srcdyn = srcbody + 8; + + if (srchdr_len != SMB2_HDR_BODY) { + return false; + } + + /* vec[SMBD_SMB2_HDR_IOV_OFS] is always boilerplate and must * be allocated with size OUTVEC_ALLOC_SIZE. */ - outvec[0].iov_base = talloc_memdup(ctx, - srcvec[0].iov_base, - OUTVEC_ALLOC_SIZE); - if (!outvec[0].iov_base) { + dsthdr = talloc_memdup(ctx, srchdr, OUTVEC_ALLOC_SIZE); + if (dsthdr == NULL) { return false; } - outvec[0].iov_len = SMB2_HDR_BODY; + outvec[SMBD_SMB2_HDR_IOV_OFS].iov_base = (void *)dsthdr; + outvec[SMBD_SMB2_HDR_IOV_OFS].iov_len = SMB2_HDR_BODY; /* - * If this is a "standard" vec[1] of length 8, - * pointing to srcvec[0].iov_base + SMB2_HDR_BODY, + * If this is a "standard" vec[SMBD_SMB2_BOFY_IOV_OFS] of length 8, + * pointing to srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + SMB2_HDR_BODY, * then duplicate this. Else use talloc_memdup(). */ - if (srcvec[1].iov_len == 8 && - srcvec[1].iov_base == - ((uint8_t *)srcvec[0].iov_base) + - SMB2_HDR_BODY) { - outvec[1].iov_base = ((uint8_t *)outvec[0].iov_base) + - SMB2_HDR_BODY; - outvec[1].iov_len = 8; + if ((srcbody == expected_srcbody) && (srcbody_len == 8)) { + dstbody = dsthdr + SMB2_HDR_BODY; } else { - outvec[1].iov_base = talloc_memdup(ctx, - srcvec[1].iov_base, - srcvec[1].iov_len); - if (!outvec[1].iov_base) { + dstbody = talloc_memdup(ctx, srcbody, srcbody_len); + if (dstbody == NULL) { return false; } - outvec[1].iov_len = srcvec[1].iov_len; } + outvec[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)dstbody; + outvec[SMBD_SMB2_BODY_IOV_OFS].iov_len = srcbody_len; /* - * If this is a "standard" vec[2] of length 1, - * pointing to srcvec[0].iov_base + (OUTVEC_ALLOC_SIZE - 1) + * If this is a "standard" vec[SMBD_SMB2_DYN_IOV_OFS] of length 1, + * pointing to + * srcvec[SMBD_SMB2_HDR_IOV_OFS].iov_base + 8 * then duplicate this. Else use talloc_memdup(). */ - if (srcvec[2].iov_base && - srcvec[2].iov_len) { - if (srcvec[2].iov_base == - ((uint8_t *)srcvec[0].iov_base) + - (OUTVEC_ALLOC_SIZE - 1) && - srcvec[2].iov_len == 1) { - /* Common SMB2 error packet case. */ - outvec[2].iov_base = ((uint8_t *)outvec[0].iov_base) + - (OUTVEC_ALLOC_SIZE - 1); - } else { - outvec[2].iov_base = talloc_memdup(ctx, - srcvec[2].iov_base, - srcvec[2].iov_len); - if (!outvec[2].iov_base) { - return false; - } - } - outvec[2].iov_len = srcvec[2].iov_len; + if ((srcdyn == expected_srcdyn) && (srcdyn_len == 1)) { + dstdyn = dsthdr + SMB2_HDR_BODY + 8; + } else if (srcdyn == NULL) { + dstdyn = NULL; } else { - outvec[2].iov_base = NULL; - outvec[2].iov_len = 0; + dstdyn = talloc_memdup(ctx, srcdyn, srcdyn_len); + if (dstdyn == NULL) { + return false; + } } + outvec[SMBD_SMB2_DYN_IOV_OFS].iov_base = (void *)dstdyn; + outvec[SMBD_SMB2_DYN_IOV_OFS].iov_len = srcdyn_len; + return true; } |