]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
libcli:smb: Use smb2_signing_key for smb2_signing_sign_pdu()
authorAndreas Schneider <asn@samba.org>
Wed, 13 Mar 2019 18:34:23 +0000 (19:34 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 30 Apr 2019 23:18:28 +0000 (23:18 +0000)
This caches the gnutls hmac handle in the struct so we only allocate it
once.

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
libcli/smb/smb2_signing.c
libcli/smb/smb2_signing.h
libcli/smb/smbXcli_base.c
source3/smbd/smb2_server.c

index 72c98d6a610b8b86d2ea6bc07fb60080526fc296..38169b50f624715721547348511c56e98ff38f07 100644 (file)
@@ -50,7 +50,7 @@ bool smb2_signing_key_valid(const struct smb2_signing_key *key)
        return true;
 }
 
-NTSTATUS smb2_signing_sign_pdu(DATA_BLOB signing_key,
+NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
                               enum protocol_types protocol,
                               struct iovec *vector,
                               int count)
@@ -79,9 +79,9 @@ NTSTATUS smb2_signing_sign_pdu(DATA_BLOB signing_key,
                return NT_STATUS_OK;
        }
 
-       if (signing_key.length == 0) {
-               DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
-                        (unsigned)signing_key.length));
+       if (!smb2_signing_key_valid(signing_key)) {
+               DBG_WARNING("Wrong session key length %zu for SMB2 signing\n",
+                           signing_key->blob.length);
                return NT_STATUS_ACCESS_DENIED;
        }
 
@@ -93,7 +93,9 @@ NTSTATUS smb2_signing_sign_pdu(DATA_BLOB signing_key,
                struct aes_cmac_128_context ctx;
                uint8_t key[AES_BLOCK_SIZE] = {0};
 
-               memcpy(key, signing_key.data, MIN(signing_key.length, 16));
+               memcpy(key,
+                      signing_key->blob.data,
+                      MIN(signing_key->blob.length, 16));
 
                aes_cmac_128_init(&ctx, key);
                for (i=0; i < count; i++) {
@@ -105,28 +107,28 @@ NTSTATUS smb2_signing_sign_pdu(DATA_BLOB signing_key,
 
                ZERO_ARRAY(key);
        } else {
-               gnutls_hmac_hd_t hmac_hnd = NULL;
                uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
                int rc;
 
-               rc = gnutls_hmac_init(&hmac_hnd,
-                                     GNUTLS_MAC_SHA256,
-                                     signing_key.data,
-                                     MIN(signing_key.length, 16));
-               if (rc < 0) {
-                       return NT_STATUS_NO_MEMORY;
+               if (signing_key->hmac_hnd == NULL) {
+                       rc = gnutls_hmac_init(&signing_key->hmac_hnd,
+                                             GNUTLS_MAC_SHA256,
+                                             signing_key->blob.data,
+                                             MIN(signing_key->blob.length, 16));
+                       if (rc < 0) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
                }
 
                for (i = 0; i < count; i++) {
-                       rc = gnutls_hmac(hmac_hnd,
+                       rc = gnutls_hmac(signing_key->hmac_hnd,
                                         vector[i].iov_base,
                                         vector[i].iov_len);
                        if (rc < 0) {
-                               gnutls_hmac_deinit(hmac_hnd, NULL);
                                return NT_STATUS_NO_MEMORY;
                        }
                }
-               gnutls_hmac_deinit(hmac_hnd, digest);
+               gnutls_hmac_output(signing_key->hmac_hnd, digest);
                memcpy(res, digest, sizeof(res));
        }
        DEBUG(5,("signed SMB2 message\n"));
index 73621daf90e829143e0ab135f1a418bf3deb0845..7bc0a0263eb184194d1b1ea2ffbdcf28cdd1bd91 100644 (file)
@@ -35,7 +35,7 @@ int smb2_signing_key_destructor(struct smb2_signing_key *key);
 
 bool smb2_signing_key_valid(const struct smb2_signing_key *key);
 
-NTSTATUS smb2_signing_sign_pdu(DATA_BLOB signing_key,
+NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
                               enum protocol_types protocol,
                               struct iovec *vector,
                               int count);
index 7261609c9670b6cc279208631bb6a16d6b8d10a5..ebc293ea4a826dc0783f400699c1e39a027d674f 100644 (file)
@@ -3190,7 +3190,7 @@ NTSTATUS smb2cli_req_compound_submit(struct tevent_req **reqs,
                uint16_t charge;
                uint16_t credits;
                uint64_t mid;
-               const struct smb2_signing_key *signing_key = NULL;
+               struct smb2_signing_key *signing_key = NULL;
 
                if (!tevent_req_is_in_progress(reqs[i])) {
                        return NT_STATUS_INTERNAL_ERROR;
@@ -3323,7 +3323,7 @@ skip_credits:
                if (signing_key != NULL) {
                        NTSTATUS status;
 
-                       status = smb2_signing_sign_pdu(signing_key->blob,
+                       status = smb2_signing_sign_pdu(signing_key,
                                                       state->session->conn->protocol,
                                                       &iov[hdr_iov], num_iov - hdr_iov);
                        if (!NT_STATUS_IS_OK(status)) {
index 4331e672911013b45fc0db874f269529c7d083a6..563918bcd11fa34d75f064c2b5996b7da945484a 100644 (file)
@@ -1329,10 +1329,15 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request
                        return status;
                }
        } else if (req->last_key.length > 0) {
-               status = smb2_signing_sign_pdu(req->last_key,
+               struct smb2_signing_key key = {
+                       .blob = req->last_key,
+               };
+
+               status = smb2_signing_sign_pdu(&key,
                                               xconn->protocol,
                                               outhdr_v,
                                               SMBD_SMB2_NUM_IOV_PER_REQ - 1);
+               smb2_signing_key_destructor(&key);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -1508,20 +1513,21 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
        return NT_STATUS_OK;
 }
 
-static DATA_BLOB smbd_smb2_signing_key(struct smbXsrv_session *session,
-                                      struct smbXsrv_connection *xconn)
+static
+struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
+                                              struct smbXsrv_connection *xconn)
 {
        struct smbXsrv_channel_global0 *c = NULL;
        NTSTATUS status;
-       DATA_BLOB key = data_blob_null;
+       struct smb2_signing_key *key = NULL;
 
        status = smbXsrv_session_find_channel(session, xconn, &c);
        if (NT_STATUS_IS_OK(status)) {
-               key = c->signing_key->blob;
+               key = c->signing_key;
        }
 
-       if (key.length == 0) {
-               key = session->global->signing_key->blob;
+       if (!smb2_signing_key_valid(key)) {
+               key = session->global->signing_key;
        }
 
        return key;
@@ -1729,7 +1735,8 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
                }
        } else if (req->do_signing) {
                struct smbXsrv_session *x = req->session;
-               DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
+               struct smb2_signing_key *signing_key =
+                       smbd_smb2_signing_key(x, xconn);
 
                status = smb2_signing_sign_pdu(signing_key,
                                        xconn->protocol,
@@ -2444,7 +2451,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
        if (req->was_encrypted) {
                signing_required = false;
        } else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
-               DATA_BLOB signing_key = data_blob_null;
+               struct smb2_signing_key *signing_key = NULL;
 
                if (x == NULL) {
                        /*
@@ -2472,11 +2479,11 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
                 * If we have a signing key, we should
                 * sign the response
                 */
-               if (signing_key.length > 0) {
+               if (smb2_signing_key_valid(signing_key)) {
                        req->do_signing = true;
                }
 
-               status = smb2_signing_check_pdu(signing_key,
+               status = smb2_signing_check_pdu(signing_key->blob,
                                                xconn->protocol,
                                                SMBD_SMB2_IN_HDR_IOV(req),
                                                SMBD_SMB2_NUM_IOV_PER_REQ - 1);
@@ -2882,16 +2889,20 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
        {
                int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
                struct iovec *lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
+               struct smb2_signing_key key = {
+                       .blob = req->last_key,
+               };
 
                /*
                 * As we are sure the header of the last request in the
                 * compound chain will not change, we can to sign here
                 * with the last signing key we remembered.
                 */
-               status = smb2_signing_sign_pdu(req->last_key,
+               status = smb2_signing_sign_pdu(&key,
                                               xconn->protocol,
                                               lasthdr,
                                               SMBD_SMB2_NUM_IOV_PER_REQ - 1);
+               smb2_signing_key_destructor(&key);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -2921,7 +2932,8 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
 
                if (req->do_signing && firsttf->iov_len == 0) {
                        struct smbXsrv_session *x = req->session;
-                       DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
+                       struct smb2_signing_key *signing_key =
+                               smbd_smb2_signing_key(x, xconn);
 
                        /*
                         * we need to remember the signing key
@@ -2929,7 +2941,8 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
                         * we are sure that we do not change
                         * the header again.
                         */
-                       req->last_key = data_blob_dup_talloc(req, signing_key);
+                       req->last_key = data_blob_dup_talloc(req,
+                                                            signing_key->blob);
                        if (req->last_key.data == NULL) {
                                return NT_STATUS_NO_MEMORY;
                        }
@@ -2973,7 +2986,8 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
                }
        } else if (req->do_signing) {
                struct smbXsrv_session *x = req->session;
-               DATA_BLOB signing_key = smbd_smb2_signing_key(x, xconn);
+               struct smb2_signing_key *signing_key =
+                       smbd_smb2_signing_key(x, xconn);
 
                status = smb2_signing_sign_pdu(signing_key,
                                               xconn->protocol,