diff options
author | Karolin Seeger <kseeger@samba.org> | 2015-12-16 12:31:26 +0100 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2015-12-16 12:31:26 +0100 |
commit | f51d78c717334f5e802c04f51a89171fac150fc6 (patch) | |
tree | dbad002485a2c68b0bcb5932ccc21ce237210df8 | |
parent | b8077d861f4fd04f1d5c4187b8bf0166e2d8ae29 (diff) | |
parent | add4fe9079dda8fb0bfd9763da85d65ed0063523 (diff) | |
download | samba-f51d78c717334f5e802c04f51a89171fac150fc6.tar.gz |
Merge tag 'samba-4.2.7' into v4-2-test
samba: tag release samba-4.2.7
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | WHATSNEW.txt | 151 | ||||
-rw-r--r-- | lib/ldb/common/ldb_dn.c | 67 | ||||
-rw-r--r-- | lib/ldb/common/ldb_match.c | 33 | ||||
-rwxr-xr-x | lib/ldb/wscript | 5 | ||||
-rw-r--r-- | lib/util/charset/charset.h | 9 | ||||
-rw-r--r-- | lib/util/charset/codepoints.c | 29 | ||||
-rw-r--r-- | lib/util/charset/util_str.c | 3 | ||||
-rw-r--r-- | lib/util/charset/util_unistr.c | 6 | ||||
-rw-r--r-- | libcli/smb/smbXcli_base.c | 11 | ||||
-rwxr-xr-x | script/autobuild.py | 2 | ||||
-rw-r--r-- | source3/libsmb/clidfs.c | 7 | ||||
-rw-r--r-- | source3/libsmb/libsmb_server.c | 15 | ||||
-rw-r--r-- | source3/modules/vfs_shadow_copy2.c | 45 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 13 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/samldb.c | 24 |
16 files changed, 351 insertions, 71 deletions
@@ -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; |