The branch, v4-0-test has been updated via f9693a1 VERSION: Bump version up to 4.0.25. via 9b14925 Merge tag 'samba-4.0.24' into v4-0-test via 654b1d1 smbd: Fix CID 1063259 Uninitialized scalar variable via 03299a2 net: Fix sam addgroupmem via 017ff20 dsdb: Add tokenGroupsGlobalAndUniversal, tokenGroups, tokenGroupsNoGCAcceptable via 3be3266 VERSION: Disable git snapshots for the 4.0.24 release. via 65a088d WHATSNEW: Add release notes for Samba 4.0.24. via 3d221ef CVE-2014-8143:dsdb-samldb: Check for extended access rights before we allow changes to userAccountControl via 01a4bd7 CVE-2014-8143:dsdb: Allow use of dsdb_autotransaction_request outside util.c via 5acd6c0 CVE-2014-8143:pydsdb: Pull in UF_USE_AES_KEYS flag via 392523a CVE-2014-8143:auth: Force talloc type of session_info pointer to match via 003ae6a VERSION: Bump version up to 4.0.24... from 4f6075e nsswitch: fix soname of linux nss_*.so.2 modules
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-0-test - Log ----------------------------------------------------------------- commit f9693a1766b88ce068bb04c88f1a41ce3330e2cc Author: Karolin Seeger <ksee...@samba.org> Date: Thu Jan 15 12:12:10 2015 +0100 VERSION: Bump version up to 4.0.25. Signed-off-by: Karolin Seeger <ksee...@samba.org> commit 9b14925b20aac0f2f8aac60d7e63f50c128bffd1 Merge: 654b1d1 3be3266 Author: Karolin Seeger <ksee...@samba.org> Date: Thu Jan 15 12:11:57 2015 +0100 Merge tag 'samba-4.0.24' into v4-0-test samba: tag release samba-4.0.24 commit 654b1d119cd7127d0d60f36b8bec1efb20032431 Author: Volker Lendecke <v...@samba.org> Date: Sun Aug 18 20:35:32 2013 +0000 smbd: Fix CID 1063259 Uninitialized scalar variable Signed-off-by: Volker Lendecke <v...@samba.org> Bug: https://bugzilla.samba.org/show_bug.cgi?id=11041 Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit cc983c9a6a92f3d127ec6461b15aed3fa90e6d30) Reviewed-by: David Disseldorp <dd...@samba.org> commit 03299a23d82f653917a6df31e8bb786c26f5eb1b Author: Volker Lendecke <v...@samba.org> Date: Tue Jan 13 12:51:13 2015 +0100 net: Fix sam addgroupmem Domain local groups come across as SID_TYPE_ALIAS and are sent to us in the PAC/Info3 struct. We should allow this in net sam addgroupmem. Volker Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Guenther Deschner <g...@samba.org> Bug: https://bugzilla.samba.org/show_bug.cgi?id=11051 Autobuild-User(master): Günther Deschner <g...@samba.org> Autobuild-Date(master): Tue Jan 13 15:28:16 CET 2015 on sn-devel-104 commit 017ff207a6883a50705de985e8653e2a05f3b024 Author: Garming Sam <garm...@catalyst.net.nz> Date: Thu Dec 4 11:53:12 2014 +1300 dsdb: Add tokenGroupsGlobalAndUniversal, tokenGroups, tokenGroupsNoGCAcceptable This includes additional tests based directly on the docs, rather than simply testing our internal implementation in client and server contexts, that create a user and groups. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11022 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> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Mon Dec 22 17:17:02 CET 2014 on sn-devel-104 (similar to commit e4213512d0a967e87a74a1ae816c903fb38dd8b9) ----------------------------------------------------------------------- Summary of changes: VERSION | 2 +- WHATSNEW.txt | 53 +++- librpc/idl/security.idl | 13 +- source3/smbd/process.c | 1 + source3/utils/net_sam.c | 8 +- source4/auth/session.c | 5 + source4/dsdb/common/util.c | 4 +- source4/dsdb/pydsdb.c | 1 + source4/dsdb/samdb/ldb_modules/operational.c | 66 ++++- source4/dsdb/samdb/ldb_modules/samldb.c | 192 ++++++++++++++- source4/dsdb/samdb/samdb.h | 6 + source4/dsdb/tests/python/token_group.py | 347 ++++++++++++++++++++++++++- source4/rpc_server/lsa/dcesrv_lsa.c | 15 +- source4/setup/schema_samba4.ldif | 1 + 14 files changed, 686 insertions(+), 28 deletions(-) Changeset truncated at 500 lines: diff --git a/VERSION b/VERSION index a0ec102..705c416 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=0 -SAMBA_VERSION_RELEASE=24 +SAMBA_VERSION_RELEASE=25 ######################################################## # If a official release has a serious bug # diff --git a/WHATSNEW.txt b/WHATSNEW.txt index c74580b..777997f 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,4 +1,53 @@ ============================== + Release Notes for Samba 4.0.24 + January 15, 2015 + ============================== + + +This is a security release in order to address CVE-2014-8143 (Elevation +of privilege to Active Directory Domain Controller). + +o CVE-2014-8143: + Samba's AD DC allows the administrator to delegate + creation of user or computer accounts to specific users or groups. + + However, all released versions of Samba's AD DC did not implement the + additional required check on the UF_SERVER_TRUST_ACCOUNT bit in the + userAccountControl attributes. + + +Changes since 4.0.23: +--------------------- + +o Andrew Bartlett <abart...@samba.org> + * BUG 10993: CVE-2014-8143: dsdb-samldb: Check for extended access + rights before we allow changes to userAccountControl. + + +###################################################################### +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.0 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.0.23 December 08, 2014 ============================== @@ -89,8 +138,8 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- + ============================== Release Notes for Samba 4.0.22 diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl index d886b51..2600d49 100644 --- a/librpc/idl/security.idl +++ b/librpc/idl/security.idl @@ -653,14 +653,21 @@ interface security const string GUID_DRS_CHANGE_RID_MASTER = "d58d5f36-0a98-11d1-adbb-00c04fd8d5cd"; const string GUID_DRS_CHANGE_SCHEMA_MASTER = "e12b56b6-0a95-11d1-adbb-00c04fd8d5cd"; const string GUID_DRS_GET_CHANGES = "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2"; + const string GUID_DRS_REPL_SYNCRONIZE = "1131f6ab-9c07-11d1-f79f-00c04fc2dcd2"; + const string GUID_DRS_MANAGE_TOPOLOGY = "1131f6ac-9c07-11d1-f79f-00c04fc2dcd2"; const string GUID_DRS_GET_ALL_CHANGES = "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"; + const string GUID_DRS_RO_REPL_SECRET_SYNC = "1131f6ae-9c07-11d1-f79f-00c04fc2dcd2"; const string GUID_DRS_GET_FILTERED_ATTRIBUTES = "89e95b76-444d-4c62-991a-0facbeda640c"; - const string GUID_DRS_MANAGE_TOPOLOGY = "1131f6ac-9c07-11d1-f79f-00c04fc2dcd2"; const string GUID_DRS_MONITOR_TOPOLOGY = "f98340fb-7c5b-4cdb-a00b-2ebdfa115a96"; - const string GUID_DRS_REPL_SYNCRONIZE = "1131f6ab-9c07-11d1-f79f-00c04fc2dcd2"; - const string GUID_DRS_RO_REPL_SECRET_SYNC = "1131f6ae-9c07-11d1-f79f-00c04fc2dcd2"; const string GUID_DRS_USER_CHANGE_PASSWORD = "ab721a53-1e2f-11d0-9819-00aa0040529b"; const string GUID_DRS_FORCE_CHANGE_PASSWORD = "00299570-246d-11d0-a768-00aa006e0529"; + const string GUID_DRS_UPDATE_PASSWORD_NOT_REQUIRED_BIT + = "280f369c-67c7-438e-ae98-1d46f3c6f541"; + const string GUID_DRS_UNEXPIRE_PASSWORD = "ccc2dc7d-a6ad-4a7a-8846-c04e3cc53501"; + const string GUID_DRS_ENABLE_PER_USER_REVERSIBLY_ENCRYPTED_PASSWORD + = "05c74c5e-4deb-43b4-bd9f-86664c2a7fd5"; + const string GUID_DRS_DS_INSTALL_REPLICA = "9923a32a-3607-11d2-b9be-0000f87a36b2"; + /***************************************************************/ /* validated writes guids */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e67c56c..dcfbff6 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -173,6 +173,7 @@ bool srv_send_smb(struct smbd_server_connection *sconn, char *buffer, DEBUG(0, ("send_smb: SMB encryption failed " "on outgoing packet! Error %s\n", nt_errstr(status) )); + ret = -1; goto out; } } diff --git a/source3/utils/net_sam.c b/source3/utils/net_sam.c index b1c4e9b..c4f4326 100644 --- a/source3/utils/net_sam.c +++ b/source3/utils/net_sam.c @@ -1216,10 +1216,12 @@ static int net_sam_addmem(struct net_context *c, int argc, const char **argv) if ((grouptype == SID_NAME_ALIAS) || (grouptype == SID_NAME_WKN_GRP)) { if ((membertype != SID_NAME_USER) && + (membertype != SID_NAME_ALIAS) && (membertype != SID_NAME_DOM_GRP)) { - d_fprintf(stderr, _("%s is a local group, only users " - "and domain groups can be added.\n" - "%s is a %s\n"), argv[0], argv[1], + d_fprintf(stderr, _("Can't add %s: only users, domain " + "groups and domain local groups " + "can be added. %s is a %s\n"), + argv[0], argv[1], sid_type_lookup(membertype)); return -1; } diff --git a/source4/auth/session.c b/source4/auth/session.c index bb0b5bc..8c85302 100644 --- a/source4/auth/session.c +++ b/source4/auth/session.c @@ -204,6 +204,11 @@ struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx, { struct auth_session_info *session_info; session_info = talloc_steal(mem_ctx, session_info_transport->session_info); + /* + * This is to allow us to check the type of this pointer using + * talloc_get_type() + */ + talloc_set_name(session_info, "struct auth_session_info"); #ifdef HAVE_GSS_IMPORT_CRED if (session_info_transport->exported_gssapi_credentials.length) { struct cli_credentials *creds; diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 8e40776..1f685dc 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -1012,8 +1012,8 @@ int samdb_msg_set_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, /* * Handle ldb_request in transaction */ -static int dsdb_autotransaction_request(struct ldb_context *sam_ldb, - struct ldb_request *req) +int dsdb_autotransaction_request(struct ldb_context *sam_ldb, + struct ldb_request *req) { int ret; diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c index 99e239e..9f8db69 100644 --- a/source4/dsdb/pydsdb.c +++ b/source4/dsdb/pydsdb.c @@ -1142,6 +1142,7 @@ void initdsdb(void) ADD_DSDB_FLAG(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION); ADD_DSDB_FLAG(UF_NO_AUTH_DATA_REQUIRED); ADD_DSDB_FLAG(UF_PARTIAL_SECRETS_ACCOUNT); + ADD_DSDB_FLAG(UF_USE_AES_KEYS); /* groupType flags */ ADD_DSDB_FLAG(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP); diff --git a/source4/dsdb/samdb/ldb_modules/operational.c b/source4/dsdb/samdb/ldb_modules/operational.c index c642ad8..28c32d2 100644 --- a/source4/dsdb/samdb/ldb_modules/operational.c +++ b/source4/dsdb/samdb/ldb_modules/operational.c @@ -84,6 +84,12 @@ struct operational_data { struct ldb_dn *aggregate_dn; }; +enum search_type { + TOKEN_GROUPS, + TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL, + TOKEN_GROUPS_NO_GC_ACCEPTABLE +}; + /* construct a canonical name from a message */ @@ -127,9 +133,11 @@ static int construct_primary_group_token(struct ldb_module *module, /* construct the token groups for SAM objects from a message */ -static int construct_token_groups(struct ldb_module *module, - struct ldb_message *msg, enum ldb_scope scope, - struct ldb_request *parent) +static int construct_generic_token_groups(struct ldb_module *module, + struct ldb_message *msg, enum ldb_scope scope, + struct ldb_request *parent, + const char *attribute_string, + enum search_type type) { struct ldb_context *ldb = ldb_module_get_ctx(module);; TALLOC_CTX *tmp_ctx = talloc_new(msg); @@ -189,8 +197,18 @@ static int construct_token_groups(struct ldb_module *module, } /* only return security groups */ - filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))", - GROUP_TYPE_SECURITY_ENABLED); + switch(type) { + case TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL: + filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u)(|(groupType:1.2.840.113556.1.4.803:=%u)(groupType:1.2.840.113556.1.4.803:=%u)))", + GROUP_TYPE_SECURITY_ENABLED, GROUP_TYPE_ACCOUNT_GROUP, GROUP_TYPE_UNIVERSAL_GROUP); + break; + case TOKEN_GROUPS_NO_GC_ACCEPTABLE: + case TOKEN_GROUPS: + filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))", + GROUP_TYPE_SECURITY_ENABLED); + break; + } + if (!filter) { talloc_free(tmp_ctx); return ldb_oom(ldb); @@ -253,7 +271,7 @@ static int construct_token_groups(struct ldb_module *module, } for (i=0; i < num_groupSIDs; i++) { - ret = samdb_msg_add_dom_sid(ldb, msg, msg, "tokenGroups", &groupSIDs[i]); + ret = samdb_msg_add_dom_sid(ldb, msg, msg, attribute_string, &groupSIDs[i]); if (ret) { talloc_free(tmp_ctx); return ret; @@ -263,6 +281,40 @@ static int construct_token_groups(struct ldb_module *module, return LDB_SUCCESS; } +static int construct_token_groups(struct ldb_module *module, + struct ldb_message *msg, enum ldb_scope scope, + struct ldb_request *parent) +{ + /** + * TODO: Add in a limiting domain when we start to support + * trusted domains. + */ + return construct_generic_token_groups(module, msg, scope, parent, + "tokenGroups", + TOKEN_GROUPS); +} + +static int construct_token_groups_no_gc(struct ldb_module *module, + struct ldb_message *msg, enum ldb_scope scope, + struct ldb_request *parent) +{ + /** + * TODO: Add in a limiting domain when we start to support + * trusted domains. + */ + return construct_generic_token_groups(module, msg, scope, parent, + "tokenGroupsNoGCAcceptable", + TOKEN_GROUPS); +} + +static int construct_global_universal_token_groups(struct ldb_module *module, + struct ldb_message *msg, enum ldb_scope scope, + struct ldb_request *parent) +{ + return construct_generic_token_groups(module, msg, scope, parent, + "tokenGroupsGlobalAndUniversal", + TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL); +} /* construct the parent GUID for an entry from a message */ @@ -647,6 +699,8 @@ static const struct { { "canonicalName", NULL, NULL , construct_canonical_name }, { "primaryGroupToken", "objectClass", "objectSid", construct_primary_group_token }, { "tokenGroups", "primaryGroupID", "objectSid", construct_token_groups }, + { "tokenGroupsNoGCAcceptable", "primaryGroupID", "objectSid", construct_token_groups_no_gc}, + { "tokenGroupsGlobalAndUniversal", "primaryGroupID", "objectSid", construct_global_universal_token_groups }, { "parentGUID", NULL, NULL, construct_parent_guid }, { "subSchemaSubEntry", NULL, NULL, construct_subschema_subentry }, { "msDS-isRODC", "objectClass", "objectCategory", construct_msds_isrodc }, diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index da9c966..20f5932 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -33,6 +33,7 @@ #include "includes.h" #include "libcli/ldap/ldap_ndr.h" #include "ldb_module.h" +#include "auth/auth.h" #include "dsdb/samdb/samdb.h" #include "dsdb/samdb/ldb_modules/util.h" #include "dsdb/samdb/ldb_modules/ridalloc.h" @@ -943,6 +944,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); /* * "Objectclass" trigger (MS-SAMR 3.1.1.8.1) @@ -1037,7 +1042,6 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) el = ldb_msg_find_element(ac->msg, "userAccountControl"); if (el != NULL) { uint32_t user_account_control, account_type; - /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */ user_account_control = ldb_msg_find_attr_as_uint(ac->msg, "userAccountControl", @@ -1134,6 +1138,12 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) return ret; } } + + ret = samldb_check_user_account_control_acl(ac, NULL, + user_account_control, 0); + if (ret != LDB_SUCCESS) { + return ret; + } } break; } @@ -1421,6 +1431,172 @@ static int samldb_prim_group_trigger(struct samldb_ctx *ac) return ret; } +/** + * Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured + * + */ +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) +{ + int i, ret = 0; + bool need_acl_check = false; + struct ldb_result *res; + const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL}; + 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)); + const struct uac_to_guid { + uint32_t uac; + const char *oid; + const char *guid; + enum sec_privilege privilege; + bool delete_is_privileged; + const char *error_string; + } map[] = { + { + .uac = UF_PASSWD_NOTREQD, + .guid = GUID_DRS_UPDATE_PASSWORD_NOT_REQUIRED_BIT, + .error_string = "Adding the UF_PASSWD_NOTREQD bit in userAccountControl requires the Update-Password-Not-Required-Bit right that was not given on the Domain object" + }, + { + .uac = UF_DONT_EXPIRE_PASSWD, + .guid = GUID_DRS_UNEXPIRE_PASSWORD, + .error_string = "Adding the UF_DONT_EXPIRE_PASSWD bit in userAccountControl requires the Unexpire-Password right that was not given on the Domain object" + }, + { + .uac = UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED, + .guid = GUID_DRS_ENABLE_PER_USER_REVERSIBLY_ENCRYPTED_PASSWORD, + .error_string = "Adding the UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED bit in userAccountControl requires the Enable-Per-User-Reversibly-Encrypted-Password right that was not given on the Domain object" + }, + { + .uac = UF_SERVER_TRUST_ACCOUNT, + .guid = GUID_DRS_DS_INSTALL_REPLICA, + .error_string = "Adding the UF_SERVER_TRUST_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object" + }, + { + .uac = UF_PARTIAL_SECRETS_ACCOUNT, + .guid = GUID_DRS_DS_INSTALL_REPLICA, + .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_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", + .delete_is_privileged = true + }, + { + .uac = UF_TRUSTED_FOR_DELEGATION, + .privilege = SEC_PRIV_ENABLE_DELEGATION, + .delete_is_privileged = true, + .error_string = "Updating the UF_TRUSTED_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege" + }, + { + .uac = UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, + .privilege = SEC_PRIV_ENABLE_DELEGATION, + .delete_is_privileged = true, + .error_string = "Updating the UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege" + } + + }; + + if (dsdb_module_am_system(ac->module)) { + return LDB_SUCCESS; + } + + for (i = 0; i < ARRAY_SIZE(map); i++) { + if (user_account_control & map[i].uac) { + need_acl_check = true; + break; + } + } + if (need_acl_check == false) { + return LDB_SUCCESS; + } + + user_token = acl_user_token(ac->module); + if (user_token == NULL) { + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + + ret = dsdb_module_search_dn(ac->module, ac, &res, + domain_dn, + sd_attrs, + DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + if (res->count != 1) { + return ldb_module_operr(ac->module); + } + + ret = dsdb_get_sd_from_ldb_message(ldb_module_get_ctx(ac->module), + ac, res->msgs[0], &domain_sd); + + if (ret != LDB_SUCCESS) { + return ret; + } + + for (i = 0; i < ARRAY_SIZE(map); i++) { + uint32_t this_uac_new = user_account_control & map[i].uac; + uint32_t this_uac_old = user_account_control_old & map[i].uac; + if (this_uac_new != this_uac_old) { + if (this_uac_old != 0) { + if (map[i].delete_is_privileged == false) { + continue; + } + } + if (map[i].oid) { + struct ldb_control *control = ldb_request_get_control(ac->req, map[i].oid); + if (control == NULL) { + ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + } else if (map[i].privilege != SEC_PRIV_INVALID) { + bool have_priv = security_token_has_privilege(user_token, + map[i].privilege); + if (have_priv == false) { + ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + } else { + ret = acl_check_extended_right(ac, domain_sd, + user_token, + map[i].guid, + SEC_ADS_CONTROL_ACCESS, + sid); + } + if (ret != LDB_SUCCESS) { + break; + } + } + } + if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { + 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; -- Samba Shared Repository