# 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>
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
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])
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)
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)])
#######################################
# 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
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
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"
%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.";
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):
"""
"""
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
"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"
"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"
###############################
# 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
###############################
uint8_t nlen;
uint16_t vlen;
+ ZERO_STRUCTP(ea);
+
if (blob->length < 6) {
return 0;
}
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;
}
}
}
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);
#include "libcli/smb2/smb2_calls.h"
#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 */
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;
}
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);
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;
struct smb2_signing_context {
bool doing_signing;
bool signing_started;
- DATA_BLOB session_key;
};
/*
struct smb2_transport *transport;
struct gensec_security *gensec;
uint64_t uid;
+ DATA_BLOB session_key;
};
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);
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);
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;
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);
{
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;
}
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
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,
#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 */
_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)) {
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) {
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;
struct share_context *share_context;
struct loadparm_context *lp_ctx;
+
+ bool doing_signing;
};
struct model_ops;
} 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; \