1/* 2 ldb database library 3 4 Copyright (C) Simo Sorce 2006-2008 5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2007 6 Copyright (C) Nadezhda Ivanova 2009 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22/* 23 * Name: ldb 24 * 25 * Component: DS Security descriptor module 26 * 27 * Description: 28 * - Calculate the security descriptor of a newly created object 29 * - Perform sd recalculation on a move operation 30 * - Handle sd modification invariants 31 * 32 * Author: Nadezhda Ivanova 33 */ 34 35#include "includes.h" 36#include "ldb_module.h" 37#include "dlinklist.h" 38#include "dsdb/samdb/samdb.h" 39#include "librpc/ndr/libndr.h" 40#include "librpc/gen_ndr/ndr_security.h" 41#include "libcli/security/security.h" 42#include "auth/auth.h" 43#include "param/param.h" 44 45struct descriptor_data { 46 int _dummy; 47}; 48 49struct descriptor_context { 50 struct ldb_module *module; 51 struct ldb_request *req; 52 struct ldb_reply *search_res; 53 int (*step_fn)(struct descriptor_context *); 54}; 55 56static const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema, struct ldb_message_element *element) 57{ 58 const struct dsdb_class *last_class = NULL; 59 int i; 60 for (i = 0; i < element->num_values; i++){ 61 if (!last_class) { 62 last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]); 63 } else { 64 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]); 65 if (tmp_class->subClass_order > last_class->subClass_order) 66 last_class = tmp_class; 67 } 68 } 69 return last_class; 70} 71 72struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx, 73 struct ldb_dn *dn, 74 struct security_token *token, 75 struct ldb_context *ldb) 76{ 77 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 78 struct ldb_dn *root_base_dn = ldb_get_root_basedn(ldb); 79 struct ldb_dn *schema_base_dn = ldb_get_schema_basedn(ldb); 80 struct ldb_dn *config_base_dn = ldb_get_config_basedn(ldb); 81 const struct dom_sid *domain_sid = samdb_domain_sid(ldb); 82 struct dom_sid *da_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS); 83 struct dom_sid *ea_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ENTERPRISE_ADMINS); 84 struct dom_sid *sa_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_SCHEMA_ADMINS); 85 struct dom_sid *dag_sid; 86 87 if (ldb_dn_compare_base(schema_base_dn, dn) == 0){ 88 if (security_token_has_sid(token, sa_sid)) 89 dag_sid = dom_sid_dup(mem_ctx, sa_sid); 90 else if (security_token_has_sid(token, ea_sid)) 91 dag_sid = dom_sid_dup(mem_ctx, ea_sid); 92 else if (security_token_has_sid(token, da_sid)) 93 dag_sid = dom_sid_dup(mem_ctx, da_sid); 94 else 95 dag_sid = NULL; 96 } 97 else if (ldb_dn_compare_base(config_base_dn, dn) == 0){ 98 if (security_token_has_sid(token, ea_sid)) 99 dag_sid = dom_sid_dup(mem_ctx, ea_sid); 100 else if (security_token_has_sid(token, da_sid)) 101 dag_sid = dom_sid_dup(mem_ctx, da_sid); 102 else 103 dag_sid = NULL; 104 } 105 else if (ldb_dn_compare_base(root_base_dn, dn) == 0){ 106 if (security_token_has_sid(token, da_sid)) 107 dag_sid = dom_sid_dup(mem_ctx, da_sid); 108 else if (security_token_has_sid(token, ea_sid)) 109 dag_sid = dom_sid_dup(mem_ctx, ea_sid); 110 else 111 dag_sid = NULL; 112 } 113 else 114 dag_sid = NULL; 115 116 talloc_free(tmp_ctx); 117 return dag_sid; 118} 119 120static struct security_descriptor *get_sd_unpacked(struct ldb_module *module, TALLOC_CTX *mem_ctx, 121 const struct dsdb_class *objectclass) 122{ 123 struct ldb_context *ldb = ldb_module_get_ctx(module); 124 struct security_descriptor *sd; 125 const struct dom_sid *domain_sid = samdb_domain_sid(ldb); 126 127 if (!objectclass->defaultSecurityDescriptor || !domain_sid) { 128 return NULL; 129 } 130 131 sd = sddl_decode(mem_ctx, 132 objectclass->defaultSecurityDescriptor, 133 domain_sid); 134 return sd; 135} 136 137static struct dom_sid *get_default_group(TALLOC_CTX *mem_ctx, 138 struct ldb_context *ldb, 139 struct dom_sid *dag) 140{ 141 int *domainFunctionality; 142 143 domainFunctionality = talloc_get_type( 144 ldb_get_opaque(ldb, "domainFunctionality"), int); 145 146 if (*domainFunctionality 147 && (*domainFunctionality >= DS_DOMAIN_FUNCTION_2008)) { 148 return dag; 149 } 150 151 return NULL; 152} 153 154static DATA_BLOB *get_new_descriptor(struct ldb_module *module, 155 struct ldb_dn *dn, 156 TALLOC_CTX *mem_ctx, 157 const struct dsdb_class *objectclass, 158 const struct ldb_val *parent, 159 struct ldb_val *object) 160{ 161 struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL; 162 struct security_descriptor *new_sd; 163 DATA_BLOB *linear_sd; 164 enum ndr_err_code ndr_err; 165 struct ldb_context *ldb = ldb_module_get_ctx(module); 166 struct auth_session_info *session_info 167 = ldb_get_opaque(ldb, "sessionInfo"); 168 const struct dom_sid *domain_sid = samdb_domain_sid(ldb); 169 char *sddl_sd; 170 struct dom_sid *default_owner; 171 struct dom_sid *default_group; 172 173 if (object) { 174 user_descriptor = talloc(mem_ctx, struct security_descriptor); 175 if(!user_descriptor) 176 return NULL; 177 ndr_err = ndr_pull_struct_blob(object, user_descriptor, NULL, 178 user_descriptor, 179 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); 180 181 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)){ 182 talloc_free(user_descriptor); 183 return NULL; 184 } 185 } else { 186 user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass); 187 } 188 189 if (parent){ 190 parent_descriptor = talloc(mem_ctx, struct security_descriptor); 191 if(!parent_descriptor) 192 return NULL; 193 ndr_err = ndr_pull_struct_blob(parent, parent_descriptor, NULL, 194 parent_descriptor, 195 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); 196 197 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)){ 198 talloc_free(parent_descriptor); 199 return NULL; 200 } 201 } 202 default_owner = get_default_ag(mem_ctx, dn, 203 session_info->security_token, ldb); 204 default_group = get_default_group(mem_ctx, ldb, default_owner); 205 new_sd = create_security_descriptor(mem_ctx, parent_descriptor, user_descriptor, true, 206 NULL, SEC_DACL_AUTO_INHERIT|SEC_SACL_AUTO_INHERIT, 207 session_info->security_token, 208 default_owner, default_group, 209 map_generic_rights_ds); 210 if (!new_sd) 211 return NULL; 212 213 214 sddl_sd = sddl_encode(mem_ctx, new_sd, domain_sid); 215 DEBUG(10, ("Object %s created with desriptor %s", ldb_dn_get_linearized(dn), sddl_sd)); 216 217 linear_sd = talloc(mem_ctx, DATA_BLOB); 218 if (!linear_sd) { 219 return NULL; 220 } 221 222 ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx, 223 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 224 new_sd, 225 (ndr_push_flags_fn_t)ndr_push_security_descriptor); 226 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 227 return NULL; 228 } 229 230 return linear_sd; 231} 232 233static struct descriptor_context *descriptor_init_context(struct ldb_module *module, 234 struct ldb_request *req) 235{ 236 struct ldb_context *ldb; 237 struct descriptor_context *ac; 238 239 ldb = ldb_module_get_ctx(module); 240 241 ac = talloc_zero(req, struct descriptor_context); 242 if (ac == NULL) { 243 ldb_set_errstring(ldb, "Out of Memory"); 244 return NULL; 245 } 246 247 ac->module = module; 248 ac->req = req; 249 return ac; 250} 251 252static int get_search_callback(struct ldb_request *req, struct ldb_reply *ares) 253{ 254 struct ldb_context *ldb; 255 struct descriptor_context *ac; 256 int ret; 257 258 ac = talloc_get_type(req->context, struct descriptor_context); 259 ldb = ldb_module_get_ctx(ac->module); 260 261 if (!ares) { 262 return ldb_module_done(ac->req, NULL, NULL, 263 LDB_ERR_OPERATIONS_ERROR); 264 } 265 if (ares->error != LDB_SUCCESS && 266 ares->error != LDB_ERR_NO_SUCH_OBJECT) { 267 return ldb_module_done(ac->req, ares->controls, 268 ares->response, ares->error); 269 } 270 271 ldb_reset_err_string(ldb); 272 273 switch (ares->type) { 274 case LDB_REPLY_ENTRY: 275 if (ac->search_res != NULL) { 276 ldb_set_errstring(ldb, "Too many results"); 277 talloc_free(ares); 278 return ldb_module_done(ac->req, NULL, NULL, 279 LDB_ERR_OPERATIONS_ERROR); 280 } 281 282 ac->search_res = talloc_steal(ac, ares); 283 break; 284 285 case LDB_REPLY_REFERRAL: 286 /* ignore */ 287 talloc_free(ares); 288 break; 289 290 case LDB_REPLY_DONE: 291 talloc_free(ares); 292 ret = ac->step_fn(ac); 293 if (ret != LDB_SUCCESS) { 294 return ldb_module_done(ac->req, NULL, NULL, ret); 295 } 296 break; 297 } 298 299 return LDB_SUCCESS; 300} 301static int descriptor_op_callback(struct ldb_request *req, struct ldb_reply *ares) 302{ 303 struct descriptor_context *ac; 304 305 ac = talloc_get_type(req->context, struct descriptor_context); 306 307 if (!ares) { 308 return ldb_module_done(ac->req, NULL, NULL, 309 LDB_ERR_OPERATIONS_ERROR); 310 } 311 if (ares->error != LDB_SUCCESS) { 312 return ldb_module_done(ac->req, ares->controls, 313 ares->response, ares->error); 314 } 315 316 if (ares->type != LDB_REPLY_DONE) { 317 talloc_free(ares); 318 return ldb_module_done(ac->req, NULL, NULL, 319 LDB_ERR_OPERATIONS_ERROR); 320 } 321 322 return ldb_module_done(ac->req, ares->controls, 323 ares->response, ares->error); 324} 325 326static int descriptor_do_add(struct descriptor_context *ac) 327{ 328 struct ldb_context *ldb; 329 const struct dsdb_schema *schema; 330 struct ldb_request *add_req; 331 struct ldb_message_element *objectclass_element, *sd_element = NULL; 332 struct ldb_message *msg; 333 TALLOC_CTX *mem_ctx; 334 int ret; 335 struct ldb_val *sd_val = NULL; 336 const struct ldb_val *parentsd_val = NULL; 337 DATA_BLOB *sd; 338 const struct dsdb_class *objectclass; 339 340 ldb = ldb_module_get_ctx(ac->module); 341 schema = dsdb_get_schema(ldb); 342 343 mem_ctx = talloc_new(ac); 344 if (mem_ctx == NULL) { 345 return LDB_ERR_OPERATIONS_ERROR; 346 } 347 348 msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message); 349 350 /* get the security descriptor values*/ 351 sd_element = ldb_msg_find_element(msg, "nTSecurityDescriptor"); 352 objectclass_element = ldb_msg_find_element(msg, "objectClass"); 353 objectclass = get_last_structural_class(schema, objectclass_element); 354 355 if (!objectclass) { 356 ldb_asprintf_errstring(ldb, "No last structural objectclass found on %s", ldb_dn_get_linearized(msg->dn)); 357 return LDB_ERR_OPERATIONS_ERROR; 358 } 359 360 if (sd_element) 361 sd_val = &sd_element->values[0]; 362 /* NC's have no parent */ 363 if ((ldb_dn_compare(msg->dn, (ldb_get_schema_basedn(ldb))) == 0) || 364 (ldb_dn_compare(msg->dn, (ldb_get_config_basedn(ldb))) == 0) || 365 (ldb_dn_compare(msg->dn, (ldb_get_root_basedn(ldb))) == 0)) { 366 parentsd_val = NULL; 367 } else if (ac->search_res != NULL){ 368 parentsd_val = ldb_msg_find_ldb_val(ac->search_res->message, "nTSecurityDescriptor"); 369 } 370 371 /* get the parent descriptor and the one provided. If not provided, get the default.*/ 372 /* convert to security descriptor and calculate */ 373 sd = get_new_descriptor(ac->module, msg->dn, mem_ctx, objectclass, 374 parentsd_val, sd_val); 375 if (sd_val) { 376 ldb_msg_remove_attr(msg, "nTSecurityDescriptor"); 377 } 378 379 if (sd) { 380 ret = ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd); 381 if (ret != LDB_SUCCESS) { 382 return ret; 383 } 384 } 385 386 talloc_free(mem_ctx); 387 ret = ldb_msg_sanity_check(ldb, msg); 388 389 if (ret != LDB_SUCCESS) { 390 ldb_asprintf_errstring(ldb, "No last structural objectclass found on %s", ldb_dn_get_linearized(msg->dn)); 391 return ret; 392 } 393 394 ret = ldb_build_add_req(&add_req, ldb, ac, 395 msg, 396 ac->req->controls, 397 ac, descriptor_op_callback, 398 ac->req); 399 if (ret != LDB_SUCCESS) { 400 return ret; 401 } 402 403 /* perform the add */ 404 return ldb_next_request(ac->module, add_req); 405} 406 407static int descriptor_add(struct ldb_module *module, struct ldb_request *req) 408{ 409 struct ldb_context *ldb; 410 struct ldb_request *search_req; 411 struct descriptor_context *ac; 412 struct ldb_dn *parent_dn; 413 int ret; 414 struct descriptor_data *data; 415 static const char * const descr_attrs[] = { "nTSecurityDescriptor", NULL }; 416 417 data = talloc_get_type(ldb_module_get_private(module), struct descriptor_data); 418 ldb = ldb_module_get_ctx(module); 419 420 ldb_debug(ldb, LDB_DEBUG_TRACE, "descriptor_add\n"); 421 422 if (ldb_dn_is_special(req->op.add.message->dn)) { 423 return ldb_next_request(module, req); 424 } 425 426 ac = descriptor_init_context(module, req); 427 if (ac == NULL) { 428 return LDB_ERR_OPERATIONS_ERROR; 429 } 430 431 /* If there isn't a parent, just go on to the add processing */ 432 if (ldb_dn_get_comp_num(ac->req->op.add.message->dn) == 1) { 433 return descriptor_do_add(ac); 434 } 435 436 /* get copy of parent DN */ 437 parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn); 438 if (parent_dn == NULL) { 439 ldb_oom(ldb); 440 return LDB_ERR_OPERATIONS_ERROR; 441 } 442 443 ret = ldb_build_search_req(&search_req, ldb, 444 ac, parent_dn, LDB_SCOPE_BASE, 445 "(objectClass=*)", descr_attrs, 446 NULL, 447 ac, get_search_callback, 448 req); 449 if (ret != LDB_SUCCESS) { 450 return ret; 451 } 452 talloc_steal(search_req, parent_dn); 453 454 ac->step_fn = descriptor_do_add; 455 456 return ldb_next_request(ac->module, search_req); 457} 458/* TODO */ 459static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) 460{ 461 struct ldb_context *ldb = ldb_module_get_ctx(module); 462 ldb_debug(ldb, LDB_DEBUG_TRACE, "descriptor_modify\n"); 463 return ldb_next_request(module, req); 464} 465/* TODO */ 466static int descriptor_rename(struct ldb_module *module, struct ldb_request *req) 467{ 468 struct ldb_context *ldb = ldb_module_get_ctx(module); 469 ldb_debug(ldb, LDB_DEBUG_TRACE, "descriptor_rename\n"); 470 return ldb_next_request(module, req); 471} 472 473static int descriptor_init(struct ldb_module *module) 474{ 475 struct ldb_context *ldb; 476 struct descriptor_data *data; 477 478 ldb = ldb_module_get_ctx(module); 479 data = talloc(module, struct descriptor_data); 480 if (data == NULL) { 481 ldb_oom(ldb); 482 return LDB_ERR_OPERATIONS_ERROR; 483 } 484 485 ldb_module_set_private(module, data); 486 return ldb_next_init(module); 487} 488 489 490_PUBLIC_ const struct ldb_module_ops ldb_descriptor_module_ops = { 491 .name = "descriptor", 492 .add = descriptor_add, 493 .modify = descriptor_modify, 494 .rename = descriptor_rename, 495 .init_context = descriptor_init 496}; 497 498 499