summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2008-06-10 13:19:56 +1000
committerAndrew Bartlett <abartlet@samba.org>2008-06-10 13:19:56 +1000
commit7721ea8f9c75d304111935048167dd27525cc91a (patch)
treefdc6563d085003cf6fe003748fb85291166a5454
parent7974ccbebf5c684200850a726d79b976eaeea261 (diff)
parent1384f836b601d35f3c499a9e26c3e3b0d12b3ad0 (diff)
downloadsamba-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)
-rw-r--r--source4/build/m4/check_cc.m46
-rw-r--r--source4/configure.ac5
-rw-r--r--source4/heimdal_build/internal.m4 (renamed from source4/heimdal_build/config.m4)0
-rw-r--r--source4/heimdal_build/internal.mk (renamed from source4/heimdal_build/config.mk)0
-rw-r--r--source4/lib/replace/libreplace.m43
-rw-r--r--source4/lib/replace/win32.m48
-rw-r--r--source4/lib/tdb/tdb.i4
-rw-r--r--source4/lib/tdb/tdb.py14
-rw-r--r--source4/lib/tdb/tdb_wrap.c10
-rw-r--r--source4/lib/tls/config.m461
-rw-r--r--source4/libcli/raw/raweas.c2
-rw-r--r--source4/libcli/smb2/session.c10
-rw-r--r--source4/libcli/smb2/signing.c74
-rw-r--r--source4/libcli/smb2/smb2.h2
-rw-r--r--source4/libcli/smb2/tcon.c1
-rw-r--r--source4/libcli/smb2/transport.c32
-rw-r--r--source4/librpc/rpc/dcerpc_smb2.c2
-rw-r--r--source4/main.mk2
-rw-r--r--source4/smb_server/smb2/negprot.c15
-rw-r--r--source4/smb_server/smb2/receive.c40
-rw-r--r--source4/smb_server/smb2/sesssetup.c8
-rw-r--r--source4/smb_server/smb_server.h2
-rw-r--r--source4/torture/gentest.c4
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; \