diff options
author | Andrew Bartlett <abartlet@samba.org> | 2008-06-10 13:19:56 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2008-06-10 13:19:56 +1000 |
commit | 7721ea8f9c75d304111935048167dd27525cc91a (patch) | |
tree | fdc6563d085003cf6fe003748fb85291166a5454 /source4 | |
parent | 7974ccbebf5c684200850a726d79b976eaeea261 (diff) | |
parent | 1384f836b601d35f3c499a9e26c3e3b0d12b3ad0 (diff) | |
download | samba-7721ea8f9c75d304111935048167dd27525cc91a.tar.gz samba-7721ea8f9c75d304111935048167dd27525cc91a.tar.bz2 samba-7721ea8f9c75d304111935048167dd27525cc91a.zip |
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-local
(This used to be commit 1d52d9cc70158dbe30325220aa5c1e6203c8b72b)
Diffstat (limited to 'source4')
23 files changed, 191 insertions, 114 deletions
diff --git a/source4/build/m4/check_cc.m4 b/source4/build/m4/check_cc.m4 index 569be38721..51531ca776 100644 --- a/source4/build/m4/check_cc.m4 +++ b/source4/build/m4/check_cc.m4 @@ -30,7 +30,7 @@ fi # check if the compiler can handle negative enum values # and don't truncate the values to INT_MAX # a runtime test is needed here -AC_CACHE_CHECK([that the C compiler understands negative enum values],SMB_BUILD_CC_NEGATIVE_ENUM_VALUES, [ +AC_CACHE_CHECK([that the C compiler understands negative enum values],samba_cv_CC_NEGATIVE_ENUM_VALUES, [ AC_TRY_RUN( [ #include <stdio.h> @@ -45,8 +45,8 @@ AC_CACHE_CHECK([that the C compiler understands negative enum values],SMB_BUILD_ return 0; } ], - SMB_BUILD_CC_NEGATIVE_ENUM_VALUES=yes,SMB_BUILD_CC_NEGATIVE_ENUM_VALUES=no)]) -if test x"$SMB_BUILD_CC_NEGATIVE_ENUM_VALUES" != x"yes"; then + samba_cv_CC_NEGATIVE_ENUM_VALUES=yes,samba_cv_CC_NEGATIVE_ENUM_VALUES=no)]) +if test x"$samba_cv_CC_NEGATIVE_ENUM_VALUES" != x"yes"; then AC_DEFINE(USE_UINT_ENUMS, 1, [Whether the compiler has uint enum support]) fi diff --git a/source4/configure.ac b/source4/configure.ac index 73d3ffd4d9..7690e700a5 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -1,8 +1,7 @@ dnl -*- mode: m4-mode -*- dnl Process this file with autoconf to produce a configure script. -dnl disabled 2.53 requirement - we do work with 2.52 on suse 7.3 for example -dnl AC_PREREQ(2.53) +AC_PREREQ(2.54) AC_INIT([samba],[4],[samba-technical@samba.org]) @@ -14,7 +13,7 @@ AC_DEFINE(CONFIG_H_IS_FROM_SAMBA,1,[Marker for samba's config.h]) m4_include(build/m4/env.m4) m4_include(lib/replace/samba.m4) m4_include(lib/smbreadline/readline.m4) -m4_include(heimdal_build/config.m4) +m4_include(heimdal_build/internal.m4) m4_include(lib/util/fault.m4) m4_include(lib/util/signal.m4) m4_include(lib/util/util.m4) diff --git a/source4/heimdal_build/config.m4 b/source4/heimdal_build/internal.m4 index 18ecbb75cd..18ecbb75cd 100644 --- a/source4/heimdal_build/config.m4 +++ b/source4/heimdal_build/internal.m4 diff --git a/source4/heimdal_build/config.mk b/source4/heimdal_build/internal.mk index 17fc8c93ec..17fc8c93ec 100644 --- a/source4/heimdal_build/config.mk +++ b/source4/heimdal_build/internal.mk diff --git a/source4/lib/replace/libreplace.m4 b/source4/lib/replace/libreplace.m4 index 6a85ff5a82..71fa041672 100644 --- a/source4/lib/replace/libreplace.m4 +++ b/source4/lib/replace/libreplace.m4 @@ -299,4 +299,5 @@ m4_include(libreplace_cc.m4) m4_include(libreplace_ld.m4) m4_include(libreplace_network.m4) m4_include(libreplace_macros.m4) -m4_include(autoconf-2.60.m4) + +m4_ifndef([AC_USE_SYSTEM_EXTENSIONS],[m4_include(autoconf-2.60.m4)]) diff --git a/source4/lib/replace/win32.m4 b/source4/lib/replace/win32.m4 index 9ac84cdf2a..eb364e2cb9 100644 --- a/source4/lib/replace/win32.m4 +++ b/source4/lib/replace/win32.m4 @@ -2,7 +2,7 @@ AC_CHECK_HEADERS(direct.h windows.h winsock2.h ws2tcpip.h) ####################################### # Check for mkdir mode -AC_CACHE_CHECK( [whether mkdir supports mode], ac_mkdir_has_mode, +AC_CACHE_CHECK( [whether mkdir supports mode], libreplace_cv_mkdir_has_mode, AC_TRY_COMPILE([ #include <stdio.h> #ifdef HAVE_DIRECT_H @@ -11,10 +11,10 @@ AC_CACHE_CHECK( [whether mkdir supports mode], ac_mkdir_has_mode, mkdir("foo",0777); return 0; ], - ac_mkdir_has_mode="yes", - ac_mkdir_has_mode="no") ) + libreplace_cv_mkdir_has_mode="yes", + libreplace_cv_mkdir_has_mode="no") ) -if test "$ac_mkdir_has_mode" = "yes" +if test "$libreplace_cv_mkdir_has_mode" = "yes" then AC_DEFINE(HAVE_MKDIR_MODE, 1, [Define if target mkdir supports mode option]) fi diff --git a/source4/lib/tdb/tdb.i b/source4/lib/tdb/tdb.i index 5f23568170..3d8b697732 100644 --- a/source4/lib/tdb/tdb.i +++ b/source4/lib/tdb/tdb.i @@ -160,6 +160,8 @@ typedef struct tdb_context { tdb(const char *name, int hash_size, int tdb_flags, int flags, mode_t mode) { return tdb_open(name, hash_size, tdb_flags, flags, mode); } + %feature("docstring") error "S.error() -> int\n" + "Find last error number returned by operation on this TDB."; enum TDB_ERROR error(); ~tdb() { tdb_close($self); } %feature("docstring") close "S.close() -> None\n" @@ -179,6 +181,8 @@ typedef struct tdb_context { %feature("docstring") store "S.store(key, value, flag=TDB_REPLACE) -> None\n" "Store an entry."; int store(TDB_DATA key, TDB_DATA dbuf, int flag); + %feature("docstring") exists "S.exists(key) -> bool\n" + "Check whether key exists in this database."; int exists(TDB_DATA key); %feature("docstring") firstkey "S.firstkey() -> data\n" "Return the first key in this database."; diff --git a/source4/lib/tdb/tdb.py b/source4/lib/tdb/tdb.py index a8c1d06e0d..9f306bab8c 100644 --- a/source4/lib/tdb/tdb.py +++ b/source4/lib/tdb/tdb.py @@ -92,6 +92,13 @@ class Tdb(object): Open a TDB file. """ _tdb.Tdb_swiginit(self,_tdb.new_Tdb(*args, **kwargs)) + def error(*args, **kwargs): + """ + S.error() -> int + Find last error number returned by operation on this TDB. + """ + return _tdb.Tdb_error(*args, **kwargs) + __swig_destroy__ = _tdb.delete_Tdb def close(*args, **kwargs): """ @@ -128,6 +135,13 @@ class Tdb(object): """ return _tdb.Tdb_store(*args, **kwargs) + def exists(*args, **kwargs): + """ + S.exists(key) -> bool + Check whether key exists in this database. + """ + return _tdb.Tdb_exists(*args, **kwargs) + def firstkey(*args, **kwargs): """ S.firstkey() -> data diff --git a/source4/lib/tdb/tdb_wrap.c b/source4/lib/tdb/tdb_wrap.c index 27da552d33..32665d79fd 100644 --- a/source4/lib/tdb/tdb_wrap.c +++ b/source4/lib/tdb/tdb_wrap.c @@ -3628,7 +3628,10 @@ static PyMethodDef SwigMethods[] = { "S.__init__(name,hash_size=0,tdb_flags=TDB_DEFAULT,flags=O_RDWR,mode=0600)\n" "Open a TDB file.\n" ""}, - { (char *)"Tdb_error", (PyCFunction)_wrap_Tdb_error, METH_O, NULL}, + { (char *)"Tdb_error", (PyCFunction)_wrap_Tdb_error, METH_O, (char *)"\n" + "S.error() -> int\n" + "Find last error number returned by operation on this TDB.\n" + ""}, { (char *)"delete_Tdb", (PyCFunction)_wrap_delete_Tdb, METH_O, NULL}, { (char *)"Tdb_close", (PyCFunction)_wrap_Tdb_close, METH_O, (char *)"\n" "S.close() -> None\n" @@ -3651,7 +3654,10 @@ static PyMethodDef SwigMethods[] = { "S.store(key, value, flag=TDB_REPLACE) -> None\n" "Store an entry.\n" ""}, - { (char *)"Tdb_exists", (PyCFunction) _wrap_Tdb_exists, METH_VARARGS | METH_KEYWORDS, NULL}, + { (char *)"Tdb_exists", (PyCFunction) _wrap_Tdb_exists, METH_VARARGS | METH_KEYWORDS, (char *)"\n" + "S.exists(key) -> bool\n" + "Check whether key exists in this database.\n" + ""}, { (char *)"Tdb_firstkey", (PyCFunction)_wrap_Tdb_firstkey, METH_O, (char *)"\n" "S.firstkey() -> data\n" "Return the first key in this database.\n" diff --git a/source4/lib/tls/config.m4 b/source4/lib/tls/config.m4 index 8b6ad7dcbc..2af9192cca 100644 --- a/source4/lib/tls/config.m4 +++ b/source4/lib/tls/config.m4 @@ -1,33 +1,44 @@ ############################### # start SMB_EXT_LIB_GNUTLS # check for gnutls/gnutls.h and -lgnutls -SMB_EXT_LIB_FROM_PKGCONFIG(GNUTLS, gnutls, - [SMB_ENABLE_GNUTLS=YES], - [SMB_ENABLE_GNUTLS=NO]) -if test x$SMB_ENABLE_GNUTLS = xNO; then - AC_CHECK_HEADERS(gnutls/gnutls.h) - AC_CHECK_LIB_EXT(gnutls, GNUTLS_LIBS, gnutls_global_init) - AC_CHECK_DECL(gnutls_x509_crt_set_version, - [AC_DEFINE(HAVE_GNUTLS_X509_CRT_SET_VERSION,1,gnutls set_version)], [], [ - #include <gnutls/gnutls.h> - #include <gnutls/x509.h> - ]) - if test x"$ac_cv_header_gnutls_gnutls_h" = x"yes" -a x"$ac_cv_lib_ext_gnutls_gnutls_global_init" = x"yes" -a x"$ac_cv_have_decl_gnutls_x509_crt_set_version" = x"yes";then - SMB_ENABLE(GNUTLS,YES) - AC_CHECK_DECL(gnutls_x509_crt_set_subject_key_id, - [AC_DEFINE(HAVE_GNUTLS_X509_CRT_SET_SUBJECT_KEY_ID,1,gnutls subject_key)], [], [ - #include <gnutls/gnutls.h> - #include <gnutls/x509.h> - ]) +use_gnutls=yes +AC_ARG_ENABLE(gnutls, +[ --enable-gnutls Turn on gnutls support (default=yes)], + [if test x$enable_gnutls = xno; then + use_gnutls=no + fi]) + + +if test x$use_gnutls = xyes; then + SMB_EXT_LIB_FROM_PKGCONFIG(GNUTLS, gnutls, + [SMB_ENABLE_GNUTLS=YES], + [SMB_ENABLE_GNUTLS=NO]) + + if test x$SMB_ENABLE_GNUTLS = xNO; then + AC_CHECK_HEADERS(gnutls/gnutls.h) + AC_CHECK_LIB_EXT(gnutls, GNUTLS_LIBS, gnutls_global_init) + AC_CHECK_DECL(gnutls_x509_crt_set_version, + [AC_DEFINE(HAVE_GNUTLS_X509_CRT_SET_VERSION,1,gnutls set_version)], [], [ + #include <gnutls/gnutls.h> + #include <gnutls/x509.h> + ]) + if test x"$ac_cv_header_gnutls_gnutls_h" = x"yes" -a x"$ac_cv_lib_ext_gnutls_gnutls_global_init" = x"yes" -a x"$ac_cv_have_decl_gnutls_x509_crt_set_version" = x"yes";then + SMB_ENABLE(GNUTLS,YES) + AC_CHECK_DECL(gnutls_x509_crt_set_subject_key_id, + [AC_DEFINE(HAVE_GNUTLS_X509_CRT_SET_SUBJECT_KEY_ID,1,gnutls subject_key)], [], [ + #include <gnutls/gnutls.h> + #include <gnutls/x509.h> + ]) + fi + SMB_EXT_LIB(GNUTLS, $GNUTLS_LIBS) + fi + if test x$SMB_ENABLE_GNUTLS = xYES; then + #Some older versions have a different type name + AC_CHECK_TYPES([gnutls_datum],,,[#include "gnutls/gnutls.h"]) + AC_CHECK_TYPES([gnutls_datum_t],,,[#include "gnutls/gnutls.h"]) + AC_DEFINE(ENABLE_GNUTLS,1,[Whether we have gnutls support (SSL)]) fi - SMB_EXT_LIB(GNUTLS, $GNUTLS_LIBS) -fi -if test x$SMB_ENABLE_GNUTLS = xYES; then - #Some older versions have a different type name - AC_CHECK_TYPES([gnutls_datum],,,[#include "gnutls/gnutls.h"]) - AC_CHECK_TYPES([gnutls_datum_t],,,[#include "gnutls/gnutls.h"]) - AC_DEFINE(ENABLE_GNUTLS,1,[Whether we have gnutls support (SSL)]) fi # end SMB_EXT_LIB_GNUTLS ############################### diff --git a/source4/libcli/raw/raweas.c b/source4/libcli/raw/raweas.c index 07b517ade3..6317c49fd7 100644 --- a/source4/libcli/raw/raweas.c +++ b/source4/libcli/raw/raweas.c @@ -131,6 +131,8 @@ uint_t ea_pull_struct(const DATA_BLOB *blob, uint8_t nlen; uint16_t vlen; + ZERO_STRUCTP(ea); + if (blob->length < 6) { return 0; } diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c index 54915d8535..91616319d5 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -164,7 +164,7 @@ static void session_request_handler(struct smb2_request *req) session_key_err = gensec_session_key(session->gensec, &session_key); if (NT_STATUS_IS_OK(session_key_err)) { - session->transport->signing.session_key = session_key; + session->session_key = session_key; } } @@ -188,11 +188,13 @@ static void session_request_handler(struct smb2_request *req) } if (session->transport->signing.doing_signing) { - c->status = smb2_start_signing(session->transport); - if (!NT_STATUS_IS_OK(c->status)) { - composite_error(c, c->status); + if (session->session_key.length != 16) { + DEBUG(2,("Wrong session key length %u for SMB2 signing\n", + (unsigned)session->session_key.length)); + composite_error(c, NT_STATUS_ACCESS_DENIED); return; } + session->transport->signing.signing_started = true; } composite_done(c); diff --git a/source4/libcli/smb2/signing.c b/source4/libcli/smb2/signing.c index 16c0ff99c1..fb2c22db4e 100644 --- a/source4/libcli/smb2/signing.c +++ b/source4/libcli/smb2/signing.c @@ -26,41 +26,13 @@ #include "lib/crypto/crypto.h" /* - NOTE: this code does not yet interoperate with the windows SMB2 - implementation. We are waiting on feedback on the docs to find out - why - */ - - -/* - setup signing on a transport - */ -NTSTATUS smb2_start_signing(struct smb2_transport *transport) -{ - if (transport->signing.session_key.length != 16) { - DEBUG(2,("Wrong session key length %u for SMB2 signing\n", - (unsigned)transport->signing.session_key.length)); - return NT_STATUS_ACCESS_DENIED; - } - - transport->signing.signing_started = true; - return NT_STATUS_OK; -} - -/* sign an outgoing message */ -NTSTATUS smb2_sign_message(struct smb2_request *req) +NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_key) { - struct smb2_request_buffer *buf = &req->out; - uint64_t session_id; struct HMACSHA256Context m; uint8_t res[32]; - - if (!req->transport->signing.doing_signing || - !req->transport->signing.signing_started) { - return NT_STATUS_OK; - } + uint64_t session_id; if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) { /* can't sign non-SMB2 messages */ @@ -74,9 +46,9 @@ NTSTATUS smb2_sign_message(struct smb2_request *req) return NT_STATUS_OK; } - if (req->transport->signing.session_key.length != 16) { + if (session_key.length != 16) { DEBUG(2,("Wrong session key length %u for SMB2 signing\n", - (unsigned)req->transport->signing.session_key.length)); + (unsigned)session_key.length)); return NT_STATUS_ACCESS_DENIED; } @@ -85,7 +57,7 @@ NTSTATUS smb2_sign_message(struct smb2_request *req) SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED); ZERO_STRUCT(m); - hmac_sha256_init(req->transport->signing.session_key.data, 16, &m); + hmac_sha256_init(session_key.data, 16, &m); hmac_sha256_update(buf->buffer+NBT_HDR_SIZE, buf->size-NBT_HDR_SIZE, &m); hmac_sha256_final(res, &m); @@ -93,66 +65,56 @@ NTSTATUS smb2_sign_message(struct smb2_request *req) memcpy(buf->hdr + SMB2_HDR_SIGNATURE, res, 16); - if (DEBUGLVL(5)) { - /* check our own signature */ - smb2_check_signature(req->transport, buf->buffer, buf->size); - } - return NT_STATUS_OK; } /* check an incoming signature */ -NTSTATUS smb2_check_signature(struct smb2_transport *transport, - uint8_t *buffer, uint_t length) +NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session_key) { uint64_t session_id; struct HMACSHA256Context m; uint8_t res[SHA256_DIGEST_LENGTH]; uint8_t sig[16]; - if (!transport->signing.signing_started || - !transport->signing.doing_signing) { - return NT_STATUS_OK; - } - - if (length < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) { + if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) { /* can't check non-SMB2 messages */ return NT_STATUS_OK; } - session_id = BVAL(buffer+NBT_HDR_SIZE, SMB2_HDR_SESSION_ID); + session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID); if (session_id == 0) { /* don't sign messages with a zero session_id. See MS-SMB2 3.2.4.1.1 */ return NT_STATUS_OK; } - if (transport->signing.session_key.length == 0) { + if (session_key.length == 0) { /* we don't have the session key yet */ return NT_STATUS_OK; } - if (transport->signing.session_key.length != 16) { + if (session_key.length != 16) { DEBUG(2,("Wrong session key length %u for SMB2 signing\n", - (unsigned)transport->signing.session_key.length)); + (unsigned)session_key.length)); return NT_STATUS_ACCESS_DENIED; } - memcpy(sig, buffer+NBT_HDR_SIZE+SMB2_HDR_SIGNATURE, 16); + memcpy(sig, buf->hdr+SMB2_HDR_SIGNATURE, 16); - memset(buffer + NBT_HDR_SIZE + SMB2_HDR_SIGNATURE, 0, 16); + memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16); ZERO_STRUCT(m); - hmac_sha256_init(transport->signing.session_key.data, 16, &m); - hmac_sha256_update(buffer+NBT_HDR_SIZE, length-NBT_HDR_SIZE, &m); + hmac_sha256_init(session_key.data, 16, &m); + hmac_sha256_update(buf->hdr, buf->size-NBT_HDR_SIZE, &m); hmac_sha256_final(res, &m); - memcpy(buffer+NBT_HDR_SIZE+SMB2_HDR_SIGNATURE, sig, 16); + memcpy(buf->hdr+SMB2_HDR_SIGNATURE, sig, 16); if (memcmp(res, sig, 16) != 0) { - DEBUG(0,("Bad SMB2 signature for message of size %u\n", length)); + DEBUG(0,("Bad SMB2 signature for message of size %u\n", + (unsigned)buf->size-NBT_HDR_SIZE)); dump_data(0, sig, 16); dump_data(0, res, 16); return NT_STATUS_ACCESS_DENIED; diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 0903509528..2b468d3dc9 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -30,7 +30,6 @@ struct smb2_handle; struct smb2_signing_context { bool doing_signing; bool signing_started; - DATA_BLOB session_key; }; /* @@ -98,6 +97,7 @@ struct smb2_session { struct smb2_transport *transport; struct gensec_security *gensec; uint64_t uid; + DATA_BLOB session_key; }; diff --git a/source4/libcli/smb2/tcon.c b/source4/libcli/smb2/tcon.c index db35669d41..ec7152b264 100644 --- a/source4/libcli/smb2/tcon.c +++ b/source4/libcli/smb2/tcon.c @@ -57,6 +57,7 @@ struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree, if (req == NULL) return NULL; SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, tree->session->uid); + req->session = tree->session; SSVAL(req->out.body, 0x02, io->in.reserved); status = smb2_push_o16s16_string(&req->out, 0x04, io->in.path); diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c index 561b6e528e..6e0d523e21 100644 --- a/source4/libcli/smb2/transport.c +++ b/source4/libcli/smb2/transport.c @@ -205,12 +205,6 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) goto error; } - status = smb2_check_signature(transport, buffer, len); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(buffer); - return status; - } - flags = IVAL(hdr, SMB2_HDR_FLAGS); seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID); @@ -241,6 +235,17 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE); req->status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS)); + if (req->session && transport->signing.doing_signing) { + status = smb2_check_signature(&req->in, + req->session->session_key); + if (!NT_STATUS_IS_OK(status)) { + /* the spec says to ignore packets with a bad signature */ + talloc_free(buffer); + return status; + } + } + + if (NT_STATUS_EQUAL(req->status, STATUS_PENDING)) { if (flags & 0x00000002) { req->cancel.can_cancel = true; @@ -346,11 +351,16 @@ void smb2_transport_send(struct smb2_request *req) return; } - status = smb2_sign_message(req); - if (!NT_STATUS_IS_OK(status)) { - req->state = SMB2_REQUEST_ERROR; - req->status = status; - return; + /* possibly sign the message */ + if (req->transport->signing.doing_signing && + req->transport->signing.signing_started && + req->session) { + status = smb2_sign_message(&req->out, req->session->session_key); + if (!NT_STATUS_IS_OK(status)) { + req->state = SMB2_REQUEST_ERROR; + req->status = status; + return; + } } blob = data_blob_const(req->out.buffer, req->out.size); diff --git a/source4/librpc/rpc/dcerpc_smb2.c b/source4/librpc/rpc/dcerpc_smb2.c index 211015a4cf..4767165fba 100644 --- a/source4/librpc/rpc/dcerpc_smb2.c +++ b/source4/librpc/rpc/dcerpc_smb2.c @@ -376,7 +376,7 @@ static NTSTATUS smb2_session_key(struct dcerpc_connection *c, DATA_BLOB *session { struct smb2_private *smb = talloc_get_type(c->transport.private_data, struct smb2_private); - *session_key = smb->tree->session->transport->signing.session_key; + *session_key = smb->tree->session->session_key; if (session_key->data == NULL) { return NT_STATUS_NO_USER_SESSION_KEY; } diff --git a/source4/main.mk b/source4/main.mk index 3f3aea87e6..f0ce9685f9 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -1,5 +1,5 @@ mkinclude dynconfig/config.mk -mkinclude heimdal_build/config.mk +mkinclude heimdal_build/internal.mk mkinclude config.mk mkinclude dsdb/config.mk mkinclude smbd/config.mk diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c index 4479ae2da1..3e6e2e1a43 100644 --- a/source4/smb_server/smb2/negprot.c +++ b/source4/smb_server/smb2/negprot.c @@ -111,7 +111,20 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2 boot_time = timeval_current(); /* TODO: fix me */ ZERO_STRUCT(io->out); - io->out.security_mode = 0; /* no signing yet */ + switch (lp_server_signing(req->smb_conn->lp_ctx)) { + case SMB_SIGNING_OFF: + io->out.security_mode = 0; + break; + case SMB_SIGNING_SUPPORTED: + case SMB_SIGNING_AUTO: + io->out.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED; + break; + case SMB_SIGNING_REQUIRED: + io->out.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED; + /* force signing on immediately */ + req->smb_conn->doing_signing = true; + break; + } io->out.dialect_revision = SMB2_DIALECT_REVISION; io->out.capabilities = 0; io->out.max_transact_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL, diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index dea7c9e79e..2f4e9df2b6 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -29,6 +29,8 @@ #include "lib/stream/packet.h" #include "ntvfs/ntvfs.h" #include "param/param.h" +#include "auth/gensec/gensec.h" +#include "auth/auth.h" /* fill in the bufinfo */ @@ -233,6 +235,20 @@ void smb2srv_send_reply(struct smb2srv_request *req) _smb2_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE); } + /* if the request was signed or doing_signing is true, then we + must sign the reply */ + if (req->session && + (req->smb_conn->doing_signing || + (IVAL(req->in.hdr, SMB2_HDR_FLAGS) & SMB2_HDR_FLAG_SIGNED))) { + status = smb2_sign_message(&req->out, + req->session->session_info->session_key); + if (!NT_STATUS_IS_OK(status)) { + smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); + return; + } + } + + blob = data_blob_const(req->out.buffer, req->out.size); status = packet_send(req->smb_conn->packet, blob); if (!NT_STATUS_IS_OK(status)) { @@ -275,18 +291,42 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) uint16_t opcode; uint32_t tid; uint64_t uid; + uint32_t flags; opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE); req->chain_offset = IVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND); req->seqnum = BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID); tid = IVAL(req->in.hdr, SMB2_HDR_TID); uid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID); + flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS); req->session = smbsrv_session_find(req->smb_conn, uid, req->request_time); req->tcon = smbsrv_smb2_tcon_find(req->session, tid, req->request_time); errno = 0; + /* supporting signing is mandatory in SMB2, and is per-packet. So we + should check the signature on any incoming packet that is signed, and + should give a signed reply to any signed request */ + if (flags & SMB2_HDR_FLAG_SIGNED) { + NTSTATUS status; + if (req->session == NULL) { + /* we can't check signing with no session */ + smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED); + return NT_STATUS_OK; + } + status = smb2_check_signature(&req->in, + req->session->session_info->session_key); + if (!NT_STATUS_IS_OK(status)) { + smb2srv_send_error(req, status); + return NT_STATUS_OK; + } + } else if (req->smb_conn->doing_signing && req->session != NULL) { + /* we require signing and this request was not signed */ + smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED); + return NT_STATUS_OK; + } + /* TODO: check the seqnum */ switch (opcode) { diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c index d386bfc72d..9fb3220005 100644 --- a/source4/smb_server/smb2/sesssetup.c +++ b/source4/smb_server/smb2/sesssetup.c @@ -177,6 +177,14 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses gensec_update_send(smb_sess->gensec_ctx, io->smb2.in.secblob, smb2srv_sesssetup_callback, callback_ctx); + + /* note that we ignore SMB2_NEGOTIATE_SIGNING_ENABLED from the client. + This is deliberate as windows does not set it even when it does + set SMB2_NEGOTIATE_SIGNING_REQUIRED */ + if (io->smb2.in.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) { + req->smb_conn->doing_signing = true; + } + return; nomem: status = NT_STATUS_NO_MEMORY; diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index 776fe1b71b..ac3e0f3bd3 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -376,6 +376,8 @@ struct smbsrv_connection { struct share_context *share_context; struct loadparm_context *lp_ctx; + + bool doing_signing; }; struct model_ops; diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index 60243a5d1b..15cf321965 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -1459,7 +1459,9 @@ again: } while(0) #define CHECK_BLOB_EQUAL(field) do { \ - if (memcmp(parm[0].field.data, parm[1].field.data, parm[0].field.length) != 0 && !ignore_pattern(#field)) { \ + if (((parm[0].field.data == NULL && parm[1].field.data != NULL) || \ + (parm[1].field.data == NULL && parm[0].field.data != NULL) || \ + (memcmp(parm[0].field.data, parm[1].field.data, parm[0].field.length) != 0)) && !ignore_pattern(#field)) { \ current_op.mismatch = #field; \ printf("Mismatch in %s\n", #field); \ return false; \ |