From 1fa7300037447c6e01438509343afd2e186f066c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 Oct 2011 16:50:19 +0200 Subject: libcli/smb: move smb_signing.[ch] to the toplevel metze --- libcli/smb/smb_signing.c | 454 ++++++++++++++++++++++++++++++++++++++++++ libcli/smb/smb_signing.h | 54 +++++ libcli/smb/wscript_build | 16 +- source3/Makefile.in | 2 +- source3/include/smb_signing.h | 54 ----- source3/libsmb/clientgen.c | 2 +- source3/libsmb/clisigning.c | 2 +- source3/libsmb/smb_signing.c | 453 ----------------------------------------- source3/param/loadparm.c | 2 +- source3/smbd/signing.c | 2 +- source3/wscript_build | 1 - 11 files changed, 524 insertions(+), 518 deletions(-) create mode 100644 libcli/smb/smb_signing.c create mode 100644 libcli/smb/smb_signing.h delete mode 100644 source3/include/smb_signing.h delete mode 100644 source3/libsmb/smb_signing.c diff --git a/libcli/smb/smb_signing.c b/libcli/smb/smb_signing.c new file mode 100644 index 0000000000..a72760b1c3 --- /dev/null +++ b/libcli/smb/smb_signing.c @@ -0,0 +1,454 @@ +/* + Unix SMB/CIFS implementation. + SMB Signing Code + Copyright (C) Jeremy Allison 2003. + Copyright (C) Andrew Bartlett 2002-2003 + Copyright (C) Stefan Metzmacher 2009 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "../lib/crypto/md5.h" +#include "smb_common.h" +#include "smb_signing.h" + +/* Used by the SMB signing functions. */ + +struct smb_signing_state { + /* is signing localy allowed */ + bool allowed; + + /* is signing localy desired */ + bool desired; + + /* is signing localy mandatory */ + bool mandatory; + + /* is signing negotiated by the peer */ + bool negotiated; + + bool active; /* Have I ever seen a validly signed packet? */ + + /* mac_key.length > 0 means signing is started */ + DATA_BLOB mac_key; + + /* the next expected seqnum */ + uint32_t seqnum; + + TALLOC_CTX *mem_ctx; + void *(*alloc_fn)(TALLOC_CTX *mem_ctx, size_t len); + void (*free_fn)(TALLOC_CTX *mem_ctx, void *ptr); +}; + +static void smb_signing_reset_info(struct smb_signing_state *si) +{ + si->active = false; + si->seqnum = 0; + + if (si->free_fn) { + si->free_fn(si->mem_ctx, si->mac_key.data); + } else { + talloc_free(si->mac_key.data); + } + si->mac_key.data = NULL; + si->mac_key.length = 0; +} + +struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx, + bool allowed, + bool desired, + bool mandatory, + void *(*alloc_fn)(TALLOC_CTX *, size_t), + void (*free_fn)(TALLOC_CTX *, void *)) +{ + struct smb_signing_state *si; + + if (alloc_fn) { + void *p = alloc_fn(mem_ctx, sizeof(struct smb_signing_state)); + if (p == NULL) { + return NULL; + } + memset(p, 0, sizeof(struct smb_signing_state)); + si = (struct smb_signing_state *)p; + si->mem_ctx = mem_ctx; + si->alloc_fn = alloc_fn; + si->free_fn = free_fn; + } else { + si = talloc_zero(mem_ctx, struct smb_signing_state); + if (si == NULL) { + return NULL; + } + } + + if (mandatory) { + desired = true; + } + + if (desired) { + allowed = true; + } + + si->allowed = allowed; + si->desired = desired; + si->mandatory = mandatory; + + return si; +} + +struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx, + bool allowed, + bool desired, + bool mandatory) +{ + return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory, + NULL, NULL); +} + +static bool smb_signing_good(struct smb_signing_state *si, + bool good, uint32_t seq) +{ + if (good) { + if (!si->active) { + si->active = true; + } + return true; + } + + if (!si->mandatory && !si->active) { + /* Non-mandatory signing - just turn off if this is the first bad packet.. */ + DEBUG(5, ("smb_signing_good: signing negotiated but not required and peer\n" + "isn't sending correct signatures. Turning off.\n")); + smb_signing_reset_info(si); + return true; + } + + /* Mandatory signing or bad packet after signing started - fail and disconnect. */ + DEBUG(0, ("smb_signing_good: BAD SIG: seq %u\n", (unsigned int)seq)); + return false; +} + +static void smb_signing_md5(const DATA_BLOB *mac_key, + const uint8_t *buf, uint32_t seq_number, + uint8_t calc_md5_mac[16]) +{ + const size_t offset_end_of_sig = (NBT_HDR_SIZE + HDR_SS_FIELD + 8); + uint8_t sequence_buf[8]; + struct MD5Context md5_ctx; + + /* + * Firstly put the sequence number into the first 4 bytes. + * and zero out the next 4 bytes. + * + * We do this here, to avoid modifying the packet. + */ + + DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number )); + + SIVAL(sequence_buf, 0, seq_number); + SIVAL(sequence_buf, 4, 0); + + /* Calculate the 16 byte MAC - but don't alter the data in the + incoming packet. + + This makes for a bit of fussing about, but it's not too bad. + */ + MD5Init(&md5_ctx); + + /* intialise with the key */ + MD5Update(&md5_ctx, mac_key->data, mac_key->length); + + /* copy in the first bit of the SMB header */ + MD5Update(&md5_ctx, buf + NBT_HDR_SIZE, HDR_SS_FIELD); + + /* copy in the sequence number, instead of the signature */ + MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf)); + + /* copy in the rest of the packet in, skipping the signature */ + MD5Update(&md5_ctx, buf + offset_end_of_sig, + smb_len_nbt(buf) - (offset_end_of_sig - 4)); + + /* calculate the MD5 sig */ + MD5Final(calc_md5_mac, &md5_ctx); +} + +uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway) +{ + uint32_t seqnum; + + if (si->mac_key.length == 0) { + return 0; + } + + seqnum = si->seqnum; + if (oneway) { + si->seqnum += 1; + } else { + si->seqnum += 2; + } + + return seqnum; +} + +void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway) +{ + if (si->mac_key.length == 0) { + return; + } + + if (oneway) { + si->seqnum -= 1; + } else { + si->seqnum -= 2; + } +} + +void smb_signing_sign_pdu(struct smb_signing_state *si, + uint8_t *outbuf, uint32_t seqnum) +{ + uint8_t calc_md5_mac[16]; + uint8_t com; + uint8_t flags; + + if (si->mac_key.length == 0) { + if (!si->negotiated) { + return; + } + } + + /* JRA Paranioa test - we should be able to get rid of this... */ + if (smb_len_nbt(outbuf) < (HDR_SS_FIELD + 8)) { + DEBUG(1,("smb_signing_sign_pdu: Logic error. " + "Can't check signature on short packet! smb_len = %u\n", + smb_len_nbt(outbuf))); + abort(); + } + + com = SVAL(outbuf,NBT_HDR_SIZE+HDR_COM); + flags = SVAL(outbuf,NBT_HDR_SIZE+HDR_FLG); + + if (!(flags & FLAG_REPLY)) { + uint16_t flags2 = SVAL(outbuf,NBT_HDR_SIZE+HDR_FLG2); + /* + * If this is a request, specify what is + * supported or required by the client + */ + if (si->negotiated && si->desired) { + flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES; + } + if (si->negotiated && si->mandatory) { + flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED; + } + SSVAL(outbuf, NBT_HDR_SIZE+HDR_FLG2, flags2); + } + + if (si->mac_key.length == 0) { + /* I wonder what BSRSPYL stands for - but this is what MS + actually sends! */ + if (com == SMBsesssetupX) { + memcpy(calc_md5_mac, "BSRSPYL ", 8); + } else { + memset(calc_md5_mac, 0, 8); + } + } else { + smb_signing_md5(&si->mac_key, outbuf, + seqnum, calc_md5_mac); + } + + DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n")); + dump_data(10, calc_md5_mac, 8); + + memcpy(&outbuf[NBT_HDR_SIZE+HDR_SS_FIELD], calc_md5_mac, 8); + +/* outbuf[NBT_HDR_SIZE+HDR_SS_FIELD+2]=0; + Uncomment this to test if the remote server actually verifies signatures...*/ +} + +bool smb_signing_check_pdu(struct smb_signing_state *si, + const uint8_t *inbuf, uint32_t seqnum) +{ + bool good; + uint8_t calc_md5_mac[16]; + const uint8_t *reply_sent_mac; + + if (si->mac_key.length == 0) { + return true; + } + + if (smb_len_nbt(inbuf) < (HDR_SS_FIELD + 8)) { + DEBUG(1,("smb_signing_check_pdu: Can't check signature " + "on short packet! smb_len = %u\n", + smb_len_nbt(inbuf))); + return false; + } + + smb_signing_md5(&si->mac_key, inbuf, + seqnum, calc_md5_mac); + + reply_sent_mac = &inbuf[NBT_HDR_SIZE+HDR_SS_FIELD]; + good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0); + + if (!good) { + int i; + const int sign_range = 5; + + DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n")); + dump_data(5, calc_md5_mac, 8); + + DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n")); + dump_data(5, reply_sent_mac, 8); + + for (i = -sign_range; i < sign_range; i++) { + smb_signing_md5(&si->mac_key, inbuf, + seqnum+i, calc_md5_mac); + if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) { + DEBUG(0,("smb_signing_check_pdu: " + "out of seq. seq num %u matches. " + "We were expecting seq %u\n", + (unsigned int)seqnum+i, + (unsigned int)seqnum)); + break; + } + } + } else { + DEBUG(10, ("smb_signing_check_pdu: seq %u: " + "got good SMB signature of\n", + (unsigned int)seqnum)); + dump_data(10, reply_sent_mac, 8); + } + + return smb_signing_good(si, good, seqnum); +} + +bool smb_signing_activate(struct smb_signing_state *si, + const DATA_BLOB user_session_key, + const DATA_BLOB response) +{ + size_t len; + off_t ofs; + + if (!user_session_key.length) { + return false; + } + + if (!si->negotiated) { + return false; + } + + if (si->active) { + return false; + } + + if (si->mac_key.length > 0) { + return false; + } + + smb_signing_reset_info(si); + + len = response.length + user_session_key.length; + if (si->alloc_fn) { + si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len); + if (si->mac_key.data == NULL) { + return false; + } + } else { + si->mac_key.data = (uint8_t *)talloc_size(si, len); + if (si->mac_key.data == NULL) { + return false; + } + } + si->mac_key.length = len; + + ofs = 0; + memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length); + + DEBUG(10, ("smb_signing_activate: user_session_key\n")); + dump_data(10, user_session_key.data, user_session_key.length); + + if (response.length) { + ofs = user_session_key.length; + memcpy(&si->mac_key.data[ofs], response.data, response.length); + DEBUG(10, ("smb_signing_activate: response_data\n")); + dump_data(10, response.data, response.length); + } else { + DEBUG(10, ("smb_signing_activate: NULL response_data\n")); + } + + dump_data_pw("smb_signing_activate: mac key is:\n", + si->mac_key.data, si->mac_key.length); + + /* Initialise the sequence number */ + si->seqnum = 2; + + return true; +} + +bool smb_signing_is_active(struct smb_signing_state *si) +{ + return si->active; +} + +bool smb_signing_is_allowed(struct smb_signing_state *si) +{ + return si->allowed; +} + +bool smb_signing_is_mandatory(struct smb_signing_state *si) +{ + return si->mandatory; +} + +bool smb_signing_set_negotiated(struct smb_signing_state *si, + bool allowed, bool mandatory) +{ + if (si->active) { + return true; + } + + if (!si->allowed && mandatory) { + return false; + } + + if (si->mandatory && !allowed) { + return false; + } + + if (si->mandatory) { + si->negotiated = true; + return true; + } + + if (mandatory) { + si->negotiated = true; + return true; + } + + if (!si->desired) { + si->negotiated = false; + return true; + } + + if (si->desired && allowed) { + si->negotiated = true; + return true; + } + + si->negotiated = false; + return true; +} + +bool smb_signing_is_negotiated(struct smb_signing_state *si) +{ + return si->negotiated; +} diff --git a/libcli/smb/smb_signing.h b/libcli/smb/smb_signing.h new file mode 100644 index 0000000000..481be1d500 --- /dev/null +++ b/libcli/smb/smb_signing.h @@ -0,0 +1,54 @@ +/* + Unix SMB/CIFS implementation. + SMB Signing Code + Copyright (C) Jeremy Allison 2003. + Copyright (C) Andrew Bartlett 2002-2003 + Copyright (C) Stefan Metzmacher 2009 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SMB_SIGNING_H_ +#define _SMB_SIGNING_H_ + +struct smb_signing_state; + +struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx, + bool allowed, + bool desired, + bool mandatory); +struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx, + bool allowed, + bool desired, + bool mandatory, + void *(*alloc_fn)(TALLOC_CTX *, size_t), + void (*free_fn)(TALLOC_CTX *, void *)); +uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway); +void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway); +void smb_signing_sign_pdu(struct smb_signing_state *si, + uint8_t *outbuf, uint32_t seqnum); +bool smb_signing_check_pdu(struct smb_signing_state *si, + const uint8_t *inbuf, uint32_t seqnum); +bool smb_signing_set_bsrspyl(struct smb_signing_state *si); +bool smb_signing_activate(struct smb_signing_state *si, + const DATA_BLOB user_session_key, + const DATA_BLOB response); +bool smb_signing_is_active(struct smb_signing_state *si); +bool smb_signing_is_allowed(struct smb_signing_state *si); +bool smb_signing_is_mandatory(struct smb_signing_state *si); +bool smb_signing_set_negotiated(struct smb_signing_state *si, + bool allowed, bool mandatory); +bool smb_signing_is_negotiated(struct smb_signing_state *si); + +#endif /* _SMB_SIGNING_H_ */ diff --git a/libcli/smb/wscript_build b/libcli/smb/wscript_build index 9339b96044..8cb3e60a9f 100644 --- a/libcli/smb/wscript_build +++ b/libcli/smb/wscript_build @@ -2,14 +2,20 @@ bld.SAMBA_LIBRARY('cli_smb_common', - source='smb_seal.c smb2_create_blob.c smb2_signing.c util.c read_smb.c', + source=''' + smb_signing.c smb_seal.c + smb2_create_blob.c smb2_signing.c + util.c read_smb.c + ''', autoproto='smb_common_proto.h', deps='LIBCRYPTO errors gssapi gensec KRB5_WRAP LIBASYNC_REQ', public_deps='talloc samba-util', private_library=True, - public_headers='''smb_common.h smb2_constants.h smb_constants.h - smb_seal.h - smb2_create_blob.h smb2_signing.h smb_util.h smb_unix_ext.h - read_smb.h + public_headers=''' + smb_common.h smb2_constants.h smb_constants.h + smb_signing.h smb_seal.h + smb2_create_blob.h smb2_signing.h + smb_util.h read_smb.h + smb_unix_ext.h ''', ) diff --git a/source3/Makefile.in b/source3/Makefile.in index 6f216c67b8..c303fe99a5 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -463,7 +463,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) $(LIBTSOCKET_OBJ) \ lib/substitute.o lib/substitute_generic.o ../lib/util/substitute.o lib/dbwrap/dbwrap_util.o \ lib/ms_fnmatch.o ../lib/util/ms_fnmatch.o lib/errmap_unix.o ../libcli/util/errmap_unix.o \ lib/tallocmsg.o lib/dmallocmsg.o \ - libsmb/smb_signing.o \ + ../libcli/smb/smb_signing.o \ ../lib/util/charset/iconv.o ../lib/util/charset/weird.o \ ../lib/util/charset/charset_macosxfs.o intl/lang_tdb.o \ lib/conn_tdb.o lib/adt_tree.o lib/gencache.o \ diff --git a/source3/include/smb_signing.h b/source3/include/smb_signing.h deleted file mode 100644 index 481be1d500..0000000000 --- a/source3/include/smb_signing.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB Signing Code - Copyright (C) Jeremy Allison 2003. - Copyright (C) Andrew Bartlett 2002-2003 - Copyright (C) Stefan Metzmacher 2009 - - 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 - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _SMB_SIGNING_H_ -#define _SMB_SIGNING_H_ - -struct smb_signing_state; - -struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx, - bool allowed, - bool desired, - bool mandatory); -struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx, - bool allowed, - bool desired, - bool mandatory, - void *(*alloc_fn)(TALLOC_CTX *, size_t), - void (*free_fn)(TALLOC_CTX *, void *)); -uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway); -void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway); -void smb_signing_sign_pdu(struct smb_signing_state *si, - uint8_t *outbuf, uint32_t seqnum); -bool smb_signing_check_pdu(struct smb_signing_state *si, - const uint8_t *inbuf, uint32_t seqnum); -bool smb_signing_set_bsrspyl(struct smb_signing_state *si); -bool smb_signing_activate(struct smb_signing_state *si, - const DATA_BLOB user_session_key, - const DATA_BLOB response); -bool smb_signing_is_active(struct smb_signing_state *si); -bool smb_signing_is_allowed(struct smb_signing_state *si); -bool smb_signing_is_mandatory(struct smb_signing_state *si); -bool smb_signing_set_negotiated(struct smb_signing_state *si, - bool allowed, bool mandatory); -bool smb_signing_is_negotiated(struct smb_signing_state *si); - -#endif /* _SMB_SIGNING_H_ */ diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index f5123eaf65..117fc994ad 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -21,7 +21,7 @@ #include "includes.h" #include "libsmb/libsmb.h" #include "../lib/util/tevent_ntstatus.h" -#include "smb_signing.h" +#include "../libcli/smb/smb_signing.h" #include "../libcli/smb/smb_seal.h" #include "async_smb.h" diff --git a/source3/libsmb/clisigning.c b/source3/libsmb/clisigning.c index 4049aa0a59..2ce96c62fc 100644 --- a/source3/libsmb/clisigning.c +++ b/source3/libsmb/clisigning.c @@ -21,7 +21,7 @@ #include "includes.h" #include "libsmb/libsmb.h" -#include "smb_signing.h" +#include "../libcli/smb/smb_signing.h" bool cli_simple_set_signing(struct cli_state *cli, const DATA_BLOB user_session_key, diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c deleted file mode 100644 index 1f9d36889a..0000000000 --- a/source3/libsmb/smb_signing.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB Signing Code - Copyright (C) Jeremy Allison 2003. - Copyright (C) Andrew Bartlett 2002-2003 - Copyright (C) Stefan Metzmacher 2009 - - 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 - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "../lib/crypto/md5.h" -#include "smb_signing.h" - -/* Used by the SMB signing functions. */ - -struct smb_signing_state { - /* is signing localy allowed */ - bool allowed; - - /* is signing localy desired */ - bool desired; - - /* is signing localy mandatory */ - bool mandatory; - - /* is signing negotiated by the peer */ - bool negotiated; - - bool active; /* Have I ever seen a validly signed packet? */ - - /* mac_key.length > 0 means signing is started */ - DATA_BLOB mac_key; - - /* the next expected seqnum */ - uint32_t seqnum; - - TALLOC_CTX *mem_ctx; - void *(*alloc_fn)(TALLOC_CTX *mem_ctx, size_t len); - void (*free_fn)(TALLOC_CTX *mem_ctx, void *ptr); -}; - -static void smb_signing_reset_info(struct smb_signing_state *si) -{ - si->active = false; - si->seqnum = 0; - - if (si->free_fn) { - si->free_fn(si->mem_ctx, si->mac_key.data); - } else { - talloc_free(si->mac_key.data); - } - si->mac_key.data = NULL; - si->mac_key.length = 0; -} - -struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx, - bool allowed, - bool desired, - bool mandatory, - void *(*alloc_fn)(TALLOC_CTX *, size_t), - void (*free_fn)(TALLOC_CTX *, void *)) -{ - struct smb_signing_state *si; - - if (alloc_fn) { - void *p = alloc_fn(mem_ctx, sizeof(struct smb_signing_state)); - if (p == NULL) { - return NULL; - } - memset(p, 0, sizeof(struct smb_signing_state)); - si = (struct smb_signing_state *)p; - si->mem_ctx = mem_ctx; - si->alloc_fn = alloc_fn; - si->free_fn = free_fn; - } else { - si = talloc_zero(mem_ctx, struct smb_signing_state); - if (si == NULL) { - return NULL; - } - } - - if (mandatory) { - desired = true; - } - - if (desired) { - allowed = true; - } - - si->allowed = allowed; - si->desired = desired; - si->mandatory = mandatory; - - return si; -} - -struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx, - bool allowed, - bool desired, - bool mandatory) -{ - return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory, - NULL, NULL); -} - -static bool smb_signing_good(struct smb_signing_state *si, - bool good, uint32_t seq) -{ - if (good) { - if (!si->active) { - si->active = true; - } - return true; - } - - if (!si->mandatory && !si->active) { - /* Non-mandatory signing - just turn off if this is the first bad packet.. */ - DEBUG(5, ("smb_signing_good: signing negotiated but not required and peer\n" - "isn't sending correct signatures. Turning off.\n")); - smb_signing_reset_info(si); - return true; - } - - /* Mandatory signing or bad packet after signing started - fail and disconnect. */ - DEBUG(0, ("smb_signing_good: BAD SIG: seq %u\n", (unsigned int)seq)); - return false; -} - -static void smb_signing_md5(const DATA_BLOB *mac_key, - const uint8_t *buf, uint32_t seq_number, - uint8_t calc_md5_mac[16]) -{ - const size_t offset_end_of_sig = (NBT_HDR_SIZE + HDR_SS_FIELD + 8); - uint8_t sequence_buf[8]; - struct MD5Context md5_ctx; - - /* - * Firstly put the sequence number into the first 4 bytes. - * and zero out the next 4 bytes. - * - * We do this here, to avoid modifying the packet. - */ - - DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number )); - - SIVAL(sequence_buf, 0, seq_number); - SIVAL(sequence_buf, 4, 0); - - /* Calculate the 16 byte MAC - but don't alter the data in the - incoming packet. - - This makes for a bit of fussing about, but it's not too bad. - */ - MD5Init(&md5_ctx); - - /* intialise with the key */ - MD5Update(&md5_ctx, mac_key->data, mac_key->length); - - /* copy in the first bit of the SMB header */ - MD5Update(&md5_ctx, buf + NBT_HDR_SIZE, HDR_SS_FIELD); - - /* copy in the sequence number, instead of the signature */ - MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf)); - - /* copy in the rest of the packet in, skipping the signature */ - MD5Update(&md5_ctx, buf + offset_end_of_sig, - smb_len_nbt(buf) - (offset_end_of_sig - 4)); - - /* calculate the MD5 sig */ - MD5Final(calc_md5_mac, &md5_ctx); -} - -uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway) -{ - uint32_t seqnum; - - if (si->mac_key.length == 0) { - return 0; - } - - seqnum = si->seqnum; - if (oneway) { - si->seqnum += 1; - } else { - si->seqnum += 2; - } - - return seqnum; -} - -void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway) -{ - if (si->mac_key.length == 0) { - return; - } - - if (oneway) { - si->seqnum -= 1; - } else { - si->seqnum -= 2; - } -} - -void smb_signing_sign_pdu(struct smb_signing_state *si, - uint8_t *outbuf, uint32_t seqnum) -{ - uint8_t calc_md5_mac[16]; - uint8_t com; - uint8_t flags; - - if (si->mac_key.length == 0) { - if (!si->negotiated) { - return; - } - } - - /* JRA Paranioa test - we should be able to get rid of this... */ - if (smb_len_nbt(outbuf) < (HDR_SS_FIELD + 8)) { - DEBUG(1,("smb_signing_sign_pdu: Logic error. " - "Can't check signature on short packet! smb_len = %u\n", - smb_len_nbt(outbuf))); - abort(); - } - - com = SVAL(outbuf,NBT_HDR_SIZE+HDR_COM); - flags = SVAL(outbuf,NBT_HDR_SIZE+HDR_FLG); - - if (!(flags & FLAG_REPLY)) { - uint16_t flags2 = SVAL(outbuf,NBT_HDR_SIZE+HDR_FLG2); - /* - * If this is a request, specify what is - * supported or required by the client - */ - if (si->negotiated && si->desired) { - flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES; - } - if (si->negotiated && si->mandatory) { - flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED; - } - SSVAL(outbuf, NBT_HDR_SIZE+HDR_FLG2, flags2); - } - - if (si->mac_key.length == 0) { - /* I wonder what BSRSPYL stands for - but this is what MS - actually sends! */ - if (com == SMBsesssetupX) { - memcpy(calc_md5_mac, "BSRSPYL ", 8); - } else { - memset(calc_md5_mac, 0, 8); - } - } else { - smb_signing_md5(&si->mac_key, outbuf, - seqnum, calc_md5_mac); - } - - DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n")); - dump_data(10, calc_md5_mac, 8); - - memcpy(&outbuf[NBT_HDR_SIZE+HDR_SS_FIELD], calc_md5_mac, 8); - -/* outbuf[NBT_HDR_SIZE+HDR_SS_FIELD+2]=0; - Uncomment this to test if the remote server actually verifies signatures...*/ -} - -bool smb_signing_check_pdu(struct smb_signing_state *si, - const uint8_t *inbuf, uint32_t seqnum) -{ - bool good; - uint8_t calc_md5_mac[16]; - const uint8_t *reply_sent_mac; - - if (si->mac_key.length == 0) { - return true; - } - - if (smb_len_nbt(inbuf) < (HDR_SS_FIELD + 8)) { - DEBUG(1,("smb_signing_check_pdu: Can't check signature " - "on short packet! smb_len = %u\n", - smb_len_nbt(inbuf))); - return false; - } - - smb_signing_md5(&si->mac_key, inbuf, - seqnum, calc_md5_mac); - - reply_sent_mac = &inbuf[NBT_HDR_SIZE+HDR_SS_FIELD]; - good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0); - - if (!good) { - int i; - const int sign_range = 5; - - DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n")); - dump_data(5, calc_md5_mac, 8); - - DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n")); - dump_data(5, reply_sent_mac, 8); - - for (i = -sign_range; i < sign_range; i++) { - smb_signing_md5(&si->mac_key, inbuf, - seqnum+i, calc_md5_mac); - if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) { - DEBUG(0,("smb_signing_check_pdu: " - "out of seq. seq num %u matches. " - "We were expecting seq %u\n", - (unsigned int)seqnum+i, - (unsigned int)seqnum)); - break; - } - } - } else { - DEBUG(10, ("smb_signing_check_pdu: seq %u: " - "got good SMB signature of\n", - (unsigned int)seqnum)); - dump_data(10, reply_sent_mac, 8); - } - - return smb_signing_good(si, good, seqnum); -} - -bool smb_signing_activate(struct smb_signing_state *si, - const DATA_BLOB user_session_key, - const DATA_BLOB response) -{ - size_t len; - off_t ofs; - - if (!user_session_key.length) { - return false; - } - - if (!si->negotiated) { - return false; - } - - if (si->active) { - return false; - } - - if (si->mac_key.length > 0) { - return false; - } - - smb_signing_reset_info(si); - - len = response.length + user_session_key.length; - if (si->alloc_fn) { - si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len); - if (si->mac_key.data == NULL) { - return false; - } - } else { - si->mac_key.data = (uint8_t *)talloc_size(si, len); - if (si->mac_key.data == NULL) { - return false; - } - } - si->mac_key.length = len; - - ofs = 0; - memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length); - - DEBUG(10, ("smb_signing_activate: user_session_key\n")); - dump_data(10, user_session_key.data, user_session_key.length); - - if (response.length) { - ofs = user_session_key.length; - memcpy(&si->mac_key.data[ofs], response.data, response.length); - DEBUG(10, ("smb_signing_activate: response_data\n")); - dump_data(10, response.data, response.length); - } else { - DEBUG(10, ("smb_signing_activate: NULL response_data\n")); - } - - dump_data_pw("smb_signing_activate: mac key is:\n", - si->mac_key.data, si->mac_key.length); - - /* Initialise the sequence number */ - si->seqnum = 2; - - return true; -} - -bool smb_signing_is_active(struct smb_signing_state *si) -{ - return si->active; -} - -bool smb_signing_is_allowed(struct smb_signing_state *si) -{ - return si->allowed; -} - -bool smb_signing_is_mandatory(struct smb_signing_state *si) -{ - return si->mandatory; -} - -bool smb_signing_set_negotiated(struct smb_signing_state *si, - bool allowed, bool mandatory) -{ - if (si->active) { - return true; - } - - if (!si->allowed && mandatory) { - return false; - } - - if (si->mandatory && !allowed) { - return false; - } - - if (si->mandatory) { - si->negotiated = true; - return true; - } - - if (mandatory) { - si->negotiated = true; - return true; - } - - if (!si->desired) { - si->negotiated = false; - return true; - } - - if (si->desired && allowed) { - si->negotiated = true; - return true; - } - - si->negotiated = false; - return true; -} - -bool smb_signing_is_negotiated(struct smb_signing_state *si) -{ - return si->negotiated; -} diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 3ea6f66c0b..407ef68d4c 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -64,7 +64,7 @@ #include "ads.h" #include "../librpc/gen_ndr/svcctl.h" #include "intl.h" -#include "smb_signing.h" +#include "../libcli/smb/smb_signing.h" #include "dbwrap/dbwrap.h" #include "dbwrap/dbwrap_rbt.h" #include "smbldap.h" diff --git a/source3/smbd/signing.c b/source3/smbd/signing.c index bdf920c91a..8e08ae9691 100644 --- a/source3/smbd/signing.c +++ b/source3/smbd/signing.c @@ -22,7 +22,7 @@ #include "includes.h" #include "smbd/smbd.h" #include "smbd/globals.h" -#include "smb_signing.h" +#include "../libcli/smb/smb_signing.h" /*********************************************************** Called to validate an incoming packet from the client. diff --git a/source3/wscript_build b/source3/wscript_build index 26a1ea200f..f2c4148458 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -66,7 +66,6 @@ LIB_SRC = ''' lib/substitute.c lib/substitute_generic.c lib/ms_fnmatch.c lib/tallocmsg.c lib/dmallocmsg.c - libsmb/smb_signing.c intl/lang_tdb.c lib/conn_tdb.c lib/gencache.c lib/sessionid_tdb.c -- cgit