[SCM] Samba Shared Repository - branch master updated

Nadezhda Ivanova nivanova at samba.org
Sun Sep 26 16:37:57 MDT 2010


The branch, master has been updated
       via  99ac4e9 s4-ldbmodules: Added new module aclread to handle access checks on LDAP search
       via  93ba172 s4-tests: Added tests for search checks on attributes
       via  3e08965 s4-tests: Removed search tests with anonymous credentials as they fail againts Windows
       via  dc9991a s4-dsdb: Added a function to check access on a particular object by its guid
       via  4d3f528 s4-dsdb: A helper to determine if an attribute is part of the search filter
       via  b77edca s4-dsdb: Moved some helper functions to a separate file
       via  3d0e36b s4-ldap: Added a control to apply the access checks on read via LDAP
      from  5ffacff autobuild: use killbysubdir if available

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 99ac4e92ff3205f80ef0fe823cbbd05eed7d2bb6
Author: Nadezhda Ivanova <nivanova at samba.org>
Date:   Sun Sep 26 11:47:47 2010 -0700

    s4-ldbmodules: Added new module aclread to handle access checks on LDAP search
    
    It is currently enabled only if the request comes from the LDAP server, and is
    disabled  by default. Use acl:search=true in smb.conf to enable it.
    It filters out all objects the user is not allowed to see, and all attributes
    the user does not have RP on. Extended access not supported yet.

commit 93ba17285d8afb0d6e4040bf443e88ca4ad5147e
Author: Nadezhda Ivanova <nivanova at samba.org>
Date:   Sun Sep 26 11:39:36 2010 -0700

    s4-tests: Added tests for search checks on attributes
    
    The ACL reach tests are in the knowfail because aclread module is not
    enabled by default

commit 3e08965369c4a03c5c7b939f72a1b3ff0874059f
Author: Nadezhda Ivanova <nivanova at samba.org>
Date:   Sun Sep 26 11:37:00 2010 -0700

    s4-tests: Removed search tests with anonymous credentials as they fail againts Windows
    
    These tests will fail in make test as well if the acl_read module is enabled.

commit dc9991ab0e191fe5b7dadbcf1d9e57b9ecbd7958
Author: Nadezhda Ivanova <nivanova at samba.org>
Date:   Sun Sep 26 11:32:22 2010 -0700

    s4-dsdb: Added a function to check access on a particular object by its guid
    
    Similar to dsdb_check_access_on_dn, only it searches by guid.

commit 4d3f528411301d0bc48110921a1ecb4b4f752b1e
Author: Nadezhda Ivanova <nivanova at samba.org>
Date:   Wed Sep 22 12:50:51 2010 -0700

    s4-dsdb: A helper to determine if an attribute is part of the search filter

commit b77edca7f8728fbba8d4a3e6fe9f226793dad9cb
Author: Nadezhda Ivanova <nivanova at samba.org>
Date:   Wed Sep 22 12:41:44 2010 -0700

    s4-dsdb: Moved some helper functions to a separate file
    
    We need these to be accessible to the aclread module as well.

commit 3d0e36bc87bd23e3d1bff7468db2eb99531d8d87
Author: Nadezhda Ivanova <nivanova at samba.org>
Date:   Tue Sep 14 10:51:14 2010 +0300

    s4-ldap: Added a control to apply the access checks on read via LDAP

-----------------------------------------------------------------------

Summary of changes:
 source4/dsdb/common/util.c                      |   46 ++++
 source4/dsdb/samdb/ldb_modules/acl.c            |  220 ----------------
 source4/dsdb/samdb/ldb_modules/acl_read.c       |  307 +++++++++++++++++++++++
 source4/dsdb/samdb/ldb_modules/acl_util.c       |  292 +++++++++++++++++++++
 source4/dsdb/samdb/ldb_modules/config.mk        |   14 +-
 source4/dsdb/samdb/ldb_modules/extended_dn_in.c |    2 +-
 source4/dsdb/samdb/ldb_modules/samba_dsdb.c     |    1 +
 source4/dsdb/samdb/ldb_modules/util.h           |    2 +
 source4/dsdb/samdb/ldb_modules/wscript_build    |   10 +-
 source4/dsdb/samdb/samdb.h                      |    3 +
 source4/dsdb/tests/python/acl.py                |  105 ++++++++-
 source4/ldap_server/ldap_backend.c              |    1 +
 source4/libcli/ldap/ldap_controls.c             |    2 +
 source4/selftest/knownfail                      |    2 +
 source4/selftest/tests.sh                       |    6 +-
 15 files changed, 782 insertions(+), 231 deletions(-)
 create mode 100644 source4/dsdb/samdb/ldb_modules/acl_read.c
 create mode 100644 source4/dsdb/samdb/ldb_modules/acl_util.c


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index a5d7cae..7bf2618 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -4075,3 +4075,49 @@ const char *samdb_dn_to_dnshostname(struct ldb_context *ldb,
 
 	return samdb_result_string(res->msgs[0], "dNSHostName", NULL);
 }
+
+/*
+  returns true if an attribute is in the filter,
+  false otherwise, provided that attribute value is provided with the expression
+*/
+bool dsdb_attr_in_parse_tree(struct ldb_parse_tree *tree,
+			     const char *attr)
+{
+       unsigned int i;
+       switch (tree->operation) {
+       case LDB_OP_AND:
+       case LDB_OP_OR:
+               for (i=0;i<tree->u.list.num_elements;i++) {
+                       if (dsdb_attr_in_parse_tree(tree->u.list.elements[i],
+                                                       attr))
+                               return true;
+               }
+               return false;
+       case LDB_OP_NOT:
+               return dsdb_attr_in_parse_tree(tree->u.isnot.child, attr);
+       case LDB_OP_EQUALITY:
+       case LDB_OP_GREATER:
+       case LDB_OP_LESS:
+       case LDB_OP_APPROX:
+               if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
+                       return true;
+               }
+               return false;
+       case LDB_OP_SUBSTRING:
+               if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) {
+                       return true;
+               }
+               return false;
+       case LDB_OP_PRESENT:
+	       /* (attrname=*) is not filtered out */
+               return false;
+       case LDB_OP_EXTENDED:
+               if (tree->u.extended.attr &&
+                   ldb_attr_cmp(tree->u.extended.attr, attr) == 0) {
+		       return true;
+               }
+               return false;
+       }
+       return false;
+}
+
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
index 497e1ad..2781b4c 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -64,58 +64,6 @@ struct acl_context {
 	struct dsdb_schema *schema;
 };
 
-static struct security_token *acl_user_token(struct ldb_module *module)
-{
-	struct ldb_context *ldb = ldb_module_get_ctx(module);
-	struct auth_session_info *session_info
-		= (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
-	if(!session_info) {
-		return NULL;
-	}
-	return session_info->security_token;
-}
-
-/* performs an access check from inside 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_module_check_access_on_dn(struct ldb_module *module,
-				   TALLOC_CTX *mem_ctx,
-				   struct ldb_dn *dn,
-				   uint32_t access,
-				   const struct GUID *guid)
-{
-	int ret;
-	struct ldb_result *acl_res;
-	static const char *acl_attrs[] = {
-		"nTSecurityDescriptor",
-		"objectSid",
-		NULL
-	};
-	struct ldb_context *ldb = ldb_module_get_ctx(module);
-	struct auth_session_info *session_info
-		= (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
-	if(!session_info) {
-		return ldb_operr(ldb);
-	}
-	ret = dsdb_module_search_dn(module, mem_ctx, &acl_res, dn,
-				    acl_attrs,
-				    DSDB_FLAG_NEXT_MODULE |
-				    DSDB_SEARCH_SHOW_DELETED);
-	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,
-						session_info->security_token,
-						dn,
-						access,
-						guid);
-}
-
-
 static int acl_module_init(struct ldb_module *module)
 {
 	struct ldb_context *ldb;
@@ -189,122 +137,6 @@ done:
 	return ldb_next_init(module);
 }
 
-static const struct GUID *get_oc_guid_from_message(struct ldb_module *module,
-						   const struct dsdb_schema *schema,
-						   struct ldb_message *msg)
-{
-	struct ldb_message_element *oc_el;
-
-	oc_el = ldb_msg_find_element(msg, "objectClass");
-	if (!oc_el) {
-		return NULL;
-	}
-
-	return class_schemaid_guid_by_lDAPDisplayName(schema,
-						      (char *)oc_el->values[oc_el->num_values-1].data);
-}
-
-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,
-					 const struct dsdb_attribute *attr)
-{
-	int ret;
-	NTSTATUS status;
-	uint32_t access_granted;
-	struct object_tree *root = NULL;
-	struct object_tree *new_node = NULL;
-	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-	struct security_token *token = acl_user_token(module);
-	if (attr) {
-		if (!GUID_all_zero(&attr->attributeSecurityGUID)) {
-			if (!insert_in_object_tree(tmp_ctx,
-						   &attr->attributeSecurityGUID, access,
-						   &root, &new_node)) {
-				DEBUG(10, ("acl_search: cannot add to object tree securityGUID\n"));
-				goto fail;
-			}
-
-			if (!insert_in_object_tree(tmp_ctx,
-						   &attr->schemaIDGUID, access, &new_node, &new_node)) {
-				DEBUG(10, ("acl_search: cannot add to object tree attributeGUID\n"));
-				goto fail;
-			}
-		}
-		else {
-			if (!insert_in_object_tree(tmp_ctx,
-						   &attr->schemaIDGUID, access, &root, &new_node)) {
-				DEBUG(10, ("acl_search: cannot add to object tree attributeGUID\n"));
-				goto fail;
-			}
-		}
-	}
-	status = sec_access_check_ds(sd, token,
-				     access,
-				     &access_granted,
-				     root,
-				     rp_sid);
-	if (!NT_STATUS_IS_OK(status)) {
-		ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
-	}
-	else {
-		ret = LDB_SUCCESS;
-	}
-	talloc_free(tmp_ctx);
-	return ret;
-fail:
-	talloc_free(tmp_ctx);
-	return ldb_operr(ldb_module_get_ctx(module));
-}
-
-static int acl_check_access_on_class(struct ldb_module *module,
-				     const struct dsdb_schema *schema,
-				     TALLOC_CTX *mem_ctx,
-				     struct security_descriptor *sd,
-				     struct dom_sid *rp_sid,
-				     uint32_t access,
-				     const char *class_name)
-{
-	int ret;
-	NTSTATUS status;
-	uint32_t access_granted;
-	struct object_tree *root = NULL;
-	struct object_tree *new_node = NULL;
-	const struct GUID *guid;
-	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-	struct security_token *token = acl_user_token(module);
-	if (class_name) {
-		guid = class_schemaid_guid_by_lDAPDisplayName(schema, class_name);
-		if (!guid) {
-			DEBUG(10, ("acl_search: cannot find class %s\n",
-				   class_name));
-			goto fail;
-		}
-		if (!insert_in_object_tree(tmp_ctx,
-					   guid, access,
-					   &root, &new_node)) {
-			DEBUG(10, ("acl_search: cannot add to object tree guid\n"));
-			goto fail;
-		}
-	}
-	status = sec_access_check_ds(sd, token,
-				     access,
-				     &access_granted,
-				     root,
-				     rp_sid);
-	if (!NT_STATUS_IS_OK(status)) {
-		ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
-	}
-	else {
-		ret = LDB_SUCCESS;
-	}
-	return ret;
-fail:
-	return ldb_operr(ldb_module_get_ctx(module));
-}
-
 static int acl_allowedAttributes(struct ldb_module *module,
 				 const struct dsdb_schema *schema,
 				 struct ldb_message *sd_msg,
@@ -647,44 +479,6 @@ static int acl_add(struct ldb_module *module, struct ldb_request *req)
 	return ldb_next_request(module, req);
 }
 
-/* checks for validated writes */
-static int acl_check_extended_right(TALLOC_CTX *mem_ctx,
-				    struct security_descriptor *sd,
-				    struct security_token *token,
-				    const char *ext_right,
-				    uint32_t right_type,
-				    struct dom_sid *sid)
-{
-	struct GUID right;
-	NTSTATUS status;
-	uint32_t access_granted;
-	struct object_tree *root = NULL;
-	struct object_tree *new_node = NULL;
-	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-
-	GUID_from_string(ext_right, &right);
-
-	if (!insert_in_object_tree(tmp_ctx, &right, right_type,
-				   &root, &new_node)) {
-		DEBUG(10, ("acl_ext_right: cannot add to object tree\n"));
-		talloc_free(tmp_ctx);
-		return LDB_ERR_OPERATIONS_ERROR;
-	}
-	status = sec_access_check_ds(sd, token,
-				     right_type,
-				     &access_granted,
-				     root,
-				     sid);
-
-	if (!NT_STATUS_IS_OK(status)) {
-		talloc_free(tmp_ctx);
-		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
-	}
-	talloc_free(tmp_ctx);
-	return LDB_SUCCESS;
-}
-
-
 /* ckecks if modifications are allowed on "Member" attribute */
 static int acl_check_self_membership(TALLOC_CTX *mem_ctx,
 				     struct ldb_module *module,
@@ -1352,20 +1146,6 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req)
 	return ldb_next_request(module, down_req);
 }
 
-static const char *acl_user_name(TALLOC_CTX *mem_ctx, struct ldb_module *module)
-{
-	struct ldb_context *ldb = ldb_module_get_ctx(module);
-	struct auth_session_info *session_info
-		= (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
-	if (!session_info) {
-		return "UNKNOWN (NULL)";
-	}
-
-	return talloc_asprintf(mem_ctx, "%s\\%s",
-			       session_info->server_info->domain_name,
-			       session_info->server_info->account_name);
-}
-
 static int acl_extended(struct ldb_module *module, struct ldb_request *req)
 {
 	struct ldb_context *ldb = ldb_module_get_ctx(module);
diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c
new file mode 100644
index 0000000..49d9095
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c
@@ -0,0 +1,307 @@
+/*
+  ldb database library
+
+  Copyright (C) Simo Sorce 2006-2008
+  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: ldb
+ *
+ *  Component: ldb ACL Read module
+ *
+ *  Description: Module that performs authorisation access checks on read requests
+ *               Only DACL checks implemented at this point
+ *
+ *  Author: Nadezhda Ivanova
+ */
+
+#include "includes.h"
+#include "ldb_module.h"
+#include "auth/auth.h"
+#include "libcli/security/security.h"
+#include "dsdb/samdb/samdb.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "param/param.h"
+#include "dsdb/samdb/ldb_modules/util.h"
+
+
+struct aclread_context {
+	struct ldb_module *module;
+	struct ldb_request *req;
+	const char * const *attrs;
+	const struct dsdb_schema *schema;
+};
+
+struct aclread_private {
+	bool enabled;
+};
+
+static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+	 struct ldb_context *ldb;
+	 struct aclread_context *ac;
+	 struct ldb_result *acl_res;
+	 struct ldb_message_element *parent;
+	 static const char *acl_attrs[] = {
+		 "nTSecurityDescriptor",
+		 "objectSid",
+		 "parentGUID",
+		 NULL
+	 };
+	 int i, ret;
+	 struct security_descriptor *sd;
+	 struct dom_sid *sid = NULL;
+	 TALLOC_CTX *tmp_ctx;
+	 ac = talloc_get_type(req->context, struct aclread_context);
+	 ldb = ldb_module_get_ctx(ac->module);
+	 if (!ares) {
+		 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR );
+	 }
+	 if (ares->error != LDB_SUCCESS) {
+		 return ldb_module_done(ac->req, ares->controls,
+					ares->response, ares->error);
+	 }
+	 tmp_ctx = talloc_new(ac);
+	 switch (ares->type) {
+	 case LDB_REPLY_ENTRY:
+		 ret = dsdb_module_search_dn(ac->module, tmp_ctx, &acl_res, ares->message->dn,
+					     acl_attrs,
+					     DSDB_FLAG_NEXT_MODULE |
+					     DSDB_SEARCH_SHOW_DELETED);
+		 if (ret != LDB_SUCCESS) {
+			 goto fail;
+		 }
+		 ret = dsdb_get_sd_from_ldb_message(ldb, tmp_ctx, acl_res->msgs[0], &sd);
+		 if (ret != LDB_SUCCESS) {
+			 DEBUG(10, ("acl_read: cannot get descriptor\n"));
+			 ret = LDB_ERR_OPERATIONS_ERROR;
+			 goto fail;
+		 }
+		 sid = samdb_result_dom_sid(tmp_ctx, acl_res->msgs[0], "objectSid");
+		 /* get the parent guid */
+		 parent = ldb_msg_find_element(acl_res->msgs[0], "parentGUID");
+		 if (parent) {
+			 /* the object has a parent, so we have to check for visibility */
+			 struct GUID parent_guid = samdb_result_guid(acl_res->msgs[0], "parentGUID");
+			 ret = dsdb_module_check_access_on_guid(ac->module,
+								tmp_ctx,
+								&parent_guid,
+								SEC_ADS_LIST,
+								NULL);
+			 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+				 talloc_free(tmp_ctx);
+				 return LDB_SUCCESS;
+			 } else if (ret != LDB_SUCCESS) {
+				 goto fail;
+			 }
+		 }
+		 /* for every element in the message check RP */
+		 i = 0;
+		 while (i < ares->message->num_elements) {
+			 char *p, *new_attr;
+			 const struct dsdb_attribute *attr;
+			 p = strchr(ares->message->elements[i].name, ';');
+			 if (!p) {
+				 attr =  dsdb_attribute_by_lDAPDisplayName(ac->schema,
+									   ares->message->elements[i].name);
+			 } else {
+				 new_attr = talloc_strndup(tmp_ctx,
+							   ares->message->elements[i].name,
+							   (size_t)(p -ares->message->elements[i].name));
+				 if (!new_attr) {
+					 ldb_oom(ldb);
+					 ret = LDB_ERR_OPERATIONS_ERROR;
+					 goto fail;
+				 }
+				 attr =  dsdb_attribute_by_lDAPDisplayName(ac->schema,
+									   new_attr);
+				 talloc_free(new_attr);
+			 }
+
+			 if (!attr) {
+				 DEBUG(2, ("acl_read: cannot find attribute %s in schema\n",
+					   ares->message->elements[i].name));
+				 ret = LDB_ERR_OPERATIONS_ERROR;
+				 goto fail;
+			 }
+			 /* nTSecurityDescriptor is a special case */
+			 if (ldb_attr_cmp("nTSecurityDescriptor",
+					  ares->message->elements[i].name) == 0) {
+				 ret = acl_check_access_on_attribute(ac->module,
+								     tmp_ctx,
+								     sd,
+								     sid,
+								     SEC_FLAG_SYSTEM_SECURITY,
+								     attr);
+			 } else {
+				 ret = acl_check_access_on_attribute(ac->module,
+								     tmp_ctx,
+								     sd,
+								     sid,
+								     SEC_ADS_READ_PROP,
+								     attr);
+			 }
+			 if (ret == LDB_SUCCESS) {
+				 i++;
+			 } else if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+				 /* do not return this entry if attribute is
+					    part of the search filter */
+				 if (dsdb_attr_in_parse_tree(ac->req->op.search.tree,
+							     ares->message->elements[i].name)) {
+					 talloc_free(tmp_ctx);
+					 return LDB_SUCCESS;
+				 }
+				 ldb_msg_remove_attr(ares->message, ares->message->elements[i].name);
+			 } else {
+				 goto fail;
+			 }
+		 }
+		 talloc_free(tmp_ctx);
+		 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
+	 case LDB_REPLY_REFERRAL:
+		 return ldb_module_send_referral(ac->req, ares->referral);
+	 case LDB_REPLY_DONE:
+		 return ldb_module_done(ac->req, ares->controls,
+					ares->response, LDB_SUCCESS);
+
+	 }
+	 return LDB_SUCCESS;
+fail:
+	 talloc_free(tmp_ctx);
+	 return ldb_module_done(ac->req, NULL, NULL, ret);
+}
+
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list