The branch, master has been updated via 496b67b dsdb-tests: Clarify that accounts really do fall back to UF_NORMAL_ACCOUNT if no account set via daeedb0 dsdb-samldb: Clarify userAccountControl manipulation code by always using UF_ flags via 1279d5e dsdb-samldb: Clarify that accounts really do fall back to UF_NORMAL_ACCOUNT if no account set via 49485ab dsdb-samldb: Only allow known and settable userAccountControl bits to be set via ad98c0e dsdb-tests: Show that we can not change the primaryGroupID of a DC via 2a43275 s4:dsdb/samldb: let samldb_prim_group_change() protect DOMAIN_RID_{READONLY_,}DCS via 735605a dsdb: Improve userAccountControl handling via bf99abb dsdb-tests: Add new test samba4.user_account_control.python via b995ef3 dsdb: Default to UF_NORMAL_ACCOUNT when no account type is specified via 412b602 libds: UF_PARTIAL_SECRETS_ACCOUNT is a flag, not an account type via 7e41bcf dsdb-tests: Align sam.py with Windows 2012R2 and uncomment userAccountControl tests from cde5d38 vfs:glusterfs: whitespace fix.
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 496b67b27ab9856017a07b2fbcc5ba465f1945b3 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jan 6 16:49:14 2015 +1300 dsdb-tests: Clarify that accounts really do fall back to UF_NORMAL_ACCOUNT if no account set Also confirm what bits have to be ignored, or otherwise processed Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Pair-programmed-with: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Thu Jan 22 10:16:42 CET 2015 on sn-devel-104 commit daeedb030fc019091332cbf3e8f6a2cc5d0d5273 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jan 6 16:48:40 2015 +1300 dsdb-samldb: Clarify userAccountControl manipulation code by always using UF_ flags The use of ACB_ flags was required before msDS-User-Account-Control-Computed was implemented Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 1279d5e863d51fb03d84bfec51e9dc6a632fabd4 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jan 6 16:47:36 2015 +1300 dsdb-samldb: Clarify that accounts really do fall back to UF_NORMAL_ACCOUNT if no account set Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 49485ab9782b7abc32581f29c35d862bb9a7058c Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jan 6 16:43:37 2015 +1300 dsdb-samldb: Only allow known and settable userAccountControl bits to be set Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Signed-off-by: Andrew Bartlett <abart...@samba.org> Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Pair-programmed-with: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit ad98c0e1755e3fdc6efd8551590c1781b318a04f Author: Andrew Bartlett <abart...@samba.org> Date: Wed Dec 10 15:54:11 2014 +1300 dsdb-tests: Show that we can not change the primaryGroupID of a DC Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Pair-programmed-with: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 2a432752c0eb8ef1ae395004ee1f0ba9b8ad88ba Author: Stefan Metzmacher <me...@samba.org> Date: Tue Apr 1 19:22:35 2014 +0200 s4:dsdb/samldb: let samldb_prim_group_change() protect DOMAIN_RID_{READONLY_,}DCS Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Signed-off-by: Stefan Metzmacher <me...@samba.org> Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 735605a6b0ad3ed98d46d1df920e64879a8c69cc Author: Andrew Bartlett <abart...@samba.org> Date: Wed Dec 10 14:15:54 2014 +1300 dsdb: Improve userAccountControl handling We now always check the ACL and invarient rules using the same function The change to libds is because UF_PARTIAL_SECRETS_ACCOUNT is a flag, not an account type This list should only be of the account exclusive account type bits. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Pair-programmed-with: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit bf99abb5db91839d8e3589722fe9be000f857691 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 8 15:07:59 2014 +1300 dsdb-tests: Add new test samba4.user_account_control.python This confirms security behaviour of the userAccountControl attribute as well as the behaviour on ADD as well as MODIFY, for every userAccountControl bit. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Change-Id: I8cd0e0b3c8d40e8b8aea844189703c756cc372f0 Pair-programmed-with: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Andrew Bartlett <abart...@samba.org> Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit b995ef3795511fadae3556e706e77abb39f8791c Author: Andrew Bartlett <abart...@samba.org> Date: Wed Dec 10 14:26:28 2014 +1300 dsdb: Default to UF_NORMAL_ACCOUNT when no account type is specified Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 412b602314e1174824d86940eacd74fb76774aba Author: Andrew Bartlett <abart...@samba.org> Date: Wed Dec 10 14:15:54 2014 +1300 libds: UF_PARTIAL_SECRETS_ACCOUNT is a flag, not an account type This list should only be of the account exclusive account type bits. Note, this corrects the behaviour in samldb modifies of userAccountControl. This reverts 6cb91a8f33516a33210a25e4019f3f3fbbfe61f2 Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Pair-programmed-with: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Andrew Bartlett <abart...@samba.org> Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 7e41bcf3053e147a6511071bd61f45db8e055165 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Dec 8 14:31:42 2014 +1300 dsdb-tests: Align sam.py with Windows 2012R2 and uncomment userAccountControl tests These tests now pass against Samba and Windows 2012R2. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993 Change-Id: I1d7ba5e6a720b8da88c667bbbf3a4302c54642f4 Pair-programmed-with: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Andrew Bartlett <abart...@samba.org> Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: libds/common/flags.h | 20 +- source4/dsdb/samdb/ldb_modules/samldb.c | 253 ++++++-- source4/dsdb/tests/python/sam.py | 150 +++-- source4/dsdb/tests/python/user_account_control.py | 699 ++++++++++++++++++++++ source4/selftest/tests.py | 1 + 5 files changed, 983 insertions(+), 140 deletions(-) create mode 100644 source4/dsdb/tests/python/user_account_control.py Changeset truncated at 500 lines: diff --git a/libds/common/flags.h b/libds/common/flags.h index 4975024..f821e17 100644 --- a/libds/common/flags.h +++ b/libds/common/flags.h @@ -64,17 +64,21 @@ UF_NORMAL_ACCOUNT |\ UF_INTERDOMAIN_TRUST_ACCOUNT |\ UF_WORKSTATION_TRUST_ACCOUNT |\ - UF_SERVER_TRUST_ACCOUNT |\ - UF_PARTIAL_SECRETS_ACCOUNT \ + UF_SERVER_TRUST_ACCOUNT \ ) +/* + * MS-SAMR 2.2.1.13 UF_FLAG Codes states that some bits are ignored by + * clients and servers. Other flags (like UF_LOCKOUT have special + * behaviours, but are not set in the traditional sense). + * + * See the samldb module for the use of this define. + */ + #define UF_SETTABLE_BITS (\ - UF_SCRIPT |\ UF_ACCOUNTDISABLE |\ UF_HOMEDIR_REQUIRED |\ - UF_LOCKOUT |\ UF_PASSWD_NOTREQD |\ - UF_PASSWD_CANT_CHANGE |\ UF_ACCOUNT_TYPE_MASK | \ UF_DONT_EXPIRE_PASSWD | \ UF_MNS_LOGON_ACCOUNT |\ @@ -83,7 +87,11 @@ UF_TRUSTED_FOR_DELEGATION |\ UF_NOT_DELEGATED |\ UF_USE_DES_KEY_ONLY |\ - UF_DONT_REQUIRE_PREAUTH \ + UF_DONT_REQUIRE_PREAUTH |\ + UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION |\ + UF_NO_AUTH_DATA_REQUIRED |\ + UF_PARTIAL_SECRETS_ACCOUNT |\ + UF_USE_AES_KEYS \ ) /* Group flags for "groupType" */ diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 54e2e5e..ade7c9a 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -945,10 +945,10 @@ static int samldb_schema_info_update(struct samldb_ctx *ac) } static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid); -static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, - struct dom_sid *sid, - uint32_t user_account_control, - uint32_t user_account_control_old); +static int samldb_check_user_account_control_rules(struct samldb_ctx *ac, + struct dom_sid *sid, + uint32_t user_account_control, + uint32_t user_account_control_old); /* * "Objectclass" trigger (MS-SAMR 3.1.1.8.1) @@ -1048,9 +1048,13 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) user_account_control = ldb_msg_find_attr_as_uint(ac->msg, "userAccountControl", 0); - /* "userAccountControl" = 0 means "UF_NORMAL_ACCOUNT" */ - if (user_account_control == 0) { - user_account_control = UF_NORMAL_ACCOUNT; + /* + * "userAccountControl" = 0 or missing one of + * the types means "UF_NORMAL_ACCOUNT". See + * MS-SAMR 3.1.1.8.10 point 8 + */ + if ((user_account_control & UF_ACCOUNT_TYPE_MASK) == 0) { + user_account_control = UF_NORMAL_ACCOUNT | user_account_control; uac_generated = true; } @@ -1066,9 +1070,10 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) uac_generated = true; } - /* Temporary duplicate accounts aren't allowed */ - if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) { - return LDB_ERR_OTHER; + ret = samldb_check_user_account_control_rules(ac, NULL, + user_account_control, 0); + if (ret != LDB_SUCCESS) { + return ret; } /* Workstation and (read-only) DC objects do need objectclass "computer" */ @@ -1160,11 +1165,6 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) } } - ret = samldb_check_user_account_control_acl(ac, NULL, - user_account_control, 0); - if (ret != LDB_SUCCESS) { - return ret; - } } break; } @@ -1289,11 +1289,15 @@ static int samldb_prim_group_set(struct samldb_ctx *ac) static int samldb_prim_group_change(struct samldb_ctx *ac) { struct ldb_context *ldb = ldb_module_get_ctx(ac->module); - const char * const attrs[] = { "primaryGroupID", "memberOf", NULL }; + const char * const attrs[] = { + "primaryGroupID", + "memberOf", + "userAccountControl", + NULL }; struct ldb_result *res, *group_res; struct ldb_message_element *el; struct ldb_message *msg; - uint32_t prev_rid, new_rid; + uint32_t prev_rid, new_rid, uac; struct dom_sid *prev_sid, *new_sid; struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn; int ret; @@ -1314,6 +1318,8 @@ static int samldb_prim_group_change(struct samldb_ctx *ac) return ret; } + uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0); + /* Finds out the DN of the old primary group */ prev_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "primaryGroupID", @@ -1353,6 +1359,24 @@ static int samldb_prim_group_change(struct samldb_ctx *ac) return LDB_SUCCESS; } + if ((uac & UF_SERVER_TRUST_ACCOUNT) && new_rid != DOMAIN_RID_DCS) { + ldb_asprintf_errstring(ldb, + "%08X: samldb: UF_SERVER_TRUST_ACCOUNT requires " + "primaryGroupID=%u!", + W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID), + DOMAIN_RID_DCS); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + if ((uac & UF_PARTIAL_SECRETS_ACCOUNT) && new_rid != DOMAIN_RID_READONLY_DCS) { + ldb_asprintf_errstring(ldb, + "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT requires " + "primaryGroupID=%u!", + W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID), + DOMAIN_RID_READONLY_DCS); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + ret = dsdb_module_search(ac->module, ac, &group_res, ldb_get_default_basedn(ldb), LDB_SCOPE_SUBTREE, @@ -1452,6 +1476,110 @@ static int samldb_prim_group_trigger(struct samldb_ctx *ac) return ret; } +static int samldb_check_user_account_control_invariants(struct samldb_ctx *ac, + uint32_t user_account_control) +{ + int i, ret = 0; + bool need_check = false; + const struct uac_to_guid { + uint32_t uac; + bool never; + uint32_t needs; + uint32_t not_with; + const char *error_string; + } map[] = { + { + .uac = UF_TEMP_DUPLICATE_ACCOUNT, + .never = true, + .error_string = "Updating the UF_TEMP_DUPLICATE_ACCOUNT flag is never allowed" + }, + { + .uac = UF_PARTIAL_SECRETS_ACCOUNT, + .needs = UF_WORKSTATION_TRUST_ACCOUNT, + .error_string = "Setting UF_PARTIAL_SECRETS_ACCOUNT only permitted with UF_WORKSTATION_TRUST_ACCOUNT" + }, + { + .uac = UF_TRUSTED_FOR_DELEGATION, + .not_with = UF_PARTIAL_SECRETS_ACCOUNT, + .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT" + }, + { + .uac = UF_NORMAL_ACCOUNT, + .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_NORMAL_ACCOUNT, + .error_string = "Setting more than one account type not permitted" + }, + { + .uac = UF_WORKSTATION_TRUST_ACCOUNT, + .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_WORKSTATION_TRUST_ACCOUNT, + .error_string = "Setting more than one account type not permitted" + }, + { + .uac = UF_INTERDOMAIN_TRUST_ACCOUNT, + .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_INTERDOMAIN_TRUST_ACCOUNT, + .error_string = "Setting more than one account type not permitted" + }, + { + .uac = UF_SERVER_TRUST_ACCOUNT, + .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_SERVER_TRUST_ACCOUNT, + .error_string = "Setting more than one account type not permitted" + }, + { + .uac = UF_TRUSTED_FOR_DELEGATION, + .not_with = UF_PARTIAL_SECRETS_ACCOUNT, + .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT" + } + }; + + for (i = 0; i < ARRAY_SIZE(map); i++) { + if (user_account_control & map[i].uac) { + need_check = true; + break; + } + } + if (need_check == false) { + return LDB_SUCCESS; + } + + for (i = 0; i < ARRAY_SIZE(map); i++) { + uint32_t this_uac = user_account_control & map[i].uac; + if (this_uac != 0) { + if (map[i].never) { + ret = LDB_ERR_OTHER; + break; + } else if (map[i].needs != 0) { + if ((map[i].needs & user_account_control) == 0) { + ret = LDB_ERR_OTHER; + break; + } + } else if (map[i].not_with != 0) { + if ((map[i].not_with & user_account_control) != 0) { + ret = LDB_ERR_OTHER; + break; + } + } + } + } + if (ret != LDB_SUCCESS) { + switch (ac->req->operation) { + case LDB_ADD: + ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), + "Failed to add %s: %s", + ldb_dn_get_linearized(ac->msg->dn), + map[i].error_string); + break; + case LDB_MODIFY: + ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), + "Failed to modify %s: %s", + ldb_dn_get_linearized(ac->msg->dn), + map[i].error_string); + break; + default: + return ldb_module_operr(ac->module); + } + } + return ret; +} + /** * Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured * @@ -1619,6 +1747,24 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, return ret; } +static int samldb_check_user_account_control_rules(struct samldb_ctx *ac, + struct dom_sid *sid, + uint32_t user_account_control, + uint32_t user_account_control_old) +{ + int ret; + ret = samldb_check_user_account_control_invariants(ac, user_account_control); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = samldb_check_user_account_control_acl(ac, sid, user_account_control, user_account_control_old); + if (ret != LDB_SUCCESS) { + return ret; + } + return ret; +} + + /** * This function is called on LDB modify operations. It performs some additions/ * replaces on the current LDB message when "userAccountControl" changes. @@ -1631,9 +1777,8 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) uint32_t raw_uac; uint32_t old_ufa; uint32_t new_ufa; - uint32_t old_acb; - uint32_t new_acb; - uint32_t clear_acb; + uint32_t old_uac_computed; + uint32_t clear_uac; uint32_t old_atype; uint32_t new_atype; uint32_t old_pgrid; @@ -1680,15 +1825,19 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) raw_uac = ldb_msg_find_attr_as_uint(tmp_msg, "userAccountControl", 0); - new_acb = samdb_result_acct_flags(tmp_msg, NULL); talloc_free(tmp_msg); /* - * UF_LOCKOUT and UF_PASSWORD_EXPIRED are only generated - * and not stored. We ignore them almost completely. + * UF_LOCKOUT, UF_PASSWD_CANT_CHANGE and UF_PASSWORD_EXPIRED + * are only generated and not stored. We ignore them almost + * completely, along with unknown bits and UF_SCRIPT. * - * The only exception is the resulting ACB_AUTOLOCK in clear_acb. + * The only exception is ACB_AUTOLOCK, which features in + * clear_acb when the bit is cleared in this modify operation. + * + * MS-SAMR 2.2.1.13 UF_FLAG Codes states that some bits are + * ignored by clients and servers */ - new_uac = raw_uac & ~(UF_LOCKOUT|UF_PASSWORD_EXPIRED); + new_uac = raw_uac & UF_SETTABLE_BITS; /* Fetch the old "userAccountControl" and "objectClass" */ ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs, @@ -1700,8 +1849,8 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) if (old_uac == 0) { return ldb_operr(ldb); } - old_acb = samdb_result_acct_flags(res->msgs[0], - "msDS-User-Account-Control-Computed"); + old_uac_computed = ldb_msg_find_attr_as_uint(res->msgs[0], + "msDS-User-Account-Control-Computed", 0); old_lockoutTime = ldb_msg_find_attr_as_int64(res->msgs[0], "lockoutTime", 0); old_is_critical = ldb_msg_find_attr_as_bool(res->msgs[0], @@ -1724,16 +1873,27 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) new_ufa = new_uac & UF_ACCOUNT_TYPE_MASK; if (new_ufa == 0) { /* - * When there is no account type embedded in "userAccountControl" - * fall back to the old. + * "userAccountControl" = 0 or missing one of the + * types means "UF_NORMAL_ACCOUNT". See MS-SAMR + * 3.1.1.8.10 point 8 */ - new_ufa = old_ufa; + new_ufa = UF_NORMAL_ACCOUNT; new_uac |= new_ufa; } + sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid"); + if (sid == NULL) { + return ldb_module_operr(ac->module); + } + + ret = samldb_check_user_account_control_rules(ac, sid, new_uac, old_uac); + if (ret != LDB_SUCCESS) { + return ret; + } + new_atype = ds_uf2atype(new_ufa); new_pgrid = ds_uf2prim_group_rid(new_uac); - clear_acb = old_acb & ~new_acb; + clear_uac = (old_uac | old_uac_computed) & ~raw_uac; switch (new_ufa) { case UF_NORMAL_ACCOUNT: @@ -1746,17 +1906,16 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) case UF_WORKSTATION_TRUST_ACCOUNT: new_is_critical = false; - break; - - case (UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT): - if (!is_computer) { - ldb_asprintf_errstring(ldb, - "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT " - "requires objectclass 'computer'!", - W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); - return LDB_ERR_UNWILLING_TO_PERFORM; + if (new_uac & UF_PARTIAL_SECRETS_ACCOUNT) { + if (!is_computer) { + ldb_asprintf_errstring(ldb, + "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT " + "requires objectclass 'computer'!", + W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + new_is_critical = true; } - new_is_critical = true; break; case UF_SERVER_TRUST_ACCOUNT: @@ -1788,7 +1947,7 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) } /* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */ - if ((clear_acb & ACB_AUTOLOCK) && (old_lockoutTime != 0)) { + if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) { /* "pwdLastSet" reset as password expiration has been forced */ ldb_msg_remove_attr(ac->msg, "lockoutTime"); ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime", @@ -1849,16 +2008,6 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) ldb_msg_remove_attr(ac->msg, "userAccountControl"); } - sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid"); - if (sid == NULL) { - return ldb_module_operr(ac->module); - } - - ret = samldb_check_user_account_control_acl(ac, sid, new_uac, old_uac); - if (ret != LDB_SUCCESS) { - return ret; - } - return LDB_SUCCESS; } diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index 31b5a39..25da8f9 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -22,12 +22,14 @@ from ldb import ERR_OTHER, ERR_NO_SUCH_ATTRIBUTE from ldb import ERR_OBJECT_CLASS_VIOLATION from ldb import ERR_CONSTRAINT_VIOLATION from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE +from ldb import ERR_INSUFFICIENT_ACCESS_RIGHTS from ldb import Message, MessageElement, Dn from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE from samba.samdb import SamDB from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_ACCOUNTDISABLE, UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT, UF_PARTIAL_SECRETS_ACCOUNT, UF_TEMP_DUPLICATE_ACCOUNT, + UF_INTERDOMAIN_TRUST_ACCOUNT, UF_PASSWD_NOTREQD, UF_LOCKOUT, UF_PASSWORD_EXPIRED, ATYPE_NORMAL_ACCOUNT, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, GTYPE_SECURITY_DOMAIN_LOCAL_GROUP, GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP, @@ -1440,16 +1442,11 @@ class SamTests(samba.tests.TestCase): self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) -# This has to wait until s4 supports it (needs a password module change) -# try: -# ldb.add({ -# "dn": "cn=ldaptestuser,cn=users," + self.base_dn, -# "objectclass": "user", -# "userAccountControl": str(UF_NORMAL_ACCOUNT)}) -# self.fail() -# except LdbError, (num, _): -# self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) -# delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + ldb.add({ + "dn": "cn=ldaptestuser,cn=users," + self.base_dn, + "objectclass": "user", + "userAccountControl": str(UF_NORMAL_ACCOUNT)}) + delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) ldb.add({ "dn": "cn=ldaptestuser,cn=users," + self.base_dn, @@ -1519,16 +1516,15 @@ class SamTests(samba.tests.TestCase): self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) -# This isn't supported yet in s4 - needs ACL module adaption -# try: -# ldb.add({ -# "dn": "cn=ldaptestuser,cn=users," + self.base_dn, -# "objectclass": "user", -# "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)}) -# self.fail() -# except LdbError, (num, _): -# self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) -# delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) + try: + ldb.add({ + "dn": "cn=ldaptestuser,cn=users," + self.base_dn, + "objectclass": "user", + "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)}) + self.fail() + except LdbError, (num, _): + self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) + delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) # Modify operation @@ -1561,16 +1557,15 @@ class SamTests(samba.tests.TestCase): except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) -# This has to wait until s4 supports it (needs a password module change) -# try: -- Samba Shared Repository