s3-rpc_server: Provide hooks required for JSON message logging for the no-auth case
[nivanova/samba-autobuild/.git] / source3 / smbd / smb2_tcon.c
index 3750bc13d57862b8d5844aebad35a0a81632b1ea..5330fc39c36dfc8c674ebdd12bdcdc6599610ab7 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,7 +374,7 @@ 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;
        }
 
@@ -356,6 +391,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 +416,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 +431,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 +449,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;