s3/smbd: update some more DEBUG macros in smbd_smb2_create_send
[nivanova/samba-autobuild/.git] / source3 / smbd / smb2_tcon.c
index cf085a52587c051bb09a7b1f59da3be70d7a34cc..914eb87aa8c2ec6d66c8cf23f57cbf977236489a 100644 (file)
@@ -36,7 +36,8 @@ static NTSTATUS smbd_smb2_tree_connect_recv(struct tevent_req *req,
                                            uint32_t *out_share_flags,
                                            uint32_t *out_capabilities,
                                            uint32_t *out_maximal_access,
-                                           uint32_t *out_tree_id);
+                                           uint32_t *out_tree_id,
+                                           bool *disconnect);
 
 static void smbd_smb2_request_tcon_done(struct tevent_req *subreq);
 
@@ -113,6 +114,7 @@ static void smbd_smb2_request_tcon_done(struct tevent_req *subreq)
        uint32_t out_capabilities = 0;
        uint32_t out_maximal_access = 0;
        uint32_t out_tree_id = 0;
+       bool disconnect = false;
        NTSTATUS status;
        NTSTATUS error;
 
@@ -121,9 +123,15 @@ static void smbd_smb2_request_tcon_done(struct tevent_req *subreq)
                                             &out_share_flags,
                                             &out_capabilities,
                                             &out_maximal_access,
-                                            &out_tree_id);
+                                            &out_tree_id,
+                                            &disconnect);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
+               if (disconnect) {
+                       smbd_server_connection_terminate(req->xconn,
+                                                        nt_errstr(status));
+                       return;
+               }
                error = smbd_smb2_request_error(req, status);
                if (!NT_STATUS_IS_OK(error)) {
                        smbd_server_connection_terminate(req->xconn,
@@ -173,7 +181,8 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
                                       uint32_t *out_share_flags,
                                       uint32_t *out_capabilities,
                                       uint32_t *out_maximal_access,
-                                      uint32_t *out_tree_id)
+                                      uint32_t *out_tree_id,
+                                      bool *disconnect)
 {
        struct smbXsrv_connection *conn = req->xconn;
        const char *share = in_path;
@@ -184,8 +193,12 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
        connection_struct *compat_conn = NULL;
        struct user_struct *compat_vuser = req->session->compat;
        NTSTATUS status;
-       bool encryption_required = req->session->global->encryption_required;
+       bool encryption_desired = req->session->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED;
+       bool encryption_required = req->session->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED;
        bool guest_session = false;
+       bool require_signed_tcon = false;
+
+       *disconnect = false;
 
        if (strncmp(share, "\\\\", 2) == 0) {
                const char *p = strchr(share+2, '\\');
@@ -197,6 +210,25 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
        DEBUG(10,("smbd_smb2_tree_connect: path[%s] share[%s]\n",
                  in_path, share));
 
+       if (security_session_user_level(compat_vuser->session_info, NULL) < SECURITY_USER) {
+               guest_session = true;
+       }
+
+       if (conn->protocol >= PROTOCOL_SMB3_11 && !guest_session) {
+               require_signed_tcon = true;
+       }
+
+       if (require_signed_tcon && !req->do_encryption && !req->do_signing) {
+               DEBUG(1, ("smbd_smb2_tree_connect: reject request to share "
+                         "[%s] as '%s\\%s' without encryption or signing. "
+                         "Disconnecting.\n",
+                         share,
+                         req->session->global->auth_session_info->info->domain_name,
+                         req->session->global->auth_session_info->info->account_name));
+               *disconnect = true;
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        service = talloc_strdup(talloc_tos(), share);
        if(!service) {
                return NT_STATUS_NO_MEMORY;
@@ -235,19 +267,17 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
                return NT_STATUS_BAD_NETWORK_NAME;
        }
 
-       if ((lp_smb_encrypt(snum) > SMB_SIGNING_OFF) &&
-           (conn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
-               encryption_required = true;
+       if ((lp_smb_encrypt(snum) >= SMB_SIGNING_DESIRED) &&
+           (conn->smb2.server.cipher != 0))
+       {
+               encryption_desired = true;
        }
 
        if (lp_smb_encrypt(snum) == SMB_SIGNING_REQUIRED) {
+               encryption_desired = true;
                encryption_required = true;
        }
 
-       if (security_session_user_level(compat_vuser->session_info, NULL) < SECURITY_USER) {
-               guest_session = true;
-       }
-
        if (guest_session && encryption_required) {
                DEBUG(1,("reject guest as encryption is required for service %s\n",
                         service));
@@ -269,7 +299,12 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
                return status;
        }
 
-       tcon->global->encryption_required = encryption_required;
+       if (encryption_desired) {
+               tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_DESIRED;
+       }
+       if (encryption_required) {
+               tcon->global->encryption_flags |= SMBXSRV_ENCRYPTION_REQUIRED;
+       }
 
        compat_conn = make_connection_smb2(req,
                                        tcon, snum,
@@ -339,13 +374,15 @@ static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
                *out_share_flags |= SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM;
        }
 
-       if (encryption_required) {
+       if (encryption_desired) {
                *out_share_flags |= SMB2_SHAREFLAG_ENCRYPT_DATA;
        }
 
        *out_maximal_access = tcon->compat->share_access;
 
        *out_tree_id = tcon->global->tcon_wire_id;
+       req->last_tid = tcon->global->tcon_wire_id;
+
        return NT_STATUS_OK;
 }
 
@@ -356,6 +393,7 @@ struct smbd_smb2_tree_connect_state {
        uint32_t out_capabilities;
        uint32_t out_maximal_access;
        uint32_t out_tree_id;
+       bool disconnect;
 };
 
 static struct tevent_req *smbd_smb2_tree_connect_send(TALLOC_CTX *mem_ctx,
@@ -380,7 +418,8 @@ static struct tevent_req *smbd_smb2_tree_connect_send(TALLOC_CTX *mem_ctx,
                                        &state->out_share_flags,
                                        &state->out_capabilities,
                                        &state->out_maximal_access,
-                                       &state->out_tree_id);
+                                       &state->out_tree_id,
+                                       &state->disconnect);
        if (tevent_req_nterror(req, status)) {
                return tevent_req_post(req, ev);
        }
@@ -394,7 +433,8 @@ static NTSTATUS smbd_smb2_tree_connect_recv(struct tevent_req *req,
                                            uint32_t *out_share_flags,
                                            uint32_t *out_capabilities,
                                            uint32_t *out_maximal_access,
-                                           uint32_t *out_tree_id)
+                                           uint32_t *out_tree_id,
+                                           bool *disconnect)
 {
        struct smbd_smb2_tree_connect_state *state =
                tevent_req_data(req,
@@ -411,6 +451,7 @@ static NTSTATUS smbd_smb2_tree_connect_recv(struct tevent_req *req,
        *out_capabilities = state->out_capabilities;
        *out_maximal_access = state->out_maximal_access;
        *out_tree_id = state->out_tree_id;
+       *disconnect = state->disconnect;
 
        tevent_req_received(req);
        return NT_STATUS_OK;
@@ -502,8 +543,7 @@ static struct tevent_req *smbd_smb2_tdis_send(TALLOC_CTX *mem_ctx,
        struct tevent_req *req;
        struct smbd_smb2_tdis_state *state;
        struct tevent_req *subreq;
-       struct smbd_smb2_request *preq;
-       struct smbXsrv_connection *xconn = smb2req->xconn;
+       struct smbXsrv_connection *xconn = NULL;
 
        req = tevent_req_create(mem_ctx, &state,
                        struct smbd_smb2_tdis_state);
@@ -522,35 +562,40 @@ static struct tevent_req *smbd_smb2_tdis_send(TALLOC_CTX *mem_ctx,
         */
        smb2req->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
 
-       for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
-               if (preq == smb2req) {
-                       /* Can't cancel current request. */
-                       continue;
-               }
-               if (preq->tcon != smb2req->tcon) {
-                       /* Request on different tcon. */
-                       continue;
-               }
-
-               /*
-                * Never cancel anything in a compound
-                * request. Way too hard to deal with
-                * the result.
-                */
-               if (!preq->compound_related && preq->subreq != NULL) {
-                       tevent_req_cancel(preq->subreq);
-               }
-
-               /*
-                * Now wait until the request is finished.
-                *
-                * We don't set a callback, as we just want to block the
-                * wait queue and the talloc_free() of the request will
-                * remove the item from the wait queue.
-                */
-               subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
-               if (tevent_req_nomem(subreq, req)) {
-                       return tevent_req_post(req, ev);
+       xconn = smb2req->xconn->client->connections;
+       for (; xconn != NULL; xconn = xconn->next) {
+               struct smbd_smb2_request *preq;
+
+               for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
+                       if (preq == smb2req) {
+                               /* Can't cancel current request. */
+                               continue;
+                       }
+                       if (preq->tcon != smb2req->tcon) {
+                               /* Request on different tcon. */
+                               continue;
+                       }
+
+                       /*
+                        * Never cancel anything in a compound
+                        * request. Way too hard to deal with
+                        * the result.
+                        */
+                       if (!preq->compound_related && preq->subreq != NULL) {
+                               tevent_req_cancel(preq->subreq);
+                       }
+
+                       /*
+                        * Now wait until the request is finished.
+                        *
+                        * We don't set a callback, as we just want to block the
+                        * wait queue and the talloc_free() of the request will
+                        * remove the item from the wait queue.
+                        */
+                       subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
+                       if (tevent_req_nomem(subreq, req)) {
+                               return tevent_req_post(req, ev);
+                       }
                }
        }