Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bdd/fix getinfo buffer overflow #393

Merged
merged 3 commits into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
}

Loading