summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarolin Seeger <kseeger@samba.org>2015-12-16 12:31:26 +0100
committerKarolin Seeger <kseeger@samba.org>2015-12-16 12:31:26 +0100
commitf51d78c717334f5e802c04f51a89171fac150fc6 (patch)
treedbad002485a2c68b0bcb5932ccc21ce237210df8
parentb8077d861f4fd04f1d5c4187b8bf0166e2d8ae29 (diff)
parentadd4fe9079dda8fb0bfd9763da85d65ed0063523 (diff)
downloadsamba-f51d78c717334f5e802c04f51a89171fac150fc6.tar.gz
Merge tag 'samba-4.2.7' into v4-2-test
samba: tag release samba-4.2.7
-rw-r--r--VERSION2
-rw-r--r--WHATSNEW.txt151
-rw-r--r--lib/ldb/common/ldb_dn.c67
-rw-r--r--lib/ldb/common/ldb_match.c33
-rwxr-xr-xlib/ldb/wscript5
-rw-r--r--lib/util/charset/charset.h9
-rw-r--r--lib/util/charset/codepoints.c29
-rw-r--r--lib/util/charset/util_str.c3
-rw-r--r--lib/util/charset/util_unistr.c6
-rw-r--r--libcli/smb/smbXcli_base.c11
-rwxr-xr-xscript/autobuild.py2
-rw-r--r--source3/libsmb/clidfs.c7
-rw-r--r--source3/libsmb/libsmb_server.c15
-rw-r--r--source3/modules/vfs_shadow_copy2.c45
-rw-r--r--source3/smbd/vfs.c13
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c24
16 files changed, 351 insertions, 71 deletions
diff --git a/VERSION b/VERSION
index 91950020fa0..ee428293f6a 100644
--- a/VERSION
+++ b/VERSION
@@ -99,7 +99,7 @@ SAMBA_VERSION_RC_RELEASE=
# e.g. SAMBA_VERSION_IS_SVN_SNAPSHOT=yes #
# -> "3.0.0-SVN-build-199" #
########################################################
-SAMBA_VERSION_IS_GIT_SNAPSHOT=yes
+SAMBA_VERSION_IS_GIT_SNAPSHOT=no
########################################################
# This is for specifying a release nickname #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index a13c8372836..055f03f9345 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,4 +1,151 @@
=============================
+ Release Notes for Samba 4.2.7
+ December 16, 2015
+ =============================
+
+
+This is a security release in order to address the following CVEs:
+
+o CVE-2015-3223 (Denial of service in Samba Active Directory
+ server)
+o CVE-2015-5252 (Insufficient symlink verification in smbd)
+o CVE-2015-5299 (Missing access control check in shadow copy
+ code)
+o CVE-2015-5296 (Samba client requesting encryption vulnerable
+ to downgrade attack)
+o CVE-2015-8467 (Denial of service attack against Windows
+ Active Directory server)
+o CVE-2015-5330 (Remote memory read in Samba LDAP server)
+
+Please note that if building against a system libldb, the required
+version has been bumped to ldb-1.1.24. This is needed to ensure
+we build against a system ldb library that contains the fixes
+for CVE-2015-5330 and CVE-2015-3223.
+
+=======
+Details
+=======
+
+o CVE-2015-3223:
+ All versions of Samba from 4.0.0 to 4.3.2 inclusive (resp. all
+ ldb versions up to 1.1.23 inclusive) are vulnerable to
+ a denial of service attack in the samba daemon LDAP server.
+
+ A malicious client can send packets that cause the LDAP server in the
+ samba daemon process to become unresponsive, preventing the server
+ from servicing any other requests.
+
+ This flaw is not exploitable beyond causing the code to loop expending
+ CPU resources.
+
+o CVE-2015-5252:
+ All versions of Samba from 3.0.0 to 4.3.2 inclusive are vulnerable to
+ a bug in symlink verification, which under certain circumstances could
+ allow client access to files outside the exported share path.
+
+ If a Samba share is configured with a path that shares a common path
+ prefix with another directory on the file system, the smbd daemon may
+ allow the client to follow a symlink pointing to a file or directory
+ in that other directory, even if the share parameter "wide links" is
+ set to "no" (the default).
+
+o CVE-2015-5299:
+ All versions of Samba from 3.2.0 to 4.3.2 inclusive are vulnerable to
+ a missing access control check in the vfs_shadow_copy2 module. When
+ looking for the shadow copy directory under the share path the current
+ accessing user should have DIRECTORY_LIST access rights in order to
+ view the current snapshots.
+
+ This was not being checked in the affected versions of Samba.
+
+o CVE-2015-5296:
+ Versions of Samba from 3.2.0 to 4.3.2 inclusive do not ensure that
+ signing is negotiated when creating an encrypted client connection to
+ a server.
+
+ Without this a man-in-the-middle attack could downgrade the connection
+ and connect using the supplied credentials as an unsigned, unencrypted
+ connection.
+
+o CVE-2015-8467:
+ Samba, operating as an AD DC, is sometimes operated in a domain with a
+ mix of Samba and Windows Active Directory Domain Controllers.
+
+ All versions of Samba from 4.0.0 to 4.3.2 inclusive, when deployed as
+ an AD DC in the same domain with Windows DCs, could be used to
+ override the protection against the MS15-096 / CVE-2015-2535 security
+ issue in Windows.
+
+ Prior to MS16-096 it was possible to bypass the quota of machine
+ accounts a non-administrative user could create. Pure Samba domains
+ are not impacted, as Samba does not implement the
+ SeMachineAccountPrivilege functionality to allow non-administrator
+ users to create new computer objects.
+
+o CVE-2015-5330:
+ All versions of Samba from 4.0.0 to 4.3.2 inclusive (resp. all
+ ldb versions up to 1.1.23 inclusive) are vulnerable to
+ a remote memory read attack in the samba daemon LDAP server.
+
+ A malicious client can send packets that cause the LDAP server in the
+ samba daemon process to return heap memory beyond the length of the
+ requested value.
+
+ This memory may contain data that the client should not be allowed to
+ see, allowing compromise of the server.
+
+ The memory may either be returned to the client in an error string, or
+ stored in the database by a suitabily privileged user. If untrusted
+ users can create objects in your database, please confirm that all DN
+ and name attributes are reasonable.
+
+
+Changes since 4.2.6:
+--------------------
+
+o Andrew Bartlett <abartlet@samba.org>
+ * BUG 11552: CVE-2015-8467: samdb: Match MS15-096 behaviour for
+ userAccountControl.
+
+o Jeremy Allison <jra@samba.org>
+ * BUG 11325: CVE-2015-3223: Fix LDAP \00 search expression attack DoS.
+ * BUG 11395: CVE-2015-5252: Fix insufficient symlink verification (file
+ access outside the share).
+ * BUG 11529: CVE-2015-5299: s3-shadow-copy2: Fix missing access check on
+ snapdir.
+
+o Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
+ * BUG 11599: CVE-2015-5330: Fix remote read memory exploit in LDB.
+
+o Stefan Metzmacher <metze@samba.org>
+ * BUG 11536: CVE-2015-5296: Add man in the middle protection when forcing
+ smb encryption on the client side.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored. All bug reports should
+be filed under the "Samba 4.1 and newer" product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Release notes for older releases follow:
+----------------------------------------
+
+ =============================
Release Notes for Samba 4.2.6
December 08, 2015
=============================
@@ -80,10 +227,8 @@ database (https://bugzilla.samba.org/).
======================================================================
-Release notes for older releases follow:
-----------------------------------------
+----------------------------------------------------------------------
-======================================================================
=============================
Release Notes for Samba 4.2.5
diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c
index 6b6f90c13ea..cd17cda3aad 100644
--- a/lib/ldb/common/ldb_dn.c
+++ b/lib/ldb/common/ldb_dn.c
@@ -189,33 +189,23 @@ struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx,
/* see RFC2253 section 2.4 */
static int ldb_dn_escape_internal(char *dst, const char *src, int len)
{
- const char *p, *s;
+ char c;
char *d;
- size_t l;
-
- p = s = src;
+ int i;
d = dst;
- while (p - src < len) {
- p += strcspn(p, ",=\n\r+<>#;\\\" ");
-
- if (p - src == len) /* found no escapable chars */
- break;
-
- /* copy the part of the string before the stop */
- memcpy(d, s, p - s);
- d += (p - s); /* move to current position */
-
- switch (*p) {
+ for (i = 0; i < len; i++){
+ c = src[i];
+ switch (c) {
case ' ':
- if (p == src || (p-src)==(len-1)) {
+ if (i == 0 || i == len - 1) {
/* if at the beginning or end
* of the string then escape */
*d++ = '\\';
- *d++ = *p++;
+ *d++ = c;
} else {
/* otherwise don't escape */
- *d++ = *p++;
+ *d++ = c;
}
break;
@@ -231,36 +221,36 @@ static int ldb_dn_escape_internal(char *dst, const char *src, int len)
case '?':
/* these must be escaped using \c form */
*d++ = '\\';
- *d++ = *p++;
+ *d++ = c;
break;
- default: {
+ case ';':
+ case '\r':
+ case '\n':
+ case '=':
+ case '\0': {
/* any others get \XX form */
unsigned char v;
const char *hexbytes = "0123456789ABCDEF";
- v = *(const unsigned char *)p;
+ v = (const unsigned char)c;
*d++ = '\\';
*d++ = hexbytes[v>>4];
*d++ = hexbytes[v&0xF];
- p++;
break;
}
+ default:
+ *d++ = c;
}
- s = p; /* move forward */
}
- /* copy the last part (with zero) and return */
- l = len - (s - src);
- memcpy(d, s, l + 1);
-
/* return the length of the resulting string */
- return (l + (d - dst));
+ return (d - dst);
}
char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value)
{
char *dst;
-
+ size_t len;
if (!value.length)
return NULL;
@@ -271,10 +261,14 @@ char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value)
return NULL;
}
- ldb_dn_escape_internal(dst, (const char *)value.data, value.length);
-
- dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1);
+ len = ldb_dn_escape_internal(dst, (const char *)value.data, value.length);
+ dst = talloc_realloc(mem_ctx, dst, char, len + 1);
+ if ( ! dst) {
+ talloc_free(dst);
+ return NULL;
+ }
+ dst[len] = '\0';
return dst;
}
@@ -592,12 +586,15 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
p++;
*d++ = '\0';
- dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
+ dn->components[dn->comp_num].value.data = \
+ (uint8_t *)talloc_memdup(dn->components, dt, l + 1);
dn->components[dn->comp_num].value.length = l;
if ( ! dn->components[dn->comp_num].value.data) {
/* ouch ! */
goto failed;
}
+ talloc_set_name_const(dn->components[dn->comp_num].value.data,
+ (const char *)dn->components[dn->comp_num].value.data);
dt = d;
@@ -713,11 +710,13 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
*d++ = '\0';
dn->components[dn->comp_num].value.length = l;
dn->components[dn->comp_num].value.data =
- (uint8_t *)talloc_strdup(dn->components, dt);
+ (uint8_t *)talloc_memdup(dn->components, dt, l + 1);
if ( ! dn->components[dn->comp_num].value.data) {
/* ouch */
goto failed;
}
+ talloc_set_name_const(dn->components[dn->comp_num].value.data,
+ (const char *)dn->components[dn->comp_num].value.data);
dn->comp_num++;
diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c
index a493daec49f..182c6ce5720 100644
--- a/lib/ldb/common/ldb_match.c
+++ b/lib/ldb/common/ldb_match.c
@@ -241,7 +241,6 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
struct ldb_val val;
struct ldb_val cnk;
struct ldb_val *chunk;
- char *p, *g;
uint8_t *save_p = NULL;
unsigned int c = 0;
@@ -271,6 +270,14 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
if (cnk.length > val.length) {
goto mismatch;
}
+ /*
+ * Empty strings are returned as length 0. Ensure
+ * we can cope with this.
+ */
+ if (cnk.length == 0) {
+ goto mismatch;
+ }
+
if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto mismatch;
val.length -= cnk.length;
val.data += cnk.length;
@@ -280,20 +287,36 @@ static int ldb_wildcard_compare(struct ldb_context *ldb,
}
while (tree->u.substring.chunks[c]) {
+ uint8_t *p;
chunk = tree->u.substring.chunks[c];
if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch;
- /* FIXME: case of embedded nulls */
- p = strstr((char *)val.data, (char *)cnk.data);
+ /*
+ * Empty strings are returned as length 0. Ensure
+ * we can cope with this.
+ */
+ if (cnk.length == 0) {
+ goto mismatch;
+ }
+ /*
+ * Values might be binary blobs. Don't use string
+ * search, but memory search instead.
+ */
+ p = memmem((const void *)val.data,val.length,
+ (const void *)cnk.data, cnk.length);
if (p == NULL) goto mismatch;
if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) {
+ uint8_t *g;
do { /* greedy */
- g = strstr((char *)p + cnk.length, (char *)cnk.data);
+ g = memmem(p + cnk.length,
+ val.length - (p - val.data),
+ (const uint8_t *)cnk.data,
+ cnk.length);
if (g) p = g;
} while(g);
}
- val.length = val.length - (p - (char *)(val.data)) - cnk.length;
+ val.length = val.length - (p - (uint8_t *)(val.data)) - cnk.length;
val.data = (uint8_t *)(p + cnk.length);
c++;
talloc_free(cnk.data);
diff --git a/lib/ldb/wscript b/lib/ldb/wscript
index 6391e74a016..18e315b36bf 100755
--- a/lib/ldb/wscript
+++ b/lib/ldb/wscript
@@ -2,6 +2,7 @@
APPNAME = 'ldb'
VERSION = '1.1.20'
+SYSTEM_VERSION = '1.1.24'
blddir = 'bin'
@@ -55,11 +56,11 @@ def configure(conf):
conf.env.standalone_ldb = conf.IN_LAUNCH_DIR()
if not conf.env.standalone_ldb:
- if conf.CHECK_BUNDLED_SYSTEM_PKG('ldb', minversion=VERSION,
+ if conf.CHECK_BUNDLED_SYSTEM_PKG('ldb', minversion=SYSTEM_VERSION,
onlyif='talloc tdb tevent',
implied_deps='replace talloc tdb tevent'):
conf.define('USING_SYSTEM_LDB', 1)
- if conf.CHECK_BUNDLED_SYSTEM_PKG('pyldb-util', minversion=VERSION,
+ if conf.CHECK_BUNDLED_SYSTEM_PKG('pyldb-util', minversion=SYSTEM_VERSION,
onlyif='talloc tdb tevent ldb',
implied_deps='replace talloc tdb tevent ldb'):
conf.define('USING_SYSTEM_PYLDB_UTIL', 1)
diff --git a/lib/util/charset/charset.h b/lib/util/charset/charset.h
index e4297e4f3ce..060f1cf56f7 100644
--- a/lib/util/charset/charset.h
+++ b/lib/util/charset/charset.h
@@ -171,15 +171,16 @@ smb_iconv_t get_conv_handle(struct smb_iconv_handle *ic,
charset_t from, charset_t to);
const char *charset_name(struct smb_iconv_handle *ic, charset_t ch);
-codepoint_t next_codepoint_ext(const char *str, charset_t src_charset,
- size_t *size);
+codepoint_t next_codepoint_ext(const char *str, size_t len,
+ charset_t src_charset, size_t *size);
codepoint_t next_codepoint(const char *str, size_t *size);
ssize_t push_codepoint(char *str, codepoint_t c);
/* codepoints */
codepoint_t next_codepoint_handle_ext(struct smb_iconv_handle *ic,
- const char *str, charset_t src_charset,
- size_t *size);
+ const char *str, size_t len,
+ charset_t src_charset,
+ size_t *size);
codepoint_t next_codepoint_handle(struct smb_iconv_handle *ic,
const char *str, size_t *size);
ssize_t push_codepoint_handle(struct smb_iconv_handle *ic,
diff --git a/lib/util/charset/codepoints.c b/lib/util/charset/codepoints.c
index 0984164d483..19d084f3d4a 100644
--- a/lib/util/charset/codepoints.c
+++ b/lib/util/charset/codepoints.c
@@ -319,7 +319,8 @@ smb_iconv_t get_conv_handle(struct smb_iconv_handle *ic,
*/
_PUBLIC_ codepoint_t next_codepoint_handle_ext(
struct smb_iconv_handle *ic,
- const char *str, charset_t src_charset,
+ const char *str, size_t len,
+ charset_t src_charset,
size_t *bytes_consumed)
{
/* it cannot occupy more than 4 bytes in UTF16 format */
@@ -330,7 +331,10 @@ _PUBLIC_ codepoint_t next_codepoint_handle_ext(
size_t olen;
char *outbuf;
- if ((str[0] & 0x80) == 0) {
+
+ if (((str[0] & 0x80) == 0) && (src_charset == CH_DOS ||
+ src_charset == CH_UNIX ||
+ src_charset == CH_UTF8)) {
*bytes_consumed = 1;
return (codepoint_t)str[0];
}
@@ -339,7 +343,7 @@ _PUBLIC_ codepoint_t next_codepoint_handle_ext(
* we assume that no multi-byte character can take more than 5 bytes.
* This is OK as we only support codepoints up to 1M (U+100000)
*/
- ilen_orig = strnlen(str, 5);
+ ilen_orig = MIN(len, 5);
ilen = ilen_orig;
descriptor = get_conv_handle(ic, src_charset, CH_UTF16);
@@ -395,9 +399,16 @@ _PUBLIC_ codepoint_t next_codepoint_handle_ext(
return INVALID_CODEPOINT if the next character cannot be converted
*/
_PUBLIC_ codepoint_t next_codepoint_handle(struct smb_iconv_handle *ic,
- const char *str, size_t *size)
+ const char *str, size_t *size)
{
- return next_codepoint_handle_ext(ic, str, CH_UNIX, size);
+ /*
+ * We assume that no multi-byte character can take more than 5 bytes
+ * thus avoiding walking all the way down a long string. This is OK as
+ * Unicode codepoints only go up to (U+10ffff), which can always be
+ * encoded in 4 bytes or less.
+ */
+ return next_codepoint_handle_ext(ic, str, strnlen(str, 5), CH_UNIX,
+ size);
}
/*
@@ -459,11 +470,11 @@ _PUBLIC_ ssize_t push_codepoint_handle(struct smb_iconv_handle *ic,
return 5 - olen;
}
-_PUBLIC_ codepoint_t next_codepoint_ext(const char *str, charset_t src_charset,
- size_t *size)
+_PUBLIC_ codepoint_t next_codepoint_ext(const char *str, size_t len,
+ charset_t src_charset, size_t *size)
{
- return next_codepoint_handle_ext(get_iconv_handle(), str,
- src_charset, size);
+ return next_codepoint_handle_ext(get_iconv_handle(), str, len,
+ src_charset, size);
}
_PUBLIC_ codepoint_t next_codepoint(const char *str, size_t *size)
diff --git a/lib/util/charset/util_str.c b/lib/util/charset/util_str.c
index d2e6cbbc620..2653bfc2d81 100644
--- a/lib/util/charset/util_str.c
+++ b/lib/util/charset/util_str.c
@@ -210,7 +210,8 @@ _PUBLIC_ size_t strlen_m_ext_handle(struct smb_iconv_handle *ic,
while (*s) {
size_t c_size;
- codepoint_t c = next_codepoint_handle_ext(ic, s, src_charset, &c_size);
+ codepoint_t c = next_codepoint_handle_ext(ic, s, strnlen(s, 5),
+ src_charset, &c_size);
s += c_size;
switch (dst_charset) {
diff --git a/lib/util/charset/util_unistr.c b/lib/util/charset/util_unistr.c
index e4ae65053c7..2cc87186dae 100644
--- a/lib/util/charset/util_unistr.c
+++ b/lib/util/charset/util_unistr.c
@@ -110,10 +110,12 @@ _PUBLIC_ char *strupper_talloc_n_handle(struct smb_iconv_handle *iconv_handle,
return NULL;
}
- while (n-- && *src) {
+ while (n && *src) {
size_t c_size;
- codepoint_t c = next_codepoint_handle(iconv_handle, src, &c_size);
+ codepoint_t c = next_codepoint_handle_ext(iconv_handle, src, n,
+ CH_UNIX, &c_size);
src += c_size;
+ n -= c_size;
c = toupper_m(c);
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 69599bd0443..b00afbc2d5a 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -5085,6 +5085,9 @@ uint8_t smb2cli_session_security_mode(struct smbXcli_session *session)
if (conn->mandatory_signing) {
security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
}
+ if (session->smb2->should_sign) {
+ security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
+ }
return security_mode;
}
@@ -5383,6 +5386,14 @@ NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session,
NTSTATUS smb2cli_session_encryption_on(struct smbXcli_session *session)
{
+ if (!session->smb2->should_sign) {
+ /*
+ * We need required signing on the session
+ * in order to prevent man in the middle attacks.
+ */
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ }
+
if (session->smb2->should_encrypt) {
return NT_STATUS_OK;
}
diff --git a/script/autobuild.py b/script/autobuild.py
index 2b25a105755..9433a0d60f5 100755
--- a/script/autobuild.py
+++ b/script/autobuild.py
@@ -93,7 +93,7 @@ tasks = {
("ldb-make", "cd lib/ldb && make", "text/plain"),
("ldb-install", "cd lib/ldb && make install", "text/plain"),
- ("configure", "PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=!talloc,!tdb,!pytdb,!ntdb,!pyntdb,!ldb,!pyldb,!tevent,!pytevent --abi-check --enable-debug -C ${PREFIX}", "text/plain"),
+ ("configure", "PYTHONPATH=${PYTHON_PREFIX}/site-packages:$PYTHONPATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig ./configure --bundled-libraries=!talloc,!tdb,!pytdb,!ntdb,!pyntdb,!ldb,!pyldb,!tevent,!pytevent --minimum-library-version=ldb:1.1.20,pyldb-util:1.1.20 --abi-check --enable-debug -C ${PREFIX}", "text/plain"),
("make", "make", "text/plain"),
("install", "make install", "text/plain"),
("dist", "make dist", "text/plain")],
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index b8233702ab3..5dfddeee739 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -114,6 +114,11 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx,
const char *domain;
NTSTATUS status;
int flags = 0;
+ int signing_state = get_cmdline_auth_info_signing_state(auth_info);
+
+ if (force_encrypt) {
+ signing_state = SMB_SIGNING_REQUIRED;
+ }
/* make a copy so we don't modify the global string 'service' */
servicename = talloc_strdup(ctx,share);
@@ -152,7 +157,7 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx,
status = cli_connect_nb(
server, NULL, port, name_type, NULL,
- get_cmdline_auth_info_signing_state(auth_info),
+ signing_state,
flags, &c);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index 5410099face..0a58d8cc9fa 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -273,6 +273,7 @@ SMBC_server_internal(TALLOC_CTX *ctx,
char *newserver, *newshare;
int flags = 0;
struct smbXcli_tcon *tcon = NULL;
+ int signing_state = SMB_SIGNING_DEFAULT;
ZERO_STRUCT(c);
*in_cache = false;
@@ -439,6 +440,10 @@ SMBC_server_internal(TALLOC_CTX *ctx,
flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
}
+ if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
+ signing_state = SMB_SIGNING_REQUIRED;
+ }
+
if (port == 0) {
if (share == NULL || *share == '\0' || is_ipc) {
/*
@@ -446,7 +451,7 @@ SMBC_server_internal(TALLOC_CTX *ctx,
*/
status = cli_connect_nb(server_n, NULL, NBT_SMB_PORT, 0x20,
smbc_getNetbiosName(context),
- SMB_SIGNING_DEFAULT, flags, &c);
+ signing_state, flags, &c);
}
}
@@ -456,7 +461,7 @@ SMBC_server_internal(TALLOC_CTX *ctx,
*/
status = cli_connect_nb(server_n, NULL, port, 0x20,
smbc_getNetbiosName(context),
- SMB_SIGNING_DEFAULT, flags, &c);
+ signing_state, flags, &c);
}
if (!NT_STATUS_IS_OK(status)) {
@@ -745,6 +750,7 @@ SMBC_attr_server(TALLOC_CTX *ctx,
ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$",
pp_workgroup, pp_username, pp_password);
if (!ipc_srv) {
+ int signing_state = SMB_SIGNING_DEFAULT;
/* We didn't find a cached connection. Get the password */
if (!*pp_password || (*pp_password)[0] == '\0') {
@@ -766,6 +772,9 @@ SMBC_attr_server(TALLOC_CTX *ctx,
if (smbc_getOptionUseCCache(context)) {
flags |= CLI_FULL_CONNECTION_USE_CCACHE;
}
+ if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
+ signing_state = SMB_SIGNING_REQUIRED;
+ }
nt_status = cli_full_connection(&ipc_cli,
lp_netbios_name(), server,
@@ -774,7 +783,7 @@ SMBC_attr_server(TALLOC_CTX *ctx,
*pp_workgroup,
*pp_password,
flags,
- SMB_SIGNING_DEFAULT);
+ signing_state);
if (! NT_STATUS_IS_OK(nt_status)) {
DEBUG(1,("cli_full_connection failed! (%s)\n",
nt_errstr(nt_status)));
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index 439df5ddf4d..c5c2015795e 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -30,6 +30,7 @@
*/
#include "includes.h"
+#include "smbd/smbd.h"
#include "system/filesys.h"
#include "include/ntioctl.h"
#include <ccan/hash/hash.h>
@@ -1179,6 +1180,42 @@ static char *have_snapdir(struct vfs_handle_struct *handle,
return NULL;
}
+static bool check_access_snapdir(struct vfs_handle_struct *handle,
+ const char *path)
+{
+ struct smb_filename smb_fname;
+ int ret;
+ NTSTATUS status;
+
+ ZERO_STRUCT(smb_fname);
+ smb_fname.base_name = talloc_asprintf(talloc_tos(),
+ "%s",
+ path);
+ if (smb_fname.base_name == NULL) {
+ return false;
+ }
+
+ ret = SMB_VFS_NEXT_STAT(handle, &smb_fname);
+ if (ret != 0 || !S_ISDIR(smb_fname.st.st_ex_mode)) {
+ TALLOC_FREE(smb_fname.base_name);
+ return false;
+ }
+
+ status = smbd_check_access_rights(handle->conn,
+ &smb_fname,
+ false,
+ SEC_DIR_LIST);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("user does not have list permission "
+ "on snapdir %s\n",
+ smb_fname.base_name));
+ TALLOC_FREE(smb_fname.base_name);
+ return false;
+ }
+ TALLOC_FREE(smb_fname.base_name);
+ return true;
+}
+
/**
* Find the snapshot directory (if any) for the given
* filename (which is relative to the share).
@@ -1328,6 +1365,7 @@ static int shadow_copy2_get_shadow_copy_data(
const char *snapdir;
struct dirent *d;
TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ bool ret;
snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle, fsp->fsp_name);
if (snapdir == NULL) {
@@ -1337,6 +1375,13 @@ static int shadow_copy2_get_shadow_copy_data(
talloc_free(tmp_ctx);
return -1;
}
+ ret = check_access_snapdir(handle, snapdir);
+ if (!ret) {
+ DEBUG(0,("access denied on listing snapdir %s\n", snapdir));
+ errno = EACCES;
+ talloc_free(tmp_ctx);
+ return -1;
+ }
p = SMB_VFS_NEXT_OPENDIR(handle, snapdir, NULL, 0);
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 12813225cb7..7138759bf09 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -996,6 +996,7 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
struct smb_filename *smb_fname_cwd = NULL;
struct privilege_paths *priv_paths = NULL;
int ret;
+ bool matched;
DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
fname,
@@ -1090,7 +1091,10 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
}
rootdir_len = strlen(conn_rootdir);
- if (strncmp(conn_rootdir, resolved_name, rootdir_len) != 0) {
+ matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0);
+
+ if (!matched || (resolved_name[rootdir_len] != '/' &&
+ resolved_name[rootdir_len] != '\0')) {
DEBUG(2, ("check_reduced_name_with_privilege: Bad access "
"attempt: %s is a symlink outside the "
"share path\n",
@@ -1230,6 +1234,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
if (!allow_widelinks || !allow_symlinks) {
const char *conn_rootdir;
size_t rootdir_len;
+ bool matched;
conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
if (conn_rootdir == NULL) {
@@ -1240,8 +1245,10 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
}
rootdir_len = strlen(conn_rootdir);
- if (strncmp(conn_rootdir, resolved_name,
- rootdir_len) != 0) {
+ matched = (strncmp(conn_rootdir, resolved_name,
+ rootdir_len) == 0);
+ if (!matched || (resolved_name[rootdir_len] != '/' &&
+ resolved_name[rootdir_len] != '\0')) {
DEBUG(2, ("check_reduced_name: Bad access "
"attempt: %s is a symlink outside the "
"share path\n", fname));
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 54e2e5e6299..5537fdf56ae 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -1468,12 +1468,15 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
struct security_token *user_token;
struct security_descriptor *domain_sd;
struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module));
+ struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
const struct uac_to_guid {
uint32_t uac;
+ uint32_t priv_to_change_from;
const char *oid;
const char *guid;
enum sec_privilege privilege;
bool delete_is_privileged;
+ bool admin_required;
const char *error_string;
} map[] = {
{
@@ -1502,6 +1505,16 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
.error_string = "Adding the UF_PARTIAL_SECRETS_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object"
},
{
+ .uac = UF_WORKSTATION_TRUST_ACCOUNT,
+ .priv_to_change_from = UF_NORMAL_ACCOUNT,
+ .error_string = "Swapping UF_NORMAL_ACCOUNT to UF_WORKSTATION_TRUST_ACCOUNT requires the user to be a member of the domain admins group"
+ },
+ {
+ .uac = UF_NORMAL_ACCOUNT,
+ .priv_to_change_from = UF_WORKSTATION_TRUST_ACCOUNT,
+ .error_string = "Swapping UF_WORKSTATION_TRUST_ACCOUNT to UF_NORMAL_ACCOUNT requires the user to be a member of the domain admins group"
+ },
+ {
.uac = UF_INTERDOMAIN_TRUST_ACCOUNT,
.oid = DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
.error_string = "Updating the UF_INTERDOMAIN_TRUST_ACCOUNT bit in userAccountControl is not permitted over LDAP. This bit is restricted to the LSA CreateTrustedDomain interface",
@@ -1553,7 +1566,7 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
return ldb_module_operr(ac->module);
}
- ret = dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(ac->module),
+ ret = dsdb_get_sd_from_ldb_message(ldb,
ac, res->msgs[0], &domain_sd);
if (ret != LDB_SUCCESS) {
@@ -1580,12 +1593,19 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
if (have_priv == false) {
ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
}
- } else {
+ } else if (map[i].priv_to_change_from & user_account_control_old) {
+ bool is_admin = security_token_has_builtin_administrators(user_token);
+ if (is_admin == false) {
+ ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
+ }
+ } else if (map[i].guid) {
ret = acl_check_extended_right(ac, domain_sd,
user_token,
map[i].guid,
SEC_ADS_CONTROL_ACCESS,
sid);
+ } else {
+ ret = LDB_SUCCESS;
}
if (ret != LDB_SUCCESS) {
break;