[SCM] Samba Shared Repository - branch master updated - tevent-0-9-8-621-g9e85192
Nadezhda Ivanova
nivanova at samba.org
Mon Sep 21 18:33:24 MDT 2009
The branch, master has been updated
via 9e85192e6415fbaacf394330f6e61759190485ad (commit)
via 10c6f3f71a4fe3e36e2a0476dc0077187371fafb (commit)
via 13b979b03d86f3ae43dc5fd539fa5d3f22f579a0 (commit)
via 025590e7a4758e86e7942642971b92fc6bab7a8e (commit)
via 6283f2caaa42c7238bdc9c2e8bc1246207645019 (commit)
from b850d7fb08b97fff8ce5ec2cbff2256aa390e440 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 9e85192e6415fbaacf394330f6e61759190485ad
Merge: 10c6f3f71a4fe3e36e2a0476dc0077187371fafb b850d7fb08b97fff8ce5ec2cbff2256aa390e440
Author: Nadezhda Ivanova <nadezhda.ivanova at postpath.com>
Date: Mon Sep 21 17:29:28 2009 -0700
Merge branch 'master' of git://git.samba.org/samba
commit 10c6f3f71a4fe3e36e2a0476dc0077187371fafb
Author: Nadezhda Ivanova <nadezhda.ivanova at postpath.com>
Date: Mon Sep 21 17:27:50 2009 -0700
Initial Implementation of the DS objects access checks.
Currently disabled. The search will be greatly modified,
also the object tree stuff will be simplified.
commit 13b979b03d86f3ae43dc5fd539fa5d3f22f579a0
Merge: 025590e7a4758e86e7942642971b92fc6bab7a8e 1afc7c453c1d5f7e761e46cdc69900305a149820
Author: Nadezhda Ivanova <nadezhda.ivanova at postpath.com>
Date: Mon Sep 21 14:26:15 2009 -0700
Merge branch 'master' of git://git.samba.org/samba
commit 025590e7a4758e86e7942642971b92fc6bab7a8e
Merge: 6283f2caaa42c7238bdc9c2e8bc1246207645019 11bfbc516077d1cead94d0bc70ef24267b9014e7
Author: Nadezhda Ivanova <nadezhda.ivanova at postpath.com>
Date: Sun Sep 20 17:43:46 2009 -0700
Merge branch 'master' of git://git.samba.org/samba
commit 6283f2caaa42c7238bdc9c2e8bc1246207645019
Author: Nadezhda Ivanova <nadezhda.ivanova at postpath.com>
Date: Sun Sep 20 13:50:34 2009 -0700
Initial implementation of security descriptor creation in DS
TODO's:
ACE sorting and clarifying the inheritance of object specific ace's.
-----------------------------------------------------------------------
Summary of changes:
libcli/security/security_descriptor.c | 50 +
libcli/security/security_descriptor.h | 4 +
source4/dsdb/samdb/ldb_modules/acl.c | 1151 +++++++++++++++++++++
source4/dsdb/samdb/ldb_modules/config.mk | 12 +
source4/dsdb/samdb/ldb_modules/kludge_acl.c | 13 +
source4/dsdb/schema/schema_query.c | 12 +
source4/lib/ldb/tests/python/sec_descriptor.py | 13 +-
source4/libcli/security/access_check.c | 135 +++
source4/libcli/security/config.mk | 3 +-
source4/libcli/security/create_descriptor.c | 352 +++++++-
source4/libcli/security/object_tree.c | 106 ++
source4/libcli/security/security.h | 9 +
source4/scripting/python/samba/provision.py | 49 +-
source4/selftest/knownfail | 3 +-
source4/setup/provision_configuration_basedn.ldif | 1 +
source4/setup/provision_schema_basedn.ldif | 1 +
16 files changed, 1899 insertions(+), 15 deletions(-)
create mode 100644 source4/dsdb/samdb/ldb_modules/acl.c
create mode 100644 source4/libcli/security/object_tree.c
Changeset truncated at 500 lines:
diff --git a/libcli/security/security_descriptor.c b/libcli/security/security_descriptor.c
index dbe1160..b77a281 100644
--- a/libcli/security/security_descriptor.c
+++ b/libcli/security/security_descriptor.c
@@ -77,6 +77,56 @@ struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx,
}
+struct security_acl *security_acl_concatenate(TALLOC_CTX *mem_ctx,
+ const struct security_acl *acl1,
+ const struct security_acl *acl2)
+{
+ struct security_acl *nacl;
+ int i;
+
+ if (!acl1 && !acl2)
+ return NULL;
+
+ if (!acl1){
+ nacl = security_acl_dup(mem_ctx, acl2);
+ return nacl;
+ }
+
+ if (!acl2){
+ nacl = security_acl_dup(mem_ctx, acl1);
+ return nacl;
+ }
+
+ nacl = talloc (mem_ctx, struct security_acl);
+ if (nacl == NULL) {
+ return NULL;
+ }
+
+ nacl->revision = acl1->revision;
+ nacl->size = acl1->size + acl2->size;
+ nacl->num_aces = acl1->num_aces + acl2->num_aces;
+
+ if (nacl->num_aces == 0)
+ return nacl;
+
+ nacl->aces = (struct security_ace *)talloc_array (mem_ctx, struct security_ace, acl1->num_aces+acl2->num_aces);
+ if ((nacl->aces == NULL) && (nacl->num_aces > 0)) {
+ goto failed;
+ }
+
+ for (i = 0; i < acl1->num_aces; i++)
+ nacl->aces[i] = acl1->aces[i];
+ for (i = 0; i < acl2->num_aces; i++)
+ nacl->aces[i + acl1->num_aces] = acl2->aces[i];
+
+ return nacl;
+
+ failed:
+ talloc_free (nacl);
+ return NULL;
+
+}
+
/*
talloc and copy a security descriptor
*/
diff --git a/libcli/security/security_descriptor.h b/libcli/security/security_descriptor.h
index a377ef5..bc5761a 100644
--- a/libcli/security/security_descriptor.h
+++ b/libcli/security/security_descriptor.h
@@ -64,4 +64,8 @@ struct security_ace *security_ace_create(TALLOC_CTX *mem_ctx,
struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx,
const struct security_acl *oacl);
+struct security_acl *security_acl_concatenate(TALLOC_CTX *mem_ctx,
+ const struct security_acl *acl1,
+ const struct security_acl *acl2);
+
#endif /* __SECURITY_DESCRIPTOR_H__ */
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
new file mode 100644
index 0000000..1b02abc
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -0,0 +1,1151 @@
+/*
+ ldb database library
+
+ Copyright (C) Simo Sorce 2006-2008
+ Copyright (C) Nadezhda Ivanova 2009
+ Copyright (C) Anatoliy Atanasov 2009
+
+ 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 module
+ *
+ * Description: Module that performs authorisation access checks based on the
+ * account's security context and the DACL of the object being polled.
+ * Only DACL checks implemented at this point
+ *
+ * Authors: Nadezhda Ivanova, Anatoliy Atanasov
+ */
+
+#include "includes.h"
+#include "ldb_module.h"
+#include "auth/auth.h"
+#include "libcli/security/security.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "dsdb/samdb/samdb.h"
+#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;
+};
+
+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;
+ struct ldb_dn *root_base_dn = ldb_get_root_basedn(ldb);
+ result = ldb_dn_compare(root_base_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)
+{
+ 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;
+}
+
+static int acl_access_check_modify(struct ldb_reply *ares, struct acl_context *ac,
+ struct security_descriptor *sd)
+{
+ 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;
+ }
+ 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;
+}
+
+static int acl_access_check_delete(struct ldb_reply *ares, struct acl_context *ac,
+ struct security_descriptor *sd)
+{
+ 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;
--
Samba Shared Repository
More information about the samba-cvs
mailing list