s3:smb2_server: add encryption state tracking flags
authorRalph Boehme <slow@samba.org>
Fri, 13 Nov 2015 09:30:50 +0000 (10:30 +0100)
committerRalph Boehme <slow@samba.org>
Fri, 22 Jan 2016 06:52:20 +0000 (07:52 +0100)
Add two encryption state tracking flags that can be used to tell whether
a session or tcon is "encrypted" and add a helper function to calculate
the encryption state from those flags.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/librpc/idl/smbXsrv.idl
source3/smbd/globals.h
source3/smbd/smb2_server.c

index 109151b94a29a7e13fc71cbf6664acc2e3f92d99..5078d0d2800e741b58c1aedec3e354c68fc98e64 100644 (file)
@@ -118,7 +118,9 @@ interface smbXsrv
 
        typedef [public,bitmap8bit] bitmap {
                SMBXSRV_ENCRYPTION_REQUIRED             = 0x01,
-               SMBXSRV_ENCRYPTION_DESIRED              = 0x02
+               SMBXSRV_ENCRYPTION_DESIRED              = 0x02,
+               SMBXSRV_PROCESSED_ENCRYPTED_PACKET      = 0x04,
+               SMBXSRV_PROCESSED_UNENCRYPTED_PACKET    = 0x08
        } smbXsrv_encrpytion_flags;
 
        typedef struct {
index 0422cbeb995e7aaa7c3c3ea2c9db0d534d10b4c7..676ab75b2f43bb28fe3d7cf139213c2b4e54917e 100644 (file)
@@ -636,6 +636,9 @@ NTSTATUS smbXsrv_open_global_traverse(
        void *private_data);
 
 NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id);
+bool smbXsrv_is_encrypted(uint8_t encryption_flags);
+bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags);
+bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag);
 
 struct smbd_smb2_send_queue {
        struct smbd_smb2_send_queue *prev, *next;
index bd8261a153f148f8dda397e8f69d3748b5129404..70fbdc7a0b3b5df0f17f62dceeef3f55cf6bc033 100644 (file)
@@ -2004,6 +2004,65 @@ NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
        return NT_STATUS_OK;
 }
 
+bool smbXsrv_is_encrypted(uint8_t encryption_flags)
+{
+       return (!(encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET)
+               &&
+               (encryption_flags & (SMBXSRV_PROCESSED_ENCRYPTED_PACKET |
+                                    SMBXSRV_ENCRYPTION_DESIRED |
+                                    SMBXSRV_ENCRYPTION_REQUIRED)));
+}
+
+bool smbXsrv_is_partially_encrypted(uint8_t encryption_flags)
+{
+       return ((encryption_flags & SMBXSRV_PROCESSED_ENCRYPTED_PACKET) &&
+               (encryption_flags & SMBXSRV_PROCESSED_UNENCRYPTED_PACKET));
+}
+
+/* Set a flag if not already set, return true if set */
+bool smbXsrv_set_crypto_flag(uint8_t *flags, uint8_t flag)
+{
+       if ((flag == 0) || (*flags & flag)) {
+               return false;
+       }
+
+       *flags |= flag;
+       return true;
+}
+
+/*
+ * Update encryption state tracking flags, this can be used to
+ * determine whether whether the session or tcon is "encrypted".
+ */
+static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
+                                       uint16_t opcode,
+                                       bool *update_session_globalp,
+                                       bool *update_tcon_globalp)
+{
+       /* Default: assume unecrypted */
+       struct smbXsrv_session *session = req->session;
+       struct smbXsrv_tcon *tcon = req->tcon;
+       uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
+       bool update_session = false;
+       bool update_tcon = false;
+
+       if (req->was_encrypted && req->do_encryption) {
+               encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+       }
+
+       update_session |= smbXsrv_set_crypto_flag(
+               &session->global->encryption_flags, encrypt_flag);
+
+       if (tcon) {
+               update_tcon |= smbXsrv_set_crypto_flag(
+                       &tcon->global->encryption_flags, encrypt_flag);
+       }
+
+       *update_session_globalp = update_session;
+       *update_tcon_globalp = update_tcon;
+       return;
+}
+
 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 {
        struct smbXsrv_connection *xconn = req->xconn;
@@ -2240,6 +2299,28 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
                req->do_encryption = true;
        }
 
+       if (req->session) {
+               bool update_session_global = false;
+               bool update_tcon_global = false;
+
+               smb2srv_update_crypto_flags(req, opcode,
+                                           &update_session_global,
+                                           &update_tcon_global);
+
+               if (update_session_global) {
+                       status = smbXsrv_session_update(x);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return smbd_smb2_request_error(req, status);
+                       }
+               }
+               if (update_tcon_global) {
+                       status = smbXsrv_tcon_update(req->tcon);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return smbd_smb2_request_error(req, status);
+                       }
+               }
+       }
+
        if (call->fileid_ofs != 0) {
                size_t needed = call->fileid_ofs + 16;
                const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);