summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-12-15 14:45:56 +0100
committerStefan Metzmacher <metze@samba.org>2012-05-12 01:01:34 +0200
commitb3235d483da924a41ca9cecf72e1c62bab7fedd5 (patch)
tree9d34739a9e01e7d9176613a71ce68727e1ecf79d
parentc8a3c0e0f793c622e071953b25a70a3fd8a0da65 (diff)
downloadsamba-b3235d483da924a41ca9cecf72e1c62bab7fedd5.tar.gz
samba-b3235d483da924a41ca9cecf72e1c62bab7fedd5.tar.bz2
samba-b3235d483da924a41ca9cecf72e1c62bab7fedd5.zip
s3:smbd: introduce struct smbXsrv_connection
This will represent a transport connection for SMB 1 or 2 in the server. smbd_server_connection will slowly be moved to the SMB_VFS layer to satisfy the existing modules, but it will hopefully be protocol independend in future. metze
-rw-r--r--source3/smbd/globals.h37
-rw-r--r--source3/smbd/negprot.c11
-rw-r--r--source3/smbd/process.c25
-rw-r--r--source3/smbd/smb2_negprot.c56
4 files changed, 122 insertions, 7 deletions
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 56ee251483..0a57013a68 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -326,6 +326,41 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
char *private_data,
size_t priv_len);
+struct smbXsrv_connection {
+ struct smbd_server_connection *sconn;
+
+ const struct tsocket_address *local_address;
+ const struct tsocket_address *remote_address;
+ const char *remote_hostname;
+
+ struct tevent_context *ev_ctx;
+ struct messaging_context *msg_ctx;
+
+ enum protocol_types protocol;
+
+ struct {
+ struct {
+ uint32_t capabilities;
+ struct GUID guid;
+ uint16_t security_mode;
+ uint16_t num_dialects;
+ uint16_t *dialects;
+ } client;
+ struct {
+ uint32_t capabilities;
+ struct GUID guid;
+ uint16_t security_mode;
+ uint16_t dialect;
+ uint32_t max_trans;
+ uint32_t max_read;
+ uint32_t max_write;
+ } server;
+ } smb2;
+};
+
+NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn,
+ enum protocol_types protocol);
+
struct smbd_smb2_request {
struct smbd_smb2_request *prev, *next;
@@ -599,6 +634,8 @@ struct smbd_server_connection {
struct bitmap *credits_bitmap;
bool compound_related_in_progress;
} smb2;
+
+ struct smbXsrv_connection *conn;
};
extern struct smbd_server_connection *smbd_server_conn;
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 9ddafee657..a55a7c336c 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -65,7 +65,7 @@ static void reply_corep(struct smb_request *req, uint16 choice)
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf, smb_vwv0, choice);
- set_Protocol(PROTOCOL_CORE);
+ smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_CORE);
}
/****************************************************************************
@@ -85,7 +85,8 @@ static void reply_coreplus(struct smb_request *req, uint16 choice)
SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't
* encrypt */
- set_Protocol(PROTOCOL_COREPLUS);
+
+ smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_COREPLUS);
}
/****************************************************************************
@@ -118,7 +119,7 @@ static void reply_lanman1(struct smb_request *req, uint16 choice)
SSVAL(req->outbuf,smb_vwv11, 8);
}
- set_Protocol(PROTOCOL_LANMAN1);
+ smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN1);
/* Reply, SMBlockread, SMBwritelock supported. */
SCVAL(req->outbuf,smb_flg, FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
@@ -167,7 +168,7 @@ static void reply_lanman2(struct smb_request *req, uint16 choice)
SSVAL(req->outbuf,smb_vwv11, 8);
}
- set_Protocol(PROTOCOL_LANMAN2);
+ smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN2);
/* Reply, SMBlockread, SMBwritelock supported. */
SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
@@ -360,7 +361,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
SSVAL(req->outbuf,smb_vwv0,choice);
SCVAL(req->outbuf,smb_vwv1,secword);
- set_Protocol(PROTOCOL_NT1);
+ smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_NT1);
SSVAL(req->outbuf,smb_vwv1+1, lp_maxmux()); /* maxmpx */
SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 7b12315fc3..087326205c 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -3149,6 +3149,17 @@ static void smbd_id_cache_kill(struct messaging_context *msg_ctx,
id_cache_delete_from_cache(&id);
}
+NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn,
+ enum protocol_types protocol)
+{
+ NTSTATUS status;
+
+ set_Protocol(protocol);
+ conn->protocol = protocol;
+
+ return NT_STATUS_OK;
+}
+
/****************************************************************************
Process commands from the client
****************************************************************************/
@@ -3167,6 +3178,12 @@ void smbd_process(struct tevent_context *ev_ctx,
char *rhost;
int ret;
+ sconn->conn = talloc_zero(sconn, struct smbXsrv_connection);
+ if (sconn->conn == NULL) {
+ DEBUG(0,("talloc_zero(struct smbXsrv_connection)\n"));
+ exit_server_cleanly("talloc_zero(struct smbXsrv_connection).\n");
+ }
+
if (lp_srv_maxprotocol() >= PROTOCOL_SMB2_02) {
/*
* We're not making the decision here,
@@ -3430,6 +3447,14 @@ void smbd_process(struct tevent_context *ev_ctx,
exit_server("failed to create smbd_server_connection fde");
}
+ sconn->conn->sconn = sconn;
+ sconn->conn->ev_ctx = sconn->ev_ctx;
+ sconn->conn->msg_ctx = sconn->msg_ctx;
+ sconn->conn->local_address = sconn->local_address;
+ sconn->conn->remote_address = sconn->remote_address;
+ sconn->conn->remote_hostname = sconn->remote_hostname;
+ sconn->conn->protocol = PROTOCOL_NONE;
+
TALLOC_FREE(frame);
while (True) {
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
index 6d60117710..cfb5dcb777 100644
--- a/source3/smbd/smb2_negprot.c
+++ b/source3/smbd/smb2_negprot.c
@@ -23,6 +23,7 @@
#include "smbd/globals.h"
#include "../libcli/smb/smb_common.h"
#include "../lib/tsocket/tsocket.h"
+#include "../librpc/ndr/libndr.h"
/*
* this is the entry point if SMB2 is selected via
@@ -94,8 +95,15 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
size_t c;
uint16_t security_mode;
uint16_t dialect_count;
+ uint16_t in_security_mode;
+ uint32_t in_capabilities;
+ DATA_BLOB in_guid_blob;
+ struct GUID in_guid;
+ NTTIME in_start_time;
uint16_t dialect = 0;
uint32_t capabilities;
+ DATA_BLOB out_guid_blob;
+ struct GUID out_guid;
enum protocol_types protocol = PROTOCOL_NONE;
uint32_t max_limit;
uint32_t max_trans = lp_smb2_max_trans();
@@ -109,10 +117,21 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
dialect_count = SVAL(inbody, 0x02);
+
+ in_security_mode = SVAL(inbody, 0x04);
+ in_capabilities = IVAL(inbody, 0x08);
+ in_guid_blob = data_blob_const(inbody + 0x0C, 16);
+ in_start_time = BVAL(inbody, 0x1C);
+
if (dialect_count == 0) {
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
}
+ status = GUID_from_ndr_blob(&in_guid_blob, &in_guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+
expected_dyn_size = dialect_count * 2;
if (req->in.vector[i+2].iov_len < expected_dyn_size) {
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
@@ -280,6 +299,12 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
security_buffer = data_blob_const(NULL, 0);
#endif
+ out_guid_blob = data_blob_const(negprot_spnego_blob.data, 16);
+ status = GUID_from_ndr_blob(&out_guid_blob, &out_guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+
outbody = data_blob_talloc(req->out.vector, NULL, 0x40);
if (outbody.data == NULL) {
return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
@@ -291,7 +316,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
SSVAL(outbody.data, 0x04, dialect); /* dialect revision */
SSVAL(outbody.data, 0x06, 0); /* reserved */
memcpy(outbody.data + 0x08,
- negprot_spnego_blob.data, 16); /* server guid */
+ out_guid_blob.data, 16); /* server guid */
SIVAL(outbody.data, 0x18,
capabilities); /* capabilities */
SIVAL(outbody.data, 0x1C, max_trans); /* max transact size */
@@ -310,7 +335,34 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
req->sconn->using_smb2 = true;
if (dialect != SMB2_DIALECT_REVISION_2FF) {
- set_Protocol(protocol);
+ struct smbXsrv_connection *conn = req->sconn->conn;
+
+ status = smbXsrv_connection_init_tables(conn, protocol);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+
+ conn->smb2.client.capabilities = in_capabilities;
+ conn->smb2.client.security_mode = in_security_mode;
+ conn->smb2.client.guid = in_guid;
+ conn->smb2.client.num_dialects = dialect_count;
+ conn->smb2.client.dialects = talloc_array(conn,
+ uint16_t,
+ dialect_count);
+ if (conn->smb2.client.dialects == NULL) {
+ return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+ }
+ for (c=0; c < dialect_count; c++) {
+ conn->smb2.client.dialects[c] = SVAL(indyn, c*2);
+ }
+
+ conn->smb2.server.capabilities = capabilities;
+ conn->smb2.server.security_mode = security_mode;
+ conn->smb2.server.guid = out_guid;
+ conn->smb2.server.dialect = dialect;
+ conn->smb2.server.max_trans = max_trans;
+ conn->smb2.server.max_read = max_read;
+ conn->smb2.server.max_write = max_write;
req->sconn->smb2.max_trans = max_trans;
req->sconn->smb2.max_read = max_read;