summaryrefslogtreecommitdiff
path: root/source4/dsdb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb')
-rw-r--r--source4/dsdb/common/dsdb_access.c181
-rw-r--r--source4/dsdb/config.mk3
-rw-r--r--source4/dsdb/samdb/ldb_modules/acl.c175
3 files changed, 202 insertions, 157 deletions
diff --git a/source4/dsdb/common/dsdb_access.c b/source4/dsdb/common/dsdb_access.c
new file mode 100644
index 0000000000..1f8b795a7b
--- /dev/null
+++ b/source4/dsdb/common/dsdb_access.c
@@ -0,0 +1,181 @@
+/*
+ ldb database library
+
+ Copyright (C) Nadezhda Ivanova 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Name: dsdb_access
+ *
+ * Description: utility functions for access checking on objects
+ *
+ * Authors: Nadezhda Ivanova
+ */
+
+#include "includes.h"
+#include "events/events.h"
+#include "ldb.h"
+#include "ldb_errors.h"
+#include "../lib/util/util_ldb.h"
+#include "../lib/crypto/crypto.h"
+#include "libcli/security/security.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "../libds/common/flags.h"
+#include "libcli/ldap/ldap_ndr.h"
+#include "param/param.h"
+#include "libcli/auth/libcli_auth.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "system/locale.h"
+#include "auth/auth.h"
+#include "lib/util/tsort.h"
+
+void dsdb_acl_debug(struct security_descriptor *sd,
+ struct security_token *token,
+ struct ldb_dn *dn,
+ bool denied,
+ int level)
+{
+ if (denied) {
+ DEBUG(level, ("Access on %s denied", ldb_dn_get_linearized(dn)));
+ } else {
+ DEBUG(level, ("Access on %s granted", ldb_dn_get_linearized(dn)));
+ }
+
+ DEBUG(level,("Security context: %s\n",
+ ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_token,"", token)));
+ DEBUG(level,("Security descriptor: %s\n",
+ ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_descriptor,"", sd)));
+}
+
+int dsdb_get_sd_from_ldb_message(TALLOC_CTX *mem_ctx,
+ struct ldb_message *acl_res,
+ struct security_descriptor **sd)
+{
+ struct ldb_message_element *sd_element;
+ enum ndr_err_code ndr_err;
+
+ sd_element = ldb_msg_find_element(acl_res, "nTSecurityDescriptor");
+ if (!sd_element) {
+ *sd = NULL;
+ return LDB_SUCCESS;
+ }
+ *sd = talloc(mem_ctx, struct security_descriptor);
+ if(!*sd) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ndr_err = ndr_pull_struct_blob(&sd_element->values[0], *sd, NULL, *sd,
+ (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return LDB_SUCCESS;
+}
+
+int dsdb_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;
+}
+
+int dsdb_check_access_on_dn(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *dn,
+ uint32_t access,
+ const struct GUID *guid)
+{
+ int ret;
+ struct ldb_result *acl_res;
+ struct security_descriptor *sd = NULL;
+ struct dom_sid *sid = NULL;
+ struct object_tree *root = NULL;
+ struct object_tree *new_node = NULL;
+ NTSTATUS status;
+ uint32_t access_granted;
+ static const char *acl_attrs[] = {
+ "nTSecurityDescriptor",
+ "objectSid",
+ NULL
+ };
+
+ struct auth_session_info *session_info
+ = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
+ if(!session_info) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_search(ldb, mem_ctx, &acl_res, dn, LDB_SCOPE_BASE, acl_attrs, NULL);
+ /* we sould be able to find the parent */
+ if (ret != LDB_SUCCESS) {
+ DEBUG(10,("acl: failed to find object %s\n", ldb_dn_get_linearized(dn)));
+ return ret;
+ }
+
+ ret = dsdb_get_sd_from_ldb_message(mem_ctx, acl_res->msgs[0], &sd);
+ if (ret != LDB_SUCCESS) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ /* Theoretically we pass the check if the object has no sd */
+ if (!sd) {
+ return LDB_SUCCESS;
+ }
+ ret = dsdb_get_dom_sid_from_ldb_message(mem_ctx, acl_res->msgs[0], &sid);
+ if (ret != LDB_SUCCESS) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (guid) {
+ if (!insert_in_object_tree(mem_ctx, guid, access, &root, &new_node)) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+ status = sec_access_check_ds(sd, session_info->security_token,
+ access,
+ &access_granted,
+ root,
+ sid);
+ if (!NT_STATUS_IS_OK(status)) {
+ dsdb_acl_debug(sd,
+ session_info->security_token,
+ dn,
+ true,
+ 10);
+ return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
+ }
+ return LDB_SUCCESS;
+}
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk
index 9a1cee979f..356f732ee3 100644
--- a/source4/dsdb/config.mk
+++ b/source4/dsdb/config.mk
@@ -26,7 +26,8 @@ PRIVATE_DEPENDENCIES = LIBLDB NDR_DRSBLOBS LIBCLI_LDAP_NDR UTIL_LDB LIBCLI_AUTH
SAMDB_COMMON_OBJ_FILES = $(addprefix $(dsdbsrcdir)/common/, \
util.o \
- dsdb_dn.o) \
+ dsdb_dn.o \
+ dsdb_access.o) \
../libds/common/flag_mapping.o
$(eval $(call proto_header_template,$(dsdbsrcdir)/common/proto.h,$(SAMDB_COMMON_OBJ_FILES:.o=.c)))
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
index e7665c792f..4bc8b82bdd 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -156,32 +156,6 @@ done:
return ldb_next_init(module);
}
-static int get_sd_from_ldb_message(TALLOC_CTX *mem_ctx,
- struct ldb_message *acl_res,
- struct security_descriptor **sd)
-{
- struct ldb_message_element *sd_element;
- enum ndr_err_code ndr_err;
-
- sd_element = ldb_msg_find_element(acl_res, "nTSecurityDescriptor");
- if (!sd_element) {
- *sd = NULL;
- return LDB_SUCCESS;
- }
- *sd = talloc(mem_ctx, struct security_descriptor);
- if(!*sd) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ndr_err = ndr_pull_struct_blob(&sd_element->values[0], *sd, NULL, *sd,
- (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
-
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- return LDB_SUCCESS;
-}
-
static const struct GUID *get_oc_guid_from_message(struct ldb_module *module,
struct ldb_message *msg)
{
@@ -197,106 +171,6 @@ 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,
- bool denied,
- int level)
-{
- if (denied) {
- DEBUG(level, ("Access on %s denied", ldb_dn_get_linearized(dn)));
- } else {
- DEBUG(level, ("Access on %s granted", ldb_dn_get_linearized(dn)));
- }
-
- DEBUG(level,("Security context: %s\n",
- ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_token,"", token)));
- DEBUG(level,("Security descriptor: %s\n",
- ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_descriptor,"", sd)));
-}
-
-static int check_access_on_dn(struct ldb_module *module,
- TALLOC_CTX *mem_ctx,
- struct ldb_dn *dn,
- uint32_t access,
- struct object_tree *tree)
-{
- int ret;
- 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
- };
-
- ret = ldb_search(ldb, mem_ctx, &acl_res, dn, LDB_SCOPE_BASE, acl_attrs, NULL);
- /* we sould be able to find the parent */
- if (ret != LDB_SUCCESS) {
- DEBUG(10,("acl: failed to find object %s\n", ldb_dn_get_linearized(dn)));
- return ret;
- }
-
- ret = get_sd_from_ldb_message(mem_ctx, acl_res->msgs[0], &sd);
- if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- /* Theoretically we pass the check if the object has no sd */
- 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,
- sid);
- if (!NT_STATUS_IS_OK(status)) {
- acl_debug(sd,
- acl_user_token(module),
- dn,
- true,
- 10);
- return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
- }
- return LDB_SUCCESS;
-}
-
static int acl_check_access_on_attribute(struct ldb_module *module,
TALLOC_CTX *mem_ctx,
struct security_descriptor *sd,
@@ -455,12 +329,12 @@ static int acl_allowedAttributes(struct ldb_module *module,
return LDB_SUCCESS;
}
- ret = get_sd_from_ldb_message(mem_ctx, sd_msg, &sd);
+ ret = dsdb_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);
+ ret = dsdb_get_dom_sid_from_ldb_message(mem_ctx, sd_msg, &sid);
if (ret != LDB_SUCCESS) {
return ret;
@@ -577,11 +451,11 @@ static int acl_childClassesEffective(struct ldb_module *module,
ldb_msg_remove_attr(msg, "allowedChildClassesEffective");
oc_el = ldb_msg_find_element(sd_msg, "objectClass");
- ret = get_sd_from_ldb_message(msg, sd_msg, &sd);
+ ret = dsdb_get_sd_from_ldb_message(msg, sd_msg, &sd);
if (ret != LDB_SUCCESS) {
return ret;
}
- ret = get_dom_sid_from_ldb_message(msg, sd_msg, &sid);
+ ret = dsdb_get_dom_sid_from_ldb_message(msg, sd_msg, &sid);
if (ret != LDB_SUCCESS) {
return ret;
@@ -654,11 +528,11 @@ static int acl_sDRightsEffective(struct ldb_module *module,
}
else {
/* Get the security descriptor from the message */
- ret = get_sd_from_ldb_message(msg, sd_msg, &sd);
+ ret = dsdb_get_sd_from_ldb_message(msg, sd_msg, &sd);
if (ret != LDB_SUCCESS) {
return ret;
}
- ret = get_dom_sid_from_ldb_message(msg, sd_msg, &sid);
+ ret = dsdb_get_dom_sid_from_ldb_message(msg, sd_msg, &sid);
if (ret != LDB_SUCCESS) {
return ret;
@@ -702,8 +576,6 @@ static int acl_add(struct ldb_module *module, struct ldb_request *req)
struct ldb_context *ldb;
struct ldb_message_element *oc_el;
const struct GUID *guid;
- struct object_tree *root = NULL;
- struct object_tree *new_node = NULL;
struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID);
if (as_system != NULL) {
@@ -734,16 +606,10 @@ static int acl_add(struct ldb_module *module, struct ldb_request *req)
guid = class_schemaid_guid_by_lDAPDisplayName(dsdb_get_schema(ldb),
(char *)oc_el->values[oc_el->num_values-1].data);
-
- if (!insert_in_object_tree(req, guid, SEC_ADS_CREATE_CHILD, &root, &new_node)) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ret = check_access_on_dn(module, req, parent, SEC_ADS_CREATE_CHILD, root);
+ ret = dsdb_check_access_on_dn(ldb, req, parent, SEC_ADS_CREATE_CHILD, guid);
if (ret != LDB_SUCCESS) {
return ret;
}
-
return ldb_next_request(module, req);
}
@@ -793,7 +659,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
return ret;
}
- ret = get_sd_from_ldb_message(req, acl_res->msgs[0], &sd);
+ ret = dsdb_get_sd_from_ldb_message(req, acl_res->msgs[0], &sd);
if (ret != LDB_SUCCESS) {
DEBUG(10, ("acl_modify: cannot get descriptor\n"));
return ret;
@@ -809,7 +675,7 @@ 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);
+ ret = dsdb_get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid);
if (ret != LDB_SUCCESS) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -862,7 +728,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("Object %s nas no write property access\n",
ldb_dn_get_linearized(req->op.mod.message->dn)));
- acl_debug(sd,
+ dsdb_acl_debug(sd,
acl_user_token(module),
req->op.mod.message->dn,
true,
@@ -881,7 +747,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("Object %s nas no write dacl access\n",
ldb_dn_get_linearized(req->op.mod.message->dn)));
- acl_debug(sd,
+ dsdb_acl_debug(sd,
acl_user_token(module),
req->op.mod.message->dn,
true,
@@ -921,7 +787,7 @@ static int acl_delete(struct ldb_module *module, struct ldb_request *req)
}
ldb = ldb_module_get_ctx(module);
/* first check if we have delete object right */
- ret = check_access_on_dn(module, req, req->op.del.dn, SEC_STD_DELETE, NULL);
+ ret = dsdb_check_access_on_dn(ldb, req, req->op.del.dn, SEC_STD_DELETE, NULL);
if (ret == LDB_SUCCESS) {
return ldb_next_request(module, req);
}
@@ -935,7 +801,7 @@ static int acl_delete(struct ldb_module *module, struct ldb_request *req)
return ldb_module_done(req, NULL, NULL, LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS);
}
- ret = check_access_on_dn(module, req, parent, SEC_ADS_DELETE_CHILD, NULL);
+ ret = dsdb_check_access_on_dn(ldb, req, parent, SEC_ADS_DELETE_CHILD, NULL);
if (ret != LDB_SUCCESS) {
return ret;
}
@@ -1013,7 +879,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_OPERATIONS_ERROR;
};
- ret = get_sd_from_ldb_message(req, acl_res->msgs[0], &sd);
+ ret = dsdb_get_sd_from_ldb_message(req, acl_res->msgs[0], &sd);
if (ret != LDB_SUCCESS) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -1022,7 +888,7 @@ 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);
+ ret = dsdb_get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid);
if (ret != LDB_SUCCESS) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -1036,7 +902,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("Object %s nas no wp on name\n",
ldb_dn_get_linearized(req->op.rename.olddn)));
- acl_debug(sd,
+ dsdb_acl_debug(sd,
acl_user_token(module),
req->op.rename.olddn,
true,
@@ -1066,11 +932,8 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
DEBUG(10,("acl:renamed object has no object class\n"));
return ldb_module_done(req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
}
- if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_CREATE_CHILD,
- &root, &new_node)) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ret = check_access_on_dn(module, req, newparent, SEC_ADS_CREATE_CHILD, root);
+
+ ret = dsdb_check_access_on_dn(ldb, req, newparent, SEC_ADS_CREATE_CHILD, guid);
if (ret != LDB_SUCCESS) {
DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn)));
return ret;
@@ -1087,7 +950,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
/* what about delete child on the current parent */
- ret = check_access_on_dn(module, req, oldparent, SEC_ADS_DELETE_CHILD, NULL);
+ ret = dsdb_check_access_on_dn(ldb, req, oldparent, SEC_ADS_DELETE_CHILD, NULL);
if (ret != LDB_SUCCESS) {
DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn)));
return ldb_module_done(req, NULL, NULL, ret);