From 83e8b015253c68b24007676b6efda4ebcf5f346c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 16 Aug 2012 06:55:36 +0200 Subject: [PATCH] libcli/smb: support broken OS/2 error responses bug #9096 OS/2 skips the DATA Block in SMB1 responses. metze --- libcli/smb/smbXcli_base.c | 60 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index 45da5fd..97774d2 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -1608,13 +1608,27 @@ static NTSTATUS smb1cli_inbuf_parse_chain(uint8_t *buf, TALLOC_CTX *mem_ctx, uint8_t *hdr; uint8_t cmd; uint32_t wct_ofs; + NTSTATUS status; + size_t min_size = MIN_SMB_SIZE; buflen = smb_len_nbt(buf); taken = 0; hdr = buf + NBT_HDR_SIZE; - if (buflen < MIN_SMB_SIZE) { + status = smb1cli_pull_raw_error(inhdr); + if (NT_STATUS_IS_ERR(status)) { + /* + * This is an ugly hack to support OS/2 + * which skips the byte_count in the DATA block + * on some error responses. + * + * See bug #9096 + */ + min_size -= sizeof(uint16_t); + } + + if (buflen < min_size) { return NT_STATUS_INVALID_NETWORK_RESPONSE; } @@ -1655,9 +1669,9 @@ static NTSTATUS smb1cli_inbuf_parse_chain(uint8_t *buf, TALLOC_CTX *mem_ctx, size_t needed; /* - * we need at least WCT and BCC + * we need at least WCT */ - needed = sizeof(uint8_t) + sizeof(uint16_t); + needed = sizeof(uint8_t); if (len < needed) { DEBUG(10, ("%s: %d bytes left, expected at least %d\n", __location__, (int)len, (int)needed)); @@ -1675,6 +1689,46 @@ static NTSTATUS smb1cli_inbuf_parse_chain(uint8_t *buf, TALLOC_CTX *mem_ctx, goto inval; } + if ((num_iov == 1) && + (len == needed) && + NT_STATUS_IS_ERR(status)) + { + /* + * This is an ugly hack to support OS/2 + * which skips the byte_count in the DATA block + * on some error responses. + * + * See bug #9096 + */ + iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec, + num_iov + 2); + if (iov_tmp == NULL) { + TALLOC_FREE(iov); + return NT_STATUS_NO_MEMORY; + } + iov = iov_tmp; + cur = &iov[num_iov]; + num_iov += 2; + + cur[0].iov_len = 0; + cur[0].iov_base = hdr + (wct_ofs + sizeof(uint8_t)); + cur[1].iov_len = 0; + cur[1].iov_base = cur[0].iov_base; + + taken += needed; + break; + } + + /* + * we need at least BCC + */ + needed += sizeof(uint16_t); + if (len < needed) { + DEBUG(10, ("%s: %d bytes left, expected at least %d\n", + __location__, (int)len, (int)needed)); + goto inval; + } + /* * Now we check if the specified bytes are there */ -- 1.7.9.5