Skip to content

Commit 36314be

Browse files
authored
Merge pull request #393 from bdodge/bdd/fix-getinfo-buffer-overflow
Bdd/fix getinfo buffer overflow
2 parents 39c02e8 + 14286e4 commit 36314be

File tree

8 files changed

+115
-3
lines changed

8 files changed

+115
-3
lines changed

Diff for: include/libsmb2-private.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ extern "C" {
3232
#include <gssapi/gssapi.h>
3333
#include <gssapi/gssapi_ext.h>
3434
#endif /* __APPLE__ */
35-
#endif /* HAVE_LIBKRB5 */
35+
#endif /* HAVE_LIBKRB5 */
3636

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

@@ -341,7 +341,7 @@ struct smb2dir {
341341
int index;
342342
};
343343

344-
344+
345345
#define smb2_is_server(ctx) ((ctx)->owning_server != NULL)
346346

347347
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,
554554
struct smb2_file_network_open_info *fs,
555555
struct smb2_iovec *vec);
556556

557+
int smb2_decode_file_normalized_name_info(struct smb2_context *smb2,
558+
void *memctx,
559+
struct smb2_file_name_info *fs,
560+
struct smb2_iovec *vec);
561+
int smb2_encode_file_normalized_name_info(struct smb2_context *smb2,
562+
struct smb2_file_name_info *fs,
563+
struct smb2_iovec *vec);
557564
int smb2_decode_security_descriptor(struct smb2_context *smb2,
558565
void *memctx,
559566
struct smb2_security_descriptor *sd,

Diff for: include/smb2/libsmb2.h

+1
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ void smb2_add_compound_pdu(struct smb2_context *smb2,
642642
struct smb2_pdu *pdu, struct smb2_pdu *next_pdu);
643643
void smb2_free_pdu(struct smb2_context *smb2, struct smb2_pdu *pdu);
644644
void smb2_queue_pdu(struct smb2_context *smb2, struct smb2_pdu *pdu);
645+
void smb2_set_pdu_status(struct smb2_context *smb2, struct smb2_pdu *pdu, int status);
645646
int smb2_pdu_is_compound(struct smb2_context *smb2);
646647

647648
/*

Diff for: include/smb2/smb2-errors.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -544,4 +544,6 @@
544544
#define SMB2_STATUS_SERVER_UNAVAILABLE 0xC0000466
545545

546546
/* Warning codes */
547-
#define SMB2_STATUS_STOPPED_ON_SYMLINK 0x8000002d
547+
#define SMB2_STATUS_BUFFER_OVERFLOW 0x80000005
548+
#define SMB2_STATUS_STOPPED_ON_SYMLINK 0x8000002D
549+

Diff for: include/smb2/smb2.h

+8
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,14 @@ struct smb2_file_position_info {
633633
uint64_t current_byte_offset;
634634
};
635635

636+
/*
637+
* FILE_NAME_INFORMATION
638+
*/
639+
struct smb2_file_name_info {
640+
uint32_t file_name_length;
641+
const uint8_t *name;
642+
};
643+
636644
/*
637645
* FILE_ALL_INFORMATION.
638646
*/

Diff for: lib/Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ libsmb2_la_CPPFLAGS = -I$(abs_top_srcdir)/include \
88

99
libsmb2_la_SOURCES = \
1010
aes.h \
11+
aes_reference.c \
1112
aes.c \
1213
aes128ccm.h \
1314
aes128ccm.c \

Diff for: lib/pdu.c

+6
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,12 @@ smb2_queue_pdu(struct smb2_context *smb2, struct smb2_pdu *pdu)
654654
smb2_add_to_outqueue(smb2, pdu);
655655
}
656656

657+
void
658+
smb2_set_pdu_status(struct smb2_context *smb2, struct smb2_pdu *pdu, int status)
659+
{
660+
pdu->header.status = status;
661+
}
662+
657663
struct smb2_pdu *
658664
smb2_find_pdu(struct smb2_context *smb2,
659665
uint64_t message_id) {

Diff for: lib/smb2-cmd-query-info.c

+16
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ smb2_encode_query_info_reply(struct smb2_context *smb2,
204204
(struct smb2_file_network_open_info *)rep->output_buffer, iov);
205205
break;
206206
case SMB2_FILE_NORMALIZED_NAME_INFORMATION:
207+
created_output_buffer_length =
208+
smb2_encode_file_normalized_name_info(smb2,
209+
(struct smb2_file_name_info *)rep->output_buffer, iov);
207210
break;
208211
case SMB2_FILE_PIPE_INFORMATION:
209212
break;
@@ -300,6 +303,11 @@ smb2_encode_query_info_reply(struct smb2_context *smb2,
300303
req->info_type, req->file_info_class);
301304
}
302305
} else {
306+
if (created_output_buffer_length > req->output_buffer_length) {
307+
/* truncate output buffer to what request can handle in return */
308+
created_output_buffer_length = req->output_buffer_length;
309+
smb2_set_pdu_status(smb2, pdu, SMB2_STATUS_BUFFER_OVERFLOW);
310+
}
303311
iov->len = PAD_TO_64BIT(created_output_buffer_length);
304312
rep->output_buffer_length = created_output_buffer_length;
305313
}
@@ -472,6 +480,14 @@ int smb2_process_query_info_variable(struct smb2_context *smb2,
472480
}
473481
break;
474482
case SMB2_FILE_NORMALIZED_NAME_INFORMATION:
483+
ptr = smb2_alloc_init(smb2,
484+
sizeof(struct smb2_file_name_info));
485+
if (smb2_decode_file_normalized_name_info(smb2, ptr, ptr, &vec)) {
486+
smb2_set_error(smb2, "could not decode file "
487+
"normalized name info. %s",
488+
smb2_get_error(smb2));
489+
return -1;
490+
}
475491
break;
476492
case SMB2_FILE_PIPE_INFORMATION:
477493
break;

Diff for: lib/smb2-data-file-info.c

+71
Original file line numberDiff line numberDiff line change
@@ -320,3 +320,74 @@ smb2_encode_file_network_open_info(struct smb2_context *smb2,
320320
return 52;
321321
}
322322

323+
324+
int
325+
smb2_decode_file_normalized_name_info(struct smb2_context *smb2,
326+
void *memctx,
327+
struct smb2_file_name_info *fs,
328+
struct smb2_iovec *vec)
329+
{
330+
struct smb2_iovec v _U_;
331+
uint32_t name_len;
332+
const char *name;
333+
334+
if (vec->len < 40) {
335+
return -1;
336+
}
337+
338+
v.buf = &vec->buf[0];
339+
v.len = 4;
340+
smb2_get_uint32(vec, 0, &name_len);
341+
342+
fs->file_name_length = name_len / 2;
343+
344+
if (name_len > 0) {
345+
if (vec->len < (name_len + 4)) {
346+
return -1;
347+
}
348+
name = smb2_utf16_to_utf8((uint16_t *)&vec->buf[4], name_len / 2);
349+
fs->name = smb2_alloc_data(smb2, memctx, strlen(name) + 1);
350+
if (fs->name == NULL) {
351+
free(discard_const(name));
352+
return -1;
353+
}
354+
strcpy(discard_const(fs->name), name);
355+
free(discard_const(name));
356+
} else {
357+
fs->name = NULL;
358+
}
359+
return 0;
360+
}
361+
362+
int
363+
smb2_encode_file_normalized_name_info(struct smb2_context *smb2,
364+
struct smb2_file_name_info *fs,
365+
struct smb2_iovec *vec)
366+
{
367+
struct smb2_utf16 *name = NULL;
368+
int name_len;
369+
370+
if (vec->len < 4) {
371+
return -1;
372+
}
373+
374+
if (fs->name) {
375+
name = smb2_utf8_to_utf16((const char*)fs->name);
376+
if (name) {
377+
name_len = 2 * name->len;
378+
if (vec->len < name_len + 4) {
379+
return -1;
380+
}
381+
smb2_set_uint32(vec, 0, name_len);
382+
memcpy((uint16_t *)&vec->buf[4], name->val, name_len);
383+
free(name);
384+
return 4 + name_len;
385+
} else {
386+
return -1;
387+
}
388+
} else {
389+
smb2_set_uint32(vec, 0, 0);
390+
return 4;
391+
}
392+
}
393+

0 commit comments

Comments
 (0)