From ccc27e681cbd6283513b929d58f2ebce35e6658b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Feb 2008 12:54:44 +1100 Subject: fixed up the .in side of SMB2 negprot fixed the input side of the SMB2 negprot structure and parsers according to the documentation (This used to be commit 55af8acc7b32c24e4b1187e9d8d1c8f060e914b0) --- source4/libcli/smb2/connect.c | 8 +++++++- source4/libcli/smb2/negprot.c | 31 ++++++++++++++++++++++++------- source4/libcli/smb2/smb2_calls.h | 13 ++++++++----- 3 files changed, 39 insertions(+), 13 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 4518203183..a2ae828fa5 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -120,6 +120,7 @@ static void continue_socket(struct composite_context *creq) struct smbcli_socket *sock; struct smb2_transport *transport; struct smb2_request *req; + uint16_t dialects[1]; c->status = smbcli_sock_connect_recv(creq, state, &sock); if (!composite_is_ok(c)) return; @@ -128,7 +129,12 @@ static void continue_socket(struct composite_context *creq) if (composite_nomem(transport, c)) return; ZERO_STRUCT(state->negprot); - state->negprot.in.unknown1 = 0x0001; + state->negprot.in.dialect_count = 1; + state->negprot.in.security_mode = 0; + state->negprot.in.capabilities = 0; + unix_to_nt_time(&state->negprot.in.start_time, time(NULL)); + dialects[0] = 0; + state->negprot.in.dialects = dialects; req = smb2_negprot_send(transport, &state->negprot); if (composite_nomem(req, c)) return; diff --git a/source4/libcli/smb2/negprot.c b/source4/libcli/smb2/negprot.c index 38fe0e7e53..a678ebe229 100644 --- a/source4/libcli/smb2/negprot.c +++ b/source4/libcli/smb2/negprot.c @@ -31,16 +31,33 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport, struct smb2_negprot *io) { struct smb2_request *req; - - req = smb2_request_init(transport, SMB2_OP_NEGPROT, 0x26, false, 0); + uint16_t size = 0x24 + io->in.dialect_count*2; + DATA_BLOB guid_blob; + enum ndr_err_code ndr_err; + int i; + + req = smb2_request_init(transport, SMB2_OP_NEGPROT, size, false, 0); if (req == NULL) return NULL; - /* this seems to be a bug, they use 0x24 but the length is 0x26 */ - SSVAL(req->out.body, 0x00, 0x24); - SSVAL(req->out.body, 0x02, io->in.unknown1); - memcpy(req->out.body+0x04, io->in.unknown2, 32); - SSVAL(req->out.body, 0x24, io->in.unknown3); + ndr_err = ndr_push_struct_blob(&guid_blob, req, NULL, + &io->in.client_guid, + (ndr_push_flags_fn_t)ndr_push_GUID); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || guid_blob.length != 16) { + talloc_free(req); + return NULL; + } + + SSVAL(req->out.body, 0x00, 0x24); + SSVAL(req->out.body, 0x02, io->in.dialect_count); + SSVAL(req->out.body, 0x04, io->in.security_mode); + SSVAL(req->out.body, 0x06, io->in.reserved); + SIVAL(req->out.body, 0x08, io->in.capabilities); + memcpy(req->out.body+0x0C, guid_blob.data, guid_blob.length); + smbcli_push_nttime(req->out.body, 0x1C, io->in.start_time); + for (i=0;iin.dialect_count;i++) { + SSVAL(req->out.body, 0x24 + i*2, io->in.dialects[i]); + } smb2_transport_send(req); diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index 6a551da4ae..41fb35b8f3 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -23,11 +23,14 @@ struct smb2_negprot { struct { - /* static body buffer 38 (0x26) bytes */ - /* uint16_t buffer_code; 0x24 (why?) */ - uint16_t unknown1; /* 0x0001 */ - uint8_t unknown2[32]; /* all zero */ - uint16_t unknown3; /* 0x00000 */ + uint16_t dialect_count; /* size of dialects array */ + uint16_t security_mode; /* 0==signing disabled + 1==signing enabled */ + uint16_t reserved; + uint32_t capabilities; + struct GUID client_guid; + NTTIME start_time; + uint16_t *dialects; } in; struct { /* static body buffer 64 (0x40) bytes */ -- cgit From 8fdb9504dcfc98080c5c2b5ce134b51ab631fa95 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Feb 2008 16:20:13 +1100 Subject: converted the out side of SMB2 negprot handling This follows the SMB2 PFIF docs. Current versions of Vista can now connect to Samba4 as a SMB2 server and do basic operations (This used to be commit 9dc284770df9393a1a619735dc7a148713936fa7) --- source4/libcli/smb2/negprot.c | 43 ++++++++++++++++++++-------------------- source4/libcli/smb2/smb2_calls.h | 24 ++++++++++------------ 2 files changed, 32 insertions(+), 35 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/negprot.c b/source4/libcli/smb2/negprot.c index a678ebe229..6b879e2add 100644 --- a/source4/libcli/smb2/negprot.c +++ b/source4/libcli/smb2/negprot.c @@ -32,7 +32,6 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport, { struct smb2_request *req; uint16_t size = 0x24 + io->in.dialect_count*2; - DATA_BLOB guid_blob; enum ndr_err_code ndr_err; int i; @@ -40,20 +39,16 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport, if (req == NULL) return NULL; - ndr_err = ndr_push_struct_blob(&guid_blob, req, NULL, - &io->in.client_guid, - (ndr_push_flags_fn_t)ndr_push_GUID); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || guid_blob.length != 16) { - talloc_free(req); - return NULL; - } - SSVAL(req->out.body, 0x00, 0x24); SSVAL(req->out.body, 0x02, io->in.dialect_count); SSVAL(req->out.body, 0x04, io->in.security_mode); SSVAL(req->out.body, 0x06, io->in.reserved); SIVAL(req->out.body, 0x08, io->in.capabilities); - memcpy(req->out.body+0x0C, guid_blob.data, guid_blob.length); + ndr_err = smbcli_push_guid(req->out.body, 0x0C, &io->in.client_guid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(req); + return NULL; + } smbcli_push_nttime(req->out.body, 0x1C, io->in.start_time); for (i=0;iin.dialect_count;i++) { SSVAL(req->out.body, 0x24 + i*2, io->in.dialects[i]); @@ -71,6 +66,7 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct smb2_negprot *io) { NTSTATUS status; + enum ndr_err_code ndr_err; if (!smb2_request_receive(req) || smb2_request_is_error(req)) { @@ -79,24 +75,27 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, SMB2_CHECK_PACKET_RECV(req, 0x40, true); - io->out._pad = SVAL(req->in.body, 0x02); - io->out.unknown2 = IVAL(req->in.body, 0x04); - memcpy(io->out.sessid, req->in.body + 0x08, 16); - io->out.unknown3 = IVAL(req->in.body, 0x18); - io->out.unknown4 = SVAL(req->in.body, 0x1C); - io->out.unknown5 = IVAL(req->in.body, 0x1E); - io->out.unknown6 = IVAL(req->in.body, 0x22); - io->out.unknown7 = SVAL(req->in.body, 0x26); - io->out.current_time = smbcli_pull_nttime(req->in.body, 0x28); - io->out.boot_time = smbcli_pull_nttime(req->in.body, 0x30); + io->out.security_mode = SVAL(req->in.body, 0x02); + io->out.dialect_revision = SVAL(req->in.body, 0x04); + io->out.reserved = SVAL(req->in.body, 0x06); + ndr_err = smbcli_pull_guid(req->in.body, 0x08, &io->in.client_guid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + smb2_request_destroy(req); + return NT_STATUS_INTERNAL_ERROR; + } + io->out.capabilities = IVAL(req->in.body, 0x18); + io->out.max_transact_size = IVAL(req->in.body, 0x1C); + io->out.max_read_size = IVAL(req->in.body, 0x20); + io->out.max_write_size = IVAL(req->in.body, 0x24); + io->out.system_time = smbcli_pull_nttime(req->in.body, 0x28); + io->out.server_start_time = smbcli_pull_nttime(req->in.body, 0x30); + io->out.reserved2 = IVAL(req->in.body, 0x3C); status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x38, &io->out.secblob); if (!NT_STATUS_IS_OK(status)) { smb2_request_destroy(req); return status; } - - io->out.unknown9 = IVAL(req->in.body, 0x3C); return smb2_request_destroy(req); } diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index 41fb35b8f3..423d9d1579 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -35,21 +35,19 @@ struct smb2_negprot { struct { /* static body buffer 64 (0x40) bytes */ /* uint16_t buffer_code; 0x41 = 0x40 + 1 */ - uint16_t _pad; - uint32_t unknown2; /* 0x06 */ - uint8_t sessid[16]; - uint32_t unknown3; /* 0x0d */ - uint16_t unknown4; /* 0x00 */ - uint32_t unknown5; /* 0x01 */ - uint32_t unknown6; /* 0x01 */ - uint16_t unknown7; /* 0x01 */ - NTTIME current_time; - NTTIME boot_time; + uint16_t security_mode; + uint16_t dialect_revision; + uint16_t reserved; + struct GUID server_guid; + uint32_t capabilities; + uint32_t max_transact_size; + uint32_t max_read_size; + uint32_t max_write_size; + NTTIME system_time; + NTTIME server_start_time; /* uint16_t secblob_ofs */ /* uint16_t secblob_size */ - uint32_t unknown9; /* 0x204d4c20 */ - - /* dynamic body buffer */ + uint32_t reserved2; DATA_BLOB secblob; } out; }; -- cgit From 416360895f36d41ce8d29c25ef08e2b8b4e38571 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Feb 2008 16:43:38 +1100 Subject: converted SMB2 session setup to use WSPP protocol field names (This used to be commit 3c2af0fdc4916dce32c2690e49dde0852d1a0c50) --- source4/libcli/smb2/session.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c index a784ea65d8..d06688a598 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -75,9 +75,11 @@ struct smb2_request *smb2_session_setup_send(struct smb2_session *session, if (req == NULL) return NULL; SBVAL(req->out.hdr, SMB2_HDR_UID, session->uid); - SSVAL(req->out.body, 0x02, io->in._pad); /* pad */ - SIVAL(req->out.body, 0x04, io->in.unknown2); - SIVAL(req->out.body, 0x08, io->in.unknown3); + SCVAL(req->out.body, 0x02, io->in.vc_number); + SCVAL(req->out.body, 0x03, io->in.security_mode); + SIVAL(req->out.body, 0x04, io->in.capabilities); + SIVAL(req->out.body, 0x08, io->in.channel); + SBVAL(req->out.body, 0x10, io->in.previous_sessionid); req->session = session; @@ -86,7 +88,6 @@ struct smb2_request *smb2_session_setup_send(struct smb2_session *session, talloc_free(req); return NULL; } - SBVAL(req->out.body, 0x10, io->in.unknown4); smb2_transport_send(req); @@ -110,8 +111,8 @@ NTSTATUS smb2_session_setup_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, SMB2_CHECK_PACKET_RECV(req, 0x08, true); - io->out._pad = SVAL(req->in.body, 0x02); - io->out.uid = BVAL(req->in.hdr, SMB2_HDR_UID); + io->out.session_flags = SVAL(req->in.body, 0x02); + io->out.uid = BVAL(req->in.hdr, SMB2_HDR_UID); status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x04, &io->out.secblob); if (!NT_STATUS_IS_OK(status)) { @@ -206,10 +207,11 @@ struct composite_context *smb2_session_setup_spnego_send(struct smb2_session *se c->private_data = state; ZERO_STRUCT(state->io); - state->io.in._pad = 0x0000; - state->io.in.unknown2 = 0x0000000F; - state->io.in.unknown3 = 0x00000000; - state->io.in.unknown4 = 0; /* uint64_t */ + state->io.in.vc_number = 0; + state->io.in.security_mode = 0; + state->io.in.capabilities = 0; + state->io.in.channel = 0; + state->io.in.previous_sessionid = 0; c->status = gensec_set_credentials(session->gensec, credentials); if (!composite_is_ok(c)) return c; -- cgit From a2505c5a2cc2b7b692ffbcdd8c6b86000a15d2c7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Feb 2008 17:00:35 +1100 Subject: updated SMB2 header defines to match WSPP docs (This used to be commit d2c6ad55eca27f50a38fc6e2a85032eddb3f0aae) --- source4/libcli/smb2/cancel.c | 6 +++--- source4/libcli/smb2/logoff.c | 2 +- source4/libcli/smb2/notify.c | 2 +- source4/libcli/smb2/request.c | 14 +++++++------- source4/libcli/smb2/session.c | 4 ++-- source4/libcli/smb2/smb2.h | 15 ++++++++------- source4/libcli/smb2/tcon.c | 2 +- source4/libcli/smb2/transport.c | 2 +- 8 files changed, 24 insertions(+), 23 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/cancel.c b/source4/libcli/smb2/cancel.c index 096919f177..80127feea5 100644 --- a/source4/libcli/smb2/cancel.c +++ b/source4/libcli/smb2/cancel.c @@ -52,11 +52,11 @@ NTSTATUS smb2_cancel(struct smb2_request *r) c->seqnum = 0; SIVAL(c->out.hdr, SMB2_HDR_FLAGS, 0x00000002); - SSVAL(c->out.hdr, SMB2_HDR_UNKNOWN1, 0x0030); + SSVAL(c->out.hdr, SMB2_HDR_CREDIT, 0x0030); SIVAL(c->out.hdr, SMB2_HDR_PID, r->cancel.pending_id); - SBVAL(c->out.hdr, SMB2_HDR_SEQNUM, c->seqnum); + SBVAL(c->out.hdr, SMB2_HDR_MESSAGE_ID, c->seqnum); if (r->session) { - SBVAL(c->out.hdr, SMB2_HDR_UID, r->session->uid); + SBVAL(c->out.hdr, SMB2_HDR_SESSION_ID, r->session->uid); } SSVAL(c->out.body, 0x02, 0); diff --git a/source4/libcli/smb2/logoff.c b/source4/libcli/smb2/logoff.c index 321a4db1a6..b38a08ca43 100644 --- a/source4/libcli/smb2/logoff.c +++ b/source4/libcli/smb2/logoff.c @@ -33,7 +33,7 @@ struct smb2_request *smb2_logoff_send(struct smb2_session *session) req = smb2_request_init(session->transport, SMB2_OP_LOGOFF, 0x04, false, 0); if (req == NULL) return NULL; - SBVAL(req->out.hdr, SMB2_HDR_UID, session->uid); + SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, session->uid); SSVAL(req->out.body, 0x02, 0); diff --git a/source4/libcli/smb2/notify.c b/source4/libcli/smb2/notify.c index a3bea41eb0..e7c38a27f9 100644 --- a/source4/libcli/smb2/notify.c +++ b/source4/libcli/smb2/notify.c @@ -35,7 +35,7 @@ struct smb2_request *smb2_notify_send(struct smb2_tree *tree, struct smb2_notify req = smb2_request_init_tree(tree, SMB2_OP_NOTIFY, 0x20, false, 0); if (req == NULL) return NULL; - SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1, 0x0030); + SSVAL(req->out.hdr, SMB2_HDR_CREDIT, 0x0030); SSVAL(req->out.body, 0x02, io->in.recursive); SIVAL(req->out.body, 0x04, io->in.buffer_size); diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 73c74dcfeb..46ec24145f 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -83,17 +83,17 @@ struct smb2_request *smb2_request_init(struct smb2_transport *transport, uint16_ SIVAL(req->out.hdr, 0, SMB2_MAGIC); SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); - SSVAL(req->out.hdr, SMB2_HDR_PAD1, 0); + SSVAL(req->out.hdr, SMB2_HDR_EPOCH, 0); SIVAL(req->out.hdr, SMB2_HDR_STATUS, 0); SSVAL(req->out.hdr, SMB2_HDR_OPCODE, opcode); - SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1, 0); + SSVAL(req->out.hdr, SMB2_HDR_CREDIT, 0); SIVAL(req->out.hdr, SMB2_HDR_FLAGS, 0); - SIVAL(req->out.hdr, SMB2_HDR_CHAIN_OFFSET, 0); - SBVAL(req->out.hdr, SMB2_HDR_SEQNUM, req->seqnum); + SIVAL(req->out.hdr, SMB2_HDR_NEXT_COMMAND, 0); + SBVAL(req->out.hdr, SMB2_HDR_MESSAGE_ID, req->seqnum); SIVAL(req->out.hdr, SMB2_HDR_PID, 0); SIVAL(req->out.hdr, SMB2_HDR_TID, 0); - SBVAL(req->out.hdr, SMB2_HDR_UID, 0); - memset(req->out.hdr+SMB2_HDR_SIG, 0, 16); + SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, 0); + memset(req->out.hdr+SMB2_HDR_SIGNATURE, 0, 16); /* set the length of the fixed body part and +1 if there's a dynamic part also */ SSVAL(req->out.body, 0, body_fixed_size + (body_dynamic_size?1:0)); @@ -122,7 +122,7 @@ struct smb2_request *smb2_request_init_tree(struct smb2_tree *tree, uint16_t opc body_dynamic_size); if (req == NULL) return NULL; - SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid); + SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, tree->session->uid); SIVAL(req->out.hdr, SMB2_HDR_TID, tree->tid); req->session = tree->session; req->tree = tree; diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c index d06688a598..18fe3486a4 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -74,7 +74,7 @@ struct smb2_request *smb2_session_setup_send(struct smb2_session *session, 0x18, true, io->in.secblob.length); if (req == NULL) return NULL; - SBVAL(req->out.hdr, SMB2_HDR_UID, session->uid); + SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, session->uid); SCVAL(req->out.body, 0x02, io->in.vc_number); SCVAL(req->out.body, 0x03, io->in.security_mode); SIVAL(req->out.body, 0x04, io->in.capabilities); @@ -112,7 +112,7 @@ NTSTATUS smb2_session_setup_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, SMB2_CHECK_PACKET_RECV(req, 0x08, true); io->out.session_flags = SVAL(req->in.body, 0x02); - io->out.uid = BVAL(req->in.hdr, SMB2_HDR_UID); + io->out.uid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID); status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x04, &io->out.secblob); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 33876c6f7c..60cf3e0173 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -156,19 +156,20 @@ struct smb2_request { #define SMB2_MIN_SIZE 0x42 -/* offsets into header elements */ +/* offsets into header elements for a sync SMB2 request */ +#define SMB2_HDR_PROTOCOL_ID 0x00 #define SMB2_HDR_LENGTH 0x04 -#define SMB2_HDR_PAD1 0x06 +#define SMB2_HDR_EPOCH 0x06 #define SMB2_HDR_STATUS 0x08 #define SMB2_HDR_OPCODE 0x0c -#define SMB2_HDR_UNKNOWN1 0x0e +#define SMB2_HDR_CREDIT 0x0e #define SMB2_HDR_FLAGS 0x10 -#define SMB2_HDR_CHAIN_OFFSET 0x14 -#define SMB2_HDR_SEQNUM 0x18 +#define SMB2_HDR_NEXT_COMMAND 0x14 +#define SMB2_HDR_MESSAGE_ID 0x18 #define SMB2_HDR_PID 0x20 #define SMB2_HDR_TID 0x24 -#define SMB2_HDR_UID 0x28 /* 64 bit */ -#define SMB2_HDR_SIG 0x30 /* guess ... */ +#define SMB2_HDR_SESSION_ID 0x28 +#define SMB2_HDR_SIGNATURE 0x30 /* 16 bytes */ #define SMB2_HDR_BODY 0x40 /* SMB2 opcodes */ diff --git a/source4/libcli/smb2/tcon.c b/source4/libcli/smb2/tcon.c index ad1ba4c92d..5a09970584 100644 --- a/source4/libcli/smb2/tcon.c +++ b/source4/libcli/smb2/tcon.c @@ -56,7 +56,7 @@ struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree, 0x08, true, 0); if (req == NULL) return NULL; - SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid); + SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, tree->session->uid); SSVAL(req->out.body, 0x02, io->in.unknown1); status = smb2_push_o16s16_string(&req->out, 0x04, io->in.path); diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c index 83e9436a58..dceb78382a 100644 --- a/source4/libcli/smb2/transport.c +++ b/source4/libcli/smb2/transport.c @@ -167,7 +167,7 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) } flags = IVAL(hdr, SMB2_HDR_FLAGS); - seqnum = BVAL(hdr, SMB2_HDR_SEQNUM); + seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID); /* match the incoming request against the list of pending requests */ for (req=transport->pending_recv; req; req=req->next) { -- cgit From e94d710b0b959d8e69eb02ef0704ebcff56485fb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Feb 2008 10:13:28 +1100 Subject: updated SMB2 tcon as per WSPP docs (This used to be commit 5913e3e549e71affc66c28cacb6563331fb0c790) --- source4/libcli/smb2/connect.c | 2 +- source4/libcli/smb2/smb2.h | 22 ++++++++++++++++++++++ source4/libcli/smb2/smb2_calls.h | 2 +- source4/libcli/smb2/tcon.c | 16 ++++++++++++---- 4 files changed, 36 insertions(+), 6 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index a2ae828fa5..535df11d9d 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -73,7 +73,7 @@ static void continue_session(struct composite_context *creq) state->tree = smb2_tree_init(state->session, state, true); if (composite_nomem(state->tree, c)) return; - state->tcon.in.unknown1 = 0x09; + state->tcon.in.reserved = 0; state->tcon.in.path = talloc_asprintf(state, "\\\\%s\\%s", state->host, state->share); if (composite_nomem(state->tcon.in.path, c)) return; diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 60cf3e0173..549b477ffd 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -195,6 +195,28 @@ struct smb2_request { #define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */ +/* SMB2 negotiate security_mode */ +#define SMB2_NEGOTIATE_SIGNING_ENABLED 0x01 +#define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x02 + +/* SMB2 capabilities - only 1 so far. I'm sure more will be added */ +#define SMB2_CAP_DFS 0x0 +/* so we can spot new caps as added */ +#define SMB2_CAP_ALL SMB2_CAP_DFS + +/* SMB2 share flags */ +#define SMB2_SHAREFLAG_MANUAL_CACHING 0x0000 +#define SMB2_SHAREFLAG_AUTO_CACHING 0x0010 +#define SMB2_SHAREFLAG_VDO_CACHING 0x0020 +#define SMB2_SHAREFLAG_NO_CACHING 0x0030 +#define SMB2_SHAREFLAG_DFS 0x0001 +#define SMB2_SHAREFLAG_DFS_ROOT 0x0002 +#define SMB2_SHAREFLAG_RESTRICT_EXCLUSIVE_OPENS 0x0100 +#define SMB2_SHAREFLAG_FORCE_SHARED_DELETE 0x0200 +#define SMB2_SHAREFLAG_ALLOW_NAMESPACE_CACHING 0x0400 +#define SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM 0x0800 +#define SMB2_SHAREFLAG_ALL 0x0F33 + /* check that a body has the expected size */ diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index 423d9d1579..f2e3019d83 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -35,7 +35,7 @@ struct smb2_negprot { struct { /* static body buffer 64 (0x40) bytes */ /* uint16_t buffer_code; 0x41 = 0x40 + 1 */ - uint16_t security_mode; + uint16_t security_mode; /* SMB2_NEGOTIATE_SIGNING_* */ uint16_t dialect_revision; uint16_t reserved; struct GUID server_guid; diff --git a/source4/libcli/smb2/tcon.c b/source4/libcli/smb2/tcon.c index 5a09970584..db35669d41 100644 --- a/source4/libcli/smb2/tcon.c +++ b/source4/libcli/smb2/tcon.c @@ -58,7 +58,7 @@ struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree, SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, tree->session->uid); - SSVAL(req->out.body, 0x02, io->in.unknown1); + SSVAL(req->out.body, 0x02, io->in.reserved); status = smb2_push_o16s16_string(&req->out, 0x04, io->in.path); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); @@ -85,10 +85,18 @@ NTSTATUS smb2_tree_connect_recv(struct smb2_request *req, struct smb2_tree_conne io->out.tid = IVAL(req->in.hdr, SMB2_HDR_TID); - io->out.unknown1 = SVAL(req->in.body, 0x02); - io->out.unknown2 = IVAL(req->in.body, 0x04); - io->out.unknown3 = IVAL(req->in.body, 0x08); + io->out.share_type = CVAL(req->in.body, 0x02); + io->out.reserved = CVAL(req->in.body, 0x03); + io->out.flags = IVAL(req->in.body, 0x04); + io->out.capabilities= IVAL(req->in.body, 0x08); io->out.access_mask = IVAL(req->in.body, 0x0C); + + if (io->out.capabilities & ~SMB2_CAP_ALL) { + DEBUG(0,("Unknown capabilities mask 0x%x\n", io->out.capabilities)); + } + if (io->out.flags & ~SMB2_SHAREFLAG_ALL) { + DEBUG(0,("Unknown tcon shareflag 0x%x\n", io->out.flags)); + } return smb2_request_destroy(req); } -- cgit From 88d2e0522737fb8856fb0f52c2af8a2f56130f19 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Feb 2008 15:05:44 +1100 Subject: updated SMB2 create operation to match WSPP. Adding some defined for various new create options (This used to be commit d037dc23ced3df6bce98cbf4810fb5f1247336bd) --- source4/libcli/smb2/create.c | 52 ++++++++++++++++++++++---------------------- source4/libcli/smb2/smb2.h | 28 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 26 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c index ba11c22e87..cca83a040c 100644 --- a/source4/libcli/smb2/create.c +++ b/source4/libcli/smb2/create.c @@ -24,34 +24,33 @@ #include "libcli/smb2/smb2.h" #include "libcli/smb2/smb2_calls.h" -#define CREATE_TAG_EXTA 0x41747845 /* "ExtA" */ -#define CREATE_TAG_MXAC 0x6341784D /* "MxAc" */ - /* add a blob to a smb2_create attribute blob */ NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, - uint32_t tag, + const char *tag, DATA_BLOB add, bool last) { uint32_t ofs = blob->length; - uint8_t pad = smb2_padding_size(add.length, 8); - if (!data_blob_realloc(mem_ctx, blob, blob->length + 0x18 + add.length + pad)) + size_t tag_length = strlen(tag); + uint8_t pad = smb2_padding_size(add.length+tag_length, 8); + if (!data_blob_realloc(mem_ctx, blob, + blob->length + 0x14 + tag_length + add.length + pad)) return NT_STATUS_NO_MEMORY; if (last) { SIVAL(blob->data, ofs+0x00, 0); } else { - SIVAL(blob->data, ofs+0x00, 0x18 + add.length + pad); + SIVAL(blob->data, ofs+0x00, 0x14 + tag_length + add.length + pad); } SSVAL(blob->data, ofs+0x04, 0x10); /* offset of tag */ - SIVAL(blob->data, ofs+0x06, 0x04); /* tag length */ - SSVAL(blob->data, ofs+0x0A, 0x18); /* offset of data */ + SIVAL(blob->data, ofs+0x06, tag_length); /* tag length */ + SSVAL(blob->data, ofs+0x0A, 0x14 + tag_length); /* offset of data */ SIVAL(blob->data, ofs+0x0C, add.length); - SIVAL(blob->data, ofs+0x10, tag); - SIVAL(blob->data, ofs+0x14, 0); /* pad? */ - memcpy(blob->data+ofs+0x18, add.data, add.length); - memset(blob->data+ofs+0x18+add.length, 0, pad); + memcpy(blob->data+ofs+0x10, tag, tag_length); + SIVAL(blob->data, ofs+0x10+tag_length, 0); /* pad? */ + memcpy(blob->data+ofs+0x14+tag_length, add.data, add.length); + memset(blob->data+ofs+0x14+tag_length+add.length, 0, pad); return NT_STATUS_OK; } @@ -68,16 +67,15 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, true, 0); if (req == NULL) return NULL; - SSVAL(req->out.body, 0x02, io->in.oplock_flags); - SIVAL(req->out.body, 0x04, io->in.impersonation); - SIVAL(req->out.body, 0x08, io->in.unknown3[0]); - SIVAL(req->out.body, 0x0C, io->in.unknown3[1]); - SIVAL(req->out.body, 0x10, io->in.unknown3[2]); - SIVAL(req->out.body, 0x14, io->in.unknown3[3]); - SIVAL(req->out.body, 0x18, io->in.access_mask); - SIVAL(req->out.body, 0x1C, io->in.file_attr); + SCVAL(req->out.body, 0x02, io->in.security_flags); + SCVAL(req->out.body, 0x03, io->in.oplock_level); + SIVAL(req->out.body, 0x04, io->in.impersonation_level); + SBVAL(req->out.body, 0x08, io->in.create_flags); + SBVAL(req->out.body, 0x10, io->in.reserved); + SIVAL(req->out.body, 0x18, io->in.desired_access); + SIVAL(req->out.body, 0x1C, io->in.file_attributes); SIVAL(req->out.body, 0x20, io->in.share_access); - SIVAL(req->out.body, 0x24, io->in.open_disposition); + SIVAL(req->out.body, 0x24, io->in.create_disposition); SIVAL(req->out.body, 0x28, io->in.create_options); status = smb2_push_o16s16_string(&req->out, 0x2C, io->in.fname); @@ -90,7 +88,7 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create DATA_BLOB b = data_blob_talloc(req, NULL, ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas)); ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas); - status = smb2_create_blob_add(req, &blob, CREATE_TAG_EXTA, b, false); + status = smb2_create_blob_add(req, &blob, SMB2_CREATE_TAG_EXTA, b, false); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; @@ -100,7 +98,8 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create /* an empty MxAc tag seems to be used to ask the server to return the maximum access mask allowed on the file */ - status = smb2_create_blob_add(req, &blob, CREATE_TAG_MXAC, data_blob(NULL, 0), true); + status = smb2_create_blob_add(req, &blob, SMB2_CREATE_TAG_MXAC, + data_blob(NULL, 0), true); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); @@ -132,7 +131,8 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct SMB2_CHECK_PACKET_RECV(req, 0x58, true); - io->out.oplock_flags = SVAL(req->in.body, 0x02); + io->out.oplock_level = CVAL(req->in.body, 0x02); + io->out.reserved = CVAL(req->in.body, 0x03); io->out.create_action = IVAL(req->in.body, 0x04); io->out.create_time = smbcli_pull_nttime(req->in.body, 0x08); io->out.access_time = smbcli_pull_nttime(req->in.body, 0x10); @@ -141,7 +141,7 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct io->out.alloc_size = BVAL(req->in.body, 0x28); io->out.size = BVAL(req->in.body, 0x30); io->out.file_attr = IVAL(req->in.body, 0x38); - io->out._pad = IVAL(req->in.body, 0x3C); + io->out.reserved2 = IVAL(req->in.body, 0x3C); smb2_pull_handle(req->in.body+0x40, &io->out.file.handle); status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x50, &io->out.blob); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 549b477ffd..db13ab69b3 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -217,6 +217,34 @@ struct smb2_request { #define SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM 0x0800 #define SMB2_SHAREFLAG_ALL 0x0F33 +/* SMB2 create security flags */ +#define SMB2_SECURITY_DYNAMIC_TRACKING 0x01 +#define SMB2_SECURITY_EFFECTIVE_ONLY 0x02 + +/* SMB2 requested oplock levels */ +#define SMB2_OPLOCK_LEVEL_NONE 0x00 +#define SMB2_OPLOCK_LEVEL_II 0x01 +#define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08 +#define SMB2_OPLOCK_LEVEL_BATCH 0x09 + +/* SMB2 impersonation levels */ +#define SMB2_IMPERSONATION_ANONYMOUS 0x00 +#define SMB2_IMPERSONATION_IDENTIFICATION 0x01 +#define SMB2_IMPERSONATION_IMPERSONATION 0x02 +#define SMB2_IMPERSONATION_DELEGATE 0x03 + +/* SMB2 create tags */ +#define SMB2_CREATE_TAG_EXTA "ExtA" +#define SMB2_CREATE_TAG_MXAC "MxAc" +#define SMB2_CREATE_TAG_SECD "SecD" +#define SMB2_CREATE_TAG_DHNQ "DHnQ" +#define SMB2_CREATE_TAG_DHNC "DHnC" +#define SMB2_CREATE_TAG_ALSI "AlSi" +#define SMB2_CREATE_TAG_TWRP "TWrp" +#define SMB2_CREATE_TAG_QFID "QFid" + + + /* check that a body has the expected size */ -- cgit From e870cfec9f3512b0f1bd3110d7b975652525e28a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Feb 2008 10:12:33 +1100 Subject: 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 ca6d9be6cb6a403a81b18fa6e9a6a0518d7f0f68) --- source4/libcli/smb2/request.c | 15 +++++++++++++++ source4/libcli/smb2/smb2.h | 5 +++++ source4/libcli/smb2/transport.c | 2 ++ 3 files changed, 22 insertions(+) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 46ec24145f..0b680fb166 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -28,6 +28,21 @@ #include "libcli/smb2/smb2_calls.h" #include "param/param.h" +/* fill in the bufinfo */ +void smb2_setup_bufinfo(struct smb2_request *req) +{ + req->in.bufinfo.mem_ctx = req; + req->in.bufinfo.unicode = true; + req->in.bufinfo.align_base = req->in.buffer; + if (req->in.dynamic) { + req->in.bufinfo.data = req->in.dynamic; + req->in.bufinfo.data_size = req->in.body_size - req->in.body_fixed; + } else { + req->in.bufinfo.data = NULL; + req->in.bufinfo.data_size = 0; + } +} + /* initialise a smb2 request */ diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index db13ab69b3..af08b0180a 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -19,6 +19,8 @@ along with this program. If not, see . */ +#include "libcli/raw/request.h" + struct smb2_options { uint32_t timeout; }; @@ -102,6 +104,9 @@ struct smb2_request_buffer { * this will be moved when some dynamic data is pushed */ uint8_t *dynamic; + + /* this is used to range check and align strings and buffers */ + struct request_bufinfo bufinfo; }; diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c index dceb78382a..1d601fdbfe 100644 --- a/source4/libcli/smb2/transport.c +++ b/source4/libcli/smb2/transport.c @@ -216,6 +216,8 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) } } + smb2_setup_bufinfo(req); + DEBUG(2, ("SMB2 RECV seqnum=0x%llx\n", (long long)req->seqnum)); dump_data(5, req->in.body, req->in.body_size); -- cgit From 839ab724dc2d204bfbb0693aeed64f6f83a4266b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Feb 2008 12:30:31 +1100 Subject: Fixed SMB2 rename operations from Vista clients We needed a flag in bufinfo to mark packets as SMB2, as it seems that SMB2 uses a different format for the RenameInformation buffer than SMB does Also handle the fact that SMB2 clients give the full path to the target file in the rename, not a relative path (This used to be commit 52d7972d95ddc19d22a4187b4d4428a6c3ed32d5) --- source4/libcli/smb2/request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 0b680fb166..35229dc45f 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -32,7 +32,7 @@ void smb2_setup_bufinfo(struct smb2_request *req) { req->in.bufinfo.mem_ctx = req; - req->in.bufinfo.unicode = true; + req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE | BUFINFO_FLAG_SMB2; req->in.bufinfo.align_base = req->in.buffer; if (req->in.dynamic) { req->in.bufinfo.data = req->in.dynamic; -- cgit From 4a04a5e620a4666fc123d04cb96ef391de72c469 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Feb 2008 14:54:21 +1100 Subject: A better way to handle the different format of RenameInformation in SMB2 We now define a separate info level RAW_SFILEINFO_RENAME_INFORMATION_SMB2 and set that level when handling SMB2 packets. This makes the parsers clearer. (This used to be commit f6cdf3f1177f63d80be757f007eb15380839b4f5) --- source4/libcli/smb2/setinfo.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/setinfo.c b/source4/libcli/smb2/setinfo.c index d942568a2d..a6e22d9a68 100644 --- a/source4/libcli/smb2/setinfo.c +++ b/source4/libcli/smb2/setinfo.c @@ -92,6 +92,12 @@ struct smb2_request *smb2_setinfo_file_send(struct smb2_tree *tree, union smb_se ZERO_STRUCT(b); b.in.level = smb2_level; b.in.file.handle = io->generic.in.file.handle; + + /* change levels so the parsers know it is SMB2 */ + if (io->generic.level == RAW_SFILEINFO_RENAME_INFORMATION) { + io->generic.level = RAW_SFILEINFO_RENAME_INFORMATION_SMB2; + } + if (!smb_raw_setfileinfo_passthru(tree, io->generic.level, io, &b.in.blob)) { return NULL; } -- cgit From b640f475be9b0f83e7812a5c7756344c5891cba3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Feb 2008 17:11:36 +1100 Subject: updated SMB2 code for getinfo according to WSPP docs - Updated getinfo structures and field names - also updated the protocol revision number handling to reflect new docs (This used to be commit 3aaa2e86d94675c6c68d66d75292c3e34bfbc81b) --- source4/libcli/smb2/connect.c | 2 +- source4/libcli/smb2/getinfo.c | 45 ++++++++++++++++++++++++---------------- source4/libcli/smb2/request.c | 27 ++++++++++++++++++++++++ source4/libcli/smb2/smb2.h | 3 +++ source4/libcli/smb2/smb2_calls.h | 24 ++++++++++++++------- 5 files changed, 75 insertions(+), 26 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 535df11d9d..85ddafc031 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -133,7 +133,7 @@ static void continue_socket(struct composite_context *creq) state->negprot.in.security_mode = 0; state->negprot.in.capabilities = 0; unix_to_nt_time(&state->negprot.in.start_time, time(NULL)); - dialects[0] = 0; + dialects[0] = SMB2_DIALECT_REVISION; state->negprot.in.dialects = dialects; req = smb2_negprot_send(transport, &state->negprot); diff --git a/source4/libcli/smb2/getinfo.c b/source4/libcli/smb2/getinfo.c index 0665dd441c..e9f47140f5 100644 --- a/source4/libcli/smb2/getinfo.c +++ b/source4/libcli/smb2/getinfo.c @@ -30,21 +30,27 @@ struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getinfo *io) { struct smb2_request *req; + NTSTATUS status; - req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, false, 0); + req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, true, + io->in.blob.length); if (req == NULL) return NULL; - /* this seems to be a bug, they use 0x29 but only send 0x28 bytes */ - SSVAL(req->out.body, 0x00, 0x29); - - SSVAL(req->out.body, 0x02, io->in.level); - SIVAL(req->out.body, 0x04, io->in.max_response_size); - SIVAL(req->out.body, 0x08, io->in.unknown1); - SIVAL(req->out.body, 0x0C, io->in.unknown2); - SIVAL(req->out.body, 0x10, io->in.flags); - SIVAL(req->out.body, 0x14, io->in.flags2); + SCVAL(req->out.body, 0x02, io->in.info_type); + SCVAL(req->out.body, 0x03, io->in.info_class); + SIVAL(req->out.body, 0x04, io->in.output_buffer_length); + SIVAL(req->out.body, 0x0C, io->in.reserved); + SIVAL(req->out.body, 0x08, io->in.input_buffer_length); + SIVAL(req->out.body, 0x10, io->in.additional_information); + SIVAL(req->out.body, 0x14, io->in.getinfo_flags); smb2_push_handle(req->out.body+0x18, &io->in.file.handle); + /* this blob is used for quota queries */ + status = smb2_push_o32s32_blob(&req->out, 0x08, io->in.blob); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(req); + return NULL; + } smb2_transport_send(req); return req; @@ -116,15 +122,17 @@ struct smb2_request *smb2_getinfo_file_send(struct smb2_tree *tree, union smb_fi } ZERO_STRUCT(b); - b.in.max_response_size = 0x10000; - b.in.file.handle = io->generic.in.file.handle; - b.in.level = smb2_level; + b.in.info_type = smb2_level & 0xFF; + b.in.info_class = smb2_level >> 8; + b.in.output_buffer_length = 0x10000; + b.in.input_buffer_length = 0; + b.in.file.handle = io->generic.in.file.handle; if (io->generic.level == RAW_FILEINFO_SEC_DESC) { - b.in.flags = io->query_secdesc.in.secinfo_flags; + b.in.additional_information = io->query_secdesc.in.secinfo_flags; } if (io->generic.level == RAW_FILEINFO_SMB2_ALL_EAS) { - b.in.flags2 = io->all_eas.in.continue_flags; + b.in.getinfo_flags = io->all_eas.in.continue_flags; } return smb2_getinfo_send(tree, &b); @@ -172,9 +180,10 @@ struct smb2_request *smb2_getinfo_fs_send(struct smb2_tree *tree, union smb_fsin } ZERO_STRUCT(b); - b.in.max_response_size = 0x10000; - b.in.file.handle = io->generic.handle; - b.in.level = smb2_level; + b.in.output_buffer_length = 0x10000; + b.in.file.handle = io->generic.handle; + b.in.info_type = smb2_level & 0xFF; + b.in.info_class = smb2_level >> 8; return smb2_getinfo_send(tree, &b); } diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 35229dc45f..7a0311f886 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -548,6 +548,33 @@ NTSTATUS smb2_pull_o32s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ return NT_STATUS_OK; } +/* + pull a uint16_t ofs/ uint32_t length/blob triple from a data blob + the ptr points to the start of the offset/length pair + + In this varient the uint16_t is padded by an extra 2 bytes, making + the size aligned on 4 byte boundary +*/ +NTSTATUS smb2_pull_o16As32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob) +{ + uint32_t ofs, size; + if (smb2_oob(buf, ptr, 8)) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + ofs = SVAL(ptr, 0); + size = IVAL(ptr, 4); + if (ofs == 0 || size == 0) { + *blob = data_blob(NULL, 0); + return NT_STATUS_OK; + } + if (smb2_oob(buf, buf->hdr + ofs, size)) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size); + NT_STATUS_HAVE_NO_MEMORY(blob->data); + return NT_STATUS_OK; +} + /* pull a uint32_t length/ uint32_t ofs/blob triple from a data blob the ptr points to the start of the offset/length pair diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index af08b0180a..726df64090 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -200,6 +200,9 @@ struct smb2_request { #define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */ +/* the dialect we support */ +#define SMB2_DIALECT_REVISION 0x202 + /* SMB2 negotiate security_mode */ #define SMB2_NEGOTIATE_SIGNING_ENABLED 0x01 #define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x02 diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index f2e3019d83..f66236af30 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -56,6 +56,13 @@ struct smb2_negprot { #define SMB2_GETINFO_FILE 0x01 #define SMB2_GETINFO_FS 0x02 #define SMB2_GETINFO_SECURITY 0x03 +#define SMB2_GETINFO_QUOTA 0x04 + +#define SMB2_GETINFO_ADD_OWNER_SECURITY 0x01 +#define SMB2_GETINFO_ADD_GROUP_SECURITY 0x02 +#define SMB2_GETINFO_ADD_DACL_SECURITY 0x04 +#define SMB2_GETINFO_ADD_SACL_SECURITY 0x08 +#define SMB2_GETINFO_ADD_LABEL_SECURITY 0x10 /* NOTE! the getinfo fs and file levels exactly match up with the 'passthru' SMB levels, which are levels >= 1000. The SMB2 client @@ -64,14 +71,17 @@ struct smb2_negprot { struct smb2_getinfo { struct { /* static body buffer 40 (0x28) bytes */ - /* uint16_t buffer_code; 0x29 = 0x28 + 1 (why???) */ - uint16_t level; - uint32_t max_response_size; - uint32_t unknown1; - uint32_t unknown2; - uint32_t flags; /* level specific */ - uint32_t flags2; /* used by all_eas level */ + /* uint16_t buffer_code; 0x29 = 0x28 + 1 */ + uint8_t info_type; + uint8_t info_class; + uint32_t output_buffer_length; + /* uint32_t input_buffer_offset; */ + uint32_t reserved; + uint32_t input_buffer_length; + uint32_t additional_information; /* SMB2_GETINFO_ADD_* */ + uint32_t getinfo_flags; /* level specific */ union smb_handle file; + DATA_BLOB blob; } in; struct { -- cgit From 2e4e06c6e69d881b0fc3c53df50db607fcce4a91 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 16 Feb 2008 07:25:38 +1100 Subject: fixed handling of zero sized buffers versus NULL buffers in SMB2. Thanks to Metze for spotting this. (This used to be commit fbcf3e65b9284e5d1862c98706d7f148a36afe47) --- source4/libcli/smb2/request.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 7a0311f886..1de0531d9a 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -206,6 +206,10 @@ bool smb2_request_is_ok(struct smb2_request *req) */ bool smb2_oob(struct smb2_request_buffer *buf, const uint8_t *ptr, size_t size) { + if (size == 0) { + /* zero bytes is never out of range */ + return false; + } /* be careful with wraparound! */ if (ptr < buf->body || ptr >= buf->body + buf->body_size || @@ -270,7 +274,7 @@ NTSTATUS smb2_pull_o16s16_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ } ofs = SVAL(ptr, 0); size = SVAL(ptr, 2); - if (ofs == 0 || size == 0) { + if (ofs == 0) { *blob = data_blob(NULL, 0); return NT_STATUS_OK; } @@ -310,7 +314,10 @@ NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf, return NT_STATUS_BUFFER_TOO_SMALL; } - if (blob.length == 0) { + if (blob.data == NULL) { + if (blob.length != 0) { + return NT_STATUS_INTERNAL_ERROR; + } SSVAL(ptr, 0, 0); SSVAL(ptr, 2, 0); return NT_STATUS_OK; @@ -363,7 +370,10 @@ NTSTATUS smb2_push_o16s32_blob(struct smb2_request_buffer *buf, return NT_STATUS_BUFFER_TOO_SMALL; } - if (blob.length == 0) { + if (blob.data == NULL) { + if (blob.length != 0) { + return NT_STATUS_INTERNAL_ERROR; + } SSVAL(ptr, 0, 0); SIVAL(ptr, 2, 0); return NT_STATUS_OK; @@ -416,7 +426,10 @@ NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf, return NT_STATUS_BUFFER_TOO_SMALL; } - if (blob.length == 0) { + if (blob.data == NULL) { + if (blob.length != 0) { + return NT_STATUS_INTERNAL_ERROR; + } SIVAL(ptr, 0, 0); SIVAL(ptr, 4, 0); return NT_STATUS_OK; @@ -469,7 +482,10 @@ NTSTATUS smb2_push_s32o32_blob(struct smb2_request_buffer *buf, return NT_STATUS_BUFFER_TOO_SMALL; } - if (blob.length == 0) { + if (blob.data == NULL) { + if (blob.length != 0) { + return NT_STATUS_INTERNAL_ERROR; + } SIVAL(ptr, 0, 0); SIVAL(ptr, 4, 0); return NT_STATUS_OK; @@ -512,7 +528,7 @@ NTSTATUS smb2_pull_o16s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ } ofs = SVAL(ptr, 0); size = IVAL(ptr, 2); - if (ofs == 0 || size == 0) { + if (ofs == 0) { *blob = data_blob(NULL, 0); return NT_STATUS_OK; } @@ -536,7 +552,7 @@ NTSTATUS smb2_pull_o32s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ } ofs = IVAL(ptr, 0); size = IVAL(ptr, 4); - if (ofs == 0 || size == 0) { + if (ofs == 0) { *blob = data_blob(NULL, 0); return NT_STATUS_OK; } @@ -563,7 +579,7 @@ NTSTATUS smb2_pull_o16As32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem } ofs = SVAL(ptr, 0); size = IVAL(ptr, 4); - if (ofs == 0 || size == 0) { + if (ofs == 0) { *blob = data_blob(NULL, 0); return NT_STATUS_OK; } @@ -587,7 +603,7 @@ NTSTATUS smb2_pull_s32o32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ } size = IVAL(ptr, 0); ofs = IVAL(ptr, 4); - if (ofs == 0 || size == 0) { + if (ofs == 0) { *blob = data_blob(NULL, 0); return NT_STATUS_OK; } @@ -614,6 +630,11 @@ NTSTATUS smb2_pull_o16s16_string(struct smb2_request_buffer *buf, TALLOC_CTX *me status = smb2_pull_o16s16_blob(buf, mem_ctx, ptr, &blob); NT_STATUS_NOT_OK_RETURN(status); + if (blob.data == NULL) { + *str = NULL; + return NT_STATUS_OK; + } + if (blob.length == 0) { char *s; s = talloc_strdup(mem_ctx, ""); @@ -643,7 +664,7 @@ NTSTATUS smb2_push_o16s16_string(struct smb2_request_buffer *buf, NTSTATUS status; ssize_t size; - if (strcmp("", str) == 0) { + if (str == NULL) { return smb2_push_o16s16_blob(buf, ofs, data_blob(NULL, 0)); } -- cgit From 26b8701321909e10aac124324695f9f4891b1f8d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 18 Feb 2008 14:53:48 +1100 Subject: handle pushing of zero length smb2 strings (This used to be commit 66d0502228b31533b5d93731128a681992c22eda) --- source4/libcli/smb2/request.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 1de0531d9a..2471fcaa4d 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -668,6 +668,12 @@ NTSTATUS smb2_push_o16s16_string(struct smb2_request_buffer *buf, return smb2_push_o16s16_blob(buf, ofs, data_blob(NULL, 0)); } + if (*str == 0) { + blob.data = str; + blob.length = 0; + return smb2_push_o16s16_blob(buf, ofs, blob); + } + size = convert_string_talloc(buf->buffer, lp_iconv_convenience(global_loadparm), CH_UNIX, CH_UTF16, str, strlen(str), (void **)&blob.data); if (size == -1) { -- cgit