diff options
author | Nadezhda Ivanova <nadezhda.ivanova@postpath.com> | 2009-09-14 19:44:41 +0300 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2009-09-16 07:52:05 -0700 |
commit | d70e17171912c190b258848edb1ae627fe59cde4 (patch) | |
tree | 91293861c1a4447a85f0c63dd65928cb706dee02 | |
parent | fec33db90ebd998f17ed2d539d67abb448e09af2 (diff) | |
download | samba-d70e17171912c190b258848edb1ae627fe59cde4.tar.gz samba-d70e17171912c190b258848edb1ae627fe59cde4.tar.bz2 samba-d70e17171912c190b258848edb1ae627fe59cde4.zip |
Owner and group defaulting.
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r-- | libcli/security/security_descriptor.c | 2 | ||||
-rw-r--r-- | libcli/security/security_descriptor.h | 3 | ||||
-rw-r--r-- | librpc/idl/security.idl | 34 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/config.mk | 12 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/descriptor.c | 459 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/objectclass.c | 65 | ||||
-rw-r--r-- | source4/libcli/security/config.mk | 2 | ||||
-rw-r--r-- | source4/libcli/security/create_descriptor.c | 117 | ||||
-rw-r--r-- | source4/scripting/python/samba/provision.py | 1 |
9 files changed, 636 insertions, 59 deletions
diff --git a/libcli/security/security_descriptor.c b/libcli/security/security_descriptor.c index f18a326e99..dbe11604fd 100644 --- a/libcli/security/security_descriptor.c +++ b/libcli/security/security_descriptor.c @@ -50,7 +50,7 @@ struct security_descriptor *security_descriptor_initialise(TALLOC_CTX *mem_ctx) return sd; } -static struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx, +struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx, const struct security_acl *oacl) { struct security_acl *nacl; diff --git a/libcli/security/security_descriptor.h b/libcli/security/security_descriptor.h index c535f5d253..a377ef59ce 100644 --- a/libcli/security/security_descriptor.h +++ b/libcli/security/security_descriptor.h @@ -61,4 +61,7 @@ struct security_ace *security_ace_create(TALLOC_CTX *mem_ctx, uint32_t access_mask, uint8_t flags); +struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx, + const struct security_acl *oacl); + #endif /* __SECURITY_DESCRIPTOR_H__ */ diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl index 9728c7fb07..96d24b6685 100644 --- a/librpc/idl/security.idl +++ b/librpc/idl/security.idl @@ -159,6 +159,32 @@ interface security SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER); /* 0x000f0000 */ + /* generic->specific mappings for Directory Service objects */ + /* directory specific part of GENERIC_ALL */ + const int SEC_ADS_GENERIC_ALL_DS = + (SEC_STD_DELETE | + SEC_STD_WRITE_DAC | + SEC_STD_WRITE_OWNER | + SEC_ADS_CREATE_CHILD | + SEC_ADS_DELETE_CHILD | + SEC_ADS_DELETE_TREE | + SEC_ADS_CONTROL_ACCESS); + const int SEC_ADS_GENERIC_EXECUTE = SEC_STD_READ_CONTROL | SEC_ADS_LIST; + const int SEC_ADS_GENERIC_WRITE = + (SEC_STD_READ_CONTROL | + SEC_ADS_SELF_WRITE | + SEC_ADS_WRITE_PROP); + const int SEC_ADS_GENERIC_READ = + (SEC_STD_READ_CONTROL | + SEC_ADS_LIST | + SEC_ADS_READ_PROP | + SEC_ADS_LIST_OBJECT); + const int SEC_ADS_GENERIC_ALL = + (SEC_ADS_GENERIC_EXECUTE | + SEC_ADS_GENERIC_WRITE | + SEC_ADS_GENERIC_READ | + SEC_ADS_GENERIC_ALL_DS); + /***************************************************************/ /* WELL KNOWN SIDS */ @@ -397,6 +423,7 @@ interface security uint32 num_sids; [size_is(num_sids)] dom_sid *sids[*]; udlong privilege_mask; + security_acl *default_dacl; } security_token; /* bits that determine which parts of a security descriptor @@ -420,4 +447,11 @@ interface security KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 = 0x00000010 } kerb_EncTypes; + typedef [public,bitmap32bit] bitmap { + SEC_DACL_AUTO_INHERIT = 0x00000001, + SEC_SACL_AUTO_INHERIT = 0x00000002, + SEC_DEFAULT_DESCRIPTOR = 0x00000004, + SEC_OWNER_FROM_PARENT = 0x00000008, + SEC_GROUP_FROM_PARENT = 0x00000010 + } security_autoinherit; } diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index 18144dd2c5..f868f8a9db 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -334,3 +334,15 @@ INIT_FUNCTION = LDB_MODULE(operational) ################################################ ldb_operational_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/operational.o + +################################################ +# Start MODULE ldb_descriptor +[MODULE::ldb_descriptor] +INIT_FUNCTION = LDB_MODULE(descriptor) +CFLAGS = -Ilib/ldb/include +PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBSECURITY NDR_SECURITY SAMDB +SUBSYSTEM = LIBLDB +# End MODULE ldb_descriptor +################################################ + +ldb_descriptor_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/descriptor.o diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c new file mode 100644 index 0000000000..a22cce76a1 --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -0,0 +1,459 @@ + /* + ldb database library + + Copyright (C) Simo Sorce 2006-2008 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007 + Copyright (C) Nadezhda Ivanova 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: DS Security descriptor module + * + * Description: + * - Calculate the security descriptor of a newly created object + * - Perform sd recalculation on a move operation + * - Handle sd modification invariants + * + * Author: Nadezhda Ivanova + */ + +#include "includes.h" +#include "ldb_module.h" +#include "dlinklist.h" +#include "dsdb/samdb/samdb.h" +#include "librpc/ndr/libndr.h" +#include "librpc/gen_ndr/ndr_security.h" +#include "libcli/security/security.h" +#include "auth/auth.h" +#include "param/param.h" + +struct descriptor_context { + struct ldb_module *module; + struct ldb_request *req; + struct ldb_reply *search_res; + int (*step_fn)(struct descriptor_context *); +}; + +static struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema, struct ldb_message_element *element) +{ + struct dsdb_class *last_class = NULL; + int i; + for (i = 0; i < element->num_values; i++){ + if (!last_class) + last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]); + else { + struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]); + if (tmp_class->subClass_order > last_class->subClass_order) + last_class = tmp_class; + } + } + return last_class; +} + +struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx, + struct ldb_dn *dn, + struct security_token *token, + struct ldb_context *ldb) +{ + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + struct ldb_dn *root_base_dn = ldb_get_root_basedn(ldb); + struct ldb_dn *schema_base_dn = ldb_get_schema_basedn(ldb); + struct ldb_dn *config_base_dn = ldb_get_config_basedn(ldb); + const struct dom_sid *domain_sid = samdb_domain_sid(ldb); + struct dom_sid *da_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS); + struct dom_sid *ea_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ENTERPRISE_ADMINS); + struct dom_sid *sa_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_SCHEMA_ADMINS); + struct dom_sid *dag_sid; + + if (ldb_dn_compare_base(schema_base_dn, dn) == 0){ + if (security_token_has_sid(token, sa_sid)) + dag_sid = dom_sid_dup(mem_ctx, sa_sid); + else if (security_token_has_sid(token, ea_sid)) + dag_sid = dom_sid_dup(mem_ctx, ea_sid); + else if (security_token_has_sid(token, da_sid)) + dag_sid = dom_sid_dup(mem_ctx, da_sid); + else + dag_sid = NULL; + } + else if (ldb_dn_compare_base(config_base_dn, dn) == 0){ + if (security_token_has_sid(token, ea_sid)) + dag_sid = dom_sid_dup(mem_ctx, ea_sid); + else if (security_token_has_sid(token, da_sid)) + dag_sid = dom_sid_dup(mem_ctx, da_sid); + else + dag_sid = NULL; + } + else if (ldb_dn_compare_base(root_base_dn, dn) == 0){ + if (security_token_has_sid(token, da_sid)) + dag_sid = dom_sid_dup(mem_ctx, da_sid); + else if (security_token_has_sid(token, ea_sid)) + dag_sid = dom_sid_dup(mem_ctx, ea_sid); + else + dag_sid = NULL; + } + else + dag_sid = NULL; + + talloc_free(tmp_ctx); + return dag_sid; +} + +static struct security_descriptor *get_sd_unpacked(struct ldb_module *module, TALLOC_CTX *mem_ctx, + const struct dsdb_class *objectclass) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct security_descriptor *sd; + const struct dom_sid *domain_sid = samdb_domain_sid(ldb); + + if (!objectclass->defaultSecurityDescriptor || !domain_sid) { + return NULL; + } + + sd = sddl_decode(mem_ctx, + objectclass->defaultSecurityDescriptor, + domain_sid); + return sd; +} + +static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb, + struct dom_sid *dag) +{ + int *domainFunctionality; + + domainFunctionality = talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int); + + if (*domainFunctionality && (*domainFunctionality >= DS_BEHAVIOR_WIN2008)){ + return dag; + } + + return NULL; +} + +static DATA_BLOB *get_new_descriptor(struct ldb_module *module, + struct ldb_dn *dn, + TALLOC_CTX *mem_ctx, + const struct dsdb_class *objectclass, + struct ldb_val *parent, + struct ldb_val *object) +{ + struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL; + struct security_descriptor *new_sd; + DATA_BLOB *linear_sd; + enum ndr_err_code ndr_err; + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct auth_session_info *session_info + = ldb_get_opaque(ldb, "sessionInfo"); + const struct dom_sid *domain_sid = samdb_domain_sid(ldb); + char *sddl_sd; + struct dom_sid *default_owner; + struct dom_sid *default_group; + + if (object){ + user_descriptor = talloc(mem_ctx, struct security_descriptor); + if(!user_descriptor) + return NULL; + ndr_err = ndr_pull_struct_blob(object, user_descriptor, NULL, + user_descriptor, + (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)){ + talloc_free(user_descriptor); + return NULL; + } + } + else + user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass); + + if (parent){ + parent_descriptor = talloc(mem_ctx, struct security_descriptor); + if(!parent_descriptor) + return NULL; + ndr_err = ndr_pull_struct_blob(parent, parent_descriptor, NULL, + parent_descriptor, + (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)){ + talloc_free(parent_descriptor); + return NULL; + } + } + default_owner = get_default_ag(mem_ctx, dn, + session_info->security_token, ldb); + default_group = get_default_group(mem_ctx, ldb, default_owner); + new_sd = create_security_descriptor(mem_ctx, parent_descriptor, user_descriptor, true, + NULL, SEC_DACL_AUTO_INHERIT|SEC_SACL_AUTO_INHERIT, + session_info->security_token, + default_owner, default_group, + map_generic_rights_ds); + if (!new_sd) + return NULL; + + + sddl_sd = sddl_encode(mem_ctx, new_sd, domain_sid); + DEBUG(10, ("Object %s created with desriptor %s", ldb_dn_get_linearized(dn), sddl_sd)); + + linear_sd = talloc(mem_ctx, DATA_BLOB); + if (!linear_sd) { + return NULL; + } + + ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx, + lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), + new_sd, + (ndr_push_flags_fn_t)ndr_push_security_descriptor); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return NULL; + } + + return linear_sd; +} + +static struct descriptor_context *descriptor_init_context(struct ldb_module *module, + struct ldb_request *req) +{ + struct ldb_context *ldb; + struct descriptor_context *ac; + + ldb = ldb_module_get_ctx(module); + + ac = talloc_zero(req, struct descriptor_context); + if (ac == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + return NULL; + } + + ac->module = module; + ac->req = req; + return ac; +} + +static int get_search_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct descriptor_context *ac; + int ret; + + ac = talloc_get_type(req->context, struct descriptor_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 && + ares->error != LDB_ERR_NO_SUCH_OBJECT) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + if (ac->search_res != NULL) { + ldb_set_errstring(ldb, "Too many results"); + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + + ac->search_res = talloc_steal(ac, ares); + break; + + case LDB_REPLY_REFERRAL: + /* ignore */ + talloc_free(ares); + break; + + case LDB_REPLY_DONE: + talloc_free(ares); + ret = ac->step_fn(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + break; + } + + return LDB_SUCCESS; +} +static int descriptor_op_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct descriptor_context *ac; + + ac = talloc_get_type(req->context, struct descriptor_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 descriptor_do_add(struct descriptor_context *ac) +{ + struct ldb_context *ldb; + const struct dsdb_schema *schema; + struct ldb_request *add_req; + struct ldb_message_element *objectclass_element, *sd_element = NULL; + struct ldb_message *msg; + TALLOC_CTX *mem_ctx; + int ret; + struct ldb_val *sd_val = NULL, *parentsd_val = NULL; + DATA_BLOB *sd; + struct dsdb_class *objectclass; + + ldb = ldb_module_get_ctx(ac->module); + schema = dsdb_get_schema(ldb); + + mem_ctx = talloc_new(ac); + if (mem_ctx == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message); + + /* get the security descriptor values*/ + sd_element = ldb_msg_find_element(msg, "nTSecurityDescriptor"); + objectclass_element = ldb_msg_find_element(msg, "objectClass"); + objectclass = get_last_structural_class(schema, objectclass_element); + + if (!objectclass) + return LDB_ERR_OPERATIONS_ERROR; + + if (sd_element) + sd_val = &sd_element->values[0]; + /* NC's have no parent */ + if ((ldb_dn_compare(msg->dn, (ldb_get_schema_basedn(ldb))) == 0) || + (ldb_dn_compare(msg->dn, (ldb_get_config_basedn(ldb))) == 0) || + (ldb_dn_compare(msg->dn, (ldb_get_root_basedn(ldb))) == 0)) + parentsd_val = NULL; + else if (ac->search_res != NULL) + parentsd_val = ldb_msg_find_ldb_val(ac->search_res->message, "nTSecurityDescriptor"); + + + /* get the parent descriptor and the one provided. If not provided, get the default.*/ + /* convert to security descriptor and calculate */ + sd = get_new_descriptor(ac->module, msg->dn, mem_ctx, objectclass, + parentsd_val, sd_val); + if (sd) { + ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd); + } + + talloc_free(mem_ctx); + ret = ldb_msg_sanity_check(ldb, msg); + + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_add_req(&add_req, ldb, ac, + msg, + ac->req->controls, + ac, descriptor_op_callback, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + + /* perform the add */ + return ldb_next_request(ac->module, add_req); +} + +static int descriptor_add(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb; + struct ldb_request *search_req; + struct descriptor_context *ac; + struct ldb_dn *parent_dn; + int ret; + static const char * const descr_attrs[] = { "nTSecurityDescriptor", NULL }; + + ldb = ldb_module_get_ctx(module); + + ldb_debug(ldb, LDB_DEBUG_TRACE, "descriptor_add\n"); + + if (ldb_dn_is_special(req->op.add.message->dn)) { + return ldb_next_request(module, req); + } + + ac = descriptor_init_context(module, req); + if (ac == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* If there isn't a parent, just go on to the add processing */ + if (ldb_dn_get_comp_num(ac->req->op.add.message->dn) == 1) { + return descriptor_do_add(ac); + } + + /* get copy of parent DN */ + parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn); + if (parent_dn == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_build_search_req(&search_req, ldb, + ac, parent_dn, LDB_SCOPE_BASE, + "(objectClass=*)", descr_attrs, + NULL, + ac, get_search_callback, + req); + if (ret != LDB_SUCCESS) { + return ret; + } + talloc_steal(search_req, parent_dn); + + ac->step_fn = descriptor_do_add; + + return ldb_next_request(ac->module, search_req); +} +/* TODO */ +static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + ldb_debug(ldb, LDB_DEBUG_TRACE, "descriptor_modify\n"); + return ldb_next_request(module, req); +} +/* TODO */ +static int descriptor_rename(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_context *ldb = ldb_module_get_ctx(module); + ldb_debug(ldb, LDB_DEBUG_TRACE, "descriptor_rename\n"); + return ldb_next_request(module, req); +} + +_PUBLIC_ const struct ldb_module_ops ldb_descriptor_module_ops = { + .name = "descriptor", + .add = descriptor_add, + .modify = descriptor_modify, + .rename = descriptor_rename, +}; + + diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index 6dbafac965..0246de130c 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -231,49 +231,6 @@ static int objectclass_sort(struct ldb_module *module, return LDB_ERR_OBJECT_CLASS_VIOLATION; } -static DATA_BLOB *get_sd(struct ldb_module *module, TALLOC_CTX *mem_ctx, - const struct dsdb_class *objectclass) -{ - struct ldb_context *ldb = ldb_module_get_ctx(module); - enum ndr_err_code ndr_err; - DATA_BLOB *linear_sd; - struct auth_session_info *session_info - = ldb_get_opaque(ldb, "sessionInfo"); - struct security_descriptor *sd; - const struct dom_sid *domain_sid = samdb_domain_sid(ldb); - - if (!objectclass->defaultSecurityDescriptor || !domain_sid) { - return NULL; - } - - sd = sddl_decode(mem_ctx, - objectclass->defaultSecurityDescriptor, - domain_sid); - - if (!sd || !session_info || !session_info->security_token) { - return NULL; - } - - sd->owner_sid = session_info->security_token->user_sid; - sd->group_sid = session_info->security_token->group_sid; - - linear_sd = talloc(mem_ctx, DATA_BLOB); - if (!linear_sd) { - return NULL; - } - - ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx, - lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), - sd, - (ndr_push_flags_fn_t)ndr_push_security_descriptor); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return NULL; - } - - return linear_sd; - -} - static int get_search_callback(struct ldb_request *req, struct ldb_reply *ares) { struct ldb_context *ldb; @@ -536,7 +493,6 @@ static int objectclass_do_add(struct oc_context *ac) return LDB_ERR_UNWILLING_TO_PERFORM; } } - if (schema) { ret = fix_attributes(ldb, schema, msg); if (ret != LDB_SUCCESS) { @@ -546,7 +502,7 @@ static int objectclass_do_add(struct oc_context *ac) /* This is now the objectClass list from the database */ objectclass_element = ldb_msg_find_element(msg, "objectClass"); - + if (!objectclass_element) { /* Where did it go? bail now... */ talloc_free(mem_ctx); @@ -565,10 +521,10 @@ static int objectclass_do_add(struct oc_context *ac) talloc_free(mem_ctx); return ret; } - + /* We must completely replace the existing objectClass entry, * because we need it sorted */ - + /* Move from the linked list back into an ldb msg */ for (current = sorted; current; current = current->next) { value = talloc_strdup(msg, current->objectclass->lDAPDisplayName); @@ -579,7 +535,7 @@ static int objectclass_do_add(struct oc_context *ac) } ret = ldb_msg_add_string(msg, "objectClass", value); if (ret != LDB_SUCCESS) { - ldb_set_errstring(ldb, + ldb_set_errstring(ldb, "objectclass: could not re-add sorted " "objectclass to modify msg"); talloc_free(mem_ctx); @@ -589,6 +545,7 @@ static int objectclass_do_add(struct oc_context *ac) if (!current->next) { struct ldb_message_element *el; int32_t systemFlags = 0; + DATA_BLOB *sd; if (!ldb_msg_find_element(msg, "objectCategory")) { value = talloc_strdup(msg, current->objectclass->defaultObjectCategory); if (value == NULL) { @@ -599,15 +556,9 @@ static int objectclass_do_add(struct oc_context *ac) ldb_msg_add_string(msg, "objectCategory", value); } if (!ldb_msg_find_element(msg, "showInAdvancedViewOnly") && (current->objectclass->defaultHidingValue == true)) { - ldb_msg_add_string(msg, "showInAdvancedViewOnly", + ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE"); } - if (!ldb_msg_find_element(msg, "nTSecurityDescriptor")) { - DATA_BLOB *sd = get_sd(ac->module, mem_ctx, current->objectclass); - if (sd) { - ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd); - } - } /* There are very special rules for systemFlags, see MS-ADTS 3.1.1.5.2.4 */ el = ldb_msg_find_element(msg, "systemFlags"); @@ -619,7 +570,7 @@ static int objectclass_do_add(struct oc_context *ac) /* systemFlags &= ( SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_LIMITED_MOVE); */ ldb_msg_remove_element(msg, el); } - + /* This flag is only allowed on attributeSchema objects */ if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, "attributeSchema") == 0) { systemFlags &= ~SYSTEM_FLAG_ATTR_IS_RDN; @@ -632,7 +583,7 @@ static int objectclass_do_add(struct oc_context *ac) || ldb_attr_cmp(current->objectclass->lDAPDisplayName, "ntDSDSA") == 0) { systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE); - } else if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, "siteLink") == 0 + } else if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, "siteLink") == 0 || ldb_attr_cmp(current->objectclass->lDAPDisplayName, "siteLinkBridge") == 0 || ldb_attr_cmp(current->objectclass->lDAPDisplayName, "nTDSConnection") == 0) { systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME); diff --git a/source4/libcli/security/config.mk b/source4/libcli/security/config.mk index d08c25d66f..ca545f817f 100644 --- a/source4/libcli/security/config.mk +++ b/source4/libcli/security/config.mk @@ -2,6 +2,6 @@ PUBLIC_DEPENDENCIES = LIBNDR LIBSECURITY_COMMON LIBSECURITY_OBJ_FILES = $(addprefix $(libclisrcdir)/security/, \ - security_token.o access_check.o privilege.o sddl.o) \ + security_token.o access_check.o privilege.o sddl.o create_descriptor.o) \ $(eval $(call proto_header_template,$(libclisrcdir)/security/proto.h,$(LIBSECURITY_OBJ_FILES:.o=.c))) diff --git a/source4/libcli/security/create_descriptor.c b/source4/libcli/security/create_descriptor.c new file mode 100644 index 0000000000..6a928273b7 --- /dev/null +++ b/source4/libcli/security/create_descriptor.c @@ -0,0 +1,117 @@ +/* + Copyright (C) Nadezhda Ivanova 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: create_descriptor + * + * Component: routines for calculating and creating security descriptors + * as described in MS-DTYP 2.5.2.2 + * + * Description: + * + * + * Author: Nadezhda Ivanova + */ +#include "includes.h" +#include "libcli/security/security.h" + +/* the mapping function for generic rights for DS.(GA,GR,GW,GX) + * The mapping function is passed as an argument to the + * descriptor calculating routine and depends on the security + * manager that calls the calculating routine. + * TODO: need similar mappings for the file system and + * registry security managers in order to make this code + * generic for all security managers + */ + +uint32_t map_generic_rights_ds(uint32_t access_mask) +{ + if (access_mask & SEC_GENERIC_ALL){ + access_mask |= SEC_ADS_GENERIC_ALL; + access_mask = ~SEC_GENERIC_ALL; + } + + if (access_mask & SEC_GENERIC_EXECUTE){ + access_mask |= SEC_ADS_GENERIC_EXECUTE; + access_mask = ~SEC_GENERIC_EXECUTE; + } + + if (access_mask & SEC_GENERIC_WRITE){ + access_mask |= SEC_ADS_GENERIC_WRITE; + access_mask &= ~SEC_GENERIC_WRITE; + } + + if (access_mask & SEC_GENERIC_READ){ + access_mask |= SEC_ADS_GENERIC_READ; + access_mask &= ~SEC_GENERIC_READ; + } + + return access_mask; +} + +struct security_descriptor *create_security_descriptor(TALLOC_CTX *mem_ctx, + struct security_descriptor *parent_sd, + struct security_descriptor *creator_sd, + bool is_container, + struct GUID *object_list, + uint32_t inherit_flags, + struct security_token *token, + struct dom_sid *default_owner, /* valid only for DS, NULL for the other RSs */ + struct dom_sid *default_group, /* valid only for DS, NULL for the other RSs */ + uint32_t (*generic_map)(uint32_t access_mask)) +{ + struct security_descriptor *new_sd; + struct dom_sid *new_owner = NULL; + struct dom_sid *new_group = NULL; + + new_sd = security_descriptor_initialise(mem_ctx); + if (!new_sd) + return NULL; + if (!creator_sd || !creator_sd->owner_sid){ + if (inherit_flags & SEC_OWNER_FROM_PARENT) + new_owner = parent_sd->owner_sid; + else if (!default_owner) + new_owner = token->user_sid; + else + new_owner = default_owner; + } + else + new_owner = creator_sd->owner_sid; + + if (!creator_sd || !creator_sd->group_sid){ + if (inherit_flags & SEC_GROUP_FROM_PARENT && parent_sd) + new_group = parent_sd->group_sid; + else if (!default_group) + new_group = token->group_sid; + else new_group = default_group; + } + else + new_group = creator_sd->group_sid; + + new_sd->owner_sid = talloc_memdup(new_sd, new_owner, sizeof(struct dom_sid)); + new_sd->group_sid = talloc_memdup(new_sd, new_group, sizeof(struct dom_sid)); + if (!new_sd->owner_sid || !new_sd->group_sid){ + talloc_free(new_sd); + return NULL; + } + /* Todo remove */ + if (creator_sd && creator_sd->type & SEC_DESC_DACL_PRESENT){ + new_sd->dacl = security_acl_dup(new_sd, creator_sd->dacl); + new_sd->type |= SEC_DESC_DACL_PRESENT; + } + return new_sd; +} diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 8f7859c215..8fef50ca37 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -584,6 +584,7 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, "extended_dn_in", "rdn_name", "objectclass", + "descriptor", "samldb", "password_hash", "operational", |