mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
dsdb:extended_dn_store: add support for FPO (foreignSecurityPrincipal) enabled attributes
This implements the handling for FPO-enabled attributes, see [MS-ADTS] 3.1.1.5.2.3 Special Classes and Attributes: FPO-enabled attributes: member, msDS-MembersForAzRole, msDS-NeverRevealGroup, msDS-NonMembers, msDS-RevealOnDemandGroup, msDS-ServiceAccount. Note there's no msDS-ServiceAccount in any schema (only msDS-HostServiceAccount and that's not an FPO-enabled attribute at least not in W2008R2) msDS-NonMembers always generates NOT_SUPPORTED against W2008R2. See also [MS-SAMR] 3.1.1.8.9 member. We now create foreignSeurityPrincipal objects on the fly (as needed). BUG: https://bugzilla.samba.org/show_bug.cgi?id=13300 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
parent
799c9d1ce3
commit
fb03f9a1de
@ -1,5 +0,0 @@
|
||||
^samba.tests.dsdb.*.samba.tests.dsdb.DsdbTests.test_foreignSecurityPrincipal_member
|
||||
^samba.tests.dsdb.*.samba.tests.dsdb.DsdbTests.test_foreignSecurityPrincipal_MembersForAzRole
|
||||
^samba.tests.dsdb.*.samba.tests.dsdb.DsdbTests.test_foreignSecurityPrincipal_NeverRevealGroup
|
||||
^samba.tests.dsdb.*.samba.tests.dsdb.DsdbTests.test_foreignSecurityPrincipal_RevealOnDemandGroup
|
||||
^samba.tests.dsdb.*.samba.tests.dsdb.DsdbTests.test_foreignSecurityPrincipal_NonMembers
|
@ -67,6 +67,11 @@ struct extended_dn_context {
|
||||
|
||||
struct extended_dn_replace_list *ops;
|
||||
struct extended_dn_replace_list *cur;
|
||||
|
||||
/*
|
||||
* Used by the FPO-enabled attribute validation.
|
||||
*/
|
||||
struct dsdb_trust_routing_table *routing_table;
|
||||
};
|
||||
|
||||
|
||||
@ -121,6 +126,171 @@ static int extended_replace_dn(struct extended_dn_replace_list *os,
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
static int extended_dn_handle_fpo_attr(struct extended_dn_replace_list *os)
|
||||
{
|
||||
struct dom_sid target_sid = { 0, };
|
||||
struct dom_sid target_domain = { 0, };
|
||||
struct ldb_message *fmsg = NULL;
|
||||
char *fsid = NULL;
|
||||
const struct dom_sid *domain_sid = NULL;
|
||||
struct ldb_dn *domain_dn = NULL;
|
||||
const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
|
||||
uint32_t trust_attributes = 0;
|
||||
const char *no_attrs[] = { NULL, };
|
||||
struct ldb_result *res = NULL;
|
||||
NTSTATUS status;
|
||||
bool match;
|
||||
bool ok;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* DN doesn't exist yet
|
||||
*
|
||||
* Check if a foreign SID is specified,
|
||||
* which would trigger the creation
|
||||
* of a foreignSecurityPrincipal.
|
||||
*/
|
||||
status = dsdb_get_extended_dn_sid(os->dsdb_dn->dn,
|
||||
&target_sid,
|
||||
"SID");
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||
/*
|
||||
* No SID specified
|
||||
*/
|
||||
return dsdb_module_werror(os->ac->module,
|
||||
LDB_ERR_NO_SUCH_OBJECT,
|
||||
WERR_NO_SUCH_USER,
|
||||
"specified dn doesn't exist");
|
||||
}
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ldb_module_operr(os->ac->module);
|
||||
}
|
||||
if (ldb_dn_get_extended_comp_num(os->dsdb_dn->dn) != 1) {
|
||||
return dsdb_module_werror(os->ac->module,
|
||||
LDB_ERR_NO_SUCH_OBJECT,
|
||||
WERR_NO_SUCH_USER,
|
||||
"specified extended component other than SID");
|
||||
}
|
||||
if (ldb_dn_get_comp_num(os->dsdb_dn->dn) != 0) {
|
||||
return dsdb_module_werror(os->ac->module,
|
||||
LDB_ERR_NO_SUCH_OBJECT,
|
||||
WERR_NO_SUCH_USER,
|
||||
"specified more the SID");
|
||||
}
|
||||
|
||||
target_domain = target_sid;
|
||||
sid_split_rid(&target_domain, NULL);
|
||||
|
||||
match = dom_sid_equal(&global_sid_Builtin, &target_domain);
|
||||
if (match) {
|
||||
/*
|
||||
* Non existing BUILTIN sid
|
||||
*/
|
||||
return dsdb_module_werror(os->ac->module,
|
||||
LDB_ERR_NO_SUCH_OBJECT,
|
||||
WERR_NO_SUCH_MEMBER,
|
||||
"specified sid doesn't exist in BUILTIN");
|
||||
}
|
||||
|
||||
domain_sid = samdb_domain_sid(os->ac->ldb);
|
||||
if (domain_sid == NULL) {
|
||||
return ldb_module_operr(os->ac->module);
|
||||
}
|
||||
match = dom_sid_equal(domain_sid, &target_domain);
|
||||
if (match) {
|
||||
/*
|
||||
* Non existing SID in our domain.
|
||||
*/
|
||||
return dsdb_module_werror(os->ac->module,
|
||||
LDB_ERR_UNWILLING_TO_PERFORM,
|
||||
WERR_DS_INVALID_GROUP_TYPE,
|
||||
"specified sid doesn't exist in domain");
|
||||
}
|
||||
|
||||
if (os->ac->routing_table == NULL) {
|
||||
status = dsdb_trust_routing_table_load(os->ac->ldb, os->ac,
|
||||
&os->ac->routing_table);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ldb_module_operr(os->ac->module);
|
||||
}
|
||||
}
|
||||
|
||||
tdo = dsdb_trust_domain_by_sid(os->ac->routing_table,
|
||||
&target_domain, NULL);
|
||||
if (tdo != NULL) {
|
||||
trust_attributes = tdo->trust_attributes;
|
||||
}
|
||||
|
||||
if (trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
|
||||
return dsdb_module_werror(os->ac->module,
|
||||
LDB_ERR_UNWILLING_TO_PERFORM,
|
||||
WERR_DS_INVALID_GROUP_TYPE,
|
||||
"specified sid doesn't exist in forest");
|
||||
}
|
||||
|
||||
fmsg = ldb_msg_new(os);
|
||||
if (fmsg == NULL) {
|
||||
return ldb_module_oom(os->ac->module);
|
||||
}
|
||||
|
||||
fsid = dom_sid_string(fmsg, &target_sid);
|
||||
if (fsid == NULL) {
|
||||
return ldb_module_oom(os->ac->module);
|
||||
}
|
||||
|
||||
domain_dn = ldb_get_default_basedn(os->ac->ldb);
|
||||
if (domain_dn == NULL) {
|
||||
return ldb_module_operr(os->ac->module);
|
||||
}
|
||||
|
||||
fmsg->dn = ldb_dn_copy(fmsg, domain_dn);
|
||||
if (fmsg->dn == NULL) {
|
||||
return ldb_module_oom(os->ac->module);
|
||||
}
|
||||
|
||||
ok = ldb_dn_add_child_fmt(fmsg->dn,
|
||||
"CN=%s,CN=ForeignSecurityPrincipals",
|
||||
fsid);
|
||||
if (!ok) {
|
||||
return ldb_module_oom(os->ac->module);
|
||||
}
|
||||
|
||||
ret = ldb_msg_add_string(fmsg, "objectClass", "foreignSecurityPrincipal");
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dsdb_module_add(os->ac->module, fmsg,
|
||||
DSDB_FLAG_AS_SYSTEM |
|
||||
DSDB_FLAG_NEXT_MODULE,
|
||||
os->ac->req);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dsdb_module_search_dn(os->ac->module, fmsg, &res,
|
||||
fmsg->dn, no_attrs,
|
||||
DSDB_FLAG_AS_SYSTEM |
|
||||
DSDB_FLAG_NEXT_MODULE |
|
||||
DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
|
||||
os->ac->req);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* dsdb_module_search_dn() garantees exactly one result message
|
||||
* on success.
|
||||
*/
|
||||
ret = extended_replace_dn(os, res->msgs[0]->dn);
|
||||
TALLOC_FREE(fmsg);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
/* An extra layer of indirection because LDB does not allow the original request to be altered */
|
||||
|
||||
static int extended_final_callback(struct ldb_request *req, struct ldb_reply *ares)
|
||||
@ -171,21 +341,13 @@ static int extended_replace_callback(struct ldb_request *req, struct ldb_reply *
|
||||
if (os->require_object && os->fpo_enabled) {
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* It's an error if the target doesn't exist,
|
||||
* unless it's a delete.
|
||||
*
|
||||
* Note FPO-enabled attributes generate
|
||||
* a different error.
|
||||
*/
|
||||
ret = dsdb_module_werror(os->ac->module,
|
||||
LDB_ERR_NO_SUCH_OBJECT,
|
||||
WERR_NO_SUCH_USER,
|
||||
"specified dn doesn't exist");
|
||||
|
||||
ret = extended_dn_handle_fpo_attr(os);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ldb_module_done(os->ac->req, NULL, NULL,
|
||||
ret);
|
||||
}
|
||||
/* os->got_entry is true at this point... */
|
||||
}
|
||||
|
||||
if (!os->got_entry && os->require_object) {
|
||||
/*
|
||||
@ -250,21 +412,13 @@ static int extended_replace_callback(struct ldb_request *req, struct ldb_reply *
|
||||
if (!os->got_entry && os->require_object && os->fpo_enabled) {
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* It's an error if the target doesn't exist,
|
||||
* unless it's a delete.
|
||||
*
|
||||
* Note FPO-enabled attributes generate
|
||||
* a different error.
|
||||
*/
|
||||
ret = dsdb_module_werror(os->ac->module,
|
||||
LDB_ERR_NO_SUCH_OBJECT,
|
||||
WERR_NO_SUCH_USER,
|
||||
"specified dn doesn't exist");
|
||||
|
||||
ret = extended_dn_handle_fpo_attr(os);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ldb_module_done(os->ac->req, NULL, NULL,
|
||||
ret);
|
||||
}
|
||||
/* os->got_entry is true at this point... */
|
||||
}
|
||||
|
||||
if (!os->got_entry && os->require_object) {
|
||||
/*
|
||||
@ -389,18 +543,38 @@ static int extended_store_replace(struct extended_dn_context *ac,
|
||||
os->require_object = true;
|
||||
|
||||
/*
|
||||
* Handle FPO-enabled attributes cause a different
|
||||
* error.
|
||||
* Handle FPO-enabled attributes, see
|
||||
* [MS-ADTS] 3.1.1.5.2.3 Special Classes and Attributes:
|
||||
*
|
||||
* FPO-enabled attributes: member, msDS-MembersForAzRole,
|
||||
* msDS-NeverRevealGroup, msDS-NonMembers, msDS-RevealOnDemandGroup,
|
||||
* msDS-ServiceAccount.
|
||||
*
|
||||
* Note there's no msDS-ServiceAccount in any schema (only
|
||||
* msDS-HostServiceAccount and that's not an FPO-enabled attribute
|
||||
* at least not in W2008R2)
|
||||
*
|
||||
* msDS-NonMembers always generates NOT_SUPPORTED against W2008R2.
|
||||
*
|
||||
* See also [MS-SAMR] 3.1.1.8.9 member.
|
||||
*/
|
||||
switch (schema_attr->attributeID_id) {
|
||||
case DRSUAPI_ATTID_member:
|
||||
case DRSUAPI_ATTID_msDS_NonMembers:
|
||||
case DRSUAPI_ATTID_msDS_MembersForAzRole:
|
||||
case DRSUAPI_ATTID_msDS_NeverRevealGroup:
|
||||
case DRSUAPI_ATTID_msDS_RevealOnDemandGroup:
|
||||
case DRSUAPI_ATTID_msDS_HostServiceAccount:
|
||||
os->fpo_enabled = true;
|
||||
break;
|
||||
|
||||
case DRSUAPI_ATTID_msDS_HostServiceAccount:
|
||||
/* This is NOT a FPO-enabled attribute */
|
||||
break;
|
||||
|
||||
case DRSUAPI_ATTID_msDS_NonMembers:
|
||||
return dsdb_module_werror(os->ac->module,
|
||||
LDB_ERR_UNWILLING_TO_PERFORM,
|
||||
WERR_NOT_SUPPORTED,
|
||||
"msDS-NonMembers is not supported");
|
||||
}
|
||||
|
||||
if (schema_attr->linkID == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user