From: Ralph Boehme Date: Sun, 15 Nov 2015 10:12:34 +0000 (+0100) Subject: s3:smb2_server: add signing state tracking flags X-Git-Tag: samba-4.4.0rc1~90 X-Git-Url: http://git.samba.org/samba.git/?p=kai%2Fsamba-autobuild%2F.git;a=commitdiff_plain;h=9d284431fc478bc6e19ac2d98b3c330800521ad3 s3:smb2_server: add signing state tracking flags 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 Reviewed-by: Jeremy Allison --- diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index f6a5fd98c36..852877096ae 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -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 { diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 676ab75b2f4..90d8dccfa09 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -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; diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index a9916cca2a8..9adbb996067 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -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;