diff options
author | Stefan Metzmacher <metze@samba.org> | 2012-08-16 06:55:36 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2012-08-16 13:16:48 +0200 |
commit | 56fc7bc661bcea0a63d28efdd50c345715ea21bd (patch) | |
tree | d61a4f5b82bad3fe03489da209b964fd1f280cda /libcli | |
parent | df8e9c128716c89f5a1d58f032e3d641e033c8b0 (diff) | |
download | samba-56fc7bc661bcea0a63d28efdd50c345715ea21bd.tar.gz |
libcli/smb: support broken OS/2 error responses bug #9096
OS/2 skips the DATA Block in SMB1 responses.
metze
Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(master): Thu Aug 16 13:16:49 CEST 2012 on sn-devel-104
Diffstat (limited to 'libcli')
-rw-r--r-- | libcli/smb/smbXcli_base.c | 60 |
1 files changed, 57 insertions, 3 deletions
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index 45da5fd90f..a9adcbb0b7 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(hdr); + 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 */ |