From 2da33ae2196b6945abfdf84c35ab2c300cf2019c Mon Sep 17 00:00:00 2001 From: bdodge Date: Sun, 19 Jan 2025 15:48:36 -0500 Subject: [PATCH 1/3] fix linux build post aes ref --- lib/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Makefile.am b/lib/Makefile.am index a5794926..c6bff442 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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 \ From bdaef47fa94d96a06015e8258384bff14f4d9ea3 Mon Sep 17 00:00:00 2001 From: bdodge Date: Sun, 19 Jan 2025 15:49:12 -0500 Subject: [PATCH 2/3] add ability to set status in pdu in public api --- include/smb2/libsmb2.h | 1 + include/smb2/smb2-errors.h | 4 +++- lib/pdu.c | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/smb2/libsmb2.h b/include/smb2/libsmb2.h index 703a9794..6f5b19b5 100644 --- a/include/smb2/libsmb2.h +++ b/include/smb2/libsmb2.h @@ -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); /* diff --git a/include/smb2/smb2-errors.h b/include/smb2/smb2-errors.h index 0c8c4449..783ecbbc 100644 --- a/include/smb2/smb2-errors.h +++ b/include/smb2/smb2-errors.h @@ -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 + diff --git a/lib/pdu.c b/lib/pdu.c index c8bde482..be3d0dc8 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -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) { From 14286e43b987aa859a3ce5fd3ecc502308e7ed63 Mon Sep 17 00:00:00 2001 From: bdodge Date: Sun, 19 Jan 2025 16:37:12 -0500 Subject: [PATCH 3/3] add handlers for transcoding normalized file info, detect buffer overflow on reply encoding --- include/libsmb2-private.h | 11 ++++-- include/smb2/smb2.h | 8 +++++ lib/smb2-cmd-query-info.c | 16 +++++++++ lib/smb2-data-file-info.c | 71 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/include/libsmb2-private.h b/include/libsmb2-private.h index d73bbc5d..79af160f 100644 --- a/include/libsmb2-private.h +++ b/include/libsmb2-private.h @@ -32,7 +32,7 @@ extern "C" { #include #include #endif /* __APPLE__ */ -#endif /* HAVE_LIBKRB5 */ +#endif /* HAVE_LIBKRB5 */ #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -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, @@ -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, diff --git a/include/smb2/smb2.h b/include/smb2/smb2.h index 7dee273a..9ea94338 100644 --- a/include/smb2/smb2.h +++ b/include/smb2/smb2.h @@ -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. */ diff --git a/lib/smb2-cmd-query-info.c b/lib/smb2-cmd-query-info.c index 0cef94d1..00e52fdf 100644 --- a/lib/smb2-cmd-query-info.c +++ b/lib/smb2-cmd-query-info.c @@ -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; @@ -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; } @@ -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; diff --git a/lib/smb2-data-file-info.c b/lib/smb2-data-file-info.c index 7b921ffa..73e87d36 100644 --- a/lib/smb2-data-file-info.c +++ b/lib/smb2-data-file-info.c @@ -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; + } +} +