summaryrefslogtreecommitdiffstats
path: root/source4/dsdb/common/dsdb_access.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/common/dsdb_access.c')
-rw-r--r--source4/dsdb/common/dsdb_access.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/source4/dsdb/common/dsdb_access.c b/source4/dsdb/common/dsdb_access.c
new file mode 100644
index 0000000..6edae35
--- /dev/null
+++ b/source4/dsdb/common/dsdb_access.c
@@ -0,0 +1,183 @@
+/*
+ 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 "ldb.h"
+#include "ldb_module.h"
+#include "ldb_errors.h"
+#include "libcli/security/security.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "libcli/ldap/ldap_ndr.h"
+#include "param/param.h"
+#include "auth/auth.h"
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/common/util.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\n", ldb_dn_get_linearized(dn)));
+ } else {
+ DEBUG(level, ("Access on %s granted\n", 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(struct ldb_context *ldb,
+ 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 == NULL) {
+ return ldb_error(ldb, LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS,
+ "nTSecurityDescriptor is missing");
+ }
+ *sd = talloc(mem_ctx, struct security_descriptor);
+ if(!*sd) {
+ return ldb_oom(ldb);
+ }
+ ndr_err = ndr_pull_struct_blob(&sd_element->values[0], *sd, *sd,
+ (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ TALLOC_FREE(*sd);
+ return ldb_operr(ldb);
+ }
+
+ return LDB_SUCCESS;
+}
+
+int dsdb_check_access_on_dn_internal(struct ldb_context *ldb,
+ struct ldb_result *acl_res,
+ TALLOC_CTX *mem_ctx,
+ struct security_token *token,
+ struct ldb_dn *dn,
+ uint32_t access_mask,
+ const struct GUID *guid)
+{
+ struct security_descriptor *sd = NULL;
+ struct dom_sid *sid = NULL;
+ struct object_tree *root = NULL;
+ NTSTATUS status;
+ uint32_t access_granted;
+ int ret;
+
+ ret = dsdb_get_sd_from_ldb_message(ldb, mem_ctx, acl_res->msgs[0], &sd);
+ if (ret != LDB_SUCCESS) {
+ return ldb_operr(ldb);
+ }
+
+ sid = samdb_result_dom_sid(mem_ctx, acl_res->msgs[0], "objectSid");
+ if (guid) {
+ if (!insert_in_object_tree(mem_ctx, guid, access_mask, NULL,
+ &root)) {
+ TALLOC_FREE(sd);
+ TALLOC_FREE(sid);
+ return ldb_operr(ldb);
+ }
+ }
+ status = sec_access_check_ds(sd, token,
+ access_mask,
+ &access_granted,
+ root,
+ sid);
+ if (!NT_STATUS_IS_OK(status)) {
+ dsdb_acl_debug(sd,
+ token,
+ dn,
+ true,
+ 10);
+ ldb_asprintf_errstring(ldb,
+ "dsdb_access: Access check failed on %s",
+ ldb_dn_get_linearized(dn));
+ TALLOC_FREE(sd);
+ TALLOC_FREE(sid);
+ return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
+ }
+ return LDB_SUCCESS;
+}
+
+/* performs an access check from outside the module stack
+ * given the dn of the object to be checked, the required access
+ * guid is either the guid of the extended right, or NULL
+ */
+
+int dsdb_check_access_on_dn(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *dn,
+ struct security_token *token,
+ uint32_t access_mask,
+ const char *ext_right)
+{
+ int ret;
+ struct GUID guid;
+ struct ldb_result *acl_res;
+ static const char *acl_attrs[] = {
+ "nTSecurityDescriptor",
+ "objectSid",
+ NULL
+ };
+
+ if (ext_right != NULL) {
+ NTSTATUS status = GUID_from_string(ext_right, &guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+
+ /*
+ * We need AS_SYSTEM in order to get the nTSecurityDescriptor attribute.
+ * Also the result of this search not controlled by the client
+ * nor is the result exposed to the client.
+ */
+ ret = dsdb_search_dn(ldb, mem_ctx, &acl_res, dn, acl_attrs,
+ DSDB_FLAG_AS_SYSTEM | DSDB_SEARCH_SHOW_RECYCLED);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(10,("access_check: failed to find object %s\n", ldb_dn_get_linearized(dn)));
+ return ret;
+ }
+
+ return dsdb_check_access_on_dn_internal(ldb, acl_res,
+ mem_ctx,
+ token,
+ dn,
+ access_mask,
+ ext_right ? &guid : NULL);
+}
+