s3/smbd: update some more DEBUG macros in smbd_smb2_create_send
[nivanova/samba-autobuild/.git] / source3 / smbd / smb2_negprot.c
index 158207225a032a4902f341ebcc134bb9981b3a8b..d9ccdbeea8ec7e2bc803c2f9d3b84a97f26cc9c6 100644 (file)
@@ -25,6 +25,7 @@
 #include "../libcli/smb/smb2_negotiate_context.h"
 #include "../lib/tsocket/tsocket.h"
 #include "../librpc/ndr/libndr.h"
+#include "../libcli/smb/smb_signing.h"
 
 extern fstring remote_proto;
 
@@ -160,6 +161,8 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
        uint32_t max_read = lp_smb2_max_read();
        uint32_t max_write = lp_smb2_max_write();
        NTTIME now = timeval_to_nttime(&req->request_time);
+       bool signing_required = true;
+       bool ok;
 
        status = smbd_smb2_request_verify_sizes(req, 0x24);
        if (!NT_STATUS_IS_OK(status)) {
@@ -258,8 +261,26 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
                }
        }
 
-       if (get_remote_arch() != RA_SAMBA) {
+       if ((dialect != SMB2_DIALECT_REVISION_2FF) &&
+           (protocol >= PROTOCOL_SMB2_10) &&
+           !GUID_all_zero(&in_guid))
+       {
+               ok = remote_arch_cache_update(&in_guid);
+               if (!ok) {
+                       return smbd_smb2_request_error(
+                               req, NT_STATUS_UNSUCCESSFUL);
+               }
+       }
+
+       switch (get_remote_arch()) {
+       case RA_VISTA:
+       case RA_SAMBA:
+       case RA_CIFSFS:
+       case RA_OSX:
+               break;
+       default:
                set_remote_arch(RA_VISTA);
+               break;
        }
 
        fstr_sprintf(remote_proto, "SMB%X_%02X",
@@ -287,7 +308,13 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
        }
 
        security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
-       if (lp_server_signing() == SMB_SIGNING_REQUIRED) {
+       /*
+        * We use xconn->smb1.signing_state as that's already present
+        * and used lpcfg_server_signing_allowed() to get the correct
+        * defaults, e.g. signing_required for an ad_dc.
+        */
+       signing_required = smb_signing_is_mandatory(xconn->smb1.signing_state);
+       if (signing_required) {
                security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
        }
 
@@ -414,7 +441,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
                req->preauth = &req->xconn->smb2.preauth;
        }
 
-       if (in_cipher != NULL) {
+       if ((capabilities & SMB2_CAP_ENCRYPTION) && (in_cipher != NULL)) {
                size_t needed = 2;
                uint16_t cipher_count;
                const uint8_t *p;
@@ -517,7 +544,6 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
                static const uint8_t zeros[8];
                size_t pad = 0;
                size_t ofs;
-               bool ok;
 
                outdyn = data_blob_dup_talloc(req, security_buffer);
                if (outdyn.length != security_buffer.length) {
@@ -587,6 +613,8 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
        req->sconn->using_smb2 = true;
 
        if (dialect != SMB2_DIALECT_REVISION_2FF) {
+               struct smbXsrv_client_global0 *global0 = NULL;
+
                status = smbXsrv_connection_init_tables(xconn, protocol);
                if (!NT_STATUS_IS_OK(status)) {
                        return smbd_smb2_request_error(req, status);
@@ -613,6 +641,62 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
                xconn->smb2.server.max_trans = max_trans;
                xconn->smb2.server.max_read  = max_read;
                xconn->smb2.server.max_write = max_write;
+
+               if (xconn->protocol < PROTOCOL_SMB2_10) {
+                       /*
+                        * SMB2_02 doesn't support client guids
+                        */
+                       return smbd_smb2_request_done(req, outbody, &outdyn);
+               }
+
+               if (!xconn->client->server_multi_channel_enabled) {
+                       /*
+                        * Only deal with the client guid database
+                        * if multi-channel is enabled.
+                        */
+                       return smbd_smb2_request_done(req, outbody, &outdyn);
+               }
+
+               if (xconn->smb2.client.guid_verified) {
+                       /*
+                        * The connection was passed from another
+                        * smbd process.
+                        */
+                       return smbd_smb2_request_done(req, outbody, &outdyn);
+               }
+
+               status = smb2srv_client_lookup_global(xconn->client,
+                                               xconn->smb2.client.guid,
+                                               req, &global0);
+               /*
+                * TODO: check for races...
+                */
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECTID_NOT_FOUND)) {
+                       /*
+                        * This stores the new client information in
+                        * smbXsrv_client_global.tdb
+                        */
+                       xconn->client->global->client_guid =
+                                               xconn->smb2.client.guid;
+                       status = smbXsrv_client_update(xconn->client);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
+
+                       xconn->smb2.client.guid_verified = true;
+               } else if (NT_STATUS_IS_OK(status)) {
+                       status = smb2srv_client_connection_pass(req,
+                                                               global0);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return smbd_smb2_request_error(req, status);
+                       }
+
+                       smbd_server_connection_terminate(xconn,
+                                                        "passed connection");
+                       return NT_STATUS_OBJECTID_EXISTS;
+               } else {
+                       return smbd_smb2_request_error(req, status);
+               }
        }
 
        return smbd_smb2_request_done(req, outbody, &outdyn);