mirror of
https://github.com/samba-team/samba.git
synced 2025-08-04 08:22:08 +03:00
Convert SMB and SMB2 code to use a common buffer handling structure
This converts our SMB and SMB2 code to use a common structure "struct
request_bufinfo" for information on the buffer bounds of a packet,
alignment information and string handling. This allows us to use a
common backend for SMB and SMB2 code, while still using all the same
string and blob handling functions.
Up to now we had been passing a NULL req handle into these common
routines from the SMB2 side of the server, which meant that we failed
any operation which did a bounds checked string extraction (such as a
RenameInformation setinfo call, which is what Vista uses for renaming
files)
There is still some more work to be done on this - for example we can
now remove many of the SMB2 specific buffer handling functions that we
had, and use the SMB ones.
(This used to be commit ca6d9be6cb
)
This commit is contained in:
@ -34,6 +34,17 @@
|
||||
/* assume that a character will not consume more than 3 bytes per char */
|
||||
#define MAX_BYTES_PER_CHAR 3
|
||||
|
||||
/* setup the bufinfo used for strings and range checking */
|
||||
void smb_setup_bufinfo(struct smbcli_request *req)
|
||||
{
|
||||
req->in.bufinfo.mem_ctx = req;
|
||||
req->in.bufinfo.unicode = (req->flags2 & FLAGS2_UNICODE_STRINGS)?true:false;
|
||||
req->in.bufinfo.align_base = req->in.buffer;
|
||||
req->in.bufinfo.data = req->in.data;
|
||||
req->in.bufinfo.data_size = req->in.data_size;
|
||||
}
|
||||
|
||||
|
||||
/* destroy a request structure and return final status */
|
||||
NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
|
||||
{
|
||||
@ -298,6 +309,9 @@ NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
|
||||
req->in.data = req->in.vwv + 2 + req->in.wct * 2;
|
||||
req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
|
||||
|
||||
/* fix the bufinfo */
|
||||
smb_setup_bufinfo(req);
|
||||
|
||||
if (buffer + 3 + req->in.wct*2 + req->in.data_size >
|
||||
req->in.buffer + req->in.size) {
|
||||
return NT_STATUS_BUFFER_TOO_SMALL;
|
||||
@ -544,13 +558,13 @@ size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *by
|
||||
on failure zero is returned and *dest is set to NULL, otherwise the number
|
||||
of bytes consumed in the packet is returned
|
||||
*/
|
||||
static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
|
||||
static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
|
||||
char **dest, const uint8_t *src, int byte_len, uint_t flags)
|
||||
{
|
||||
int src_len, src_len2, alignment=0;
|
||||
ssize_t ret;
|
||||
|
||||
if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
|
||||
if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
|
||||
src++;
|
||||
alignment=1;
|
||||
if (byte_len != -1) {
|
||||
@ -558,7 +572,7 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c
|
||||
}
|
||||
}
|
||||
|
||||
src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
|
||||
src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
|
||||
if (src_len < 0) {
|
||||
*dest = NULL;
|
||||
return 0;
|
||||
@ -597,13 +611,13 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c
|
||||
on failure zero is returned and *dest is set to NULL, otherwise the number
|
||||
of bytes consumed in the packet is returned
|
||||
*/
|
||||
size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
|
||||
size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
|
||||
char **dest, const uint8_t *src, int byte_len, uint_t flags)
|
||||
{
|
||||
int src_len, src_len2;
|
||||
ssize_t ret;
|
||||
|
||||
src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
|
||||
src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
|
||||
if (src_len < 0) {
|
||||
*dest = NULL;
|
||||
return 0;
|
||||
@ -640,15 +654,15 @@ size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
|
||||
on failure zero is returned and *dest is set to NULL, otherwise the number
|
||||
of bytes consumed in the packet is returned
|
||||
*/
|
||||
size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
|
||||
size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
|
||||
char **dest, const uint8_t *src, int byte_len, uint_t flags)
|
||||
{
|
||||
if (!(flags & STR_ASCII) &&
|
||||
(((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
|
||||
return smbcli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
|
||||
(((flags & STR_UNICODE) || bufinfo->unicode))) {
|
||||
return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
|
||||
}
|
||||
|
||||
return smbcli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
|
||||
return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
|
||||
}
|
||||
|
||||
|
||||
@ -658,11 +672,11 @@ size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
|
||||
|
||||
if byte_len is -1 then limit the blob only by packet size
|
||||
*/
|
||||
DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
|
||||
DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
|
||||
{
|
||||
int src_len;
|
||||
|
||||
src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
|
||||
src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
|
||||
|
||||
if (src_len < 0) {
|
||||
return data_blob(NULL, 0);
|
||||
@ -677,13 +691,13 @@ DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
|
||||
|
||||
/* check that a lump of data in a request is within the bounds of the data section of
|
||||
the packet */
|
||||
static bool smbcli_req_data_oob(struct smbcli_request *req, const uint8_t *ptr, uint32_t count)
|
||||
static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
|
||||
{
|
||||
/* be careful with wraparound! */
|
||||
if (ptr < req->in.data ||
|
||||
ptr >= req->in.data + req->in.data_size ||
|
||||
count > req->in.data_size ||
|
||||
ptr + count > req->in.data + req->in.data_size) {
|
||||
if (ptr < bufinfo->data ||
|
||||
ptr >= bufinfo->data + bufinfo->data_size ||
|
||||
count > bufinfo->data_size ||
|
||||
ptr + count > bufinfo->data + bufinfo->data_size) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -694,11 +708,11 @@ static bool smbcli_req_data_oob(struct smbcli_request *req, const uint8_t *ptr,
|
||||
|
||||
return false if any part is outside the data portion of the packet
|
||||
*/
|
||||
bool smbcli_raw_pull_data(struct smbcli_request *req, const uint8_t *src, int len, uint8_t *dest)
|
||||
bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
|
||||
{
|
||||
if (len == 0) return true;
|
||||
|
||||
if (smbcli_req_data_oob(req, src, len)) {
|
||||
if (smbcli_req_data_oob(bufinfo, src, len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user