[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