summaryrefslogtreecommitdiff
path: root/source4/smb_server
diff options
context:
space:
mode:
Diffstat (limited to 'source4/smb_server')
-rw-r--r--source4/smb_server/smb/negprot.c32
-rw-r--r--source4/smb_server/smb2/negprot.c53
-rw-r--r--source4/smb_server/smb_server.c4
3 files changed, 86 insertions, 3 deletions
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;
}