Skip to content

Commit

Permalink
Merge pull request #393 from bdodge/bdd/fix-getinfo-buffer-overflow
Browse files Browse the repository at this point in the history
Bdd/fix getinfo buffer overflow
  • Loading branch information
sahlberg authored Jan 19, 2025
2 parents 39c02e8 + 14286e4 commit 36314be
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 3 deletions.
11 changes: 9 additions & 2 deletions include/libsmb2-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extern "C" {
#include <gssapi/gssapi.h>
#include <gssapi/gssapi_ext.h>
#endif /* __APPLE__ */
#endif /* HAVE_LIBKRB5 */
#endif /* HAVE_LIBKRB5 */

#define MIN(a,b) (((a)<(b))?(a):(b))

Expand Down Expand Up @@ -341,7 +341,7 @@ struct smb2dir {
int index;
};


#define smb2_is_server(ctx) ((ctx)->owning_server != NULL)

void smb2_set_nterror(struct smb2_context *smb2, int nterror,
Expand Down Expand Up @@ -554,6 +554,13 @@ int smb2_encode_file_network_open_info(struct smb2_context *smb2,
struct smb2_file_network_open_info *fs,
struct smb2_iovec *vec);

int smb2_decode_file_normalized_name_info(struct smb2_context *smb2,
void *memctx,
struct smb2_file_name_info *fs,
struct smb2_iovec *vec);
int smb2_encode_file_normalized_name_info(struct smb2_context *smb2,
struct smb2_file_name_info *fs,
struct smb2_iovec *vec);
int smb2_decode_security_descriptor(struct smb2_context *smb2,
void *memctx,
struct smb2_security_descriptor *sd,
Expand Down
1 change: 1 addition & 0 deletions include/smb2/libsmb2.h
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ void smb2_add_compound_pdu(struct smb2_context *smb2,
struct smb2_pdu *pdu, struct smb2_pdu *next_pdu);
void smb2_free_pdu(struct smb2_context *smb2, struct smb2_pdu *pdu);
void smb2_queue_pdu(struct smb2_context *smb2, struct smb2_pdu *pdu);
void smb2_set_pdu_status(struct smb2_context *smb2, struct smb2_pdu *pdu, int status);
int smb2_pdu_is_compound(struct smb2_context *smb2);

/*
Expand Down
4 changes: 3 additions & 1 deletion include/smb2/smb2-errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,4 +544,6 @@
#define SMB2_STATUS_SERVER_UNAVAILABLE 0xC0000466

/* Warning codes */
#define SMB2_STATUS_STOPPED_ON_SYMLINK 0x8000002d
#define SMB2_STATUS_BUFFER_OVERFLOW 0x80000005
#define SMB2_STATUS_STOPPED_ON_SYMLINK 0x8000002D

8 changes: 8 additions & 0 deletions include/smb2/smb2.h
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,14 @@ struct smb2_file_position_info {
uint64_t current_byte_offset;
};

/*
* FILE_NAME_INFORMATION
*/
struct smb2_file_name_info {
uint32_t file_name_length;
const uint8_t *name;
};

/*
* FILE_ALL_INFORMATION.
*/
Expand Down
1 change: 1 addition & 0 deletions lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ libsmb2_la_CPPFLAGS = -I$(abs_top_srcdir)/include \

libsmb2_la_SOURCES = \
aes.h \
aes_reference.c \
aes.c \
aes128ccm.h \
aes128ccm.c \
Expand Down
6 changes: 6 additions & 0 deletions lib/pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,12 @@ smb2_queue_pdu(struct smb2_context *smb2, struct smb2_pdu *pdu)
smb2_add_to_outqueue(smb2, pdu);
}

void
smb2_set_pdu_status(struct smb2_context *smb2, struct smb2_pdu *pdu, int status)
{
pdu->header.status = status;
}

struct smb2_pdu *
smb2_find_pdu(struct smb2_context *smb2,
uint64_t message_id) {
Expand Down
16 changes: 16 additions & 0 deletions lib/smb2-cmd-query-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ smb2_encode_query_info_reply(struct smb2_context *smb2,
(struct smb2_file_network_open_info *)rep->output_buffer, iov);
break;
case SMB2_FILE_NORMALIZED_NAME_INFORMATION:
created_output_buffer_length =
smb2_encode_file_normalized_name_info(smb2,
(struct smb2_file_name_info *)rep->output_buffer, iov);
break;
case SMB2_FILE_PIPE_INFORMATION:
break;
Expand Down Expand Up @@ -300,6 +303,11 @@ smb2_encode_query_info_reply(struct smb2_context *smb2,
req->info_type, req->file_info_class);
}
} else {
if (created_output_buffer_length > req->output_buffer_length) {
/* truncate output buffer to what request can handle in return */
created_output_buffer_length = req->output_buffer_length;
smb2_set_pdu_status(smb2, pdu, SMB2_STATUS_BUFFER_OVERFLOW);
}
iov->len = PAD_TO_64BIT(created_output_buffer_length);
rep->output_buffer_length = created_output_buffer_length;
}
Expand Down Expand Up @@ -472,6 +480,14 @@ int smb2_process_query_info_variable(struct smb2_context *smb2,
}
break;
case SMB2_FILE_NORMALIZED_NAME_INFORMATION:
ptr = smb2_alloc_init(smb2,
sizeof(struct smb2_file_name_info));
if (smb2_decode_file_normalized_name_info(smb2, ptr, ptr, &vec)) {
smb2_set_error(smb2, "could not decode file "
"normalized name info. %s",
smb2_get_error(smb2));
return -1;
}
break;
case SMB2_FILE_PIPE_INFORMATION:
break;
Expand Down
71 changes: 71 additions & 0 deletions lib/smb2-data-file-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,74 @@ smb2_encode_file_network_open_info(struct smb2_context *smb2,
return 52;
}


int
smb2_decode_file_normalized_name_info(struct smb2_context *smb2,
void *memctx,
struct smb2_file_name_info *fs,
struct smb2_iovec *vec)
{
struct smb2_iovec v _U_;
uint32_t name_len;
const char *name;

if (vec->len < 40) {
return -1;
}

v.buf = &vec->buf[0];
v.len = 4;
smb2_get_uint32(vec, 0, &name_len);

fs->file_name_length = name_len / 2;

if (name_len > 0) {
if (vec->len < (name_len + 4)) {
return -1;
}
name = smb2_utf16_to_utf8((uint16_t *)&vec->buf[4], name_len / 2);
fs->name = smb2_alloc_data(smb2, memctx, strlen(name) + 1);
if (fs->name == NULL) {
free(discard_const(name));
return -1;
}
strcpy(discard_const(fs->name), name);
free(discard_const(name));
} else {
fs->name = NULL;
}
return 0;
}

int
smb2_encode_file_normalized_name_info(struct smb2_context *smb2,
struct smb2_file_name_info *fs,
struct smb2_iovec *vec)
{
struct smb2_utf16 *name = NULL;
int name_len;

if (vec->len < 4) {
return -1;
}

if (fs->name) {
name = smb2_utf8_to_utf16((const char*)fs->name);
if (name) {
name_len = 2 * name->len;
if (vec->len < name_len + 4) {
return -1;
}
smb2_set_uint32(vec, 0, name_len);
memcpy((uint16_t *)&vec->buf[4], name->val, name_len);
free(name);
return 4 + name_len;
} else {
return -1;
}
} else {
smb2_set_uint32(vec, 0, 0);
return 4;
}
}

0 comments on commit 36314be

Please sign in to comment.