Fixed incorrect checking of PRINCIPAL_SELF permissions.
authorNadezhda Ivanova <nadezhda.ivanova@postpath.com>
Thu, 17 Dec 2009 15:25:11 +0000 (17:25 +0200)
committerNadezhda Ivanova <nadezhda.ivanova@postpath.com>
Thu, 17 Dec 2009 15:25:11 +0000 (17:25 +0200)
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.

source4/dsdb/samdb/ldb_modules/acl.c
source4/lib/ldb/tests/python/acl.py
source4/libcli/security/access_check.c

index dcd015b2a5342f768658c98a963518b822f633f6..6cb50b2098400321bacc5f825f7840c15e17be2d 100644 (file)
@@ -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;
index ae35ddfb2941f826a58e32917ad651b86f9f53f2..4544f60736a5075f5e06c035ad9f63ae43a711d6 100755 (executable)
@@ -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"""
index fb78e0aa47aff147ab9cf9763dce92b6ad590b3a..19fb160d58043c18572659d4098a347aa1662c0a 100644 (file)
@@ -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;
                 }