]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:smbd: Add SMB3 connection information to session info
authorAndreas Schneider <asn@samba.org>
Fri, 7 Feb 2020 15:48:29 +0000 (16:48 +0100)
committerAndreas Schneider <asn@cryptomilk.org>
Thu, 29 Oct 2020 14:19:36 +0000 (14:19 +0000)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
source3/include/vfs.h
source3/smbd/pipes.c
source3/smbd/smb2_server.c

index 22c139607e2c9659e33a53279b812d5e59586208..7aff0c67ada2bd0acd614e180e63af8de367fcdb 100644 (file)
@@ -414,6 +414,7 @@ typedef struct files_struct {
                bool use_ofd_locks : 1;
                bool closing : 1;
                bool lock_failure_seen : 1;
+               bool encryption_required : 1;
        } fsp_flags;
 
        struct tevent_timer *update_write_time_event;
index 2dd38bb7ab3e0c10f5131b71a7b10431f34ec76f..d51a3de94974ddc5698a3f41bfa7c5f5c9bb6065 100644 (file)
 #include "smbd/globals.h"
 #include "libcli/security/security.h"
 #include "rpc_server/srv_pipe_hnd.h"
+#include "auth/auth_util.h"
 
 NTSTATUS open_np_file(struct smb_request *smb_req, const char *name,
                      struct files_struct **pfsp)
 {
+       struct smbXsrv_connection *xconn = smb_req->xconn;
        struct connection_struct *conn = smb_req->conn;
        struct files_struct *fsp;
        struct smb_filename *smb_fname = NULL;
+       struct auth_session_info *session_info = conn->session_info;
        NTSTATUS status;
 
        status = file_new(smb_req, conn, &fsp);
@@ -68,10 +71,87 @@ NTSTATUS open_np_file(struct smb_request *smb_req, const char *name,
                return status;
        }
 
+       if (smb_req->smb2req != NULL && smb_req->smb2req->was_encrypted) {
+               struct security_token *security_token = NULL;
+               uint16_t dialect = xconn->smb2.server.dialect;
+               uint16_t srv_smb_encrypt = 0x0002;
+               uint16_t cipher = xconn->smb2.server.cipher;
+               char smb3_sid_str[SID_MAX_SIZE];
+               struct dom_sid smb3_dom_sid;
+               struct dom_sid smb3_sid;
+               uint32_t i;
+               bool ok;
+               int rc;
+
+               session_info = copy_session_info(fsp, conn->session_info);
+               if (session_info == NULL) {
+                       DBG_ERR("Failed to copy session info\n");
+                       file_free(smb_req, fsp);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               security_token = session_info->security_token;
+
+               ok = dom_sid_parse(SID_SAMBA_SMB3, &smb3_dom_sid);
+               if (!ok) {
+                       file_free(smb_req, fsp);
+                       return NT_STATUS_BUFFER_TOO_SMALL;
+               }
+
+               /*
+                * Security check:
+                *
+                * Make sure we don't have a SMB3 SID in the security token!
+                */
+               for (i = 0; i < security_token->num_sids; i++) {
+                       int cmp;
+
+                       cmp = dom_sid_compare_domain(&security_token->sids[i],
+                                                    &smb3_dom_sid);
+                       if (cmp == 0) {
+                               DBG_ERR("ERROR: An SMB3 SID has already been "
+                                       "detected in the security token!\n");
+                               file_free(smb_req, fsp);
+                               return NT_STATUS_ACCESS_DENIED;
+                       }
+               }
+
+               rc = snprintf(smb3_sid_str,
+                             sizeof(smb3_sid_str),
+                             "%s-%u-%u-%u",
+                             SID_SAMBA_SMB3,
+                             dialect,
+                             srv_smb_encrypt,
+                             cipher);
+               if (rc < 0) {
+                       DBG_ERR("Buffer too small\n");
+                       file_free(smb_req, fsp);
+                       return NT_STATUS_BUFFER_TOO_SMALL;
+               }
+
+               ok = dom_sid_parse(smb3_sid_str, &smb3_sid);
+               if (!ok) {
+                       DBG_ERR("Failed to parse SMB3 SID\n");
+                       file_free(smb_req, fsp);
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               status = add_sid_to_array_unique(security_token,
+                                                &smb3_sid,
+                                                &security_token->sids,
+                                                &security_token->num_sids);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DBG_ERR("Failed to add SMB3 SID to security token\n");
+                       file_free(smb_req, fsp);
+                       return status;
+               }
+
+               fsp->fsp_flags.encryption_required = true;
+       }
+
        status = np_open(fsp, name,
                         conn->sconn->remote_address,
                         conn->sconn->local_address,
-                        conn->session_info,
+                        session_info,
                         conn->sconn->ev_ctx,
                         conn->sconn->msg_ctx,
                         conn->sconn->dce_ctx,
index 2750c93b1e8019ccaedc374e828343d47f595851..ba9cbd173023f1d36c4c436b087d99599795a055 100644 (file)
@@ -3232,6 +3232,11 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
                                return smbd_smb2_request_error(req,
                                                NT_STATUS_FILE_CLOSED);
                        }
+               } else {
+                       if (fsp->fsp_flags.encryption_required && !req->was_encrypted) {
+                               return smbd_smb2_request_error(req,
+                                               NT_STATUS_ACCESS_DENIED);
+                       }
                }
        }