summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-09-05 13:14:40 +0200
committerStefan Metzmacher <metze@samba.org>2011-09-05 19:30:58 +0200
commit012c9d06a94b532377e9e96f60b20b5f0975af74 (patch)
tree0065c2161af15c9cf92c23e1fb931bc838e71a14 /source3/smbd
parent1c8e8c7e7b4cc00628b91e2e0596bfa428a2bcdb (diff)
downloadsamba-012c9d06a94b532377e9e96f60b20b5f0975af74.tar.gz
samba-012c9d06a94b532377e9e96f60b20b5f0975af74.tar.bz2
samba-012c9d06a94b532377e9e96f60b20b5f0975af74.zip
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 <metze@samba.org> Autobuild-Date: Mon Sep 5 19:30:58 CEST 2011 on sn-devel-104
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/globals.h2
-rw-r--r--source3/smbd/negprot.c1
-rw-r--r--source3/smbd/smb2_negprot.c66
3 files changed, 65 insertions, 4 deletions
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);