[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Wed Dec 16 15:04:04 UTC 2015


The branch, master has been updated
       via  1595f56 CVE-2015-8467: samdb: Match MS15-096 behaviour for userAccountControl
       via  bc2d859 CVE-2015-5296: libcli/smb: make sure we require signing when we demand encryption on a session
       via  aef4113 CVE-2015-5296: s3:libsmb: force signing when requiring encryption in SMBC_server_internal()
       via  f8b0f7f CVE-2015-5296: s3:libsmb: force signing when requiring encryption in do_connect()
       via  acbb4dd CVE-2015-5299: s3-shadow-copy2: fix missing access check on snapdir
       via  cc137fa CVE-2015-5252: s3: smbd: Fix symlink verification (file access outside the share).
       via  7606c0d CVE-2015-5252: s3: smbd: Fix symlink verification (file access outside the share).
      from  067640b Merge tag 'ldb-1.1.24' into master

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 1595f56634a8950c4493799b30c2dbe254466751
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Nov 18 17:36:21 2015 +1300

    CVE-2015-8467: samdb: Match MS15-096 behaviour for userAccountControl
    
    Swapping between account types is now restricted
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=11552
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Wed Dec 16 16:03:18 CET 2015 on sn-devel-104

commit bc2d8592f4e22dd91790bcd78e7a1a99b8a83de5
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Sep 30 21:23:25 2015 +0200

    CVE-2015-5296: libcli/smb: make sure we require signing when we demand encryption on a session
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11536
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit aef4113823a48cffc429ed6b7eb2c01e80fd639a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Sep 30 21:17:02 2015 +0200

    CVE-2015-5296: s3:libsmb: force signing when requiring encryption in SMBC_server_internal()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11536
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit f8b0f7fd94cf3c7630a108b80ea745d3e4e947be
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Sep 30 21:17:02 2015 +0200

    CVE-2015-5296: s3:libsmb: force signing when requiring encryption in do_connect()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11536
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit acbb4ddb6876c15543c5370e6d27faacebc8a231
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Oct 23 14:54:31 2015 -0700

    CVE-2015-5299: s3-shadow-copy2: fix missing access check on snapdir
    
    Fix originally from <partha at exablox.com>
    
    https://bugzilla.samba.org/show_bug.cgi?id=11529
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: David Disseldorp <ddiss at samba.org>

commit cc137fa3868c9f84519a9c3aa047aefacc0c4878
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jul 9 13:57:58 2015 -0700

    CVE-2015-5252: s3: smbd: Fix symlink verification (file access outside the share).
    
    New tests for fix.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11395
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

commit 7606c0db257b3f9d84da5b2bf5fbb4034cc8d77d
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jul 9 10:58:11 2015 -0700

    CVE-2015-5252: s3: smbd: Fix symlink verification (file access outside the share).
    
    Ensure matching component ends in '/' or '\0'.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=11395
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Volker Lendecke <vl at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 libcli/smb/smbXcli_base.c                         | 11 ++++
 selftest/target/Samba3.pm                         | 30 +++++++++++
 source3/libsmb/clidfs.c                           |  7 ++-
 source3/libsmb/libsmb_server.c                    | 15 ++++--
 source3/modules/vfs_shadow_copy2.c                | 45 ++++++++++++++++
 source3/script/tests/test_smbclient_s3.sh         | 60 +++++++++++++++++++++
 source3/smbd/vfs.c                                | 13 +++--
 source4/dsdb/samdb/ldb_modules/samldb.c           | 24 ++++++++-
 source4/dsdb/tests/python/user_account_control.py | 63 +++++++++++++++++++----
 9 files changed, 250 insertions(+), 18 deletions(-)


Changeset truncated at 500 lines:

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 1f1b6cd..5fc380e 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -5445,6 +5445,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;
 }
@@ -5876,6 +5879,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/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 94612b2..c9e57ad 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1118,6 +1118,12 @@ sub provision($$$$$$$$)
 	my $manglenames_shrdir="$shrdir/manglenames";
 	push(@dirs,$manglenames_shrdir);
 
+	my $widelinks_shrdir="$shrdir/widelinks";
+	push(@dirs,$widelinks_shrdir);
+
+	my $widelinks_linkdir="$shrdir/widelinks_foo";
+	push(@dirs,$widelinks_linkdir);
+
 	# this gets autocreated by winbindd
 	my $wbsockdir="$prefix_abs/winbindd";
 	my $wbsockprivdir="$lockdir/winbindd_privileged";
@@ -1207,6 +1213,25 @@ sub provision($$$$$$$$)
         my $manglename_target = "$manglenames_shrdir/foo:bar";
 	mkdir($manglename_target, 0777);
 
+	##
+	## create symlinks for widelinks tests.
+	##
+	my $widelinks_target = "$widelinks_linkdir/target";
+	unless (open(WIDELINKS_TARGET, ">$widelinks_target")) {
+		warn("Unable to open $widelinks_target");
+		return undef;
+	}
+	close(WIDELINKS_TARGET);
+	chmod 0666, $widelinks_target;
+	##
+	## This link should get ACCESS_DENIED
+	##
+	symlink "$widelinks_target", "$widelinks_shrdir/source";
+	##
+	## This link should be allowed
+	##
+	symlink "$widelinks_shrdir", "$widelinks_shrdir/dot";
+
 	my $conffile="$libdir/server.conf";
 
 	my $nss_wrapper_pl = "$ENV{PERL} $self->{srcdir}/lib/nss_wrapper/nss_wrapper.pl";
@@ -1512,6 +1537,11 @@ sub provision($$$$$$$$)
 	path = $shrdir/%R
 	guest ok = yes
 
+[widelinks_share]
+	path = $widelinks_shrdir
+	wide links = no
+	guest ok = yes
+
 [fsrvp_share]
 	path = $shrdir
 	comment = fake shapshots using rsync
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index 2121ad0..d3b0580 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 07d51ea..2abd37e 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)) {
@@ -737,6 +742,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') {
@@ -758,6 +764,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,
@@ -766,7 +775,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 4d2ec54..d1673a4 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 "util_tdb.h"
@@ -1180,6 +1181,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).
@@ -1329,6 +1366,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) {
@@ -1338,6 +1376,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/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh
index c073b43..5e3db5d 100755
--- a/source3/script/tests/test_smbclient_s3.sh
+++ b/source3/script/tests/test_smbclient_s3.sh
@@ -1003,6 +1003,62 @@ EOF
     fi
 }
 
+# Test wide links are restricted.
+test_widelinks()
+{
+    tmpfile=$PREFIX/smbclient_interactive_prompt_commands
+    cat > $tmpfile <<EOF
+cd dot
+ls
+quit
+EOF
+    cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/widelinks_share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
+    eval echo "$cmd"
+    out=`eval $cmd`
+    ret=$?
+    rm -f $tmpfile
+
+    if [ $ret != 0 ] ; then
+	echo "$out"
+	echo "failed accessing widelinks_share with error $ret"
+	false
+	return
+    fi
+
+    echo "$out" | grep 'NT_STATUS'
+    ret=$?
+    if [ $ret == 0 ] ; then
+	echo "$out"
+	echo "failed - NT_STATUS_XXXX listing \\widelinks_share\\dot"
+	false
+    fi
+
+    cat > $tmpfile <<EOF
+allinfo source
+quit
+EOF
+    cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/widelinks_share -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
+    eval echo "$cmd"
+    out=`eval $cmd`
+    ret=$?
+    rm -f $tmpfile
+
+    if [ $ret != 0 ] ; then
+	echo "$out"
+	echo "failed accessing widelinks_share with error $ret"
+	false
+	return
+    fi
+
+# This should fail with NT_STATUS_ACCESS_DENIED
+    echo "$out" | grep 'NT_STATUS_ACCESS_DENIED'
+    ret=$?
+    if [ $ret != 0 ] ; then
+	echo "$out"
+	echo "failed - should get NT_STATUS_ACCESS_DENIED listing \\widelinks_share\\source"
+	false
+    fi
+}
 
 LOGDIR_PREFIX=test_smbclient_s3
 
@@ -1095,6 +1151,10 @@ testit "creating a :stream at root of share" \
     test_toplevel_stream || \
     failed=`expr $failed + 1`
 
+testit "Ensure widelinks are restricted" \
+    test_widelinks || \
+    failed=`expr $failed + 1`
+
 testit "rm -rf $LOGDIR" \
     rm -rf $LOGDIR || \
     failed=`expr $failed + 1`
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 0c272a7..27b38d6 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -982,6 +982,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,
@@ -1076,7 +1077,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",
@@ -1216,6 +1220,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) {
@@ -1226,8 +1231,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 fbb392d..153c85e 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -1558,12 +1558,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[] = {
 		{
@@ -1592,6 +1595,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",
@@ -1643,7 +1656,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) {
@@ -1670,12 +1683,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;
diff --git a/source4/dsdb/tests/python/user_account_control.py b/source4/dsdb/tests/python/user_account_control.py
index 16c7f81..a53c4f9 100644
--- a/source4/dsdb/tests/python/user_account_control.py
+++ b/source4/dsdb/tests/python/user_account_control.py
@@ -240,6 +240,16 @@ class UserAccountControlTests(samba.tests.TestCase):
         m.dn = res[0].dn
         m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT),
                                                      ldb.FLAG_MOD_REPLACE, "userAccountControl")
+        try:
+            self.samdb.modify(m)
+            self.fail("Unexpectedly able to set userAccountControl to be an Workstation on %s" % m.dn)
+        except LdbError, (enum, estr):
+            self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum)
+
+        m = ldb.Message()
+        m.dn = res[0].dn
+        m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_NORMAL_ACCOUNT),
+                                                     ldb.FLAG_MOD_REPLACE, "userAccountControl")
         self.samdb.modify(m)
 
         m = ldb.Message()
@@ -306,7 +316,12 @@ class UserAccountControlTests(samba.tests.TestCase):
         m.dn = res[0].dn
         m["userAccountControl"] = ldb.MessageElement(str(samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT),
                                                      ldb.FLAG_MOD_REPLACE, "userAccountControl")
-        self.samdb.modify(m)
+        try:
+            self.samdb.modify(m)
+            self.fail("Unexpectedly able to set userAccountControl to be an Workstation on %s" % m.dn)
+        except LdbError, (enum, estr):
+            self.assertEqual(ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS, enum)
+
 
     def test_admin_mod_uac(self):
         computername=self.computernames[0]
@@ -382,9 +397,10 @@ class UserAccountControlTests(samba.tests.TestCase):
         priv_to_auth_users_bits = set([UF_PASSWD_NOTREQD, UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED,
                                        UF_DONT_EXPIRE_PASSWD])
 
-        # These bits really are privileged
+        # These bits really are privileged, or can't be changed from UF_NORMAL as a non-admin
         priv_bits = set([UF_INTERDOMAIN_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT,
-                         UF_TRUSTED_FOR_DELEGATION, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION])
+                         UF_TRUSTED_FOR_DELEGATION, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION,
+                         UF_WORKSTATION_TRUST_ACCOUNT])
 
         invalid_bits = set([UF_TEMP_DUPLICATE_ACCOUNT, UF_PARTIAL_SECRETS_ACCOUNT])
 
@@ -446,7 +462,7 @@ class UserAccountControlTests(samba.tests.TestCase):
                             int("0x10000000", 16), int("0x20000000", 16), int("0x40000000", 16), int("0x80000000", 16)])
         super_priv_bits = set([UF_INTERDOMAIN_TRUST_ACCOUNT])
 
-        priv_to_remove_bits = set([UF_TRUSTED_FOR_DELEGATION, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION])
+        priv_to_remove_bits = set([UF_TRUSTED_FOR_DELEGATION, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, UF_WORKSTATION_TRUST_ACCOUNT])
 
         for bit in bits:


-- 
Samba Shared Repository



More information about the samba-cvs mailing list