From ee0ea8e3cc6f2ad059774a551456bee1189eb990 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 10 Sep 2008 20:43:37 +0200 Subject: [PATCH] make smb_signing more generic... --- source/libcli/config.mk | 2 +- source/libcli/raw/signing.h | 7 +- source/libcli/raw/smb_signing.c | 465 ++++++++++-------------- source/libcli/smb_composite/sesssetup.c | 5 +- source/smb_server/smb/negprot.c | 12 +- source/smb_server/smb/receive.c | 4 +- source/smb_server/smb/signing.c | 155 ++------ 7 files changed, 238 insertions(+), 412 deletions(-) diff --git a/source/libcli/config.mk b/source/libcli/config.mk index 262a2cfa22a6..3eb9e9aec7bd 100644 --- a/source/libcli/config.mk +++ b/source/libcli/config.mk @@ -170,7 +170,7 @@ PRIVATE_DEPENDENCIES = LIBCLI_COMPOSITE LP_RESOLVE gensec LIBCLI_RESOLVE LIBSECU #LDFLAGS = $(LIBCLI_SMB_COMPOSITE_OUTPUT) PUBLIC_DEPENDENCIES = samba-socket LIBPACKET gensec LIBCRYPTO CREDENTIALS -LIBCLI_RAW_OBJ_FILES = $(addprefix $(libclisrcdir)/raw/, rawfile.o smb_signing.o clisocket.o \ +LIBCLI_RAW_OBJ_FILES = $(addprefix $(libclisrcdir)/raw/, rawfile.o smb_signing.o clisigning.o clisocket.o \ clitransport.o clisession.o clitree.o clierror.o rawrequest.o \ rawreadwrite.o rawsearch.o rawsetfileinfo.o raweas.o rawtrans.o \ clioplock.o rawnegotiate.o rawfsinfo.o rawfileinfo.o rawnotify.o \ diff --git a/source/libcli/raw/signing.h b/source/libcli/raw/signing.h index 56e977ed7c34..fb58f371406d 100644 --- a/source/libcli/raw/signing.h +++ b/source/libcli/raw/signing.h @@ -31,13 +31,12 @@ enum smb_signing_state { SMB_SIGNING_REQUIRED, SMB_SIGNING_AUTO}; struct smb_signing_context { - enum smb_signing_engine_state signing_state; + enum smb_signing_engine_state engine_state; DATA_BLOB mac_key; uint32_t next_seq_num; - bool allow_smb_signing; + bool allow_signing; + bool require_signing; bool doing_signing; - bool mandatory_signing; - bool seen_valid; /* Have I ever seen a validly signed packet? */ }; #endif diff --git a/source/libcli/raw/smb_signing.c b/source/libcli/raw/smb_signing.c index c4bcc41b8bf4..3fe97117d5a4 100644 --- a/source/libcli/raw/smb_signing.c +++ b/source/libcli/raw/smb_signing.c @@ -1,9 +1,10 @@ /* Unix SMB/CIFS implementation. - SMB Signing Code + SMB Signing Common Code Copyright (C) Jeremy Allison 2002. Copyright (C) Andrew Bartlett 2002-2003 Copyright (C) James J Myers 2003 + Copyright (C) Stefan Metzmacher 2008 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,17 +27,47 @@ #include "lib/crypto/crypto.h" #include "param/param.h" -/*********************************************************** - SMB signing - Common code before we set a new signing implementation -************************************************************/ -bool set_smb_signing_common(struct smb_signing_context *sign_info) +void smb_signing_init_context(struct smb_signing_context *sign_ctx, + enum smb_signing_state state) +{ + sign_ctx->engine_state = SMB_SIGNING_ENGINE_OFF; + sign_ctx->mac_key = data_blob(NULL, 0); + sign_ctx->next_seq_num = 0; + sign_ctx->doing_signing = false; + + switch (state) { + case SMB_SIGNING_OFF: + sign_ctx->allow_signing = false; + sign_ctx->require_signing = false; + break; + + case SMB_SIGNING_SUPPORTED: + sign_ctx->allow_signing = true; + sign_ctx->require_signing = false; + break; + + case SMB_SIGNING_REQUIRED: + case SMB_SIGNING_AUTO: + default: + /* + * it's the callers task to map 'auto' + * if wanted, but here we choose the most secure + * option as default + */ + sign_ctx->allow_signing = true; + sign_ctx->require_signing = true; + break; + } +} + +bool smb_signing_allow_state_change(struct smb_signing_context *sign_info) { if (sign_info->doing_signing) { DEBUG(5, ("SMB Signing already in progress, so we don't start it again\n")); return false; } - if (!sign_info->allow_smb_signing) { + if (!sign_info->allow_signing) { DEBUG(5, ("SMB Signing has been locally disabled\n")); return false; } @@ -44,29 +75,74 @@ bool set_smb_signing_common(struct smb_signing_context *sign_info) return true; } -/*********************************************************** - SMB signing - Common code before we set a new signing implementation -************************************************************/ -static bool smbcli_set_smb_signing_common(struct smbcli_transport *transport) +void smb_signing_set_bsrspyl(struct smb_signing_context *sign_info) { - if (!set_smb_signing_common(&transport->negotiate.sign_info)) { - return false; + DEBUG(5,("BSRSPYL SMB signing enabled\n")); + + sign_info->engine_state = SMB_SIGNING_ENGINE_BSRSPYL; +} + +bool smb_signing_set_mac_key(TALLOC_CTX *mem_ctx, + struct smb_signing_context *sign_info, + const DATA_BLOB *user_session_key, + const DATA_BLOB *response) +{ + if (sign_info->require_signing) { + DEBUG(5, ("Mandatory SMB signing enabled!\n")); } - if (!(transport->negotiate.sec_mode & - (NEGOTIATE_SECURITY_SIGNATURES_REQUIRED|NEGOTIATE_SECURITY_SIGNATURES_ENABLED))) { - DEBUG(5, ("SMB Signing is not negotiated by the peer\n")); - return false; + DEBUG(5, ("SMB signing enabled!\n")); + + if (response && response->length) { + sign_info->mac_key = data_blob_talloc(mem_ctx, NULL, response->length + user_session_key->length); + } else { + sign_info->mac_key = data_blob_talloc(mem_ctx, NULL, user_session_key->length); } - /* These calls are INCOMPATIBLE with SMB signing */ - transport->negotiate.readbraw_supported = false; - transport->negotiate.writebraw_supported = false; + memcpy(&sign_info->mac_key.data[0], user_session_key->data, user_session_key->length); + + if (response && response->length) { + memcpy(&sign_info->mac_key.data[user_session_key->length],response->data, response->length); + } + + dump_data_pw("Started Signing with key:\n", sign_info->mac_key.data, sign_info->mac_key.length); + + sign_info->engine_state = SMB_SIGNING_ENGINE_ON; return true; } -void mark_packet_signed(struct smb_request_buffer *out) +uint32_t smb_signing_next_seq_num(struct smb_signing_context *sign_info, + bool single_increment) +{ + uint32_t seq_num; + + seq_num = sign_info->next_seq_num; + + switch (sign_info->engine_state) { + case SMB_SIGNING_ENGINE_OFF: + break; + + case SMB_SIGNING_ENGINE_BSRSPYL: + break; + + case SMB_SIGNING_ENGINE_ON: + /* + * some requests (eg. NTcancel) are one way, and the sequence number + * should be increased by 1 not 2 + */ + if (single_increment) { + sign_info->next_seq_num += 1; + } else { + sign_info->next_seq_num += 2; + } + break; + } + + return seq_num; +} + +static void mark_packet_signed(struct smb_request_buffer *out) { uint16_t flags2; flags2 = SVAL(out->hdr, HDR_FLG2); @@ -74,67 +150,83 @@ void mark_packet_signed(struct smb_request_buffer *out) SSVAL(out->hdr, HDR_FLG2, flags2); } -bool signing_good(struct smb_signing_context *sign_info, - unsigned int seq, bool good) +void smb_signing_create_signature(struct smb_signing_context *sign_info, + struct smb_request_buffer *buf, + uint32_t seq_num, + const struct smb_request_buffer *peer_buf) { - if (good) { - if (!sign_info->doing_signing) { - DEBUG(5, ("Seen valid packet, so turning signing on\n")); - sign_info->doing_signing = true; - } - if (!sign_info->seen_valid) { - DEBUG(5, ("Seen valid packet, so marking signing as 'seen valid'\n")); - sign_info->seen_valid = true; - } - } else { - if (!sign_info->seen_valid) { - /* If we have never seen a good packet, just turn it off */ - DEBUG(5, ("signing_good: signing negotiated but not required and peer\n" - "isn't sending correct signatures. Turning off.\n")); - smbcli_set_signing_off(sign_info); - return true; + const uint8_t *signature; + uint8_t calc_md5_mac[16]; + struct MD5Context md5_ctx; + +#if 0 + /* enable this when packet signing is preventing you working out why valgrind + says that data is uninitialised */ + file_save("pkt.dat", buf->buffer, buf->size); +#endif + + if (buf->size < (NBT_HDR_SIZE + HDR_SS_FIELD + 8)) { + return; + } + + switch (sign_info->engine_state) { + case SMB_SIGNING_ENGINE_OFF: + break; + + case SMB_SIGNING_ENGINE_BSRSPYL: + if (peer_buf && peer_buf->size >= (NBT_HDR_SIZE + HDR_SS_FIELD + 8)) { + /* as server we just echo the signature from the client */ + signature = buf->hdr + HDR_SS_FIELD; } else { - /* bad packet after signing started - fail and disconnect. */ - DEBUG(0, ("signing_good: BAD SIG: seq %u\n", seq)); - return false; + /* + * I wonder what BSRSPYL stands for - but this is what MS + * actually sends! + */ + signature = (const uint8_t *)"BSRSPYL "; } - } - return true; -} -void sign_outgoing_message(struct smb_request_buffer *out, DATA_BLOB *mac_key, unsigned int seq_num) -{ - uint8_t calc_md5_mac[16]; - struct MD5Context md5_ctx; + mark_packet_signed(buf); + + memcpy(buf->hdr + HDR_SS_FIELD, signature, 8); + break; - /* - * Firstly put the sequence number into the first 4 bytes. - * and zero out the next 4 bytes. - */ - SIVAL(out->hdr, HDR_SS_FIELD, seq_num); - SIVAL(out->hdr, HDR_SS_FIELD + 4, 0); - - /* mark the packet as signed - BEFORE we sign it...*/ - mark_packet_signed(out); - - /* Calculate the 16 byte MAC and place first 8 bytes into the field. */ - MD5Init(&md5_ctx); - MD5Update(&md5_ctx, mac_key->data, mac_key->length); - MD5Update(&md5_ctx, - out->buffer + NBT_HDR_SIZE, - out->size - NBT_HDR_SIZE); - MD5Final(calc_md5_mac, &md5_ctx); - - memcpy(&out->hdr[HDR_SS_FIELD], calc_md5_mac, 8); - - DEBUG(5, ("sign_outgoing_message: SENT SIG (seq: %d): sent SMB signature of\n", - seq_num)); - dump_data(5, calc_md5_mac, 8); -/* req->out.hdr[HDR_SS_FIELD+2]=0; - Uncomment this to test if the remote server actually verifies signitures...*/ + case SMB_SIGNING_ENGINE_ON: + /* + * Firstly put the sequence number into the first 4 bytes. + * and zero out the next 4 bytes. + */ + SIVAL(buf->hdr, HDR_SS_FIELD, seq_num); + SIVAL(buf->hdr, HDR_SS_FIELD + 4, 0); + + /* mark the packet as signed - BEFORE we sign it...*/ + mark_packet_signed(buf); + + /* Calculate the 16 byte MAC and place first 8 bytes into the field. */ + MD5Init(&md5_ctx); + MD5Update(&md5_ctx, sign_info->mac_key.data, sign_info->mac_key.length); + MD5Update(&md5_ctx, + buf->buffer + NBT_HDR_SIZE, + buf->size - NBT_HDR_SIZE); + MD5Final(calc_md5_mac, &md5_ctx); + + memcpy(buf->hdr + HDR_SS_FIELD, calc_md5_mac, 8); + + DEBUG(5,("smb_signing_create_signature: SENT SIG (seq: %u): sent SMB signature of\n", + seq_num)); + dump_data(5, calc_md5_mac, 8); + + /* + * Uncomment this to test if the remote server actually verifies signitures... + */ + /*req->out.hdr[HDR_SS_FIELD+2]=0;*/ + break; + } + return; } -bool check_signed_incoming_message(struct smb_request_buffer *in, DATA_BLOB *mac_key, uint_t seq_num) +static bool check_signed_incoming_message(const struct smb_request_buffer *in, + DATA_BLOB *mac_key, + uint32_t seq_num) { bool good; uint8_t calc_md5_mac[16]; @@ -204,132 +296,45 @@ bool check_signed_incoming_message(struct smb_request_buffer *in, DATA_BLOB *mac return good; } -static void smbcli_req_allocate_seq_num(struct smbcli_request *req) +static bool signing_good(struct smb_signing_context *sign_info, + unsigned int seq, bool good) { - req->seq_num = req->transport->negotiate.sign_info.next_seq_num; - - /* some requests (eg. NTcancel) are one way, and the sequence number - should be increased by 1 not 2 */ - if (req->sign_single_increment) { - req->transport->negotiate.sign_info.next_seq_num += 1; + if (good) { + if (!sign_info->doing_signing) { + DEBUG(5, ("Seen valid packet, so turning signing on\n")); + sign_info->doing_signing = true; + } } else { - req->transport->negotiate.sign_info.next_seq_num += 2; - } -} - -/*********************************************************** - SMB signing - Simple implementation - calculate a MAC to send. -************************************************************/ -void smbcli_request_calculate_sign_mac(struct smbcli_request *req) -{ - const uint8_t *signature; -#if 0 - /* enable this when packet signing is preventing you working out why valgrind - says that data is uninitialised */ - file_save("pkt.dat", req->out.buffer, req->out.size); -#endif - - switch (req->transport->negotiate.sign_info.signing_state) { - case SMB_SIGNING_ENGINE_OFF: - break; - - case SMB_SIGNING_ENGINE_BSRSPYL: - if (req->in.size >= (HDR_SS_FIELD + 8) && req->in.hdr) { - /* as server we just echo the signature from the client */ - signature = req->in.hdr + HDR_SS_FIELD; + if (!sign_info->doing_signing && !sign_info->require_signing) { + /* If we have never seen a good packet, just turn it off */ + DEBUG(5, ("signing_good: signing negotiated but not required and peer\n" + "isn't sending correct signatures. Turning off.\n")); + sign_info->engine_state = SMB_SIGNING_ENGINE_OFF; + data_blob_free(&sign_info->mac_key); + return true; } else { - /* - * I wonder what BSRSPYL stands for - but this is what MS - * actually sends! - */ - signature = (const uint8_t *)"BSRSPYL "; + /* bad packet after signing started - fail and disconnect. */ + DEBUG(0, ("signing_good: BAD SIG: seq %u\n", seq)); + return false; } - - /* mark the packet as signed - BEFORE we sign it...*/ - mark_packet_signed(&req->out); - - memcpy((req->out.hdr + HDR_SS_FIELD), signature, 8); - break; - - case SMB_SIGNING_ENGINE_ON: - - smbcli_req_allocate_seq_num(req); - sign_outgoing_message(&req->out, - &req->transport->negotiate.sign_info.mac_key, - req->seq_num); - break; } - return; -} - - -/** - SMB signing - NULL implementation - - @note Used as an initialisation only - it will not correctly - shut down a real signing mechanism -*/ -bool smbcli_set_signing_off(struct smb_signing_context *sign_info) -{ - DEBUG(5, ("Shutdown SMB signing\n")); - sign_info->doing_signing = false; - data_blob_free(&sign_info->mac_key); - sign_info->signing_state = SMB_SIGNING_ENGINE_OFF; - return true; -} - -/** - SMB signing - TEMP implementation - setup the MAC key. - -*/ -bool smbcli_temp_set_signing(struct smbcli_transport *transport) -{ - if (!smbcli_set_smb_signing_common(transport)) { - return false; - } - DEBUG(5, ("BSRSPYL SMB signing enabled\n")); - smbcli_set_signing_off(&transport->negotiate.sign_info); - - transport->negotiate.sign_info.mac_key = data_blob(NULL, 0); - transport->negotiate.sign_info.signing_state = SMB_SIGNING_ENGINE_BSRSPYL; - return true; } -/*********************************************************** - SMB signing - Simple implementation - check a MAC sent by server. -************************************************************/ -/** - * Check a packet supplied by the server. - * @return false if we had an established signing connection - * which had a back checksum, true otherwise - */ -bool smbcli_request_check_sign_mac(struct smbcli_request *req) +bool smb_signing_check_signature(struct smb_signing_context *sign_info, + const struct smb_request_buffer *buf, + uint32_t seq_num) { bool good; - if (!req->transport->negotiate.sign_info.doing_signing && - req->sign_caller_checks) { - return true; - } - - req->sign_caller_checks = false; - - switch (req->transport->negotiate.sign_info.signing_state) - { + switch (sign_info->engine_state) { case SMB_SIGNING_ENGINE_OFF: return true; - case SMB_SIGNING_ENGINE_BSRSPYL: - if (req->in.size < (HDR_SS_FIELD + 8)) { - return false; - } - good = check_signed_incoming_message(&req->in, - &req->transport->negotiate.sign_info.mac_key, - req->seq_num+1); + case SMB_SIGNING_ENGINE_BSRSPYL: + good = check_signed_incoming_message(buf, &sign_info->mac_key, seq_num); if (good) { - return signing_good(&req->transport->negotiate.sign_info, - req->seq_num+1, good); + return signing_good(sign_info, seq_num, good); } /* * It's not an error if the signature isn't valid. @@ -338,93 +343,9 @@ bool smbcli_request_check_sign_mac(struct smbcli_request *req) return true; case SMB_SIGNING_ENGINE_ON: - if (req->in.size < (HDR_SS_FIELD + 8)) { - return false; - } - - good = check_signed_incoming_message(&req->in, - &req->transport->negotiate.sign_info.mac_key, - req->seq_num+1); - - return signing_good(&req->transport->negotiate.sign_info, - req->seq_num+1, good); - } - return false; -} - - -/*********************************************************** - SMB signing - Simple implementation - setup the MAC key. -************************************************************/ -bool smbcli_simple_set_signing(TALLOC_CTX *mem_ctx, - struct smb_signing_context *sign_info, - const DATA_BLOB *user_session_key, - const DATA_BLOB *response) -{ - if (sign_info->mandatory_signing) { - DEBUG(5, ("Mandatory SMB signing enabled!\n")); - } - - DEBUG(5, ("SMB signing enabled!\n")); - - if (response && response->length) { - sign_info->mac_key = data_blob_talloc(mem_ctx, NULL, response->length + user_session_key->length); - } else { - sign_info->mac_key = data_blob_talloc(mem_ctx, NULL, user_session_key->length); - } - - memcpy(&sign_info->mac_key.data[0], user_session_key->data, user_session_key->length); - - if (response && response->length) { - memcpy(&sign_info->mac_key.data[user_session_key->length],response->data, response->length); + good = check_signed_incoming_message(buf, &sign_info->mac_key, seq_num); + return signing_good(sign_info, seq_num, good); } - dump_data_pw("Started Signing with key:\n", sign_info->mac_key.data, sign_info->mac_key.length); - - sign_info->signing_state = SMB_SIGNING_ENGINE_ON; - - return true; -} - - -/*********************************************************** - SMB signing - Simple implementation - setup the MAC key. -************************************************************/ -bool smbcli_transport_simple_set_signing(struct smbcli_transport *transport, - const DATA_BLOB user_session_key, - const DATA_BLOB response) -{ - if (!smbcli_set_smb_signing_common(transport)) { - return false; - } - - return smbcli_simple_set_signing(transport, - &transport->negotiate.sign_info, - &user_session_key, - &response); -} - - -bool smbcli_init_signing(struct smbcli_transport *transport) -{ - transport->negotiate.sign_info.next_seq_num = 0; - transport->negotiate.sign_info.mac_key = data_blob(NULL, 0); - if (!smbcli_set_signing_off(&transport->negotiate.sign_info)) { - return false; - } - - switch (transport->options.signing) { - case SMB_SIGNING_OFF: - transport->negotiate.sign_info.allow_smb_signing = false; - break; - case SMB_SIGNING_SUPPORTED: - case SMB_SIGNING_AUTO: - transport->negotiate.sign_info.allow_smb_signing = true; - break; - case SMB_SIGNING_REQUIRED: - transport->negotiate.sign_info.allow_smb_signing = true; - transport->negotiate.sign_info.mandatory_signing = true; - break; - } - return true; + return false; } diff --git a/source/libcli/smb_composite/sesssetup.c b/source/libcli/smb_composite/sesssetup.c index b918c842d5a2..4c0cbd327076 100644 --- a/source/libcli/smb_composite/sesssetup.c +++ b/source/libcli/smb_composite/sesssetup.c @@ -229,7 +229,8 @@ static void request_handler(struct smbcli_request *req) /* enforce the local signing required flag */ if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) { if (!session->transport->negotiate.sign_info.doing_signing - && session->transport->negotiate.sign_info.mandatory_signing) { + && session->transport->negotiate.sign_info.require_signing) { +/* TODO: moves this checks*/ DEBUG(0, ("SMB signing required, but server does not support it\n")); c->status = NT_STATUS_ACCESS_DENIED; } @@ -499,7 +500,7 @@ static NTSTATUS session_setup_spnego(struct composite_context *c, session_key_err = gensec_session_key(session->gensec, &session_key); if (NT_STATUS_IS_OK(session_key_err)) { smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob); - session->transport->negotiate.sign_info.next_seq_num += 2; + smb_signing_next_seq_num(&session->transport->negotiate.sign_info, false); } } diff --git a/source/smb_server/smb/negprot.c b/source/smb_server/smb/negprot.c index 00ff3862f5ed..514268eefcd4 100644 --- a/source/smb_server/smb/negprot.c +++ b/source/smb_server/smb/negprot.c @@ -76,7 +76,7 @@ static void reply_corep(struct smbsrv_request *req, uint16_t choice) req->smb_conn->negotiate.protocol = PROTOCOL_CORE; - if (req->smb_conn->signing.mandatory_signing) { + if (req->smb_conn->signing.require_signing) { smbsrv_terminate_connection(req->smb_conn, "CORE does not support SMB signing, and it is mandatory\n"); return; @@ -109,7 +109,7 @@ static void reply_coreplus(struct smbsrv_request *req, uint16_t choice) req->smb_conn->negotiate.protocol = PROTOCOL_COREPLUS; - if (req->smb_conn->signing.mandatory_signing) { + if (req->smb_conn->signing.require_signing) { smbsrv_terminate_connection(req->smb_conn, "COREPLUS does not support SMB signing, and it is mandatory\n"); return; @@ -167,7 +167,7 @@ static void reply_lanman1(struct smbsrv_request *req, uint16_t choice) } } - if (req->smb_conn->signing.mandatory_signing) { + if (req->smb_conn->signing.require_signing) { smbsrv_terminate_connection(req->smb_conn, "LANMAN1 does not support SMB signing, and it is mandatory\n"); return; @@ -217,7 +217,7 @@ static void reply_lanman2(struct smbsrv_request *req, uint16_t choice) req_push_str(req, NULL, lp_workgroup(req->smb_conn->lp_ctx), -1, STR_TERMINATE); - if (req->smb_conn->signing.mandatory_signing) { + if (req->smb_conn->signing.require_signing) { smbsrv_terminate_connection(req->smb_conn, "LANMAN2 does not support SMB signing, and it is mandatory\n"); return; @@ -313,11 +313,11 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; } - if (req->smb_conn->signing.allow_smb_signing) { + if (req->smb_conn->signing.allow_signing) { secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED; } - if (req->smb_conn->signing.mandatory_signing) { + if (req->smb_conn->signing.require_signing) { secword |= NEGOTIATE_SECURITY_SIGNATURES_REQUIRED; } diff --git a/source/smb_server/smb/receive.c b/source/smb_server/smb/receive.c index fd2810e54a38..37eb76d3ece5 100644 --- a/source/smb_server/smb/receive.c +++ b/source/smb_server/smb/receive.c @@ -533,7 +533,7 @@ static void switch_message(int type, struct smbsrv_request *req) * so just skip the reply */ if ((flags & SIGNING_NO_REPLY) && - (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) { + (req->smb_conn->signing.engine_state != SMB_SIGNING_ENGINE_OFF)) { DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n", smb_fn_name(type), nt_errstr(status))); talloc_free(req); @@ -565,7 +565,7 @@ static void switch_message(int type, struct smbsrv_request *req) * so just skip the reply */ if ((flags & SIGNING_NO_REPLY) && - (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF)) { + (req->smb_conn->signing.engine_state != SMB_SIGNING_ENGINE_OFF)) { DEBUG(1,("SKIP ERROR REPLY: %s %s because of unknown smb signing case\n", smb_fn_name(type), nt_errstr(status))); talloc_free(req); diff --git a/source/smb_server/smb/signing.c b/source/smb_server/smb/signing.c index b103bbcd6053..c0243865d497 100644 --- a/source/smb_server/smb/signing.c +++ b/source/smb_server/smb/signing.c @@ -29,37 +29,10 @@ */ void smbsrv_sign_packet(struct smbsrv_request *req) { -#if 0 - /* enable this when packet signing is preventing you working out why valgrind - says that data is uninitialised */ - file_save("pkt.dat", req->out.buffer, req->out.size); -#endif - - switch (req->smb_conn->signing.signing_state) { - case SMB_SIGNING_ENGINE_OFF: - break; - - case SMB_SIGNING_ENGINE_BSRSPYL: - /* mark the packet as signed - BEFORE we sign it...*/ - mark_packet_signed(&req->out); - - /* I wonder what BSRSPYL stands for - but this is what MS - actually sends! */ - memcpy((req->out.hdr + HDR_SS_FIELD), "BSRSPYL ", 8); - break; - - case SMB_SIGNING_ENGINE_ON: - - sign_outgoing_message(&req->out, - &req->smb_conn->signing.mac_key, - req->seq_num+1); - break; - } - return; + smb_signing_create_signature(&req->smb_conn->signing, + &req->out, req->seq_num+1, &req->in); } - - /* setup the signing key for a connection. Called after authentication succeeds in a session setup @@ -68,11 +41,11 @@ bool smbsrv_setup_signing(struct smbsrv_connection *smb_conn, DATA_BLOB *session_key, DATA_BLOB *response) { - if (!set_smb_signing_common(&smb_conn->signing)) { + if (!smb_signing_allow_state_change(&smb_conn->signing)) { return false; } - return smbcli_simple_set_signing(smb_conn, - &smb_conn->signing, session_key, response); + return smb_signing_set_mac_key(smb_conn, &smb_conn->signing, + session_key, response); } void smbsrv_signing_restart(struct smbsrv_connection *smb_conn, @@ -80,113 +53,45 @@ void smbsrv_signing_restart(struct smbsrv_connection *smb_conn, DATA_BLOB *response, bool authenticated_session) { - if (!smb_conn->signing.seen_valid) { - DEBUG(5, ("Client did not send a valid signature on " - "SPNEGO session setup - ignored, expect good next time\n")); - /* force things back on (most clients do not sign this packet)... */ - smbsrv_setup_signing(smb_conn, session_key, response); - smb_conn->signing.next_seq_num = 2; + bool ok; - /* If mandetory_signing is set, and this was an authenticated logon, then force on */ - if (smb_conn->signing.mandatory_signing && authenticated_session) { - DEBUG(5, ("Configured for mandatory signing, 'good packet seen' forced on\n")); - /* if this is mandatory, then - * pretend we have seen a - * valid packet, so we don't - * turn it off */ - smb_conn->signing.seen_valid = true; - } + if (!smb_signing_allow_state_change(&smb_conn->signing)) { + return; } -} -bool smbsrv_init_signing(struct smbsrv_connection *smb_conn) -{ - smb_conn->signing.mac_key = data_blob(NULL, 0); - if (!smbcli_set_signing_off(&smb_conn->signing)) { - return false; - } - - switch (lp_server_signing(smb_conn->lp_ctx)) { - case SMB_SIGNING_OFF: - smb_conn->signing.allow_smb_signing = false; - break; - case SMB_SIGNING_SUPPORTED: - smb_conn->signing.allow_smb_signing = true; - break; - case SMB_SIGNING_REQUIRED: - smb_conn->signing.allow_smb_signing = true; - smb_conn->signing.mandatory_signing = true; - break; - case SMB_SIGNING_AUTO: - if (lp_server_role(smb_conn->lp_ctx) == ROLE_DOMAIN_CONTROLLER) { - smb_conn->signing.allow_smb_signing = true; - smb_conn->signing.mandatory_signing = true; - } else { - smb_conn->signing.allow_smb_signing = true; - } - break; - } - return true; -} +/* TODO: handle anon...*/ -/* - allocate a sequence number to a request -*/ -static void req_signing_alloc_seq_num(struct smbsrv_request *req) -{ - req->seq_num = req->smb_conn->signing.next_seq_num; + DEBUG(5, ("Client did not send a valid signature on " + "SPNEGO session setup - ignored, expect good next time\n")); - if (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF) { - req->smb_conn->signing.next_seq_num += 2; + ok = smb_signing_set_mac_key(smb_conn, &smb_conn->signing, + session_key, response); + if (ok) { + smb_signing_next_seq_num(&smb_conn->signing, false); } } -/* - called for requests that do not produce a reply of their own -*/ -void smbsrv_signing_no_reply(struct smbsrv_request *req) +void smbsrv_init_signing(struct smbsrv_connection *smb_conn) { - if (req->smb_conn->signing.signing_state != SMB_SIGNING_ENGINE_OFF) { - req->smb_conn->signing.next_seq_num--; + enum smb_signing_state signing = lp_server_signing(smb_conn->lp_ctx); + + if (signing == SMB_SIGNING_AUTO) { + if (lp_server_role(smb_conn->lp_ctx) == ROLE_DOMAIN_CONTROLLER) { + signing = SMB_SIGNING_REQUIRED; + } else { + signing = SMB_SIGNING_SUPPORTED; + } } + + smb_signing_init_context(&smb_conn->signing, signing); } -/*********************************************************** - SMB signing - Simple implementation - check a MAC sent by client -************************************************************/ -/** - * Check a packet supplied by the server. - * @return false if we had an established signing connection - * which had a back checksum, true otherwise - */ bool smbsrv_signing_check_incoming(struct smbsrv_request *req, bool single_increment) { - bool good; - - req_signing_alloc_seq_num(req); - if (single_increment) { - smbsrv_signing_no_reply(req); - } + req->seq_num = smb_signing_next_seq_num(&req->smb_conn->signing, + single_increment); - switch (req->smb_conn->signing.signing_state) - { - case SMB_SIGNING_ENGINE_OFF: - return true; - case SMB_SIGNING_ENGINE_BSRSPYL: - case SMB_SIGNING_ENGINE_ON: - { - if (req->in.size < (HDR_SS_FIELD + 8)) { - return false; - } else { - good = check_signed_incoming_message(&req->in, - &req->smb_conn->signing.mac_key, - req->seq_num); - - return signing_good(&req->smb_conn->signing, - req->seq_num+1, good); - } - } - } - return false; + return smb_signing_check_signature(&req->smb_conn->signing, + &req->in, req->seq_num); } -- 2.34.1