[SCM] Samba Shared Repository - branch master updated

Nadezhda Ivanova nivanova at samba.org
Thu Nov 5 08:40:15 MST 2009


The branch, master has been updated
       via  1fc47e12.. Version 1.0 of the directory service acls module.
      from  b6303f0... s3: Fix a crash in notify_remove_onelevel when "change notify = no"

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


- Log -----------------------------------------------------------------
commit 1fc47e1228b7f32ad0d6636d09d63d3b1c124aaa
Author: Nadezhda Ivanova <nadezhda.ivanova at postpath.com>
Date:   Thu Nov 5 17:34:12 2009 +0200

    Version 1.0 of the directory service acls module.
    
    At this point, support for checks on LDAP add, delete, rename and modify.
    Old kludge_acl is still there to handle the searches.
    This module is synchronous as the async version was impossible to debug,
    will be converted to async after some user testing.

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/acl.c        | 1305 +++++++--------------------
 source4/dsdb/samdb/ldb_modules/kludge_acl.c |    4 +-
 source4/dsdb/schema/schema_query.c          |   14 +-
 source4/libcli/security/object_tree.c       |  101 ++-
 source4/libcli/security/security.h          |    6 +-
 source4/scripting/python/samba/provision.py |    2 +-
 6 files changed, 419 insertions(+), 1013 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
index 2f12314..f96d429 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -40,30 +40,6 @@
 #include "librpc/gen_ndr/ndr_security.h"
 #include "param/param.h"
 
-/* acl_search helper */
-struct acl_context {
-
-	struct ldb_module *module;
-	struct ldb_request *req;
-	struct ldb_request *down_req;
-
-	/*needed if we have to identify if this is SYSTEM_USER*/
-	enum security_user_level user_type;
-
-	uint32_t access_needed;
-	struct ldb_dn * dn_to_check;
-
-	/* set to true when we need to process the request as a SYSTEM_USER, regardless
-	 * of the user's actual rights - for example when we need to retrieve the
-	 * ntSecurityDescriptor */
-	bool ignore_security;
-	struct security_token *token;
-	/*needed to identify if we have requested these attributes*/
-	bool nTSecurityDescriptor;
-	bool objectClass;
-	int sec_result;
-};
-
 struct extended_access_check_attribute {
 	const char *oa_name;
 	const uint32_t requires_rights;
@@ -73,199 +49,6 @@ struct acl_private{
 	bool perform_check;
 };
 
-static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares);
-
-/*FIXME: Perhaps this should go in the .idl file*/
-#define SEC_GENERIC_ACCESS_NEVER_GRANTED ( 0xFFFFFFFF )
-
-/*Contains a part of the attributes - the ones that have predefined required rights*/
-static const struct extended_access_check_attribute extended_access_checks_table[] =
-{
-	{
-		.oa_name = "nTSecurityDescriptor",
-		.requires_rights = SEC_FLAG_SYSTEM_SECURITY & SEC_STD_READ_CONTROL,
-	},
-	{
-                .oa_name = "pekList",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-        },
-	{
-                .oa_name = "currentValue",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "dBCSPwd",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "unicodePwd",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "ntPwdHistory",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "priorValue",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "supplementalCredentials",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "trustAuthIncoming",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "trustAuthOutgoing",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "ImPwdHistory",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "initialAuthIncoming",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "initialAuthOutgoing",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-	{
-                .oa_name = "msDS-ExecuteScriptPassword",
-                .requires_rights = SEC_GENERIC_ACCESS_NEVER_GRANTED,
-	},
-};
-
-static NTSTATUS extended_access_check(const char *attribute_name, const int access_rights, uint32_t searchFlags)
-{
-	int i = 0;
-	if (access_rights == SEC_GENERIC_ACCESS_NEVER_GRANTED) {
-		return NT_STATUS_ACCESS_DENIED;
-	}
-
-	/*Check if the attribute is in the table first*/
-	for ( i = 0; extended_access_checks_table[i].oa_name; i++ ) {
-		if (ldb_attr_cmp(extended_access_checks_table[i].oa_name, attribute_name) == 0) {
-			if ((access_rights & extended_access_checks_table[i].requires_rights) == access_rights) {
-				return NT_STATUS_OK;
-			} else {
-				return NT_STATUS_ACCESS_DENIED;
-			}
-		}
-	}
-
-	/*Check for attribute whose attributeSchema has 0x80 set in searchFlags*/
-	if ((searchFlags & SEARCH_FLAG_CONFIDENTIAL) == SEARCH_FLAG_CONFIDENTIAL) {
-		if (((SEC_ADS_READ_PROP & SEC_ADS_CONTROL_ACCESS) & access_rights) == access_rights) {
-			return NT_STATUS_OK;
-		} else {
-			return NT_STATUS_ACCESS_DENIED;
-		}
-	}
-
-	/*Check attributes with *special* behaviour*/
-	if (ldb_attr_cmp("msDS-QuotaEffective", attribute_name) == 0 || ldb_attr_cmp("msDS-QuotaUsed", attribute_name) == 0){
-		/*Rights required:
-		 *
-		 *(RIGHT_DS_READ_PROPERTY on the Quotas container or
-		 *((the client is querying the quota for the security principal it is authenticated as) and
-		 *(DS-Query-Self-Quota control access right on the Quotas container))
-		 */
-	}
-
-        if (ldb_attr_cmp("userPassword", attribute_name) == 0) {
-		/*When the dSHeuristics.fUserPwdSupport flag is false, the requester must be granted RIGHT_DS_READ_PROPERTY.
-		 *When the dSHeuristics.fUserPwdSupport flag is true, access is never granted.
-		 */
-	}
-
-	if (ldb_attr_cmp("sDRightsEffective", attribute_name) == 0) {
-		/*FIXME:3.1.1.4.5.4 in MS-ADTS*/
-	}
-
-	if (ldb_attr_cmp("allowedChildClassesEffective", attribute_name) == 0) {
-		/*FIXME:3.1.1.4.5.5 in MS-ADTS*/
-        }
-
-	if (ldb_attr_cmp("allowedAttributesEffective", attribute_name) == 0) {
-		/*FIXME:3.1.1.4.5.7 in MS-ADTS*/
-        }
-
-	if (ldb_attr_cmp("msDS-Approx-Immed-Subordinates", attribute_name) == 0) {
-		/*FIXME:3.1.1.4.5.15 in MS-ADTS*/
-        }
-
-	if (ldb_attr_cmp("msDS-QuotaEffective", attribute_name) == 0) {
-		/*FIXME:3.1.1.4.5.22 in MS-ADTS*/
-        }
-
-	if (ldb_attr_cmp("msDS-ReplAttributeMetaData", attribute_name) == 0 || ldb_attr_cmp("msDS-ReplAttributeMetaData", attribute_name) == 0) {
-		/*The security context of the requester must be granted the following rights on the replPropertyMetaData attribute:
-		 *(RIGHT_DS_READ_PROPERTY)or (DS-Replication-Manage-Topology by ON!nTSecurityDescriptor)
-		 */
-        }
-
-	if (ldb_attr_cmp("msDS-NCReplInboundNeighbors", attribute_name) == 0) {
-		/*The security context of the requester must be granted the following rights on repsFrom:
-		 *(RIGHT_DS_READ_PROPERTY) or (DS-Replication-Manage-Topology) or (DS-Replication-Monitor-Topology)
-		 */
-        }
-
-	if (ldb_attr_cmp("msDS-NCReplOutboundNeighbors", attribute_name) == 0) {
-		/*The security context of the requester must be granted the following rights on repsTo:
-		 *(RIGHT_DS_READ_PROPERTY) or (DS-Replication-Manage-Topology) or (DS-Replication-Monitor-Topology)
-		 */
-        }
-
-	if (ldb_attr_cmp("msDS-NCReplCursors", attribute_name) == 0) {
-		/*The security context of the requester must be granted the following rights on replUpToDateVector: (RIGHT_DS_READ_PROPERTY)
-		 *or (DS-Replication-Manage-Topology) or (DS-Replication-Monitor-Topology)
-		 */
-        }
-
-	if (ldb_attr_cmp("msDS-IsUserCachableAtRodc", attribute_name) == 0) {
-		/*The security context of the requester must be granted
-		 *the DS-Replication-Secrets-Synchronize control access right on the root of the default NC.
-		 */
-        }
-
-	return NT_STATUS_OK;
-}
-
-/* Builds an object tree for object specific access checks */
-static struct object_tree * build_object_tree_form_attr_list(TALLOC_CTX *mem_ctx,   /* Todo this context or separate? */
-							     struct ldb_context *ldb,
-							     const char ** attr_names,
-							     int num_attrs,
-							     const char * object_class,
-							     uint32_t init_access)
-{
-	const struct dsdb_schema *schema = dsdb_get_schema(ldb);
-	const struct GUID *oc_guid = class_schemaid_guid_by_lDAPDisplayName(schema, object_class);
-	struct object_tree *tree;
-	int i;
-
-	if (!oc_guid)
-		return NULL;
-
-	tree = insert_in_object_tree(mem_ctx, oc_guid, NULL, init_access, NULL);
-	if (attr_names){
-		for (i=0; i < num_attrs; i++){
-			const struct dsdb_attribute *attribute = dsdb_attribute_by_lDAPDisplayName(schema,attr_names[i]);
-			if (attribute)
-				insert_in_object_tree(mem_ctx,
-						      &attribute->schemaIDGUID,
-						      &attribute->attributeSecurityGUID,
-						      init_access,
-						      tree);
-		}
-	}
-	return tree;
-}
-
 bool is_root_base_dn(struct ldb_context *ldb, struct ldb_dn *dn_to_check)
 {
 	int result;
@@ -274,559 +57,306 @@ bool is_root_base_dn(struct ldb_context *ldb, struct ldb_dn *dn_to_check)
 	return (result==0);
 }
 
-static int acl_op_callback(struct ldb_request *req, struct ldb_reply *ares)
-{
-	struct acl_context *ac;
-
-	ac = talloc_get_type(req->context, struct acl_context);
-
-	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);
-	}
-
-	if (ares->type != LDB_REPLY_DONE) {
-		talloc_free(ares);
-		return ldb_module_done(ac->req, NULL, NULL,
-					LDB_ERR_OPERATIONS_ERROR);
-	}
-
-	return ldb_module_done(ac->req, ares->controls,
-				ares->response, ares->error);
-}
-
-
-static int acl_access_check_add(struct ldb_reply *ares,
-				struct acl_context *ac,
-				struct security_descriptor *sd)
+static enum security_user_level what_is_user(struct ldb_module *module)
 {
-	uint32_t access_granted = 0;
-	NTSTATUS status;
-	struct ldb_dn *parent;
-	struct ldb_dn *grandparent;
-	struct object_tree *tree = NULL;
-
-	parent = ldb_dn_get_parent(ac->req, ac->req->op.add.message->dn);
-	grandparent = ldb_dn_get_parent(ac->req, parent);
-	if (ldb_dn_compare(ares->message->dn, grandparent) == 0)
-		status = sec_access_check_ds(sd, ac->token,
-					     SEC_ADS_LIST,
-					     &access_granted,
-					     NULL);
-	else if (ldb_dn_compare(ares->message->dn, parent) == 0){
-		struct ldb_message_element *oc_el;
-		struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
-		const struct dsdb_schema *schema = dsdb_get_schema(ldb);
-		int i;
-
-		oc_el = ldb_msg_find_element(ares->message, "objectClass");
-		if (!oc_el || oc_el->num_values == 0)
-			return LDB_SUCCESS;
-		for (i = 0; i < oc_el->num_values; i++){
-			const struct GUID *guid = class_schemaid_guid_by_lDAPDisplayName(schema,
-											  oc_el->values[i].data);
-			ac->sec_result = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
-			tree = insert_in_object_tree(ac->req, guid, NULL, SEC_ADS_CREATE_CHILD,
-						     tree);
-			status = sec_access_check_ds(sd, ac->token, SEC_ADS_CREATE_CHILD,&access_granted, tree);
-			if (NT_STATUS_IS_OK(status))
-				ac->sec_result = LDB_SUCCESS;
-		}
-	}
-	else
-		return LDB_SUCCESS;
-
-	return ac->sec_result;
+	struct ldb_context *ldb = ldb_module_get_ctx(module);
+	struct auth_session_info *session_info
+		= (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
+	return security_session_user_level(session_info);
 }
 
-static int acl_access_check_modify(struct ldb_reply *ares, struct acl_context *ac,
-				   struct security_descriptor *sd)
+static struct security_token *acl_user_token(struct ldb_module *module)
 {
-	uint32_t access_granted = 0;
-	NTSTATUS status;
-	struct ldb_dn *parent;
-	struct object_tree *tree = NULL;
-
-	parent = ldb_dn_get_parent(ac->req, ac->req->op.add.message->dn);
-	if (ldb_dn_compare(ares->message->dn, parent) == 0)
-		status = sec_access_check_ds(sd, ac->token, SEC_ADS_LIST,&access_granted, NULL);
-	else if (ldb_dn_compare(ares->message->dn, ac->req->op.add.message->dn) == 0){
-		struct ldb_message_element *oc_el;
-		struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
-		const struct dsdb_schema *schema = dsdb_get_schema(ldb);
-		int i;
-		struct GUID *guid;
-		oc_el = ldb_msg_find_element(ares->message, "objectClass");
-		if (!oc_el || oc_el->num_values == 0)
-			return LDB_SUCCESS;
-
-		guid = class_schemaid_guid_by_lDAPDisplayName(schema,
-							      oc_el->values[oc_el->num_values-1].data);
-		tree = insert_in_object_tree(ac->req, guid, NULL, SEC_ADS_WRITE_PROP,
-						     tree);
-		for (i=0; i < ac->req->op.mod.message->num_elements; i++){
-			const struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema,
-											      ac->req->op.mod.message->elements[i].name);
-			if (!attr)
-				return LDB_ERR_OPERATIONS_ERROR; /* What should we actually return here? */
-			insert_in_object_tree(ac, &attr->schemaIDGUID,
-					      &attr->attributeSecurityGUID, ac->access_needed, tree);
-		}
-		status = sec_access_check_ds(sd, ac->token, SEC_ADS_WRITE_PROP ,&access_granted, tree);
-		if (!NT_STATUS_IS_OK(status))
-			ac->sec_result = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
+	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;
 	}
-	else
-		return LDB_SUCCESS;
-	return ac->sec_result;
-}
-/*TODO*/
-static int acl_access_check_rename(struct ldb_reply *ares, struct acl_context *ac,
-				   struct security_descriptor *sd)
-{
-	return ac->sec_result;
+	return session_info->security_token;
 }
 
-static int acl_access_check_delete(struct ldb_reply *ares, struct acl_context *ac,
-				   struct security_descriptor *sd)
+static int acl_module_init(struct ldb_module *module)
 {
-	uint32_t access_granted = 0;
-	NTSTATUS status;
-	struct ldb_dn *parent;
-	struct object_tree *tree = NULL;
-
-	parent = ldb_dn_get_parent(ac->req, ac->req->op.del.dn);
-	if (ldb_dn_compare(ares->message->dn, parent) == 0){
-		status = sec_access_check_ds(sd, ac->token, SEC_ADS_LIST,&access_granted, NULL);
-		if (!NT_STATUS_IS_OK(status)){
-			ac->sec_result = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
-			return ac->sec_result;
-		}
-		status = sec_access_check_ds(sd, ac->token, SEC_ADS_DELETE_CHILD,&access_granted, NULL);
-		if (NT_STATUS_IS_OK(status)){
-			ac->sec_result = LDB_SUCCESS;
-			return ac->sec_result;
-		}
-	}
-	else if (ldb_dn_compare(ares->message->dn, ac->req->op.del.dn) == 0){
-		status = sec_access_check_ds(sd, ac->token, SEC_STD_DELETE, &access_granted, NULL);
-		if (!NT_STATUS_IS_OK(status))
-			ac->sec_result = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
-	}
-	return ac->sec_result;
-}
+	struct ldb_context *ldb;
+	struct acl_private *data;
+	int ret;
 
-static int acl_access_check_search(struct ldb_reply *ares, struct acl_context *ac,
-				   struct security_descriptor *sd)
-{
-	uint32_t access_granted;
-	NTSTATUS status;
-	struct ldb_dn *parent;
+	ldb = ldb_module_get_ctx(module);
 
-	if (ac->user_type == SECURITY_SYSTEM || ac->user_type == SECURITY_ANONYMOUS) {
-		return LDB_SUCCESS;/*FIXME: we have anonymous access*/
+	ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
+	if (ret != LDB_SUCCESS) {
+		ldb_debug(ldb, LDB_DEBUG_ERROR,
+			  "acl_module_init: Unable to register control with rootdse!\n");
+		return LDB_ERR_OPERATIONS_ERROR;
 	}
 
-	parent = ldb_dn_get_parent(ac->req, ac->dn_to_check);
-	ac->sec_result = LDB_SUCCESS;
-	if (ldb_dn_compare(ares->message->dn, parent) == 0) {
-		status = sec_access_check_ds(sd, ac->token, SEC_ADS_LIST,&access_granted, NULL);
-		if (!NT_STATUS_IS_OK(status)) {
-			ac->sec_result = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
-		}
-	}
+	data = talloc(module, struct acl_private);
+	data->perform_check = lp_parm_bool(ldb_get_opaque(ldb, "loadparm"),
+				  NULL, "acl", "perform", false);
+	ldb_module_set_private(module, data);
 
-	return ac->sec_result;
+	return ldb_next_init(module);
 }
 
-static int acl_perform_access_check(struct ldb_request *req, struct ldb_reply *ares,
-				    struct acl_context *ac)
+static int get_sd_from_result(TALLOC_CTX *mem_ctx,
+			      struct ldb_result *acl_res,
+			      struct security_descriptor **sd)
 {
-	struct ldb_message_element *oc_el;
-	struct security_descriptor *sd;
+	struct ldb_message_element *sd_element;
 	enum ndr_err_code ndr_err;
 
-	oc_el = ldb_msg_find_element(ares->message, "ntSecurityDescriptor");
-	if (!oc_el || oc_el->num_values == 0)
+	sd_element = ldb_msg_find_element(acl_res->msgs[0], "ntSecurityDescriptor");
+	if (!sd_element) {
 		return LDB_SUCCESS;
-
-	sd = talloc(ac, struct security_descriptor);
-	if(!sd) {
-		return ldb_module_done(ac->req, ares->controls,
-				       ares->response, LDB_ERR_OPERATIONS_ERROR);
 	}
-	ndr_err = ndr_pull_struct_blob(&oc_el->values[0], sd, NULL, sd,
+	*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_module_done(ac->req, ares->controls,
-				       ares->response, LDB_ERR_OPERATIONS_ERROR);
-	switch (ac->req->operation) {
-	case LDB_SEARCH:
-		return acl_access_check_search(ares, ac, sd);
-	case LDB_ADD:
-		return acl_access_check_add(ares, ac, sd);
-	case LDB_MODIFY:
-		return acl_access_check_modify(ares, ac, sd);
-	case LDB_DELETE:
-		return acl_access_check_delete(ares, ac, sd);
-	case LDB_RENAME:
-		return acl_access_check_rename(ares, ac, sd);
-	default:
-		return ldb_module_done(ac->req, ares->controls,
-				       ares->response, LDB_ERR_OPERATIONS_ERROR);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+	       return LDB_ERR_OPERATIONS_ERROR;
 	}
+
 	return LDB_SUCCESS;
 }
 
-static int acl_forward_add(struct ldb_reply *ares,
-			   struct acl_context *ac)
+static const struct GUID *get_oc_guid_from_result(struct ldb_module *module,
+					    struct ldb_result *acl_res)
 {
-  struct ldb_request *newreq;
-	struct ldb_context *ldb;
-	int ret;
-
-	ldb = ldb_module_get_ctx(ac->module);
-	ret = ldb_build_add_req(&newreq,ldb,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list