From 4481fea86a95df2abe558b67c31f4c86db75910a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Oct 2014 14:04:25 +0200 Subject: [PATCH] s3:smb2_sesssetup.c: For SMB >= 3.1, derive crypto keys from preauth This protects the full connection setup including a posteriori verification of the negotiate messages, by signing the final session setup response with a signing key derived from the preauth hash and the authentication session key. Pair-Programmed-With: Michael Adam Signed-off-by: Stefan Metzmacher Signed-off-by: Michael Adam --- source3/librpc/idl/smbXsrv.idl | 1 + source3/smbd/smb2_sesssetup.c | 98 +++++++++++++++++++++++++++++++++++------- source3/smbd/smbXsrv_session.c | 11 +++++ 3 files changed, 94 insertions(+), 16 deletions(-) diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index ec6d0ea3d0d..b3a24a55a1e 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -190,6 +190,7 @@ interface smbXsrv [ignore] gensec_security *gensec; [ignore] user_struct *compat; [ignore] smbXsrv_tcon_table *tcon_table; + [ignore] smbXsrv_preauth *preauth; } smbXsrv_session; typedef union { diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index c56e4803a7b..28707ffae38 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -28,6 +28,7 @@ #include "../lib/tsocket/tsocket.h" #include "../libcli/security/security.h" #include "../lib/util/tevent_ntstatus.h" +#include "lib/crypto/sha512.h" static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -184,6 +185,74 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, uint8_t session_key[16]; struct smbXsrv_session *x = session; struct smbXsrv_connection *xconn = smb2req->xconn; + struct _derivation { + DATA_BLOB label; + DATA_BLOB context; + }; + struct { + struct _derivation signing; + struct _derivation encryption; + struct _derivation decryption; + struct _derivation application; + } derivation = { }; + + if (xconn->protocol >= PROTOCOL_SMB3_10) { + struct smbXsrv_preauth *preauth; + struct _derivation *d; + DATA_BLOB p; + struct hc_sha512state sctx; + size_t i; + + preauth = talloc_move(smb2req, &session->preauth); + + samba_SHA512_Init(&sctx); + samba_SHA512_Update(&sctx, preauth->sha512_value, + sizeof(preauth->sha512_value)); + for (i = 1; i < smb2req->in.vector_count; i++) { + samba_SHA512_Update(&sctx, + smb2req->in.vector[i].iov_base, + smb2req->in.vector[i].iov_len); + } + samba_SHA512_Final(preauth->sha512_value, &sctx); + + p = data_blob_const(preauth->sha512_value, + sizeof(preauth->sha512_value)); + + d = &derivation.signing; + d->label = data_blob_string_const_null("SMBSigningKey"); + d->context = p; + + d = &derivation.decryption; + d->label = data_blob_string_const_null("SMBC2SCipherKey"); + d->context = p; + + d = &derivation.encryption; + d->label = data_blob_string_const_null("SMBS2CCipherKey"); + d->context = p; + + d = &derivation.application; + d->label = data_blob_string_const_null("SMBAppKey"); + d->context = p; + + } else if (xconn->protocol >= PROTOCOL_SMB2_24) { + struct _derivation *d; + + d = &derivation.signing; + d->label = data_blob_string_const_null("SMB2AESCMAC"); + d->context = data_blob_string_const_null("SmbSign"); + + d = &derivation.decryption; + d->label = data_blob_string_const_null("SMB2AESCCM"); + d->context = data_blob_string_const_null("ServerIn "); + + d = &derivation.encryption; + d->label = data_blob_string_const_null("SMB2AESCCM"); + d->context = data_blob_string_const_null("ServerOut"); + + d = &derivation.application; + d->label = data_blob_string_const_null("SMB2APP"); + d->context = data_blob_string_const_null("SmbRpc"); + } if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) || lp_server_signing() == SMB_SIGNING_REQUIRED) { @@ -239,18 +308,16 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, } if (xconn->protocol >= PROTOCOL_SMB2_24) { - const DATA_BLOB label = data_blob_string_const_null("SMB2AESCMAC"); - const DATA_BLOB context = data_blob_string_const_null("SmbSign"); + struct _derivation *d = &derivation.signing; smb2_key_derivation(session_key, sizeof(session_key), - label.data, label.length, - context.data, context.length, + d->label.data, d->label.length, + d->context.data, d->context.length, x->global->signing_key.data); } if (xconn->protocol >= PROTOCOL_SMB2_24) { - const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM"); - const DATA_BLOB context = data_blob_string_const_null("ServerIn "); + struct _derivation *d = &derivation.decryption; x->global->decryption_key = data_blob_talloc(x->global, session_key, @@ -261,14 +328,13 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, } smb2_key_derivation(session_key, sizeof(session_key), - label.data, label.length, - context.data, context.length, + d->label.data, d->label.length, + d->context.data, d->context.length, x->global->decryption_key.data); } if (xconn->protocol >= PROTOCOL_SMB2_24) { - const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM"); - const DATA_BLOB context = data_blob_string_const_null("ServerOut"); + struct _derivation *d = &derivation.encryption; x->global->encryption_key = data_blob_talloc(x->global, session_key, @@ -279,8 +345,8 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, } smb2_key_derivation(session_key, sizeof(session_key), - label.data, label.length, - context.data, context.length, + d->label.data, d->label.length, + d->context.data, d->context.length, x->global->encryption_key.data); generate_random_buffer((uint8_t *)&x->nonce_high, sizeof(x->nonce_high)); @@ -295,12 +361,11 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, } if (xconn->protocol >= PROTOCOL_SMB2_24) { - const DATA_BLOB label = data_blob_string_const_null("SMB2APP"); - const DATA_BLOB context = data_blob_string_const_null("SmbRpc"); + struct _derivation *d = &derivation.application; smb2_key_derivation(session_key, sizeof(session_key), - label.data, label.length, - context.data, context.length, + d->label.data, d->label.length, + d->context.data, d->context.length, x->global->application_key.data); } ZERO_STRUCT(session_key); @@ -579,6 +644,7 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq) if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { state->out_session_id = state->session->global->session_wire_id; + state->smb2req->preauth = state->session->preauth; tevent_req_nterror(req, status); return; } diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c index 07375d8125f..3201670f7a3 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -1118,6 +1118,7 @@ static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session */ preq->do_signing = false; preq->do_encryption = false; + preq->preauth = NULL; } } @@ -1167,6 +1168,15 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn, session->status = NT_STATUS_MORE_PROCESSING_REQUIRED; session->client = conn->client; + if (conn->protocol >= PROTOCOL_SMB3_10) { + session->preauth = talloc(session, struct smbXsrv_preauth); + if (session->preauth == NULL) { + TALLOC_FREE(session); + return NT_STATUS_NO_MEMORY; + } + *session->preauth = conn->smb2.preauth; + } + status = smbXsrv_session_global_allocate(table->global.db_ctx, session, &global); @@ -1420,6 +1430,7 @@ struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx, */ preq->do_signing = false; preq->do_encryption = false; + preq->preauth = NULL; if (preq->subreq != NULL) { tevent_req_cancel(preq->subreq); -- 2.11.4.GIT