From d8503c6ba120172e9aae737c5510e547e8dea4a5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 6 Mar 2006 14:19:11 +0000 Subject: r13860: - add support for SMB2 ("SMB 2.001") negotiation in SMB negprot requests - the default max protocol is still NT1 metze (This used to be commit d1bae931b327dda28e648efc473e0462cf036f7c) --- source4/include/includes.h | 3 ++- source4/param/loadparm.c | 5 ++-- source4/smb_server/smb/negprot.c | 32 ++++++++++++++++++++++- source4/smb_server/smb2/negprot.c | 53 +++++++++++++++++++++++++++++++++++++++ source4/smb_server/smb_server.c | 4 +-- 5 files changed, 91 insertions(+), 6 deletions(-) diff --git a/source4/include/includes.h b/source4/include/includes.h index 02f67662f1..058eb267a8 100644 --- a/source4/include/includes.h +++ b/source4/include/includes.h @@ -89,7 +89,8 @@ enum protocol_types { PROTOCOL_COREPLUS, PROTOCOL_LANMAN1, PROTOCOL_LANMAN2, - PROTOCOL_NT1 + PROTOCOL_NT1, + PROTOCOL_SMB2 }; /* passed to br lock code. FIXME: Move to one of the smb-specific headers */ diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index 8fc061b53f..16692daec4 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -279,6 +279,7 @@ static BOOL handle_copy(const char *pszParmValue, char **ptr); static void set_default_server_announce_type(void); static const struct enum_list enum_protocol[] = { + {PROTOCOL_SMB2, "SMB2"}, {PROTOCOL_NT1, "NT1"}, {PROTOCOL_LANMAN2, "LANMAN2"}, {PROTOCOL_LANMAN1, "LANMAN1"}, @@ -595,7 +596,6 @@ static void init_globals(void) myname = get_myname(); do_parameter("netbios name", myname, NULL); SAFE_FREE(myname); - do_parameter("max protocol", "NT1", NULL); do_parameter("name resolve order", "lmhosts wins host bcast", NULL); do_parameter("fstype", FSTYPE_STRING, NULL); @@ -646,7 +646,8 @@ static void init_globals(void) do_parameter("max xmit", "12288", NULL); do_parameter("password level", "0", NULL); do_parameter("LargeReadwrite", "True", NULL); - do_parameter("minprotocol", "CORE", NULL); + do_parameter("min protocol", "CORE", NULL); + do_parameter("max protocol", "NT1", NULL); do_parameter("security", "USER", NULL); do_parameter("paranoid server security", "True", NULL); do_parameter("EncryptPasswords", "True", NULL); diff --git a/source4/smb_server/smb/negprot.c b/source4/smb_server/smb/negprot.c index b2f136f4f7..61be84ca18 100644 --- a/source4/smb_server/smb/negprot.c +++ b/source4/smb_server/smb/negprot.c @@ -21,7 +21,10 @@ #include "includes.h" #include "auth/auth.h" #include "smb_server/smb_server.h" +#include "libcli/smb2/smb2.h" +#include "smb_server/smb2/smb2_server.h" #include "smbd/service_stream.h" +#include "lib/stream/packet.h" /* initialise the auth_context for this server and return the cryptkey */ @@ -415,7 +418,33 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice) req_send_reply_nosign(req); } - +/* + after a SMB2 2.001 negprot reply to a SMB negprot request + no (SMB or SMB2) requests are allowed anymore, + vista resets the connection in this case +*/ +static NTSTATUS smbsrv_recv_disabled_request(void *private, DATA_BLOB blob) +{ + struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection); + smbsrv_terminate_connection(smb_conn, "Receive Packet after SMB -> SMB2 negprot"); + return NT_STATUS_OK; +} + +/**************************************************************************** + Reply for the SMB2 2.001 protocol +****************************************************************************/ +static void reply_smb2(struct smbsrv_request *req, uint16_t choice) +{ + struct smbsrv_connection *smb_conn = req->smb_conn; + + /* reply with a SMB2 packet */ + smb2srv_reply_smb_negprot(req); + req = NULL; + + /* disallow requests */ + packet_set_callback(smb_conn->packet, smbsrv_recv_disabled_request); +} + /* List of supported protocols, most desired first */ static const struct { const char *proto_name; @@ -423,6 +452,7 @@ static const struct { void (*proto_reply_fn)(struct smbsrv_request *req, uint16_t choice); int protocol_level; } supported_protocols[] = { + {"SMB 2.001", "SMB2", reply_smb2, PROTOCOL_SMB2}, {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c index 71e86ad805..6aab25427f 100644 --- a/source4/smb_server/smb2/negprot.c +++ b/source4/smb_server/smb2/negprot.c @@ -173,3 +173,56 @@ void smb2srv_negprot_recv(struct smb2srv_request *req) } smb2srv_negprot_send(req, io); } + +/* + * reply to a SMB negprot request with dialect "SMB 2.001" + */ +void smb2srv_reply_smb_negprot(struct smbsrv_request *smb_req) +{ + struct smb2srv_request *req; + uint32_t body_fixed_size = 0x26; + + /* create a fake SMB2 negprot request */ + req = talloc_zero(smb_req->smb_conn, struct smb2srv_request); + if (!req) goto nomem; + req->smb_conn = smb_req->smb_conn; + req->request_time = smb_req->request_time; + talloc_steal(req, smb_req); + + req->in.size = NBT_HDR_SIZE+SMB2_HDR_BODY+body_fixed_size; + req->in.allocated = req->in.size; + req->in.buffer = talloc_size(req, req->in.allocated); + if (!req->in.buffer) goto nomem; + req->in.hdr = req->in.buffer + NBT_HDR_SIZE; + req->in.body = req->in.hdr + SMB2_HDR_BODY; + req->in.body_size = body_fixed_size; + req->in.dynamic = NULL; + + SIVAL(req->in.hdr, 0, SMB2_MAGIC); + SSVAL(req->in.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); + SSVAL(req->in.hdr, SMB2_HDR_PAD1, 0); + SIVAL(req->in.hdr, SMB2_HDR_STATUS, 0); + SSVAL(req->in.hdr, SMB2_HDR_OPCODE, SMB2_OP_NEGPROT); + SSVAL(req->in.hdr, SMB2_HDR_PAD2, 0); + SIVAL(req->in.hdr, SMB2_HDR_FLAGS, 0); + SIVAL(req->in.hdr, SMB2_HDR_UNKNOWN, 0); + SBVAL(req->in.hdr, SMB2_HDR_SEQNUM, 0); + SIVAL(req->in.hdr, SMB2_HDR_PID, 0); + SIVAL(req->in.hdr, SMB2_HDR_TID, 0); + SBVAL(req->in.hdr, SMB2_HDR_UID, 0); + memset(req->in.hdr+SMB2_HDR_SIG, 0, 16); + + /* this seems to be a bug, they use 0x24 but the length is 0x26 */ + SSVAL(req->in.body, 0x00, 0x24); + + SSVAL(req->in.body, 0x02, 1); + memset(req->in.body+0x04, 0, 32); + SSVAL(req->in.body, 0x24, 0); + + smb2srv_negprot_recv(req); + return; +nomem: + smbsrv_terminate_connection(smb_req->smb_conn, nt_errstr(NT_STATUS_NO_MEMORY)); + talloc_free(req); + return; +} diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index 6740db4923..6e517cd386 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -56,14 +56,14 @@ static NTSTATUS smbsrv_recv_generic_request(void *private, DATA_BLOB blob) packet_set_callback(smb_conn->packet, smbsrv_recv_smb_request); return smbsrv_recv_smb_request(smb_conn, blob); case SMB2_MAGIC: - if (!lp_parm_bool(-1, "smbsrv", "enable smb2", False)) break; + if (lp_maxprotocol() < PROTOCOL_SMB2) break; status = smbsrv_init_smb2_connection(smb_conn); NT_STATUS_NOT_OK_RETURN(status); packet_set_callback(smb_conn->packet, smbsrv_recv_smb2_request); return smbsrv_recv_smb2_request(smb_conn, blob); } - DEBUG(2,("Invalid SMB packet: protocl prefix: 0x%08X\n", protocol_version)); + DEBUG(2,("Invalid SMB packet: protocol prefix: 0x%08X\n", protocol_version)); smbsrv_terminate_connection(smb_conn, "NON-SMB packet"); return NT_STATUS_OK; } -- cgit