s3:smbd: introduce struct smbXsrv_connection
authorStefan Metzmacher <metze@samba.org>
Thu, 15 Dec 2011 13:45:56 +0000 (14:45 +0100)
committerStefan Metzmacher <metze@samba.org>
Fri, 11 May 2012 23:01:34 +0000 (01:01 +0200)
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

source3/smbd/globals.h
source3/smbd/negprot.c
source3/smbd/process.c
source3/smbd/smb2_negprot.c

index 56ee25148350a1d9c52ea3e0709ec2bee4cf7efe..0a57013a6800ff7b8ce564356c590cd358ceed94 100644 (file)
@@ -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;
index 9ddafee657a221ba0c3b5242787b2b6ee964ef5d..a55a7c336c52b25b0e871938d347c34ede096ec4 100644 (file)
@@ -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 */
index 7b12315fc3cbbcfe5db171467751c14a7672774a..087326205c3dddc479df242f24c7643224b117c2 100644 (file)
@@ -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) {
index 6d601177107dd653f71ed09c184b418bdef37147..cfb5dcb777099729729ac53458695028a4554445 100644 (file)
@@ -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;