s3:smb2_server: add signing state tracking flags
authorRalph Boehme <slow@samba.org>
Sun, 15 Nov 2015 10:12:34 +0000 (11:12 +0100)
committerRalph Boehme <slow@samba.org>
Fri, 22 Jan 2016 06:52:21 +0000 (07:52 +0100)
Add flags that track the signing state of all incoming and outgoing SMB2
packets and a helper function that can be used to determine whether a
session of tcon can be considered "signed".

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 f6a5fd98c361239c0d1f75a8ae711a914aa867c6..852877096ae0a1f8f9eaf7983edf2bead7b72f69 100644 (file)
@@ -124,7 +124,9 @@ interface smbXsrv
        } smbXsrv_encrpytion_flags;
 
        typedef [public,bitmap8bit] bitmap {
-               SMBXSRV_SIGNING_REQUIRED                = 0x01
+               SMBXSRV_SIGNING_REQUIRED                = 0x01,
+               SMBXSRV_PROCESSED_SIGNED_PACKET         = 0x02,
+               SMBXSRV_PROCESSED_UNSIGNED_PACKET       = 0x04
        } smbXsrv_signing_flags;
 
        typedef struct {
@@ -275,6 +277,7 @@ interface smbXsrv
                 * for SMB1 this is the session that the tcon was opened on
                 */
                uint32                                  session_global_id;
+               smbXsrv_signing_flags                   signing_flags;
        } smbXsrv_tcon_global0;
 
        typedef union {
index 676ab75b2f43bb28fe3d7cf139213c2b4e54917e..90d8dccfa0965fcc52a9630cf3608f80b43efabe 100644 (file)
@@ -639,6 +639,8 @@ 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);
+bool smbXsrv_is_signed(uint8_t signing_flags);
+bool smbXsrv_is_partially_signed(uint8_t signing_flags);
 
 struct smbd_smb2_send_queue {
        struct smbd_smb2_send_queue *prev, *next;
index a9916cca2a84db3228cffb0bd194dbe5808501fd..9adbb99606795a9311460fd1b963d6cbf373fed5 100644 (file)
@@ -2039,23 +2039,37 @@ static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
                                        bool *update_session_globalp,
                                        bool *update_tcon_globalp)
 {
-       /* Default: assume unecrypted */
+       /* Default: assume unecrypted and unsigned */
        struct smbXsrv_session *session = req->session;
        struct smbXsrv_tcon *tcon = req->tcon;
        uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
+       uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
        bool update_session = false;
        bool update_tcon = false;
 
        if (req->was_encrypted && req->do_encryption) {
                encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
+               sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
+       } else {
+               /* Unencrypted packet, can be signed */
+               if (req->do_signing) {
+                       sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
+               } else if (opcode == SMB2_OP_CANCEL) {
+                       /* Cancel requests are allowed to skip signing */
+                       sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
+               }
        }
 
        update_session |= smbXsrv_set_crypto_flag(
                &session->global->encryption_flags, encrypt_flag);
+       update_session |= smbXsrv_set_crypto_flag(
+               &session->global->signing_flags, sign_flag);
 
        if (tcon) {
                update_tcon |= smbXsrv_set_crypto_flag(
                        &tcon->global->encryption_flags, encrypt_flag);
+               update_tcon |= smbXsrv_set_crypto_flag(
+                       &tcon->global->signing_flags, sign_flag);
        }
 
        *update_session_globalp = update_session;
@@ -2063,6 +2077,23 @@ static void smb2srv_update_crypto_flags(struct smbd_smb2_request *req,
        return;
 }
 
+bool smbXsrv_is_signed(uint8_t signing_flags)
+{
+       /*
+        * Signing is always enabled, so unless we got an unsigned
+        * packet and at least one signed packet that was not
+        * encrypted, the session or tcon is "signed".
+        */
+       return (!(signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
+               (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
+}
+
+bool smbXsrv_is_partially_signed(uint8_t signing_flags)
+{
+       return ((signing_flags & SMBXSRV_PROCESSED_UNSIGNED_PACKET) &&
+               (signing_flags & SMBXSRV_PROCESSED_SIGNED_PACKET));
+}
+
 NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 {
        struct smbXsrv_connection *xconn = req->xconn;