mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
Fixed incorrect checking of PRINCIPAL_SELF permissions.
If an ace has the PRINCIPAL_SELF as trustee, this sid has to be replaced with the onjectSid of the object being checked. PRINCIPAL_SELF is the way to grant rights to an account over itself.
This commit is contained in:
parent
619ad0c6ec
commit
c0883fb451
@ -204,6 +204,33 @@ static const struct GUID *get_oc_guid_from_message(struct ldb_module *module,
|
||||
(char *)oc_el->values[oc_el->num_values-1].data);
|
||||
}
|
||||
|
||||
static int get_dom_sid_from_ldb_message(TALLOC_CTX *mem_ctx,
|
||||
struct ldb_message *acl_res,
|
||||
struct dom_sid **sid)
|
||||
{
|
||||
struct ldb_message_element *sid_element;
|
||||
enum ndr_err_code ndr_err;
|
||||
|
||||
sid_element = ldb_msg_find_element(acl_res, "objectSid");
|
||||
if (!sid_element) {
|
||||
*sid = NULL;
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
*sid = talloc(mem_ctx, struct dom_sid);
|
||||
if(!*sid) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
ndr_err = ndr_pull_struct_blob(&sid_element->values[0], *sid, NULL, *sid,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_dom_sid);
|
||||
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void acl_debug(struct security_descriptor *sd,
|
||||
struct security_token *token,
|
||||
struct ldb_dn *dn,
|
||||
@ -232,10 +259,12 @@ static int check_access_on_dn(struct ldb_module *module,
|
||||
struct ldb_context *ldb = ldb_module_get_ctx(module);
|
||||
struct ldb_result *acl_res;
|
||||
struct security_descriptor *sd = NULL;
|
||||
struct dom_sid *sid = NULL;
|
||||
NTSTATUS status;
|
||||
uint32_t access_granted;
|
||||
static const char *acl_attrs[] = {
|
||||
"nTSecurityDescriptor",
|
||||
"objectSid",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -254,10 +283,16 @@ static int check_access_on_dn(struct ldb_module *module,
|
||||
if (!sd) {
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
ret = get_dom_sid_from_ldb_message(mem_ctx, acl_res->msgs[0], &sid);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
status = sec_access_check_ds(sd, acl_user_token(module),
|
||||
access,
|
||||
&access_granted,
|
||||
tree);
|
||||
tree,
|
||||
sid);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
acl_debug(sd,
|
||||
acl_user_token(module),
|
||||
@ -272,16 +307,15 @@ static int check_access_on_dn(struct ldb_module *module,
|
||||
static int acl_check_access_on_attribute(struct ldb_module *module,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct security_descriptor *sd,
|
||||
struct dom_sid *rp_sid,
|
||||
uint32_t access,
|
||||
struct dsdb_attribute *attr)
|
||||
{
|
||||
int ret;
|
||||
struct ldb_context *ldb = ldb_module_get_ctx(module);
|
||||
NTSTATUS status;
|
||||
uint32_t access_granted;
|
||||
struct object_tree *root = NULL;
|
||||
struct object_tree *new_node = NULL;
|
||||
const struct dsdb_schema *schema = dsdb_get_schema(ldb);
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
|
||||
struct security_token *token = acl_user_token(module);
|
||||
if (attr) {
|
||||
@ -310,7 +344,8 @@ static int acl_check_access_on_attribute(struct ldb_module *module,
|
||||
status = sec_access_check_ds(sd, token,
|
||||
access,
|
||||
&access_granted,
|
||||
root);
|
||||
root,
|
||||
rp_sid);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
|
||||
}
|
||||
@ -325,6 +360,7 @@ fail:
|
||||
static int acl_check_access_on_class(struct ldb_module *module,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct security_descriptor *sd,
|
||||
struct dom_sid *rp_sid,
|
||||
uint32_t access,
|
||||
const char *class_name)
|
||||
{
|
||||
@ -355,7 +391,8 @@ static int acl_check_access_on_class(struct ldb_module *module,
|
||||
status = sec_access_check_ds(sd, token,
|
||||
access,
|
||||
&access_granted,
|
||||
root);
|
||||
root,
|
||||
rp_sid);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
|
||||
}
|
||||
@ -373,8 +410,6 @@ static int acl_allowedAttributes(struct ldb_module *module,
|
||||
struct acl_context *ac)
|
||||
{
|
||||
struct ldb_message_element *oc_el;
|
||||
struct ldb_message_element *allowedAttributes;
|
||||
struct ldb_message_element *allowedAttributesEffective;
|
||||
struct ldb_context *ldb = ldb_module_get_ctx(module);
|
||||
const struct dsdb_schema *schema = dsdb_get_schema(ldb);
|
||||
TALLOC_CTX *mem_ctx;
|
||||
@ -411,6 +446,7 @@ static int acl_allowedAttributes(struct ldb_module *module,
|
||||
}
|
||||
if (ac->allowedAttributesEffective) {
|
||||
struct security_descriptor *sd;
|
||||
struct dom_sid *sid = NULL;
|
||||
ldb_msg_remove_attr(msg, "allowedAttributesEffective");
|
||||
if (ac->user_type == SECURITY_SYSTEM) {
|
||||
for (i=0; attr_list && attr_list[i]; i++) {
|
||||
@ -421,6 +457,11 @@ static int acl_allowedAttributes(struct ldb_module *module,
|
||||
|
||||
ret = get_sd_from_ldb_message(mem_ctx, sd_msg, &sd);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
ret = get_dom_sid_from_ldb_message(mem_ctx, sd_msg, &sid);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
@ -439,6 +480,7 @@ static int acl_allowedAttributes(struct ldb_module *module,
|
||||
ret = acl_check_access_on_attribute(module,
|
||||
msg,
|
||||
sd,
|
||||
sid,
|
||||
SEC_ADS_WRITE_PROP,
|
||||
attr);
|
||||
if (ret == LDB_SUCCESS) {
|
||||
@ -517,6 +559,7 @@ static int acl_childClassesEffective(struct ldb_module *module,
|
||||
const struct dsdb_schema *schema = dsdb_get_schema(ldb);
|
||||
const struct dsdb_class *sclass;
|
||||
struct security_descriptor *sd;
|
||||
struct dom_sid *sid = NULL;
|
||||
int i, j, ret;
|
||||
|
||||
if (ac->user_type == SECURITY_SYSTEM) {
|
||||
@ -536,7 +579,11 @@ static int acl_childClassesEffective(struct ldb_module *module,
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
ret = get_dom_sid_from_ldb_message(msg, sd_msg, &sid);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
for (i=0; oc_el && i < oc_el->num_values; i++) {
|
||||
sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
|
||||
if (!sclass) {
|
||||
@ -548,6 +595,7 @@ static int acl_childClassesEffective(struct ldb_module *module,
|
||||
ret = acl_check_access_on_class(module,
|
||||
msg,
|
||||
sd,
|
||||
sid,
|
||||
SEC_ADS_CREATE_CHILD,
|
||||
sclass->possibleInferiors[j]);
|
||||
if (ret == LDB_SUCCESS) {
|
||||
@ -587,6 +635,7 @@ static int acl_sDRightsEffective(struct ldb_module *module,
|
||||
struct ldb_message_element *rightsEffective;
|
||||
int ret;
|
||||
struct security_descriptor *sd;
|
||||
struct dom_sid *sid = NULL;
|
||||
uint32_t flags = 0;
|
||||
|
||||
/* Must remove any existing attribute, or else confusion reins */
|
||||
@ -604,10 +653,15 @@ static int acl_sDRightsEffective(struct ldb_module *module,
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
ret = get_dom_sid_from_ldb_message(msg, sd_msg, &sid);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
ret = acl_check_access_on_attribute(module,
|
||||
msg,
|
||||
sd,
|
||||
sid,
|
||||
SEC_STD_WRITE_OWNER,
|
||||
NULL);
|
||||
if (ret == LDB_SUCCESS) {
|
||||
@ -616,6 +670,7 @@ static int acl_sDRightsEffective(struct ldb_module *module,
|
||||
ret = acl_check_access_on_attribute(module,
|
||||
msg,
|
||||
sd,
|
||||
sid,
|
||||
SEC_STD_WRITE_DAC,
|
||||
NULL);
|
||||
if (ret == LDB_SUCCESS) {
|
||||
@ -624,6 +679,7 @@ static int acl_sDRightsEffective(struct ldb_module *module,
|
||||
ret = acl_check_access_on_attribute(module,
|
||||
msg,
|
||||
sd,
|
||||
sid,
|
||||
SEC_FLAG_SYSTEM_SECURITY,
|
||||
NULL);
|
||||
if (ret == LDB_SUCCESS) {
|
||||
@ -695,10 +751,12 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
|
||||
NTSTATUS status;
|
||||
struct ldb_result *acl_res;
|
||||
struct security_descriptor *sd;
|
||||
struct dom_sid *sid = NULL;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(req);
|
||||
static const char *acl_attrs[] = {
|
||||
"nTSecurityDescriptor",
|
||||
"objectClass",
|
||||
"objectSid",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -732,6 +790,11 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP,
|
||||
&root, &new_node)) {
|
||||
DEBUG(10, ("acl_modify: cannot add to object tree\n"));
|
||||
@ -774,7 +837,8 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
|
||||
status = sec_access_check_ds(sd, acl_user_token(module),
|
||||
SEC_ADS_WRITE_PROP,
|
||||
&access_granted,
|
||||
root);
|
||||
root,
|
||||
sid);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(10, ("Object %s nas no write property access\n",
|
||||
@ -792,7 +856,8 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
|
||||
status = sec_access_check_ds(sd, acl_user_token(module),
|
||||
SEC_STD_WRITE_DAC,
|
||||
&access_granted,
|
||||
NULL);
|
||||
NULL,
|
||||
sid);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(10, ("Object %s nas no write dacl access\n",
|
||||
@ -860,6 +925,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
|
||||
struct ldb_dn *newparent = ldb_dn_get_parent(req, req->op.rename.newdn);
|
||||
struct ldb_context *ldb;
|
||||
struct security_descriptor *sd = NULL;
|
||||
struct dom_sid *sid = NULL;
|
||||
struct ldb_result *acl_res;
|
||||
const struct GUID *guid;
|
||||
struct object_tree *root = NULL;
|
||||
@ -870,6 +936,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
|
||||
static const char *acl_attrs[] = {
|
||||
"nTSecurityDescriptor",
|
||||
"objectClass",
|
||||
"objectSid",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -914,10 +981,16 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
|
||||
if (!sd) {
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
ret = get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
status = sec_access_check_ds(sd, acl_user_token(module),
|
||||
SEC_ADS_WRITE_PROP,
|
||||
&access_granted,
|
||||
root);
|
||||
root,
|
||||
sid);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(10, ("Object %s nas no wp on name\n",
|
||||
@ -966,7 +1039,8 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
|
||||
status = sec_access_check_ds(sd, acl_user_token(module),
|
||||
SEC_STD_DELETE,
|
||||
&access_granted,
|
||||
NULL);
|
||||
NULL,
|
||||
sid);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
return ldb_next_request(module, req);
|
||||
@ -989,6 +1063,7 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares)
|
||||
static const char *acl_attrs[] = {
|
||||
"objectClass",
|
||||
"nTSecurityDescriptor",
|
||||
"objectSid",
|
||||
NULL
|
||||
};
|
||||
int ret, i;
|
||||
|
@ -393,8 +393,6 @@ userAccountControl: %s""" % userAccountControl
|
||||
res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s,%s)" \
|
||||
% ("CN=test_add_group1,OU=test_add_ou2,OU=test_add_ou1", self.base_dn) )
|
||||
self.assertEqual( res, [])
|
||||
|
||||
# ace is not inherited - filered out...
|
||||
|
||||
def test_add_granted_user(self):
|
||||
""" 3 Testing OU with the rights of regular user granted the right 'Create User child objects' """
|
||||
@ -749,6 +747,47 @@ url: www.samba.org"""
|
||||
# This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
|
||||
self.fail()
|
||||
|
||||
|
||||
def test_modify_u4(self):
|
||||
"""11 Grant WP to PRINCIPAL_SELF and test modify"""
|
||||
# Creating acluser1
|
||||
if self.SAMBA:
|
||||
self.delete_force(self.ldb_admin, self.get_user_dn("acluser3"))
|
||||
self.create_user(self.ldb_admin, self.get_user_dn("acluser3"))
|
||||
self.enable_account(self.get_user_dn("acluser3"))
|
||||
# Test if we have any additional groups for user than default
|
||||
if self.WIN:
|
||||
res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \
|
||||
% self.get_user_dn("acluser3") )
|
||||
try:
|
||||
self.assertEqual( res[0]["memberOf"][0], "" )
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
# Create user connection that we will test with
|
||||
ldb_user = self.get_ldb_connection("acluser3", "samba123@")
|
||||
ldif = """
|
||||
dn: """ + self.get_user_dn("acluser3") + """
|
||||
changetype: modify
|
||||
add: adminDescription
|
||||
adminDescription: blah blah blah"""
|
||||
try:
|
||||
ldb_user.modify_ldif(ldif)
|
||||
except LdbError, (num, _):
|
||||
self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
|
||||
else:
|
||||
# This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
|
||||
self.fail()
|
||||
|
||||
mod = "(OA;;WP;bf967919-0de6-11d0-a285-00aa003049e2;;PS)"
|
||||
self.dacl_add_ace(self.get_user_dn("acluser3"), mod)
|
||||
# Modify on attribute you have rights for
|
||||
ldb_user.modify_ldif(ldif)
|
||||
res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \
|
||||
% self.get_user_dn("acluser3"), attrs=["adminDescription"] )
|
||||
self.assertEqual(res[0]["adminDescription"][0], "blah blah blah")
|
||||
|
||||
#enable these when we have search implemented
|
||||
def _test_search_u1(self):
|
||||
"""See if can prohibit user to read another User object"""
|
||||
|
@ -180,12 +180,14 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
|
||||
const struct security_token *token,
|
||||
uint32_t access_desired,
|
||||
uint32_t *access_granted,
|
||||
struct object_tree *tree)
|
||||
struct object_tree *tree,
|
||||
struct dom_sid *replace_sid)
|
||||
{
|
||||
int i;
|
||||
uint32_t bits_remaining;
|
||||
struct object_tree *node;
|
||||
const struct GUID *type;
|
||||
struct dom_sid *ps_sid = dom_sid_parse_talloc(NULL, SID_NT_SELF);
|
||||
|
||||
*access_granted = access_desired;
|
||||
bits_remaining = access_desired;
|
||||
@ -228,13 +230,20 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
|
||||
|
||||
/* check each ace in turn. */
|
||||
for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
|
||||
struct dom_sid *trustee;
|
||||
struct security_ace *ace = &sd->dacl->aces[i];
|
||||
|
||||
if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!security_token_has_sid(token, &ace->trustee)) {
|
||||
if (dom_sid_equal(&ace->trustee, ps_sid) && replace_sid) {
|
||||
trustee = replace_sid;
|
||||
}
|
||||
else
|
||||
{
|
||||
trustee = &ace->trustee;
|
||||
}
|
||||
if (!security_token_has_sid(token, trustee)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user