From 012c9d06a94b532377e9e96f60b20b5f0975af74 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Sep 2011 13:14:40 +0200 Subject: s3:smb2_server: add basic support for SMB 2.1 This adds support for the 2 stage negprot, from SMB 1 to SMB 2.1. Support for this of for now and "max protocol = SMB2" still maps to "max protocol = SMB2_02" PROTOCOL_SMB2_02. In order to activate smb2.1, you need to use "max protocol = SMB2_10". metze Autobuild-User: Stefan Metzmacher Autobuild-Date: Mon Sep 5 19:30:58 CEST 2011 on sn-devel-104 --- source3/param/loadparm.c | 3 ++- source3/smbd/globals.h | 2 ++ source3/smbd/negprot.c | 1 + source3/smbd/smb2_negprot.c | 66 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index b0c64c7fa3..305ff2cec9 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -312,7 +312,8 @@ static void add_to_file_list(const char *fname, const char *subfname); static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values); static const struct enum_list enum_protocol[] = { - {PROTOCOL_SMB2_02, "SMB2"}, + {PROTOCOL_SMB2_02, "SMB2"}, /* for now keep PROTOCOL_SMB2_02 */ + {PROTOCOL_SMB2_10, "SMB2_10"}, {PROTOCOL_SMB2_02, "SMB2_02"}, {PROTOCOL_NT1, "NT1"}, {PROTOCOL_LANMAN2, "LANMAN2"}, diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 2e59d9bc5f..6ce9835dee 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -241,6 +241,7 @@ const char *smb2_opcode_name(uint16_t opcode); bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size); void reply_smb2002(struct smb_request *req, uint16_t choice); +void reply_smb20ff(struct smb_request *req, uint16_t choice); void smbd_smb2_first_negprot(struct smbd_server_connection *sconn, const uint8_t *inbuf, size_t size); @@ -578,6 +579,7 @@ struct smbd_server_connection { struct tevent_queue *recv_queue; struct tevent_queue *send_queue; struct tstream_context *stream; + bool negprot_2ff; struct { /* an id tree used to allocate vuids */ /* this holds info on session vuids that are already diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 49b9420fbf..a38534f323 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -536,6 +536,7 @@ static const struct { void (*proto_reply_fn)(struct smb_request *req, uint16 choice); int protocol_level; } supported_protocols[] = { + {"SMB 2.???", "SMB2_FF", reply_smb20ff, PROTOCOL_SMB2_10}, {"SMB 2.002", "SMB2_02", reply_smb2002, PROTOCOL_SMB2_02}, {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index dfb2da3fda..56a30d0d71 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -25,9 +25,9 @@ /* * this is the entry point if SMB2 is selected via - * the SMB negprot and the "SMB 2.002" dialect. + * the SMB negprot and the given dialect. */ -void reply_smb2002(struct smb_request *req, uint16_t choice) +static void reply_smb20xx(struct smb_request *req, uint16_t dialect) { uint8_t *smb2_inbuf; uint8_t *smb2_hdr; @@ -51,7 +51,7 @@ void reply_smb2002(struct smb_request *req, uint16_t choice) SSVAL(smb2_body, 0x00, 0x0024); /* struct size */ SSVAL(smb2_body, 0x02, 0x0001); /* dialect count */ - SSVAL(smb2_dyn, 0x00, SMB2_DIALECT_REVISION_202); + SSVAL(smb2_dyn, 0x00, dialect); req->outbuf = NULL; @@ -59,6 +59,25 @@ void reply_smb2002(struct smb_request *req, uint16_t choice) return; } +/* + * this is the entry point if SMB2 is selected via + * the SMB negprot and the "SMB 2.002" dialect. + */ +void reply_smb2002(struct smb_request *req, uint16_t choice) +{ + reply_smb20xx(req, SMB2_DIALECT_REVISION_202); +} + +/* + * this is the entry point if SMB2 is selected via + * the SMB negprot and the "SMB 2.???" dialect. + */ +void reply_smb20ff(struct smb_request *req, uint16_t choice) +{ + req->sconn->smb2.negprot_2ff = true; + reply_smb20xx(req, SMB2_DIALECT_REVISION_2FF); +} + NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) { const uint8_t *inbody; @@ -108,6 +127,28 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) indyn = (const uint8_t *)req->in.vector[i+2].iov_base; for (c=0; protocol == PROTOCOL_NONE && c < dialect_count; c++) { + if (lp_maxprotocol() < PROTOCOL_SMB2_10) { + break; + } + if (lp_minprotocol() > PROTOCOL_SMB2_10) { + break; + } + + dialect = SVAL(indyn, c*2); + if (dialect == SMB2_DIALECT_REVISION_210) { + protocol = PROTOCOL_SMB2_10; + break; + } + } + + for (c=0; protocol == PROTOCOL_NONE && c < dialect_count; c++) { + if (lp_maxprotocol() < PROTOCOL_SMB2_02) { + break; + } + if (lp_minprotocol() > PROTOCOL_SMB2_02) { + break; + } + dialect = SVAL(indyn, c*2); if (dialect == SMB2_DIALECT_REVISION_202) { protocol = PROTOCOL_SMB2_02; @@ -115,11 +156,28 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) } } + for (c=0; protocol == PROTOCOL_NONE && c < dialect_count; c++) { + if (lp_maxprotocol() < PROTOCOL_SMB2_10) { + break; + } + + dialect = SVAL(indyn, c*2); + if (dialect == SMB2_DIALECT_REVISION_2FF) { + if (req->sconn->smb2.negprot_2ff) { + req->sconn->smb2.negprot_2ff = false; + protocol = PROTOCOL_SMB2_10; + break; + } + } + } + if (protocol == PROTOCOL_NONE) { return smbd_smb2_request_error(req, NT_STATUS_NOT_SUPPORTED); } - set_Protocol(protocol); + if (dialect != SMB2_DIALECT_REVISION_2FF) { + set_Protocol(protocol); + } if (get_remote_arch() != RA_SAMBA) { set_remote_arch(RA_VISTA); -- cgit