From: Andreas Schneider Date: Wed, 13 Mar 2019 18:34:23 +0000 (+0100) Subject: libcli:smb: Use smb2_signing_key for smb2_signing_sign_pdu() X-Git-Tag: tdb-1.4.1~251 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dcf37228e1d920f753d4cf72204ce7ca6b1fa6e1;p=thirdparty%2Fsamba.git libcli:smb: Use smb2_signing_key for smb2_signing_sign_pdu() This caches the gnutls hmac handle in the struct so we only allocate it once. Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett --- diff --git a/libcli/smb/smb2_signing.c b/libcli/smb/smb2_signing.c index 72c98d6a610..38169b50f62 100644 --- a/libcli/smb/smb2_signing.c +++ b/libcli/smb/smb2_signing.c @@ -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")); diff --git a/libcli/smb/smb2_signing.h b/libcli/smb/smb2_signing.h index 73621daf90e..7bc0a0263eb 100644 --- a/libcli/smb/smb2_signing.h +++ b/libcli/smb/smb2_signing.h @@ -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); diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index 7261609c967..ebc293ea4a8 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -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)) { diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 4331e672911..563918bcd11 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -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,