From da7dcc443f45d07d9963df9daae458fbdd991a47 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 5 Mar 2021 22:40:43 +0100 Subject: [PATCH] smbd: make use of smb2_signing_key_{copy,sign_create,cipher_create}() helpers BUG: https://bugzilla.samba.org/show_bug.cgi?id=14512 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison --- source3/librpc/idl/smbXsrv.idl | 6 +- source3/smbd/reply.c | 20 +-- source3/smbd/sesssetup.c | 84 ++++++------ source3/smbd/smb2_sesssetup.c | 240 ++++++++++----------------------- source3/smbd/smbXsrv_session.c | 2 +- 5 files changed, 124 insertions(+), 228 deletions(-) diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index 09e3ca351f3..89df7935c35 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -220,6 +220,7 @@ interface smbXsrv [ignore] smb2_signing_key *signing_key; uint32 auth_session_info_seqnum; [ignore] smbXsrv_connection *connection; + uint16 signing_algo; uint16 encryption_cipher; } smbXsrv_channel_global0; @@ -238,14 +239,17 @@ interface smbXsrv auth_session_info *auth_session_info; uint16 connection_dialect; smbXsrv_signing_flags signing_flags; + uint16 signing_algo; smbXsrv_encrpytion_flags encryption_flags; + uint16 encryption_cipher; [noprint] DATA_BLOB signing_key_blob; [ignore] smb2_signing_key *signing_key; [noprint] DATA_BLOB encryption_key_blob; [ignore] smb2_signing_key *encryption_key; [noprint] DATA_BLOB decryption_key_blob; [ignore] smb2_signing_key *decryption_key; - [noprint] DATA_BLOB application_key; + [noprint] DATA_BLOB application_key_blob; + [ignore] smb2_signing_key *application_key; [range(1, 1024)] uint32 num_channels; smbXsrv_channel_global0 channels[num_channels]; } smbXsrv_session_global0; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 187b44cbef7..dcda32e8cc1 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -966,7 +966,7 @@ void reply_tcon_and_X(struct smb_request *req) * Once the application key is defined, it does not * change any more. */ - if (session->global->application_key.length == 0 && + if (session->global->application_key_blob.length == 0 && smb2_signing_key_valid(session->global->signing_key)) { struct smbXsrv_session *x = session; @@ -981,22 +981,23 @@ void reply_tcon_and_X(struct smb_request *req) /* * The application key is truncated/padded to 16 bytes */ - x->global->application_key = data_blob_talloc(x->global, + x->global->application_key_blob = data_blob_talloc(x->global, session_key, sizeof(session_key)); ZERO_STRUCT(session_key); - if (x->global->application_key.data == NULL) { + if (x->global->application_key_blob.data == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtconX); return; } + talloc_keep_secret(x->global->application_key_blob.data); if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) { NTSTATUS status; - status = smb_key_derivation(x->global->application_key.data, - x->global->application_key.length, - x->global->application_key.data); + status = smb_key_derivation(x->global->application_key_blob.data, + x->global->application_key_blob.length, + x->global->application_key_blob.data); if (!NT_STATUS_IS_OK(status)) { DBG_ERR("smb_key_derivation failed: %s\n", nt_errstr(status)); @@ -1011,13 +1012,14 @@ void reply_tcon_and_X(struct smb_request *req) */ data_blob_clear_free(&session_info->session_key); session_info->session_key = data_blob_dup_talloc(session_info, - x->global->application_key); + x->global->application_key_blob); if (session_info->session_key.data == NULL) { - data_blob_clear_free(&x->global->application_key); + data_blob_clear_free(&x->global->application_key_blob); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBtconX); return; } + talloc_keep_secret(session_info->session_key.data); session_key_updated = true; } @@ -1030,7 +1032,7 @@ void reply_tcon_and_X(struct smb_request *req) struct smbXsrv_session *x = session; struct auth_session_info *session_info = session->global->auth_session_info; - data_blob_clear_free(&x->global->application_key); + data_blob_clear_free(&x->global->application_key_blob); data_blob_clear_free(&session_info->session_key); } reply_nterror(req, nt_status); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 89bec95c6cb..b859762e738 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -268,33 +268,28 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) action |= SMB_SETUP_GUEST; } + session->global->signing_algo = SMB2_SIGNING_MD5_SMB1; + session->global->encryption_cipher = 0; + session->global->channels[0].signing_algo = + session->global->signing_algo; + session->global->channels[0].encryption_cipher = + session->global->encryption_cipher; + if (session_info->session_key.length > 0) { struct smbXsrv_session *x = session; - /* - * Note: the SMB1 signing key is not truncated to 16 byte! - */ - x->global->signing_key = - talloc_zero(x->global, struct smb2_signing_key); - if (x->global->signing_key == NULL) { - data_blob_free(&out_blob); - TALLOC_FREE(session); - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - /* TODO: setup destructor once we cache the hmac handle */ - - x->global->signing_key->blob = - x->global->signing_key_blob = - data_blob_dup_talloc(x->global->signing_key, - session_info->session_key); - if (!smb2_signing_key_valid(x->global->signing_key)) { + status = smb2_signing_key_sign_create(x->global, + x->global->signing_algo, + &session_info->session_key, + NULL, /* no derivation */ + &x->global->signing_key); + if (!NT_STATUS_IS_OK(status)) { data_blob_free(&out_blob); TALLOC_FREE(session); - reply_nterror(req, NT_STATUS_NO_MEMORY); + reply_nterror(req, status); return; } - talloc_keep_secret(x->global->signing_key->blob.data); + x->global->signing_key_blob = x->global->signing_key->blob; /* * clear the session key @@ -983,65 +978,64 @@ void reply_sesssetup_and_X(struct smb_request *req) return; } + session->global->signing_algo = SMB2_SIGNING_MD5_SMB1; + session->global->encryption_cipher = 0; + session->global->channels[0].signing_algo = + session->global->signing_algo; + session->global->channels[0].encryption_cipher = + session->global->encryption_cipher; + if (session_info->session_key.length > 0) { + struct smbXsrv_session *x = session; uint8_t session_key[16]; + NTSTATUS status; - /* - * Note: the SMB1 signing key is not truncated to 16 byte! - */ - session->global->signing_key = - talloc_zero(session->global, struct smb2_signing_key); - if (session->global->signing_key == NULL) { - TALLOC_FREE(session); - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBsesssetupX); - return; - } - /* TODO: setup destructor once we cache the hmac handle */ - - session->global->signing_key->blob = - session->global->signing_key_blob = - data_blob_dup_talloc(session->global->signing_key, - session_info->session_key); - if (!smb2_signing_key_valid(session->global->signing_key)) { + status = smb2_signing_key_sign_create(x->global, + x->global->signing_algo, + &session_info->session_key, + NULL, /* no derivation */ + &x->global->signing_key); + if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(session); - reply_nterror(req, NT_STATUS_NO_MEMORY); + reply_nterror(req, status); END_PROFILE(SMBsesssetupX); return; } - talloc_keep_secret(session->global->signing_key->blob.data); + x->global->signing_key_blob = x->global->signing_key->blob; /* * The application key is truncated/padded to 16 bytes */ ZERO_STRUCT(session_key); - memcpy(session_key, session->global->signing_key->blob.data, - MIN(session->global->signing_key->blob.length, + memcpy(session_key, session->global->signing_key_blob.data, + MIN(session->global->signing_key_blob.length, sizeof(session_key))); - session->global->application_key = + session->global->application_key_blob = data_blob_talloc(session->global, session_key, sizeof(session_key)); ZERO_STRUCT(session_key); - if (session->global->application_key.data == NULL) { + if (session->global->application_key_blob.data == NULL) { TALLOC_FREE(session); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBsesssetupX); return; } + talloc_keep_secret(session->global->application_key_blob.data); /* * Place the application key into the session_info */ data_blob_clear_free(&session_info->session_key); session_info->session_key = data_blob_dup_talloc(session_info, - session->global->application_key); + session->global->application_key_blob); if (session_info->session_key.data == NULL) { TALLOC_FREE(session); reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBsesssetupX); return; } + talloc_keep_secret(session_info->session_key.data); } sconn->num_users++; diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index 0fa9cc3270b..3b988252931 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -198,7 +198,6 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, { NTSTATUS status; bool guest = false; - uint8_t session_key[16]; struct smbXsrv_session *x = session; struct smbXsrv_session_auth0 *auth = *_auth; struct smbXsrv_connection *xconn = smb2req->xconn; @@ -285,111 +284,49 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, xconn->smb2.server.dialect)); return NT_STATUS_ACCESS_DENIED; } - } else { - x->global->channels[0].encryption_cipher = xconn->smb2.server.cipher; + } + x->global->signing_algo = xconn->smb2.server.sign_algo; + x->global->encryption_cipher = xconn->smb2.server.cipher; + if (guest) { + x->global->encryption_cipher = SMB2_ENCRYPTION_NONE; } if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) { *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA; } - ZERO_STRUCT(session_key); - memcpy(session_key, session_info->session_key.data, - MIN(session_info->session_key.length, sizeof(session_key))); - - x->global->signing_key = talloc_zero(x->global, - struct smb2_signing_key); - if (x->global->signing_key == NULL) { - ZERO_STRUCT(session_key); - return NT_STATUS_NO_MEMORY; - } - talloc_set_destructor(x->global->signing_key, - smb2_signing_key_destructor); - - x->global->signing_key->blob = - x->global->signing_key_blob = - data_blob_talloc(x->global, - session_key, - sizeof(session_key)); - if (!smb2_signing_key_valid(x->global->signing_key)) { - ZERO_STRUCT(session_key); - return NT_STATUS_NO_MEMORY; - } - - if (xconn->protocol >= PROTOCOL_SMB2_24) { - const struct smb2_signing_derivation *d = derivations.signing; - - status = smb2_key_derivation(session_key, sizeof(session_key), - d->label.data, d->label.length, - d->context.data, d->context.length, - x->global->signing_key->blob.data, - x->global->signing_key->blob.length); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + status = smb2_signing_key_sign_create(x->global, + x->global->signing_algo, + &session_info->session_key, + derivations.signing, + &x->global->signing_key); + if (!NT_STATUS_IS_OK(status)) { + return status; } + x->global->signing_key_blob = x->global->signing_key->blob; - if (xconn->protocol >= PROTOCOL_SMB2_24) { - const struct smb2_signing_derivation *d = derivations.cipher_c2s; - - x->global->decryption_key = - talloc_zero(x->global, struct smb2_signing_key); - if (x->global->decryption_key == NULL) { - ZERO_STRUCT(session_key); - return NT_STATUS_NO_MEMORY; - } - - x->global->decryption_key->blob = - x->global->decryption_key_blob = - data_blob_talloc(x->global->decryption_key, - session_key, - sizeof(session_key)); - if (!smb2_signing_key_valid(x->global->decryption_key)) { - ZERO_STRUCT(session_key); - return NT_STATUS_NO_MEMORY; - } - talloc_keep_secret(x->global->decryption_key->blob.data); + if (x->global->encryption_cipher != SMB2_ENCRYPTION_NONE) { + size_t nonce_size; - status = smb2_key_derivation(session_key, sizeof(session_key), - d->label.data, d->label.length, - d->context.data, d->context.length, - x->global->decryption_key->blob.data, - x->global->decryption_key->blob.length); + status = smb2_signing_key_cipher_create(x->global, + x->global->encryption_cipher, + &session_info->session_key, + derivations.cipher_s2c, + &x->global->encryption_key); if (!NT_STATUS_IS_OK(status)) { return status; } - } - - if (xconn->protocol >= PROTOCOL_SMB2_24) { - const struct smb2_signing_derivation *d = derivations.cipher_s2c; - size_t nonce_size; - - x->global->encryption_key = - talloc_zero(x->global, struct smb2_signing_key); - if (x->global->encryption_key == NULL) { - ZERO_STRUCT(session_key); - return NT_STATUS_NO_MEMORY; - } + x->global->encryption_key_blob = x->global->encryption_key->blob; - x->global->encryption_key->blob = - x->global->encryption_key_blob = - data_blob_talloc(x->global->encryption_key, - session_key, - sizeof(session_key)); - if (!smb2_signing_key_valid(x->global->encryption_key)) { - ZERO_STRUCT(session_key); - return NT_STATUS_NO_MEMORY; - } - talloc_keep_secret(x->global->encryption_key->blob.data); - - status = smb2_key_derivation(session_key, sizeof(session_key), - d->label.data, d->label.length, - d->context.data, d->context.length, - x->global->encryption_key->blob.data, - x->global->encryption_key->blob.length); + status = smb2_signing_key_cipher_create(x->global, + x->global->encryption_cipher, + &session_info->session_key, + derivations.cipher_c2s, + &x->global->decryption_key); if (!NT_STATUS_IS_OK(status)) { return status; } + x->global->decryption_key_blob = x->global->decryption_key->blob; /* * CCM and GCM algorithms must never have their @@ -418,26 +355,15 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, x->nonce_low = 0; } - x->global->application_key = - data_blob_dup_talloc(x->global, x->global->signing_key->blob); - if (x->global->application_key.data == NULL) { - ZERO_STRUCT(session_key); - return NT_STATUS_NO_MEMORY; - } - talloc_keep_secret(x->global->application_key.data); - - if (xconn->protocol >= PROTOCOL_SMB2_24) { - const struct smb2_signing_derivation *d = derivations.application; - - status = smb2_key_derivation(session_key, sizeof(session_key), - d->label.data, d->label.length, - d->context.data, d->context.length, - x->global->application_key.data, - x->global->application_key.length); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + status = smb2_signing_key_sign_create(x->global, + x->global->signing_algo, + &session_info->session_key, + derivations.application, + &x->global->application_key); + if (!NT_STATUS_IS_OK(status)) { + return status; } + x->global->application_key_blob = x->global->application_key->blob; if (xconn->protocol >= PROTOCOL_SMB3_00 && lp_debug_encryption()) { DEBUG(0, ("debug encryption: dumping generated session keys\n")); @@ -445,46 +371,41 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, dump_data(0, (uint8_t*)&session->global->session_wire_id, sizeof(session->global->session_wire_id)); DEBUGADD(0, ("Session Key ")); - dump_data(0, session_key, sizeof(session_key)); + dump_data(0, session_info->session_key.data, + session_info->session_key.length); + DEBUGADD(0, ("Signing Algo: %u\n", x->global->signing_algo)); DEBUGADD(0, ("Signing Key ")); - dump_data(0, x->global->signing_key->blob.data, - x->global->signing_key->blob.length); + dump_data(0, x->global->signing_key_blob.data, + x->global->signing_key_blob.length); DEBUGADD(0, ("App Key ")); - dump_data(0, x->global->application_key.data, - x->global->application_key.length); + dump_data(0, x->global->application_key_blob.data, + x->global->application_key_blob.length); /* In server code, ServerIn is the decryption key */ + DEBUGADD(0, ("Cipher Algo: %u\n", x->global->encryption_cipher)); DEBUGADD(0, ("ServerIn Key ")); - dump_data(0, x->global->decryption_key->blob.data, - x->global->decryption_key->blob.length); + dump_data(0, x->global->decryption_key_blob.data, + x->global->decryption_key_blob.length); DEBUGADD(0, ("ServerOut Key ")); - dump_data(0, x->global->encryption_key->blob.data, - x->global->encryption_key->blob.length); + dump_data(0, x->global->encryption_key_blob.data, + x->global->encryption_key_blob.length); } - ZERO_STRUCT(session_key); - - x->global->channels[0].signing_key = - talloc_zero(x->global->channels, struct smb2_signing_key); - if (x->global->channels[0].signing_key == NULL) { - return NT_STATUS_NO_MEMORY; - } - talloc_set_destructor(x->global->channels[0].signing_key, - smb2_signing_key_destructor); - - x->global->channels[0].signing_key->blob = - x->global->channels[0].signing_key_blob = - data_blob_dup_talloc(x->global->channels[0].signing_key, - x->global->signing_key->blob); - if (!smb2_signing_key_valid(x->global->channels[0].signing_key)) { - return NT_STATUS_NO_MEMORY; + status = smb2_signing_key_copy(x->global->channels, + x->global->signing_key, + &x->global->channels[0].signing_key); + if (!NT_STATUS_IS_OK(status)) { + return status; } - talloc_keep_secret(x->global->channels[0].signing_key->blob.data); + x->global->channels[0].signing_key_blob = + x->global->channels[0].signing_key->blob; + x->global->channels[0].signing_algo = x->global->signing_algo; + x->global->channels[0].encryption_cipher = x->global->encryption_cipher; data_blob_clear_free(&session_info->session_key); session_info->session_key = data_blob_dup_talloc(session_info, - x->global->application_key); + x->global->application_key_blob); if (session_info->session_key.data == NULL) { return NT_STATUS_NO_MEMORY; } @@ -566,7 +487,7 @@ static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session, data_blob_clear_free(&session_info->session_key); session_info->session_key = data_blob_dup_talloc(session_info, - x->global->application_key); + x->global->application_key_blob); if (session_info->session_key.data == NULL) { return NT_STATUS_NO_MEMORY; } @@ -629,7 +550,6 @@ static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session, struct smbXsrv_session_auth0 *auth = *_auth; struct smbXsrv_connection *xconn = smb2req->xconn; struct smbXsrv_channel_global0 *c = NULL; - uint8_t session_key[16]; size_t i; struct smb2_signing_derivations derivations = { .signing = NULL, @@ -693,42 +613,18 @@ static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session, return NT_STATUS_NOT_SUPPORTED; } - ZERO_STRUCT(session_key); - memcpy(session_key, session_info->session_key.data, - MIN(session_info->session_key.length, sizeof(session_key))); - - c->signing_key = talloc_zero(x->global, struct smb2_signing_key); - if (c->signing_key == NULL) { - ZERO_STRUCT(session_key); - return NT_STATUS_NO_MEMORY; - } - talloc_set_destructor(c->signing_key, - smb2_signing_key_destructor); - - c->signing_key->blob = - c->signing_key_blob = - data_blob_talloc(c->signing_key, - session_key, - sizeof(session_key)); - if (!smb2_signing_key_valid(c->signing_key)) { - ZERO_STRUCT(session_key); - return NT_STATUS_NO_MEMORY; - } - talloc_keep_secret(c->signing_key->blob.data); + c->signing_algo = xconn->smb2.server.sign_algo; + c->encryption_cipher = xconn->smb2.server.cipher; - if (xconn->protocol >= PROTOCOL_SMB2_24) { - const struct smb2_signing_derivation *d = derivations.signing; - - status = smb2_key_derivation(session_key, sizeof(session_key), - d->label.data, d->label.length, - d->context.data, d->context.length, - c->signing_key->blob.data, - c->signing_key->blob.length); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + status = smb2_signing_key_sign_create(x->global->channels, + c->signing_algo, + &session_info->session_key, + derivations.signing, + &c->signing_key); + if (!NT_STATUS_IS_OK(status)) { + return status; } - ZERO_STRUCT(session_key); + c->signing_key_blob = c->signing_key->blob; TALLOC_FREE(auth); status = smbXsrv_session_update(session); diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c index c3aa0ee26cb..1d7ebf9aff6 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -879,7 +879,7 @@ static void smbXsrv_session_global_verify_record(struct db_record *db_rec, } while(0) { uint32_t i; - __BLOB_KEEP_SECRET(global->application_key); + __BLOB_KEEP_SECRET(global->application_key_blob); __BLOB_KEEP_SECRET(global->signing_key_blob); __BLOB_KEEP_SECRET(global->encryption_key_blob); __BLOB_KEEP_SECRET(global->decryption_key_blob); -- 2.47.3