Changeset 988 for vendor/current/source4/dsdb/samdb
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- Location:
- vendor/current/source4/dsdb/samdb
- Files:
-
- 7 added
- 3 deleted
- 42 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/dsdb/samdb/cracknames.c
r740 r988 2 2 Unix SMB/CIFS implementation. 3 3 4 endpoint serverfor the drsuapi pipe4 crachnames implementation for the drsuapi pipe 5 5 DsCrackNames() 6 6 7 7 Copyright (C) Stefan Metzmacher 2004 8 8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 9 Copyright (C) Matthieu Patou <mat@matws.net> 2012 9 10 10 11 This program is free software; you can redistribute it and/or modify … … 25 26 #include "librpc/gen_ndr/drsuapi.h" 26 27 #include "lib/events/events.h" 27 #include "rpc_server/common/common.h"28 28 #include <ldb.h> 29 29 #include <ldb_errors.h> 30 #include "system/kerberos.h"31 30 #include "auth/kerberos/kerberos.h" 32 31 #include "libcli/ldap/ldap_ndr.h" … … 44 43 struct ldb_dn *name_dn, const char *name, 45 44 const char *domain_filter, const char *result_filter, 46 struct drsuapi_DsNameInfo1 *info1 );45 struct drsuapi_DsNameInfo1 *info1, int scope, struct ldb_dn *search_dn); 47 46 static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx, 48 47 enum drsuapi_DsNameFormat format_offered, … … 58 57 krb5_principal principal; 59 58 /* perhaps it's a principal with a realm, so return the right 'domain only' response */ 60 c onst char *realm;59 char *realm; 61 60 ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name, 62 61 KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &principal); … … 66 65 } 67 66 68 /* This isn't an allocation assignemnt, so it is free'ed with the krb5_free_principal */ 69 realm = krb5_principal_get_realm(smb_krb5_context->krb5_context, principal); 67 realm = smb_krb5_principal_get_realm(smb_krb5_context->krb5_context, principal); 70 68 71 69 info1->dns_domain_name = talloc_strdup(mem_ctx, realm); 72 70 krb5_free_principal(smb_krb5_context->krb5_context, principal); 71 free(realm); 73 72 74 73 W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name); … … 114 113 115 114 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { 116 DEBUG(1, ("ldb_search: dn: %s not found: %s ", service_dn_str, ldb_errstring(ldb_ctx)));115 DEBUG(1, ("ldb_search: dn: %s not found: %s\n", service_dn_str, ldb_errstring(ldb_ctx))); 117 116 return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 118 117 } else if (ret == LDB_ERR_NO_SUCH_OBJECT) { 119 DEBUG(1, ("ldb_search: dn: %s not found ", service_dn_str));118 DEBUG(1, ("ldb_search: dn: %s not found\n", service_dn_str)); 120 119 return DRSUAPI_DS_NAME_STATUS_NOT_FOUND; 121 120 } else if (res->count != 1) { 122 121 talloc_free(res); 123 DEBUG(1, ("ldb_search: dn: %s not found ", service_dn_str));122 DEBUG(1, ("ldb_search: dn: %s not found\n", service_dn_str)); 124 123 return DRSUAPI_DS_NAME_STATUS_NOT_FOUND; 125 124 } … … 127 126 spnmappings = ldb_msg_find_element(res->msgs[0], "sPNMappings"); 128 127 if (!spnmappings || spnmappings->num_values == 0) { 129 DEBUG(1, ("ldb_search: dn: %s no sPNMappings attribute ", service_dn_str));128 DEBUG(1, ("ldb_search: dn: %s no sPNMappings attribute\n", service_dn_str)); 130 129 talloc_free(tmp_ctx); 131 130 return DRSUAPI_DS_NAME_STATUS_NOT_FOUND; … … 187 186 krb5_error_code ret; 188 187 krb5_principal principal; 188 const krb5_data *component; 189 189 const char *service, *dns_name; 190 190 char *new_service; … … 196 196 name, KRB5_PRINCIPAL_PARSE_NO_REALM, &principal); 197 197 if (ret) { 198 DEBUG(2, ("Could not parse principal: %s: %s ",198 DEBUG(2, ("Could not parse principal: %s: %s\n", 199 199 name, smb_get_krb5_error_message(smb_krb5_context->krb5_context, 200 200 ret, mem_ctx))); … … 205 205 206 206 /* This is checked for in callers, but be safe */ 207 if ( principal->name.name_string.len< 2) {207 if (krb5_princ_size(smb_krb5_context->krb5_context, principal) < 2) { 208 208 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; 209 209 krb5_free_principal(smb_krb5_context->krb5_context, principal); 210 210 return WERR_OK; 211 211 } 212 service = principal->name.name_string.val[0]; 213 dns_name = principal->name.name_string.val[1]; 212 component = krb5_princ_component(smb_krb5_context->krb5_context, 213 principal, 0); 214 service = (const char *)component->data; 215 component = krb5_princ_component(smb_krb5_context->krb5_context, 216 principal, 1); 217 dns_name = (const char *)component->data; 214 218 215 219 /* MAP it */ … … 233 237 } 234 238 235 /* ooh, very nasty playing around in the Principal... */ 236 free(principal->name.name_string.val[0]); 237 principal->name.name_string.val[0] = strdup(new_service); 238 if (!principal->name.name_string.val[0]) { 239 /* reform principal */ 240 new_princ = talloc_asprintf(mem_ctx, "%s/%s", new_service, dns_name); 241 if (!new_princ) { 239 242 krb5_free_principal(smb_krb5_context->krb5_context, principal); 240 243 return WERR_NOMEM; 241 244 } 242 245 243 /* reform principal */244 ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal,245 KRB5_PRINCIPAL_UNPARSE_NO_REALM, &new_princ);246 247 if (ret) {248 krb5_free_principal(smb_krb5_context->krb5_context, principal);249 return WERR_NOMEM;250 }251 252 246 wret = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, format_offered, format_desired, 253 247 new_princ, info1); 254 free(new_princ);248 talloc_free(new_princ); 255 249 if (W_ERROR_IS_OK(wret) && (info1->status == DRSUAPI_DS_NAME_STATUS_NOT_FOUND)) { 256 250 info1->status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY; … … 278 272 krb5_error_code ret; 279 273 krb5_principal principal; 280 c onst char *realm;274 char *realm; 281 275 char *unparsed_name_short; 282 276 const char *domain_attrs[] = { NULL }; … … 296 290 } 297 291 298 realm = krb5_principal_get_realm(smb_krb5_context->krb5_context,299 principal);292 realm = smb_krb5_principal_get_realm(smb_krb5_context->krb5_context, 293 principal); 300 294 301 295 ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res, 302 samdb_partitions_dn(sam_ctx, mem_ctx), 303 LDB_SCOPE_ONELEVEL, 304 domain_attrs, 305 "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))", 306 ldb_binary_encode_string(mem_ctx, realm), 307 ldb_binary_encode_string(mem_ctx, realm)); 296 samdb_partitions_dn(sam_ctx, mem_ctx), 297 LDB_SCOPE_ONELEVEL, 298 domain_attrs, 299 "(&(objectClass=crossRef)(|(dnsRoot=%s)(netbiosName=%s))(systemFlags:%s:=%u))", 300 ldb_binary_encode_string(mem_ctx, realm), 301 ldb_binary_encode_string(mem_ctx, realm), 302 LDB_OID_COMPARATOR_AND, 303 SYSTEM_FLAG_CR_NTDS_DOMAIN); 304 free(realm); 308 305 309 306 if (ldb_ret != LDB_SUCCESS) { 310 DEBUG(2, ("DsCrackNameUPN domain ref search failed: %s ", ldb_errstring(sam_ctx)));307 DEBUG(2, ("DsCrackNameUPN domain ref search failed: %s\n", ldb_errstring(sam_ctx))); 311 308 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 312 309 krb5_free_principal(smb_krb5_context->krb5_context, principal); … … 327 324 } 328 325 326 /* 327 * The important thing here is that a samAccountName may have 328 * a space in it, and this must not be kerberos escaped to 329 * match this filter, so we specify 330 * KRB5_PRINCIPAL_UNPARSE_DISPLAY 331 */ 329 332 ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal, 330 KRB5_PRINCIPAL_UNPARSE_NO_REALM, &unparsed_name_short); 333 KRB5_PRINCIPAL_UNPARSE_NO_REALM | 334 KRB5_PRINCIPAL_UNPARSE_DISPLAY, 335 &unparsed_name_short); 331 336 krb5_free_principal(smb_krb5_context->krb5_context, principal); 332 337 … … 350 355 format_flags, format_offered, format_desired, 351 356 NULL, unparsed_name_short, domain_filter, result_filter, 352 info1 );357 info1, LDB_SCOPE_SUBTREE, NULL); 353 358 free(unparsed_name_short); 354 359 355 360 return status; 361 } 362 363 /* 364 * This function will workout the filtering parameter in order to be able to do 365 * the adapted search when the incomming format is format_functional. 366 * This boils down to defining the search_dn (passed as pointer to ldb_dn *) and the 367 * ldap filter request. 368 * Main input parameters are: 369 * * name, which is the portion of the functional name after the 370 * first '/'. 371 * * domain_filter, which is a ldap search filter used to find the NC DN given the 372 * function name to crack. 373 */ 374 static WERROR get_format_functional_filtering_param(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 375 char *name, struct drsuapi_DsNameInfo1 *info1, 376 struct ldb_dn **psearch_dn, const char *domain_filter, const char **presult_filter) 377 { 378 struct ldb_result *domain_res = NULL; 379 const char * const domain_attrs[] = {"ncName", NULL}; 380 struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx); 381 int ldb_ret; 382 char *account, *s, *result_filter = NULL; 383 struct ldb_dn *search_dn = NULL; 384 385 *psearch_dn = NULL; 386 *presult_filter = NULL; 387 388 ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res, 389 partitions_basedn, 390 LDB_SCOPE_ONELEVEL, 391 domain_attrs, 392 "%s", domain_filter); 393 394 if (ldb_ret != LDB_SUCCESS) { 395 DEBUG(2, ("DsCrackNameOne domain ref search failed: %s\n", ldb_errstring(sam_ctx))); 396 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 397 return WERR_FOOBAR; 398 } 399 400 if (domain_res->count == 1) { 401 struct ldb_dn *tmp_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL); 402 const char * const name_attrs[] = {"name", NULL}; 403 404 account = name; 405 s = strchr(account, '/'); 406 talloc_free(domain_res); 407 while(s) { 408 s[0] = '\0'; 409 s++; 410 411 ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res, 412 tmp_dn, 413 LDB_SCOPE_ONELEVEL, 414 name_attrs, 415 "name=%s", account); 416 417 if (ldb_ret != LDB_SUCCESS) { 418 DEBUG(2, ("DsCrackNameOne domain ref search failed: %s\n", ldb_errstring(sam_ctx))); 419 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 420 return WERR_OK; 421 } 422 talloc_free(tmp_dn); 423 switch (domain_res->count) { 424 case 1: 425 break; 426 case 0: 427 talloc_free(domain_res); 428 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; 429 return WERR_OK; 430 default: 431 talloc_free(domain_res); 432 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; 433 return WERR_OK; 434 } 435 436 tmp_dn = talloc_steal(mem_ctx, domain_res->msgs[0]->dn); 437 talloc_free(domain_res); 438 search_dn = tmp_dn; 439 account = s; 440 s = strchr(account, '/'); 441 } 442 account = ldb_binary_encode_string(mem_ctx, account); 443 W_ERROR_HAVE_NO_MEMORY(account); 444 result_filter = talloc_asprintf(mem_ctx, "(name=%s)", 445 account); 446 W_ERROR_HAVE_NO_MEMORY(result_filter); 447 } 448 *psearch_dn = search_dn; 449 *presult_filter = result_filter; 450 return WERR_OK; 356 451 } 357 452 … … 367 462 const char *result_filter = NULL; 368 463 struct ldb_dn *name_dn = NULL; 464 struct ldb_dn *search_dn = NULL; 369 465 370 466 struct smb_krb5_context *smb_krb5_context = NULL; 467 int scope = LDB_SCOPE_SUBTREE; 371 468 372 469 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; … … 381 478 * - handle format_flags 382 479 */ 383 480 if (format_desired == DRSUAPI_DS_NAME_FORMAT_UNKNOWN) { 481 return WERR_OK; 482 } 384 483 /* here we need to set the domain_filter and/or the result_filter */ 385 484 switch (format_offered) { … … 401 500 return werr; 402 501 } 403 if (info1->status != DRSUAPI_DS_NAME_STATUS_NOT_FOUND) { 502 if (info1->status != DRSUAPI_DS_NAME_STATUS_NOT_FOUND && 503 (formats[i] != DRSUAPI_DS_NAME_FORMAT_CANONICAL || 504 info1->status != DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR)) 505 { 404 506 return werr; 405 507 } … … 412 514 { 413 515 char *str, *s, *account; 516 scope = LDB_SCOPE_ONELEVEL; 414 517 415 518 if (strlen(name) == 0) { … … 441 544 s++; 442 545 443 domain_filter = talloc_asprintf(mem_ctx, "(&(objectClass=crossRef)(ncName=%s))", 444 ldb_dn_get_linearized(samdb_dns_domain_to_dn(sam_ctx, mem_ctx, str))); 546 domain_filter = talloc_asprintf(mem_ctx, "(&(objectClass=crossRef)(dnsRoot=%s)(systemFlags:%s:=%u))", 547 ldb_binary_encode_string(mem_ctx, str), 548 LDB_OID_COMPARATOR_AND, 549 SYSTEM_FLAG_CR_NTDS_DOMAIN); 445 550 W_ERROR_HAVE_NO_MEMORY(domain_filter); 446 551 447 552 /* There may not be anything after the domain component (search for the domain itself) */ 448 if (s[0]) { 449 450 account = strrchr(s, '/'); 451 if (!account) { 452 account = s; 453 } else { 454 account++; 553 account = s; 554 if (account && *account) { 555 WERROR werr = get_format_functional_filtering_param(sam_ctx, 556 mem_ctx, 557 account, 558 info1, 559 &search_dn, 560 domain_filter, 561 &result_filter); 562 if (!W_ERROR_IS_OK(werr)) { 563 return werr; 455 564 } 456 account = ldb_binary_encode_string(mem_ctx, account); 457 W_ERROR_HAVE_NO_MEMORY(account); 458 result_filter = talloc_asprintf(mem_ctx, "(name=%s)", 459 account); 460 W_ERROR_HAVE_NO_MEMORY(result_filter); 565 if (info1->status != DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR) 566 return WERR_OK; 461 567 } 462 568 break; … … 465 571 char *p; 466 572 char *domain; 467 struct ldb_dn *dn_domain;468 573 const char *account = NULL; 469 574 … … 483 588 } 484 589 485 /* it could be in DNS domain form */486 dn_domain = samdb_dns_domain_to_dn(sam_ctx, mem_ctx, domain);487 W_ERROR_HAVE_NO_MEMORY(dn_domain);488 489 590 domain_filter = talloc_asprintf(mem_ctx, 490 "(&( &(|(nETBIOSName=%s)(nCName=%s))(objectclass=crossRef))(ncName=*))",591 "(&(objectClass=crossRef)(netbiosName=%s)(systemFlags:%s:=%u))", 491 592 ldb_binary_encode_string(mem_ctx, domain), 492 ldb_dn_get_linearized(dn_domain)); 593 LDB_OID_COMPARATOR_AND, 594 SYSTEM_FLAG_CR_NTDS_DOMAIN); 493 595 W_ERROR_HAVE_NO_MEMORY(domain_filter); 494 596 if (account) { … … 552 654 domain_filter = NULL; 553 655 if (!sid) { 656 info1->dns_domain_name = NULL; 554 657 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; 555 658 return WERR_OK; … … 570 673 571 674 ret = smb_krb5_init_context(mem_ctx, 572 ldb_get_event_context(sam_ctx),573 675 (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"), 574 676 &smb_krb5_context); … … 587 689 domain_filter = NULL; 588 690 589 /* By getting the unparsed name here, we ensure the escaping is correct (and trust the client less) */ 590 ret = krb5_unparse_name(smb_krb5_context->krb5_context, principal, &unparsed_name); 691 /* 692 * By getting the unparsed name here, we ensure the 693 * escaping is removed correctly (and trust the client 694 * less). The important thing here is that a 695 * userPrincipalName may have a space in it, and this 696 * must not be kerberos escaped to match this filter, 697 * so we specify KRB5_PRINCIPAL_UNPARSE_DISPLAY 698 */ 699 ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, 700 principal, 701 KRB5_PRINCIPAL_UNPARSE_DISPLAY, 702 &unparsed_name); 591 703 if (ret) { 592 704 krb5_free_principal(smb_krb5_context->krb5_context, principal); … … 607 719 krb5_principal principal; 608 720 char *unparsed_name_short; 721 const krb5_data *component; 609 722 char *service; 610 723 611 724 ret = smb_krb5_init_context(mem_ctx, 612 ldb_get_event_context(sam_ctx),613 725 (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"), 614 726 &smb_krb5_context); … … 619 731 620 732 ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal); 621 if (ret == 0 && principal->name.name_string.len < 2) { 733 if (ret == 0 && 734 krb5_princ_size(smb_krb5_context->krb5_context, 735 principal) < 2) { 622 736 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; 623 737 krb5_free_principal(smb_krb5_context->krb5_context, principal); … … 642 756 } 643 757 644 service = principal->name.name_string.val[0]; 645 if ((principal->name.name_string.len == 2) && (strcasecmp(service, "host") == 0)) { 758 component = krb5_princ_component(smb_krb5_context->krb5_context, 759 principal, 0); 760 service = (char *)component->data; 761 if ((krb5_princ_size(smb_krb5_context->krb5_context, 762 principal) == 2) && 763 (strcasecmp(service, "host") == 0)) { 646 764 /* the 'cn' attribute is just the leading part of the name */ 647 765 char *computer_name; 648 computer_name = talloc_strndup(mem_ctx, principal->name.name_string.val[1], 649 strcspn(principal->name.name_string.val[1], ".")); 766 component = krb5_princ_component( 767 smb_krb5_context->krb5_context, 768 principal, 1); 769 computer_name = talloc_strndup(mem_ctx, (char *)component->data, 770 strcspn((char *)component->data, ".")); 650 771 if (computer_name == NULL) { 651 772 krb5_free_principal(smb_krb5_context->krb5_context, principal); … … 683 804 name_dn, name, 684 805 domain_filter, result_filter, 685 info1 );806 info1, scope, search_dn); 686 807 } 687 808 … … 735 856 struct ldb_dn *name_dn, const char *name, 736 857 const char *domain_filter, const char *result_filter, 737 struct drsuapi_DsNameInfo1 *info1) 858 struct drsuapi_DsNameInfo1 *info1, 859 int scope, struct ldb_dn *search_dn) 738 860 { 739 861 int ldb_ret; … … 803 925 804 926 if (ldb_ret != LDB_SUCCESS) { 805 DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s ", ldb_errstring(sam_ctx)));927 DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx))); 806 928 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 807 929 return WERR_OK; … … 831 953 struct ldb_result *res; 832 954 uint32_t dsdb_flags = 0; 833 struct ldb_dn *search_dn; 834 835 if (domain_res) { 836 dsdb_flags = 0; 837 search_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL); 955 struct ldb_dn *real_search_dn = NULL; 956 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; 957 958 /* 959 * From 4.1.4.2.11 of MS-DRSR 960 * if DS_NAME_FLAG_GCVERIFY in flags then 961 * rt := select all O from all 962 * where attrValue in GetAttrVals(O, att, false) 963 * else 964 * rt := select all O from subtree DefaultNC() 965 * where attrValue in GetAttrVals(O, att, false) 966 * endif 967 * return rt 968 */ 969 if (format_flags & DRSUAPI_DS_NAME_FLAG_GCVERIFY || 970 format_offered == DRSUAPI_DS_NAME_FORMAT_GUID) 971 { 972 dsdb_flags = DSDB_SEARCH_SEARCH_ALL_PARTITIONS; 973 } else if (domain_res) { 974 if (!search_dn) { 975 struct ldb_dn *tmp_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL); 976 real_search_dn = tmp_dn; 977 } else { 978 real_search_dn = search_dn; 979 } 838 980 } else { 839 dsdb_flags = DSDB_SEARCH_SEARCH_ALL_PARTITIONS; 840 search_dn = ldb_get_root_basedn(sam_ctx); 841 } 842 981 real_search_dn = ldb_get_default_basedn(sam_ctx); 982 } 983 if (format_desired == DRSUAPI_DS_NAME_FORMAT_GUID){ 984 dsdb_flags |= DSDB_SEARCH_SHOW_RECYCLED; 985 } 843 986 /* search with the 'phantom root' flag */ 844 987 ret = dsdb_search(sam_ctx, mem_ctx, &res, 845 search_dn,846 LDB_SCOPE_SUBTREE,988 real_search_dn, 989 scope, 847 990 result_attrs, 848 DSDB_SEARCH_SEARCH_ALL_PARTITIONS,991 dsdb_flags, 849 992 "%s", result_filter); 850 993 if (ret != LDB_SUCCESS) { 851 DEBUG(2, ("DsCrackNameOneFilter phantom root search failed: %s", 994 DEBUG(2, ("DsCrackNameOneFilter search from '%s' with flags 0x%08x failed: %s\n", 995 ldb_dn_get_linearized(real_search_dn), 996 dsdb_flags, 852 997 ldb_errstring(sam_ctx))); 853 998 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; … … 866 1011 } else { 867 1012 /* Can't happen */ 868 DEBUG(0, ("LOGIC ERROR: DsCrackNameOneFilter domain ref search not available: This can't happen... "));1013 DEBUG(0, ("LOGIC ERROR: DsCrackNameOneFilter domain ref search not available: This can't happen...\n")); 869 1014 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 870 1015 return WERR_OK; … … 893 1038 return WERR_OK; 894 1039 case -1: 895 DEBUG(2, ("DsCrackNameOneFilter result search failed: %s ", ldb_errstring(sam_ctx)));1040 DEBUG(2, ("DsCrackNameOneFilter result search failed: %s\n", ldb_errstring(sam_ctx))); 896 1041 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 897 1042 return WERR_OK; … … 924 1069 } 925 1070 } 1071 /* FALL TROUGH */ 926 1072 default: 927 1073 info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE; … … 962 1108 const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result, "objectSid"); 963 1109 const char *_acc = "", *_dom = ""; 964 965 if (samdb_find_attribute(sam_ctx, result, "objectClass", "domain")) { 966 1110 if (sid == NULL) { 1111 info1->status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING; 1112 return WERR_OK; 1113 } 1114 1115 if (samdb_find_attribute(sam_ctx, result, "objectClass", 1116 "domain")) { 1117 /* This can also find a DomainDNSZones entry, 1118 * but it won't have the SID we just 1119 * checked. */ 967 1120 ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res, 968 1121 partitions_basedn, … … 972 1125 973 1126 if (ldb_ret != LDB_SUCCESS) { 974 DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s ", ldb_errstring(sam_ctx)));1127 DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx))); 975 1128 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 976 1129 return WERR_OK; … … 1013 1166 1014 1167 if (ldb_ret != LDB_SUCCESS) { 1015 DEBUG(2, ("DsCrackNameOneFilter domain search failed: %s ", ldb_errstring(sam_ctx)));1168 DEBUG(2, ("DsCrackNameOneFilter domain search failed: %s\n", ldb_errstring(sam_ctx))); 1016 1169 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 1017 1170 return WERR_OK; … … 1036 1189 1037 1190 if (ldb_ret != LDB_SUCCESS) { 1038 DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s ", ldb_errstring(sam_ctx)));1191 DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s\n", ldb_errstring(sam_ctx))); 1039 1192 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 1040 1193 return WERR_OK; … … 1091 1244 case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN: 1092 1245 case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: { 1246 info1->dns_domain_name = NULL; 1093 1247 info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; 1094 1248 return WERR_OK; … … 1346 1500 server_dn); 1347 1501 if(!names[i].dns_domain_name) { 1348 DEBUG(4, ("list_roles: Failed to find dNSHostName for server %s ",1502 DEBUG(4, ("list_roles: Failed to find dNSHostName for server %s\n", 1349 1503 ldb_dn_get_linearized(server_dn))); 1350 1504 } … … 1366 1520 WERROR status; 1367 1521 1368 *ctr1 = talloc (mem_ctx, struct drsuapi_DsNameCtr1);1522 *ctr1 = talloc_zero(mem_ctx, struct drsuapi_DsNameCtr1); 1369 1523 W_ERROR_HAVE_NO_MEMORY(*ctr1); 1370 1524 … … 1390 1544 return WERR_OK; 1391 1545 } 1546 1547 WERROR dcesrv_drsuapi_ListInfoServer(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 1548 const struct drsuapi_DsNameRequest1 *req1, 1549 struct drsuapi_DsNameCtr1 **_ctr1) 1550 { 1551 struct drsuapi_DsNameInfo1 *names; 1552 struct ldb_result *res; 1553 struct ldb_dn *server_dn, *dn; 1554 struct drsuapi_DsNameCtr1 *ctr1; 1555 int ret, i; 1556 const char *str; 1557 const char *attrs[] = { 1558 "dn", 1559 "dNSHostName", 1560 "serverReference", 1561 NULL 1562 }; 1563 1564 *_ctr1 = NULL; 1565 1566 ctr1 = talloc_zero(mem_ctx, struct drsuapi_DsNameCtr1); 1567 W_ERROR_HAVE_NO_MEMORY(ctr1); 1568 1569 /* 1570 * No magic value here, we have to return 3 entries according to the 1571 * MS-DRSR.pdf 1572 */ 1573 ctr1->count = 3; 1574 names = talloc_zero_array(ctr1, struct drsuapi_DsNameInfo1, 1575 ctr1->count); 1576 W_ERROR_HAVE_NO_MEMORY(names); 1577 ctr1->array = names; 1578 1579 for (i=0; i < ctr1->count; i++) { 1580 names[i].status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; 1581 } 1582 *_ctr1 = ctr1; 1583 1584 if (req1->count != 1) { 1585 DEBUG(1, ("Expected a count of 1 for the ListInfoServer crackname \n")); 1586 return WERR_OK; 1587 } 1588 1589 if (req1->names[0].str == NULL) { 1590 return WERR_OK; 1591 } 1592 1593 server_dn = ldb_dn_new(mem_ctx, sam_ctx, req1->names[0].str); 1594 W_ERROR_HAVE_NO_MEMORY(server_dn); 1595 1596 ret = ldb_search(sam_ctx, mem_ctx, &res, server_dn, LDB_SCOPE_ONELEVEL, 1597 NULL, "(objectClass=nTDSDSA)"); 1598 1599 if (ret != LDB_SUCCESS) { 1600 DEBUG(1, ("Search for objectClass=nTDSDSA " 1601 "returned less than 1 objects\n")); 1602 return WERR_OK; 1603 } 1604 1605 if (res->count != 1) { 1606 DEBUG(1, ("Search for objectClass=nTDSDSA " 1607 "returned less than 1 objects\n")); 1608 return WERR_OK; 1609 } 1610 1611 if (res->msgs[0]->dn) { 1612 names[0].result_name = ldb_dn_alloc_linearized(names, res->msgs[0]->dn); 1613 W_ERROR_HAVE_NO_MEMORY(names[0].result_name); 1614 names[0].status = DRSUAPI_DS_NAME_STATUS_OK; 1615 } 1616 1617 talloc_free(res); 1618 1619 ret = ldb_search(sam_ctx, mem_ctx, &res, server_dn, LDB_SCOPE_BASE, 1620 attrs, "(objectClass=*)"); 1621 if (ret != LDB_SUCCESS) { 1622 DEBUG(1, ("Search for objectClass=* on dn %s" 1623 "returned %s\n", req1->names[0].str, 1624 ldb_strerror(ret))); 1625 return WERR_OK; 1626 } 1627 1628 if (res->count != 1) { 1629 DEBUG(1, ("Search for objectClass=* on dn %s" 1630 "returned less than 1 objects\n", req1->names[0].str)); 1631 return WERR_OK; 1632 } 1633 1634 str = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL); 1635 if (str != NULL) { 1636 names[1].result_name = talloc_strdup(names, str); 1637 W_ERROR_HAVE_NO_MEMORY(names[1].result_name); 1638 names[1].status = DRSUAPI_DS_NAME_STATUS_OK; 1639 } 1640 1641 dn = ldb_msg_find_attr_as_dn(sam_ctx, mem_ctx, res->msgs[0], "serverReference"); 1642 if (dn != NULL) { 1643 names[2].result_name = ldb_dn_alloc_linearized(names, dn); 1644 W_ERROR_HAVE_NO_MEMORY(names[2].result_name); 1645 names[2].status = DRSUAPI_DS_NAME_STATUS_OK; 1646 } 1647 1648 talloc_free(dn); 1649 talloc_free(res); 1650 1651 return WERR_OK; 1652 } -
vendor/current/source4/dsdb/samdb/ldb_modules/acl.c
r740 r988 40 40 #include "param/param.h" 41 41 #include "dsdb/samdb/ldb_modules/util.h" 42 #include "dsdb/samdb/ldb_modules/schema.h"43 42 #include "lib/util/tsort.h" 44 43 #include "system/kerberos.h" … … 51 50 52 51 struct acl_private { 53 bool acl_ perform;52 bool acl_search; 54 53 const char **password_attrs; 54 void *cached_schema_ptr; 55 uint64_t cached_schema_metadata_usn; 56 uint64_t cached_schema_loaded_usn; 57 const char **confidential_attrs; 55 58 }; 56 59 … … 59 62 struct ldb_request *req; 60 63 bool am_system; 64 bool am_administrator; 65 bool modify_search; 66 bool constructed_attrs; 61 67 bool allowedAttributes; 62 68 bool allowedAttributesEffective; … … 74 80 struct acl_private *data; 75 81 int ret; 76 unsigned int i ;82 unsigned int i, n, j; 77 83 TALLOC_CTX *mem_ctx; 78 static const char *attrs[] = { "passwordAttribute", NULL }; 84 static const char * const attrs[] = { "passwordAttribute", NULL }; 85 static const char * const secret_attrs[] = { 86 DSDB_SECRET_ATTRIBUTES 87 }; 79 88 struct ldb_result *res; 80 89 struct ldb_message *msg; … … 90 99 } 91 100 92 data = talloc (module, struct acl_private);101 data = talloc_zero(module, struct acl_private); 93 102 if (data == NULL) { 94 103 return ldb_oom(ldb); 95 104 } 96 105 97 data->password_attrs = NULL; 98 data->acl_perform = lpcfg_parm_bool(ldb_get_opaque(ldb, "loadparm"), 99 NULL, "acl", "perform", false); 106 data->acl_search = lpcfg_parm_bool(ldb_get_opaque(ldb, "loadparm"), 107 NULL, "acl", "search", true); 100 108 ldb_module_set_private(module, data); 101 109 … … 108 116 ldb_dn_new(mem_ctx, ldb, "@KLUDGEACL"), 109 117 attrs, 110 DSDB_FLAG_NEXT_MODULE, NULL); 118 DSDB_FLAG_NEXT_MODULE | 119 DSDB_FLAG_AS_SYSTEM, 120 NULL); 111 121 if (ret != LDB_SUCCESS) { 112 122 goto done; … … 127 137 goto done; 128 138 } 129 data->password_attrs = talloc_array(data, const char *, password_attributes->num_values + 1); 139 data->password_attrs = talloc_array(data, const char *, 140 password_attributes->num_values + 141 ARRAY_SIZE(secret_attrs) + 1); 130 142 if (!data->password_attrs) { 131 143 talloc_free(mem_ctx); 132 144 return ldb_oom(ldb); 133 145 } 146 147 n = 0; 134 148 for (i=0; i < password_attributes->num_values; i++) { 135 data->password_attrs[ i] = (const char *)password_attributes->values[i].data;149 data->password_attrs[n] = (const char *)password_attributes->values[i].data; 136 150 talloc_steal(data->password_attrs, password_attributes->values[i].data); 137 } 138 data->password_attrs[i] = NULL; 151 n++; 152 } 153 154 for (i=0; i < ARRAY_SIZE(secret_attrs); i++) { 155 bool found = false; 156 157 for (j=0; j < n; j++) { 158 if (strcasecmp(data->password_attrs[j], secret_attrs[i]) == 0) { 159 found = true; 160 break; 161 } 162 } 163 164 if (found) { 165 continue; 166 } 167 168 data->password_attrs[n] = talloc_strdup(data->password_attrs, 169 secret_attrs[i]); 170 if (data->password_attrs[n] == NULL) { 171 talloc_free(mem_ctx); 172 return ldb_oom(ldb); 173 } 174 n++; 175 } 176 data->password_attrs[n] = NULL; 139 177 140 178 done: … … 154 192 const char **attr_list; 155 193 int i, ret; 194 const struct dsdb_class *objectclass; 156 195 157 196 /* If we don't have a schema yet, we can't do anything... */ … … 178 217 return LDB_ERR_OPERATIONS_ERROR; 179 218 } 219 220 /* 221 * Get the top-most structural object class for the ACL check 222 */ 223 objectclass = dsdb_get_last_structural_class(ac->schema, 224 oc_el); 225 if (objectclass == NULL) { 226 ldb_asprintf_errstring(ldb, "acl_read: Failed to find a structural class for %s", 227 ldb_dn_get_linearized(sd_msg->dn)); 228 talloc_free(mem_ctx); 229 return LDB_ERR_OPERATIONS_ERROR; 230 } 231 180 232 if (ac->allowedAttributes) { 181 233 for (i=0; attr_list && attr_list[i]; i++) { … … 225 277 sid, 226 278 SEC_ADS_WRITE_PROP, 227 attr); 279 attr, 280 objectclass); 228 281 if (ret == LDB_SUCCESS) { 229 282 ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]); … … 336 389 337 390 for (j=0; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) { 338 ret = acl_check_access_on_class(module, 339 schema, 340 msg, 341 sd, 342 sid, 343 SEC_ADS_CREATE_CHILD, 344 sclass->possibleInferiors[j]); 391 const struct dsdb_class *sc; 392 393 sc = dsdb_class_by_lDAPDisplayName(schema, 394 sclass->possibleInferiors[j]); 395 if (!sc) { 396 /* We don't know this class? what is going on? */ 397 continue; 398 } 399 400 ret = acl_check_access_on_objectclass(module, ac, 401 sd, sid, 402 SEC_ADS_CREATE_CHILD, 403 sc); 345 404 if (ret == LDB_SUCCESS) { 346 405 ldb_msg_add_string(msg, "allowedChildClassesEffective", … … 374 433 struct acl_context *ac) 375 434 { 435 struct ldb_context *ldb = ldb_module_get_ctx(module); 376 436 struct ldb_message_element *rightsEffective; 377 437 int ret; … … 394 454 if (ac->am_system || as_system) { 395 455 flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_SACL | SECINFO_DACL; 396 } 397 else { 456 } else { 457 const struct dsdb_class *objectclass; 458 const struct dsdb_attribute *attr; 459 460 objectclass = dsdb_get_structural_oc_from_msg(ac->schema, sd_msg); 461 if (objectclass == NULL) { 462 return ldb_operr(ldb); 463 } 464 465 attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, 466 "nTSecurityDescriptor"); 467 if (attr == NULL) { 468 return ldb_operr(ldb); 469 } 470 398 471 /* Get the security descriptor from the message */ 399 ret = dsdb_get_sd_from_ldb_message(ldb _module_get_ctx(module), msg, sd_msg, &sd);472 ret = dsdb_get_sd_from_ldb_message(ldb, msg, sd_msg, &sd); 400 473 if (ret != LDB_SUCCESS) { 401 474 return ret; … … 407 480 sid, 408 481 SEC_STD_WRITE_OWNER, 409 NULL); 482 attr, 483 objectclass); 410 484 if (ret == LDB_SUCCESS) { 411 485 flags |= SECINFO_OWNER | SECINFO_GROUP; … … 416 490 sid, 417 491 SEC_STD_WRITE_DAC, 418 NULL); 492 attr, 493 objectclass); 419 494 if (ret == LDB_SUCCESS) { 420 495 flags |= SECINFO_DACL; … … 425 500 sid, 426 501 SEC_FLAG_SYSTEM_SECURITY, 427 NULL); 502 attr, 503 objectclass); 428 504 if (ret == LDB_SUCCESS) { 429 505 flags |= SECINFO_SACL; … … 450 526 char *serviceType; 451 527 char *serviceName; 452 const char *realm;453 528 const char *forest_name = samdb_forest_name(ldb, mem_ctx); 454 529 const char *base_domain = samdb_default_domain_name(ldb, mem_ctx); … … 458 533 (userAccountControl & UF_PARTIAL_SECRETS_ACCOUNT); 459 534 535 if (strcasecmp_m(spn_value, samAccountName) == 0) { 536 /* MacOS X sets this value, and setting an SPN of your 537 * own samAccountName is both pointless and safe */ 538 return LDB_SUCCESS; 539 } 540 460 541 kerr = smb_krb5_init_context_basic(mem_ctx, 461 542 lp_ctx, … … 472 553 } 473 554 474 instanceName = principal->name.name_string.val[1]; 475 serviceType = principal->name.name_string.val[0]; 476 realm = krb5_principal_get_realm(krb_ctx, principal); 477 if (principal->name.name_string.len == 3) { 478 serviceName = principal->name.name_string.val[2]; 555 if (krb5_princ_size(krb_ctx, principal) < 2) { 556 goto fail; 557 } 558 559 instanceName = smb_krb5_principal_get_comp_string(mem_ctx, krb_ctx, 560 principal, 1); 561 serviceType = smb_krb5_principal_get_comp_string(mem_ctx, krb_ctx, 562 principal, 0); 563 if (krb5_princ_size(krb_ctx, principal) == 3) { 564 serviceName = smb_krb5_principal_get_comp_string(mem_ctx, krb_ctx, 565 principal, 2); 479 566 } else { 480 567 serviceName = NULL; … … 504 591 /* instanceName can be samAccountName without $ or dnsHostName 505 592 * or "ntds_guid._msdcs.forest_domain for DC objects */ 506 if (strncasecmp(instanceName, samAccountName, strlen(samAccountName) - 1) == 0) { 593 if (strlen(instanceName) == (strlen(samAccountName) - 1) 594 && strncasecmp(instanceName, samAccountName, strlen(samAccountName) - 1) == 0) { 507 595 goto success; 508 } else if ( strcasecmp(instanceName, dnsHostName) == 0) {596 } else if (dnsHostName != NULL && strcasecmp(instanceName, dnsHostName) == 0) { 509 597 goto success; 510 598 } else if (is_dc) { … … 534 622 struct security_descriptor *sd, 535 623 struct dom_sid *sid, 536 const struct GUID *oc_guid,537 const struct dsdb_ attribute *attr)624 const struct dsdb_attribute *attr, 625 const struct dsdb_class *objectclass) 538 626 { 539 627 int ret; … … 569 657 sid, 570 658 SEC_ADS_WRITE_PROP, 571 attr ) == LDB_SUCCESS) {659 attr, objectclass) == LDB_SUCCESS) { 572 660 talloc_free(tmp_ctx); 573 661 return LDB_SUCCESS; … … 592 680 acl_attrs, 593 681 DSDB_FLAG_NEXT_MODULE | 594 DSDB_SEARCH_SHOW_DELETED, req); 682 DSDB_FLAG_AS_SYSTEM | 683 DSDB_SEARCH_SHOW_RECYCLED, 684 req); 595 685 if (ret != LDB_SUCCESS) { 596 686 talloc_free(tmp_ctx); … … 606 696 LDB_SCOPE_ONELEVEL, 607 697 netbios_attrs, 608 DSDB_FLAG_NEXT_MODULE, 698 DSDB_FLAG_NEXT_MODULE | 699 DSDB_FLAG_AS_SYSTEM, 609 700 req, 610 701 "(ncName=%s)", … … 655 746 { 656 747 int ret; 657 struct ldb_dn *parent = ldb_dn_get_parent(req, req->op.add.message->dn);748 struct ldb_dn *parent; 658 749 struct ldb_context *ldb; 659 750 const struct dsdb_schema *schema; 660 struct ldb_message_element *oc_el; 661 const struct GUID *guid; 662 struct ldb_dn *nc_root; 663 struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); 664 751 const struct dsdb_class *objectclass; 752 struct ldb_control *as_system; 753 struct ldb_message_element *el; 754 unsigned int instanceType = 0; 755 756 if (ldb_dn_is_special(req->op.add.message->dn)) { 757 return ldb_next_request(module, req); 758 } 759 760 as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); 665 761 if (as_system != NULL) { 666 762 as_system->critical = 0; … … 670 766 return ldb_next_request(module, req); 671 767 } 672 if (ldb_dn_is_special(req->op.add.message->dn)) {673 return ldb_next_request(module, req);674 }675 768 676 769 ldb = ldb_module_get_ctx(module); 677 770 678 /* Creating an NC. There is probably something we should do here, 679 * but we will establish that later */ 680 681 ret = dsdb_find_nc_root(ldb, req, req->op.add.message->dn, &nc_root); 682 if (ret != LDB_SUCCESS) { 683 return ret; 684 } 685 if (ldb_dn_compare(nc_root, req->op.add.message->dn) == 0) { 686 talloc_free(nc_root); 687 return ldb_next_request(module, req); 688 } 689 talloc_free(nc_root); 771 parent = ldb_dn_get_parent(req, req->op.add.message->dn); 772 if (parent == NULL) { 773 return ldb_oom(ldb); 774 } 690 775 691 776 schema = dsdb_get_schema(ldb, req); … … 694 779 } 695 780 696 oc_el = ldb_msg_find_element(req->op.add.message, "objectClass"); 697 if (!oc_el || oc_el->num_values == 0) { 698 DEBUG(10,("acl:operation error %s\n", ldb_dn_get_linearized(req->op.add.message->dn))); 781 objectclass = dsdb_get_structural_oc_from_msg(schema, req->op.add.message); 782 if (!objectclass) { 783 ldb_asprintf_errstring(ldb_module_get_ctx(module), 784 "acl: unable to find or validate structural objectClass on %s\n", 785 ldb_dn_get_linearized(req->op.add.message->dn)); 699 786 return ldb_module_done(req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); 700 787 } 701 788 702 guid = class_schemaid_guid_by_lDAPDisplayName(schema, 703 (char *)oc_el->values[oc_el->num_values-1].data); 704 ret = dsdb_module_check_access_on_dn(module, req, parent, SEC_ADS_CREATE_CHILD, guid, req); 705 if (ret != LDB_SUCCESS) { 789 el = ldb_msg_find_element(req->op.add.message, "instanceType"); 790 if ((el != NULL) && (el->num_values != 1)) { 791 ldb_set_errstring(ldb, "acl: the 'instanceType' attribute is single-valued!"); 792 return LDB_ERR_UNWILLING_TO_PERFORM; 793 } 794 795 instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, 796 "instanceType", 0); 797 if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) { 798 static const char *no_attrs[] = { NULL }; 799 struct ldb_result *partition_res; 800 struct ldb_dn *partitions_dn; 801 802 partitions_dn = samdb_partitions_dn(ldb, req); 803 if (!partitions_dn) { 804 ldb_set_errstring(ldb, "acl: CN=partitions dn could not be generated!"); 805 return LDB_ERR_UNWILLING_TO_PERFORM; 806 } 807 808 ret = dsdb_module_search(module, req, &partition_res, 809 partitions_dn, LDB_SCOPE_ONELEVEL, 810 no_attrs, 811 DSDB_FLAG_NEXT_MODULE | 812 DSDB_FLAG_AS_SYSTEM | 813 DSDB_SEARCH_ONE_ONLY | 814 DSDB_SEARCH_SHOW_RECYCLED, 815 req, 816 "(&(nCName=%s)(objectClass=crossRef))", 817 ldb_dn_get_linearized(req->op.add.message->dn)); 818 819 if (ret == LDB_SUCCESS) { 820 /* Check that we can write to the crossRef object MS-ADTS 3.1.1.5.2.8.2 */ 821 ret = dsdb_module_check_access_on_dn(module, req, partition_res->msgs[0]->dn, 822 SEC_ADS_WRITE_PROP, 823 &objectclass->schemaIDGUID, req); 824 if (ret != LDB_SUCCESS) { 825 ldb_asprintf_errstring(ldb_module_get_ctx(module), 826 "acl: ACL check failed on crossRef object %s: %s\n", 827 ldb_dn_get_linearized(partition_res->msgs[0]->dn), 828 ldb_errstring(ldb)); 829 return ret; 830 } 831 832 /* 833 * TODO: Remaining checks, like if we are 834 * the naming master etc need to be handled 835 * in the instanceType module 836 */ 837 return ldb_next_request(module, req); 838 } 839 840 /* Check that we can create a crossRef object MS-ADTS 3.1.1.5.2.8.2 */ 841 ret = dsdb_module_check_access_on_dn(module, req, partitions_dn, 842 SEC_ADS_CREATE_CHILD, 843 &objectclass->schemaIDGUID, req); 844 if (ret == LDB_ERR_NO_SUCH_OBJECT && 845 ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) 846 { 847 /* Allow provision bootstrap */ 848 ret = LDB_SUCCESS; 849 } 850 if (ret != LDB_SUCCESS) { 851 ldb_asprintf_errstring(ldb_module_get_ctx(module), 852 "acl: ACL check failed on CN=Partitions crossRef container %s: %s\n", 853 ldb_dn_get_linearized(partitions_dn), ldb_errstring(ldb)); 854 return ret; 855 } 856 857 /* 858 * TODO: Remaining checks, like if we are the naming 859 * master and adding the crossRef object need to be 860 * handled in the instanceType module 861 */ 862 return ldb_next_request(module, req); 863 } 864 865 ret = dsdb_module_check_access_on_dn(module, req, parent, 866 SEC_ADS_CREATE_CHILD, 867 &objectclass->schemaIDGUID, req); 868 if (ret != LDB_SUCCESS) { 869 ldb_asprintf_errstring(ldb_module_get_ctx(module), 870 "acl: unable to get access to %s\n", 871 ldb_dn_get_linearized(req->op.add.message->dn)); 706 872 return ret; 707 873 } … … 715 881 struct security_descriptor *sd, 716 882 struct dom_sid *sid, 717 const struct GUID *oc_guid,718 const struct dsdb_ attribute *attr)883 const struct dsdb_attribute *attr, 884 const struct dsdb_class *objectclass) 719 885 { 720 886 int ret; … … 729 895 sid, 730 896 SEC_ADS_WRITE_PROP, 731 attr ) == LDB_SUCCESS) {897 attr, objectclass) == LDB_SUCCESS) { 732 898 return LDB_SUCCESS; 733 899 } … … 771 937 struct security_descriptor *sd, 772 938 struct dom_sid *sid, 773 const struct GUID *oc_guid,939 const struct dsdb_class *objectclass, 774 940 bool userPassword) 775 941 { … … 851 1017 } 852 1018 1019 853 1020 static int acl_modify(struct ldb_module *module, struct ldb_request *req) 854 1021 { … … 857 1024 const struct dsdb_schema *schema; 858 1025 unsigned int i; 859 const struct GUID *guid; 860 uint32_t access_granted; 861 struct object_tree *root = NULL; 862 struct object_tree *new_node = NULL; 863 NTSTATUS status; 1026 const struct dsdb_class *objectclass; 864 1027 struct ldb_result *acl_res; 865 1028 struct security_descriptor *sd; 866 1029 struct dom_sid *sid = NULL; 867 struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); 868 bool userPassword = dsdb_user_password_support(module, req, req); 869 TALLOC_CTX *tmp_ctx = talloc_new(req); 1030 struct ldb_control *as_system; 1031 struct ldb_control *is_undelete; 1032 bool userPassword; 1033 TALLOC_CTX *tmp_ctx; 1034 const struct ldb_message *msg = req->op.mod.message; 870 1035 static const char *acl_attrs[] = { 871 1036 "nTSecurityDescriptor", … … 875 1040 }; 876 1041 1042 if (ldb_dn_is_special(msg->dn)) { 1043 return ldb_next_request(module, req); 1044 } 1045 1046 as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); 877 1047 if (as_system != NULL) { 878 1048 as_system->critical = 0; 879 1049 } 880 1050 1051 is_undelete = ldb_request_get_control(req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID); 1052 881 1053 /* Don't print this debug statement if elements[0].name is going to be NULL */ 882 if(req->op.mod.message->num_elements > 0) 883 { 884 DEBUG(10, ("ldb:acl_modify: %s\n", req->op.mod.message->elements[0].name)); 1054 if (msg->num_elements > 0) { 1055 DEBUG(10, ("ldb:acl_modify: %s\n", msg->elements[0].name)); 885 1056 } 886 1057 if (dsdb_module_am_system(module) || as_system) { 887 1058 return ldb_next_request(module, req); 888 1059 } 889 if (ldb_dn_is_special(req->op.mod.message->dn)) { 890 return ldb_next_request(module, req); 891 } 892 ret = dsdb_module_search_dn(module, tmp_ctx, &acl_res, req->op.mod.message->dn, 1060 1061 tmp_ctx = talloc_new(req); 1062 if (tmp_ctx == NULL) { 1063 return ldb_oom(ldb); 1064 } 1065 1066 ret = dsdb_module_search_dn(module, tmp_ctx, &acl_res, msg->dn, 893 1067 acl_attrs, 894 DSDB_FLAG_NEXT_MODULE, req); 1068 DSDB_FLAG_NEXT_MODULE | 1069 DSDB_FLAG_AS_SYSTEM | 1070 DSDB_SEARCH_SHOW_RECYCLED, 1071 req); 895 1072 896 1073 if (ret != LDB_SUCCESS) { 897 1074 goto fail; 898 1075 } 1076 1077 userPassword = dsdb_user_password_support(module, req, req); 899 1078 900 1079 schema = dsdb_get_schema(ldb, tmp_ctx); 901 1080 if (!schema) { 902 ret = LDB_ERR_OPERATIONS_ERROR; 903 goto fail; 1081 talloc_free(tmp_ctx); 1082 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, 1083 "acl_modify: Error obtaining schema."); 904 1084 } 905 1085 … … 915 1095 } 916 1096 917 guid = get_oc_guid_from_message(module,schema, acl_res->msgs[0]);918 if (! guid) {1097 objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]); 1098 if (!objectclass) { 919 1099 talloc_free(tmp_ctx); 920 1100 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, 921 "acl_modify: Error retrieving object class GUID.");1101 "acl_modify: Error retrieving object class for GUID."); 922 1102 } 923 1103 sid = samdb_result_dom_sid(req, acl_res->msgs[0], "objectSid"); 924 if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP, 925 &root, &new_node)) { 926 talloc_free(tmp_ctx); 927 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, 928 "acl_modify: Error adding new node in object tree."); 929 } 930 for (i=0; i < req->op.mod.message->num_elements; i++){ 1104 for (i=0; i < msg->num_elements; i++) { 1105 const struct ldb_message_element *el = &msg->elements[i]; 931 1106 const struct dsdb_attribute *attr; 932 attr = dsdb_attribute_by_lDAPDisplayName(schema, 933 req->op.mod.message->elements[i].name); 934 935 if (ldb_attr_cmp("nTSecurityDescriptor", req->op.mod.message->elements[i].name) == 0) { 936 status = sec_access_check_ds(sd, acl_user_token(module), 937 SEC_STD_WRITE_DAC, 938 &access_granted, 939 NULL, 940 sid); 941 942 if (!NT_STATUS_IS_OK(status)) { 943 DEBUG(10, ("Object %s has no write dacl access\n", 944 ldb_dn_get_linearized(req->op.mod.message->dn))); 1107 1108 /* 1109 * This basic attribute existence check with the right errorcode 1110 * is needed since this module is the first one which requests 1111 * schema attribute information. 1112 * The complete attribute checking is done in the 1113 * "objectclass_attrs" module behind this one. 1114 * 1115 * NOTE: "clearTextPassword" is not defined in the schema. 1116 */ 1117 attr = dsdb_attribute_by_lDAPDisplayName(schema, el->name); 1118 if (!attr && ldb_attr_cmp("clearTextPassword", el->name) != 0) { 1119 ldb_asprintf_errstring(ldb, "acl_modify: attribute '%s' " 1120 "on entry '%s' was not found in the schema!", 1121 req->op.mod.message->elements[i].name, 1122 ldb_dn_get_linearized(req->op.mod.message->dn)); 1123 ret = LDB_ERR_NO_SUCH_ATTRIBUTE; 1124 goto fail; 1125 } 1126 1127 if (ldb_attr_cmp("nTSecurityDescriptor", el->name) == 0) { 1128 uint32_t sd_flags = dsdb_request_sd_flags(req, NULL); 1129 uint32_t access_mask = 0; 1130 1131 if (sd_flags & (SECINFO_OWNER|SECINFO_GROUP)) { 1132 access_mask |= SEC_STD_WRITE_OWNER; 1133 } 1134 if (sd_flags & SECINFO_DACL) { 1135 access_mask |= SEC_STD_WRITE_DAC; 1136 } 1137 if (sd_flags & SECINFO_SACL) { 1138 access_mask |= SEC_FLAG_SYSTEM_SECURITY; 1139 } 1140 1141 ret = acl_check_access_on_attribute(module, 1142 tmp_ctx, 1143 sd, 1144 sid, 1145 access_mask, 1146 attr, 1147 objectclass); 1148 if (ret != LDB_SUCCESS) { 1149 ldb_asprintf_errstring(ldb_module_get_ctx(module), 1150 "Object %s has no write dacl access\n", 1151 ldb_dn_get_linearized(msg->dn)); 945 1152 dsdb_acl_debug(sd, 946 1153 acl_user_token(module), 947 req->op.mod.message->dn,1154 msg->dn, 948 1155 true, 949 1156 10); … … 951 1158 goto fail; 952 1159 } 953 } 954 else if (ldb_attr_cmp("member", req->op.mod.message->elements[i].name) == 0) { 1160 } else if (ldb_attr_cmp("member", el->name) == 0) { 955 1161 ret = acl_check_self_membership(tmp_ctx, 956 1162 module, … … 958 1164 sd, 959 1165 sid, 960 guid,961 attr);1166 attr, 1167 objectclass); 962 1168 if (ret != LDB_SUCCESS) { 963 1169 goto fail; 964 1170 } 965 } 966 else if (ldb_attr_cmp("dBCSPwd", req->op.mod.message->elements[i].name) == 0) { 1171 } else if (ldb_attr_cmp("dBCSPwd", el->name) == 0) { 967 1172 /* this one is not affected by any rights, we should let it through 968 1173 so that passwords_hash returns the correct error */ 969 1174 continue; 970 } 971 else if (ldb_attr_cmp("unicodePwd", req->op.mod.message->elements[i].name) == 0 || 972 (userPassword && ldb_attr_cmp("userPassword", req->op.mod.message->elements[i].name) == 0) || 973 ldb_attr_cmp("clearTextPassword", req->op.mod.message->elements[i].name) == 0) { 1175 } else if (ldb_attr_cmp("unicodePwd", el->name) == 0 || 1176 (userPassword && ldb_attr_cmp("userPassword", el->name) == 0) || 1177 ldb_attr_cmp("clearTextPassword", el->name) == 0) { 974 1178 ret = acl_check_password_rights(tmp_ctx, 975 1179 module, … … 977 1181 sd, 978 1182 sid, 979 guid,1183 objectclass, 980 1184 userPassword); 981 1185 if (ret != LDB_SUCCESS) { 982 1186 goto fail; 983 1187 } 984 } else if (ldb_attr_cmp("servicePrincipalName", req->op.mod.message->elements[i].name) == 0) {1188 } else if (ldb_attr_cmp("servicePrincipalName", el->name) == 0) { 985 1189 ret = acl_check_spn(tmp_ctx, 986 1190 module, … … 988 1192 sd, 989 1193 sid, 990 guid,991 attr);1194 attr, 1195 objectclass); 992 1196 if (ret != LDB_SUCCESS) { 993 1197 goto fail; 994 1198 } 1199 } else if (is_undelete != NULL && (ldb_attr_cmp("isDeleted", el->name) == 0)) { 1200 /* 1201 * in case of undelete op permissions on 1202 * isDeleted are irrelevant and 1203 * distinguishedName is removed by the 1204 * tombstone_reanimate module 1205 */ 1206 continue; 995 1207 } else { 996 997 /* This basic attribute existence check with the right errorcode 998 * is needed since this module is the first one which requests 999 * schema attribute information. 1000 * The complete attribute checking is done in the 1001 * "objectclass_attrs" module behind this one. 1002 */ 1003 if (!attr) { 1004 ldb_asprintf_errstring(ldb, "acl_modify: attribute '%s' on entry '%s' was not found in the schema!", 1005 req->op.mod.message->elements[i].name, 1006 ldb_dn_get_linearized(req->op.mod.message->dn)); 1007 ret = LDB_ERR_NO_SUCH_ATTRIBUTE; 1208 ret = acl_check_access_on_attribute(module, 1209 tmp_ctx, 1210 sd, 1211 sid, 1212 SEC_ADS_WRITE_PROP, 1213 attr, 1214 objectclass); 1215 if (ret != LDB_SUCCESS) { 1216 ldb_asprintf_errstring(ldb_module_get_ctx(module), 1217 "Object %s has no write property access\n", 1218 ldb_dn_get_linearized(msg->dn)); 1219 dsdb_acl_debug(sd, 1220 acl_user_token(module), 1221 msg->dn, 1222 true, 1223 10); 1224 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; 1008 1225 goto fail; 1009 1226 } 1010 if (!insert_in_object_tree(tmp_ctx,1011 &attr->attributeSecurityGUID, SEC_ADS_WRITE_PROP,1012 &new_node, &new_node)) {1013 DEBUG(10, ("acl_modify: cannot add to object tree securityGUID\n"));1014 ret = LDB_ERR_OPERATIONS_ERROR;1015 goto fail;1016 }1017 1018 if (!insert_in_object_tree(tmp_ctx,1019 &attr->schemaIDGUID, SEC_ADS_WRITE_PROP, &new_node, &new_node)) {1020 DEBUG(10, ("acl_modify: cannot add to object tree attributeGUID\n"));1021 ret = LDB_ERR_OPERATIONS_ERROR;1022 goto fail;1023 }1024 }1025 }1026 1027 if (root->num_of_children > 0) {1028 status = sec_access_check_ds(sd, acl_user_token(module),1029 SEC_ADS_WRITE_PROP,1030 &access_granted,1031 root,1032 sid);1033 1034 if (!NT_STATUS_IS_OK(status)) {1035 DEBUG(10, ("Object %s has no write property access\n",1036 ldb_dn_get_linearized(req->op.mod.message->dn)));1037 dsdb_acl_debug(sd,1038 acl_user_token(module),1039 req->op.mod.message->dn,1040 true,1041 10);1042 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;1043 goto fail;1044 1227 } 1045 1228 } … … 1058 1241 { 1059 1242 int ret; 1060 struct ldb_dn *parent = ldb_dn_get_parent(req, req->op.del.dn);1243 struct ldb_dn *parent; 1061 1244 struct ldb_context *ldb; 1062 1245 struct ldb_dn *nc_root; 1063 struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); 1064 1246 struct ldb_control *as_system; 1247 const struct dsdb_schema *schema; 1248 const struct dsdb_class *objectclass; 1249 struct security_descriptor *sd = NULL; 1250 struct dom_sid *sid = NULL; 1251 struct ldb_result *acl_res; 1252 static const char *acl_attrs[] = { 1253 "nTSecurityDescriptor", 1254 "objectClass", 1255 "objectSid", 1256 NULL 1257 }; 1258 1259 if (ldb_dn_is_special(req->op.del.dn)) { 1260 return ldb_next_request(module, req); 1261 } 1262 1263 as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); 1065 1264 if (as_system != NULL) { 1066 1265 as_system->critical = 0; 1067 1266 } 1068 1267 1069 DEBUG(10, ("ldb:acl_delete: %s\n", ldb_dn_get_linearized(req->op.del.dn)));1070 1268 if (dsdb_module_am_system(module) || as_system) { 1071 1269 return ldb_next_request(module, req); 1072 1270 } 1073 if (ldb_dn_is_special(req->op.del.dn)) { 1074 return ldb_next_request(module, req); 1075 } 1271 1272 DEBUG(10, ("ldb:acl_delete: %s\n", ldb_dn_get_linearized(req->op.del.dn))); 1076 1273 1077 1274 ldb = ldb_module_get_ctx(module); 1275 1276 parent = ldb_dn_get_parent(req, req->op.del.dn); 1277 if (parent == NULL) { 1278 return ldb_oom(ldb); 1279 } 1078 1280 1079 1281 /* Make sure we aren't deleting a NC */ … … 1092 1294 talloc_free(nc_root); 1093 1295 1296 ret = dsdb_module_search_dn(module, req, &acl_res, 1297 req->op.del.dn, acl_attrs, 1298 DSDB_FLAG_NEXT_MODULE | 1299 DSDB_FLAG_AS_SYSTEM | 1300 DSDB_SEARCH_SHOW_RECYCLED, req); 1301 /* we sould be able to find the parent */ 1302 if (ret != LDB_SUCCESS) { 1303 DEBUG(10,("acl: failed to find object %s\n", 1304 ldb_dn_get_linearized(req->op.rename.olddn))); 1305 return ret; 1306 } 1307 1308 ret = dsdb_get_sd_from_ldb_message(ldb, req, acl_res->msgs[0], &sd); 1309 if (ret != LDB_SUCCESS) { 1310 return ldb_operr(ldb); 1311 } 1312 if (!sd) { 1313 return ldb_operr(ldb); 1314 } 1315 1316 schema = dsdb_get_schema(ldb, req); 1317 if (!schema) { 1318 return ldb_operr(ldb); 1319 } 1320 1321 sid = samdb_result_dom_sid(req, acl_res->msgs[0], "objectSid"); 1322 1323 objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]); 1324 if (!objectclass) { 1325 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, 1326 "acl_modify: Error retrieving object class for GUID."); 1327 } 1328 1329 if (ldb_request_get_control(req, LDB_CONTROL_TREE_DELETE_OID)) { 1330 ret = acl_check_access_on_objectclass(module, req, sd, sid, 1331 SEC_ADS_DELETE_TREE, 1332 objectclass); 1333 if (ret != LDB_SUCCESS) { 1334 return ret; 1335 } 1336 1337 return ldb_next_request(module, req); 1338 } 1339 1094 1340 /* First check if we have delete object right */ 1095 ret = dsdb_module_check_access_on_dn(module, req, req->op.del.dn, 1096 SEC_STD_DELETE, NULL, req); 1341 ret = acl_check_access_on_objectclass(module, req, sd, sid, 1342 SEC_STD_DELETE, 1343 objectclass); 1097 1344 if (ret == LDB_SUCCESS) { 1098 1345 return ldb_next_request(module, req); … … 1102 1349 * child on the parent */ 1103 1350 ret = dsdb_module_check_access_on_dn(module, req, parent, 1104 SEC_ADS_DELETE_CHILD, NULL, req); 1351 SEC_ADS_DELETE_CHILD, 1352 &objectclass->schemaIDGUID, 1353 req); 1105 1354 if (ret != LDB_SUCCESS) { 1106 1355 return ret; … … 1108 1357 1109 1358 return ldb_next_request(module, req); 1359 } 1360 static int acl_check_reanimate_tombstone(TALLOC_CTX *mem_ctx, 1361 struct ldb_module *module, 1362 struct ldb_request *req, 1363 struct ldb_dn *nc_root) 1364 { 1365 int ret; 1366 struct ldb_result *acl_res; 1367 struct security_descriptor *sd = NULL; 1368 struct dom_sid *sid = NULL; 1369 static const char *acl_attrs[] = { 1370 "nTSecurityDescriptor", 1371 "objectClass", 1372 "objectSid", 1373 NULL 1374 }; 1375 1376 ret = dsdb_module_search_dn(module, mem_ctx, &acl_res, 1377 nc_root, acl_attrs, 1378 DSDB_FLAG_NEXT_MODULE | 1379 DSDB_FLAG_AS_SYSTEM | 1380 DSDB_SEARCH_SHOW_RECYCLED, req); 1381 if (ret != LDB_SUCCESS) { 1382 DEBUG(10,("acl: failed to find object %s\n", 1383 ldb_dn_get_linearized(nc_root))); 1384 return ret; 1385 } 1386 1387 ret = dsdb_get_sd_from_ldb_message(mem_ctx, req, acl_res->msgs[0], &sd); 1388 sid = samdb_result_dom_sid(mem_ctx, acl_res->msgs[0], "objectSid"); 1389 if (ret != LDB_SUCCESS || !sd) { 1390 return ldb_operr(ldb_module_get_ctx(module)); 1391 } 1392 return acl_check_extended_right(mem_ctx, sd, acl_user_token(module), 1393 GUID_DRS_REANIMATE_TOMBSTONE, 1394 SEC_ADS_CONTROL_ACCESS, sid); 1110 1395 } 1111 1396 … … 1113 1398 { 1114 1399 int ret; 1115 struct ldb_dn *oldparent = ldb_dn_get_parent(req, req->op.rename.olddn);1116 struct ldb_dn *newparent = ldb_dn_get_parent(req, req->op.rename.newdn);1400 struct ldb_dn *oldparent; 1401 struct ldb_dn *newparent; 1117 1402 const struct dsdb_schema *schema; 1403 const struct dsdb_class *objectclass; 1404 const struct dsdb_attribute *attr = NULL; 1118 1405 struct ldb_context *ldb; 1119 1406 struct security_descriptor *sd = NULL; 1120 1407 struct dom_sid *sid = NULL; 1121 1408 struct ldb_result *acl_res; 1122 const struct GUID *guid;1123 1409 struct ldb_dn *nc_root; 1124 struct object_tree *root = NULL; 1125 struct object_tree *new_node = NULL; 1126 struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); 1127 TALLOC_CTX *tmp_ctx = talloc_new(req); 1128 NTSTATUS status; 1129 uint32_t access_granted; 1410 struct ldb_control *as_system; 1411 struct ldb_control *is_undelete; 1412 TALLOC_CTX *tmp_ctx; 1130 1413 const char *rdn_name; 1131 1414 static const char *acl_attrs[] = { … … 1136 1419 }; 1137 1420 1421 if (ldb_dn_is_special(req->op.rename.olddn)) { 1422 return ldb_next_request(module, req); 1423 } 1424 1425 as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); 1138 1426 if (as_system != NULL) { 1139 1427 as_system->critical = 0; … … 1144 1432 return ldb_next_request(module, req); 1145 1433 } 1146 if (ldb_dn_is_special(req->op.rename.olddn)) {1147 return ldb_next_request(module, req);1148 }1149 1434 1150 1435 ldb = ldb_module_get_ctx(module); 1436 1437 tmp_ctx = talloc_new(req); 1438 if (tmp_ctx == NULL) { 1439 return ldb_oom(ldb); 1440 } 1441 1442 oldparent = ldb_dn_get_parent(tmp_ctx, req->op.rename.olddn); 1443 if (oldparent == NULL) { 1444 return ldb_oom(ldb); 1445 } 1446 newparent = ldb_dn_get_parent(tmp_ctx, req->op.rename.newdn); 1447 if (newparent == NULL) { 1448 return ldb_oom(ldb); 1449 } 1151 1450 1152 1451 /* Make sure we aren't renaming/moving a NC */ … … 1163 1462 LDB_ERR_UNWILLING_TO_PERFORM); 1164 1463 } 1464 1465 /* special check for undelete operation */ 1466 is_undelete = ldb_request_get_control(req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID); 1467 if (is_undelete != NULL) { 1468 is_undelete->critical = 0; 1469 ret = acl_check_reanimate_tombstone(tmp_ctx, module, req, nc_root); 1470 if (ret != LDB_SUCCESS) { 1471 talloc_free(tmp_ctx); 1472 return ret; 1473 } 1474 } 1165 1475 talloc_free(nc_root); 1166 1476 … … 1170 1480 req->op.rename.olddn, acl_attrs, 1171 1481 DSDB_FLAG_NEXT_MODULE | 1482 DSDB_FLAG_AS_SYSTEM | 1172 1483 DSDB_SEARCH_SHOW_RECYCLED, req); 1173 1484 /* we sould be able to find the parent */ … … 1179 1490 } 1180 1491 1492 ret = dsdb_get_sd_from_ldb_message(ldb, req, acl_res->msgs[0], &sd); 1493 if (ret != LDB_SUCCESS) { 1494 talloc_free(tmp_ctx); 1495 return ldb_operr(ldb); 1496 } 1497 if (!sd) { 1498 talloc_free(tmp_ctx); 1499 return ldb_operr(ldb); 1500 } 1501 1181 1502 schema = dsdb_get_schema(ldb, acl_res); 1182 1503 if (!schema) { … … 1185 1506 } 1186 1507 1187 guid = get_oc_guid_from_message(module, schema, acl_res->msgs[0]); 1188 if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP, 1189 &root, &new_node)) { 1508 sid = samdb_result_dom_sid(req, acl_res->msgs[0], "objectSid"); 1509 1510 objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]); 1511 if (!objectclass) { 1512 talloc_free(tmp_ctx); 1513 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, 1514 "acl_modify: Error retrieving object class for GUID."); 1515 } 1516 1517 attr = dsdb_attribute_by_lDAPDisplayName(schema, "name"); 1518 if (attr == NULL) { 1190 1519 talloc_free(tmp_ctx); 1191 1520 return ldb_operr(ldb); 1192 }; 1193 1194 guid = attribute_schemaid_guid_by_lDAPDisplayName(schema, 1195 "name"); 1196 if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP, 1197 &new_node, &new_node)) { 1198 talloc_free(tmp_ctx); 1199 return ldb_operr(ldb); 1200 }; 1201 1202 rdn_name = ldb_dn_get_rdn_name(req->op.rename.olddn); 1203 if (rdn_name == NULL) { 1204 talloc_free(tmp_ctx); 1205 return ldb_operr(ldb); 1206 } 1207 guid = attribute_schemaid_guid_by_lDAPDisplayName(schema, 1208 rdn_name); 1209 if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP, 1210 &new_node, &new_node)) { 1211 talloc_free(tmp_ctx); 1212 return ldb_operr(ldb); 1213 }; 1214 1215 ret = dsdb_get_sd_from_ldb_message(ldb, req, acl_res->msgs[0], &sd); 1216 1217 if (ret != LDB_SUCCESS) { 1218 talloc_free(tmp_ctx); 1219 return ldb_operr(ldb); 1220 } 1221 /* Theoretically we pass the check if the object has no sd */ 1222 if (!sd) { 1223 talloc_free(tmp_ctx); 1224 return LDB_SUCCESS; 1225 } 1226 sid = samdb_result_dom_sid(req, acl_res->msgs[0], "objectSid"); 1227 status = sec_access_check_ds(sd, acl_user_token(module), 1228 SEC_ADS_WRITE_PROP, 1229 &access_granted, 1230 root, 1231 sid); 1232 1233 if (!NT_STATUS_IS_OK(status)) { 1234 DEBUG(10, ("Object %s has no wp on name\n", 1235 ldb_dn_get_linearized(req->op.rename.olddn))); 1521 } 1522 1523 ret = acl_check_access_on_attribute(module, tmp_ctx, sd, sid, 1524 SEC_ADS_WRITE_PROP, 1525 attr, objectclass); 1526 if (ret != LDB_SUCCESS) { 1527 ldb_asprintf_errstring(ldb_module_get_ctx(module), 1528 "Object %s has no wp on %s\n", 1529 ldb_dn_get_linearized(req->op.rename.olddn), 1530 attr->lDAPDisplayName); 1236 1531 dsdb_acl_debug(sd, 1237 1532 acl_user_token(module), … … 1243 1538 } 1244 1539 1540 rdn_name = ldb_dn_get_rdn_name(req->op.rename.olddn); 1541 if (rdn_name == NULL) { 1542 talloc_free(tmp_ctx); 1543 return ldb_operr(ldb); 1544 } 1545 1546 attr = dsdb_attribute_by_lDAPDisplayName(schema, rdn_name); 1547 if (attr == NULL) { 1548 talloc_free(tmp_ctx); 1549 return ldb_operr(ldb); 1550 } 1551 1552 ret = acl_check_access_on_attribute(module, tmp_ctx, sd, sid, 1553 SEC_ADS_WRITE_PROP, 1554 attr, objectclass); 1555 if (ret != LDB_SUCCESS) { 1556 ldb_asprintf_errstring(ldb_module_get_ctx(module), 1557 "Object %s has no wp on %s\n", 1558 ldb_dn_get_linearized(req->op.rename.olddn), 1559 attr->lDAPDisplayName); 1560 dsdb_acl_debug(sd, 1561 acl_user_token(module), 1562 req->op.rename.olddn, 1563 true, 1564 10); 1565 talloc_free(tmp_ctx); 1566 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; 1567 } 1568 1245 1569 if (ldb_dn_compare(oldparent, newparent) == 0) { 1246 1570 /* regular rename, not move, nothing more to do */ … … 1250 1574 1251 1575 /* new parent should have create child */ 1252 root = NULL; 1253 new_node = NULL; 1254 guid = get_oc_guid_from_message(module, schema, acl_res->msgs[0]); 1255 if (!guid) { 1256 DEBUG(10,("acl:renamed object has no object class\n")); 1257 talloc_free(tmp_ctx); 1258 return ldb_module_done(req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); 1259 } 1260 1261 ret = dsdb_module_check_access_on_dn(module, req, newparent, SEC_ADS_CREATE_CHILD, guid, req); 1262 if (ret != LDB_SUCCESS) { 1263 DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn))); 1576 ret = dsdb_module_check_access_on_dn(module, req, newparent, 1577 SEC_ADS_CREATE_CHILD, 1578 &objectclass->schemaIDGUID, req); 1579 if (ret != LDB_SUCCESS) { 1580 ldb_asprintf_errstring(ldb_module_get_ctx(module), 1581 "acl:access_denied renaming %s", 1582 ldb_dn_get_linearized(req->op.rename.olddn)); 1264 1583 talloc_free(tmp_ctx); 1265 1584 return ret; 1266 1585 } 1586 1267 1587 /* do we have delete object on the object? */ 1268 1269 status = sec_access_check_ds(sd, acl_user_token(module), 1270 SEC_STD_DELETE, 1271 &access_granted, 1272 NULL, 1273 sid); 1274 1275 if (NT_STATUS_IS_OK(status)) { 1276 talloc_free(tmp_ctx); 1277 return ldb_next_request(module, req); 1278 } 1279 /* what about delete child on the current parent */ 1280 ret = dsdb_module_check_access_on_dn(module, req, oldparent, SEC_ADS_DELETE_CHILD, NULL, req); 1281 if (ret != LDB_SUCCESS) { 1282 DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn))); 1283 talloc_free(tmp_ctx); 1284 return ldb_module_done(req, NULL, NULL, ret); 1285 } 1286 1588 /* this access is not necessary for undelete ops */ 1589 if (is_undelete == NULL) { 1590 ret = acl_check_access_on_objectclass(module, tmp_ctx, sd, sid, 1591 SEC_STD_DELETE, 1592 objectclass); 1593 if (ret == LDB_SUCCESS) { 1594 talloc_free(tmp_ctx); 1595 return ldb_next_request(module, req); 1596 } 1597 /* what about delete child on the current parent */ 1598 ret = dsdb_module_check_access_on_dn(module, req, oldparent, 1599 SEC_ADS_DELETE_CHILD, 1600 &objectclass->schemaIDGUID, 1601 req); 1602 if (ret != LDB_SUCCESS) { 1603 ldb_asprintf_errstring(ldb_module_get_ctx(module), 1604 "acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn)); 1605 talloc_free(tmp_ctx); 1606 return ldb_module_done(req, NULL, NULL, ret); 1607 } 1608 } 1287 1609 talloc_free(tmp_ctx); 1288 1610 … … 1290 1612 } 1291 1613 1614 static int acl_search_update_confidential_attrs(struct acl_context *ac, 1615 struct acl_private *data) 1616 { 1617 struct dsdb_attribute *a; 1618 uint32_t n = 0; 1619 1620 if (data->acl_search) { 1621 /* 1622 * If acl:search is activated, the acl_read module 1623 * protects confidential attributes. 1624 */ 1625 return LDB_SUCCESS; 1626 } 1627 1628 if ((ac->schema == data->cached_schema_ptr) && 1629 (ac->schema->loaded_usn == data->cached_schema_loaded_usn) && 1630 (ac->schema->metadata_usn == data->cached_schema_metadata_usn)) 1631 { 1632 return LDB_SUCCESS; 1633 } 1634 1635 data->cached_schema_ptr = NULL; 1636 data->cached_schema_loaded_usn = 0; 1637 data->cached_schema_metadata_usn = 0; 1638 TALLOC_FREE(data->confidential_attrs); 1639 1640 if (ac->schema == NULL) { 1641 return LDB_SUCCESS; 1642 } 1643 1644 for (a = ac->schema->attributes; a; a = a->next) { 1645 const char **attrs = data->confidential_attrs; 1646 1647 if (!(a->searchFlags & SEARCH_FLAG_CONFIDENTIAL)) { 1648 continue; 1649 } 1650 1651 attrs = talloc_realloc(data, attrs, const char *, n + 2); 1652 if (attrs == NULL) { 1653 TALLOC_FREE(data->confidential_attrs); 1654 return ldb_module_oom(ac->module); 1655 } 1656 1657 attrs[n] = a->lDAPDisplayName; 1658 attrs[n+1] = NULL; 1659 n++; 1660 1661 data->confidential_attrs = attrs; 1662 } 1663 1664 data->cached_schema_ptr = ac->schema; 1665 data->cached_schema_loaded_usn = ac->schema->loaded_usn; 1666 data->cached_schema_metadata_usn = ac->schema->metadata_usn; 1667 1668 return LDB_SUCCESS; 1669 } 1670 1292 1671 static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares) 1293 1672 { 1294 struct ldb_context *ldb;1295 1673 struct acl_context *ac; 1296 1674 struct acl_private *data; … … 1307 1685 ac = talloc_get_type(req->context, struct acl_context); 1308 1686 data = talloc_get_type(ldb_module_get_private(ac->module), struct acl_private); 1309 ldb = ldb_module_get_ctx(ac->module);1310 1311 1687 if (!ares) { 1312 1688 return ldb_module_done(ac->req, NULL, NULL, … … 1320 1696 switch (ares->type) { 1321 1697 case LDB_REPLY_ENTRY: 1322 if (ac->allowedAttributes 1323 || ac->allowedChildClasses 1324 || ac->allowedChildClassesEffective 1325 || ac->allowedAttributesEffective 1326 || ac->sDRightsEffective) { 1698 if (ac->constructed_attrs) { 1327 1699 ret = dsdb_module_search_dn(ac->module, ac, &acl_res, ares->message->dn, 1328 1700 acl_attrs, 1329 DSDB_FLAG_NEXT_MODULE, req); 1701 DSDB_FLAG_NEXT_MODULE | 1702 DSDB_FLAG_AS_SYSTEM | 1703 DSDB_SEARCH_SHOW_RECYCLED, 1704 req); 1330 1705 if (ret != LDB_SUCCESS) { 1331 1706 return ldb_module_done(ac->req, NULL, NULL, ret); 1332 1707 } 1333 if (ac->allowedAttributes || ac->allowedAttributesEffective) { 1334 ret = acl_allowedAttributes(ac->module, ac->schema, acl_res->msgs[0], ares->message, ac); 1335 if (ret != LDB_SUCCESS) { 1336 return ldb_module_done(ac->req, NULL, NULL, ret); 1708 } 1709 1710 if (ac->allowedAttributes || ac->allowedAttributesEffective) { 1711 ret = acl_allowedAttributes(ac->module, ac->schema, 1712 acl_res->msgs[0], 1713 ares->message, ac); 1714 if (ret != LDB_SUCCESS) { 1715 return ldb_module_done(ac->req, NULL, NULL, ret); 1716 } 1717 } 1718 1719 if (ac->allowedChildClasses) { 1720 ret = acl_childClasses(ac->module, ac->schema, 1721 acl_res->msgs[0], 1722 ares->message, 1723 "allowedChildClasses"); 1724 if (ret != LDB_SUCCESS) { 1725 return ldb_module_done(ac->req, NULL, NULL, ret); 1726 } 1727 } 1728 1729 if (ac->allowedChildClassesEffective) { 1730 ret = acl_childClassesEffective(ac->module, ac->schema, 1731 acl_res->msgs[0], 1732 ares->message, ac); 1733 if (ret != LDB_SUCCESS) { 1734 return ldb_module_done(ac->req, NULL, NULL, ret); 1735 } 1736 } 1737 1738 if (ac->sDRightsEffective) { 1739 ret = acl_sDRightsEffective(ac->module, 1740 acl_res->msgs[0], 1741 ares->message, ac); 1742 if (ret != LDB_SUCCESS) { 1743 return ldb_module_done(ac->req, NULL, NULL, ret); 1744 } 1745 } 1746 1747 if (data == NULL) { 1748 return ldb_module_send_entry(ac->req, ares->message, 1749 ares->controls); 1750 } 1751 1752 if (ac->am_system) { 1753 return ldb_module_send_entry(ac->req, ares->message, 1754 ares->controls); 1755 } 1756 1757 if (data->password_attrs != NULL) { 1758 for (i = 0; data->password_attrs[i]; i++) { 1759 if ((!ac->userPassword) && 1760 (ldb_attr_cmp(data->password_attrs[i], 1761 "userPassword") == 0)) 1762 { 1763 continue; 1337 1764 } 1338 } 1339 if (ac->allowedChildClasses) { 1340 ret = acl_childClasses(ac->module, ac->schema, acl_res->msgs[0], 1341 ares->message, "allowedChildClasses"); 1342 if (ret != LDB_SUCCESS) { 1343 return ldb_module_done(ac->req, NULL, NULL, ret); 1344 } 1345 } 1346 if (ac->allowedChildClassesEffective) { 1347 ret = acl_childClassesEffective(ac->module, ac->schema, 1348 acl_res->msgs[0], ares->message, ac); 1349 if (ret != LDB_SUCCESS) { 1350 return ldb_module_done(ac->req, NULL, NULL, ret); 1351 } 1352 } 1353 if (ac->sDRightsEffective) { 1354 ret = acl_sDRightsEffective(ac->module, 1355 acl_res->msgs[0], ares->message, ac); 1356 if (ret != LDB_SUCCESS) { 1357 return ldb_module_done(ac->req, NULL, NULL, ret); 1358 } 1359 } 1360 } 1361 if (data && data->password_attrs) { 1362 if (!ac->am_system) { 1363 for (i = 0; data->password_attrs[i]; i++) { 1364 if ((!ac->userPassword) && 1365 (ldb_attr_cmp(data->password_attrs[i], 1366 "userPassword") == 0)) 1367 continue; 1368 1369 ldb_msg_remove_attr(ares->message, data->password_attrs[i]); 1370 } 1371 } 1372 } 1765 1766 ldb_msg_remove_attr(ares->message, data->password_attrs[i]); 1767 } 1768 } 1769 1770 if (ac->am_administrator) { 1771 return ldb_module_send_entry(ac->req, ares->message, 1772 ares->controls); 1773 } 1774 1775 ret = acl_search_update_confidential_attrs(ac, data); 1776 if (ret != LDB_SUCCESS) { 1777 return ret; 1778 } 1779 1780 if (data->confidential_attrs != NULL) { 1781 for (i = 0; data->confidential_attrs[i]; i++) { 1782 ldb_msg_remove_attr(ares->message, 1783 data->confidential_attrs[i]); 1784 } 1785 } 1786 1373 1787 return ldb_module_send_entry(ac->req, ares->message, ares->controls); 1374 1788 … … 1388 1802 struct ldb_context *ldb; 1389 1803 struct acl_context *ac; 1804 struct ldb_parse_tree *down_tree; 1390 1805 struct ldb_request *down_req; 1391 1806 struct acl_private *data; … … 1393 1808 unsigned int i; 1394 1809 1810 if (ldb_dn_is_special(req->op.search.base)) { 1811 return ldb_next_request(module, req); 1812 } 1813 1395 1814 ldb = ldb_module_get_ctx(module); 1396 1815 … … 1404 1823 ac->req = req; 1405 1824 ac->am_system = dsdb_module_am_system(module); 1825 ac->am_administrator = dsdb_module_am_administrator(module); 1826 ac->constructed_attrs = false; 1827 ac->modify_search = true; 1406 1828 ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes"); 1407 1829 ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective"); … … 1409 1831 ac->allowedChildClassesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedChildClassesEffective"); 1410 1832 ac->sDRightsEffective = ldb_attr_in_list(req->op.search.attrs, "sDRightsEffective"); 1411 ac->userPassword = dsdb_user_password_support(module, ac, req);1833 ac->userPassword = true; 1412 1834 ac->schema = dsdb_get_schema(ldb, ac); 1413 1835 1414 /* replace any attributes in the parse tree that are private, 1415 so we don't allow a search for 'userPassword=penguin', 1416 just as we would not allow that attribute to be returned */ 1836 ac->constructed_attrs |= ac->allowedAttributes; 1837 ac->constructed_attrs |= ac->allowedChildClasses; 1838 ac->constructed_attrs |= ac->allowedChildClassesEffective; 1839 ac->constructed_attrs |= ac->allowedAttributesEffective; 1840 ac->constructed_attrs |= ac->sDRightsEffective; 1841 1842 if (data == NULL) { 1843 ac->modify_search = false; 1844 } 1417 1845 if (ac->am_system) { 1418 /* FIXME: We should copy the tree and keep the original unmodified. */ 1419 /* remove password attributes */ 1420 if (data && data->password_attrs) { 1421 for (i = 0; data->password_attrs[i]; i++) { 1422 if ((!ac->userPassword) && 1423 (ldb_attr_cmp(data->password_attrs[i], 1424 "userPassword") == 0)) 1425 continue; 1426 1427 ldb_parse_tree_attr_replace(req->op.search.tree, 1428 data->password_attrs[i], 1429 "kludgeACLredactedattribute"); 1430 } 1431 } 1432 } 1846 ac->modify_search = false; 1847 } 1848 1849 if (!ac->constructed_attrs && !ac->modify_search) { 1850 talloc_free(ac); 1851 return ldb_next_request(module, req); 1852 } 1853 1854 if (!ac->am_system) { 1855 ac->userPassword = dsdb_user_password_support(module, ac, req); 1856 } 1857 1858 ret = acl_search_update_confidential_attrs(ac, data); 1859 if (ret != LDB_SUCCESS) { 1860 return ret; 1861 } 1862 1863 down_tree = ldb_parse_tree_copy_shallow(ac, req->op.search.tree); 1864 if (down_tree == NULL) { 1865 return ldb_oom(ldb); 1866 } 1867 1868 if (!ac->am_system && data->password_attrs) { 1869 for (i = 0; data->password_attrs[i]; i++) { 1870 if ((!ac->userPassword) && 1871 (ldb_attr_cmp(data->password_attrs[i], 1872 "userPassword") == 0)) 1873 { 1874 continue; 1875 } 1876 1877 ldb_parse_tree_attr_replace(down_tree, 1878 data->password_attrs[i], 1879 "kludgeACLredactedattribute"); 1880 } 1881 } 1882 1883 if (!ac->am_system && !ac->am_administrator && data->confidential_attrs) { 1884 for (i = 0; data->confidential_attrs[i]; i++) { 1885 ldb_parse_tree_attr_replace(down_tree, 1886 data->confidential_attrs[i], 1887 "kludgeACLredactedattribute"); 1888 } 1889 } 1890 1433 1891 ret = ldb_build_search_req_ex(&down_req, 1434 1892 ldb, ac, 1435 1893 req->op.search.base, 1436 1894 req->op.search.scope, 1437 req->op.search.tree,1895 down_tree, 1438 1896 req->op.search.attrs, 1439 1897 req->controls, -
vendor/current/source4/dsdb/samdb/ldb_modules/acl_read.c
r740 r988 45 45 const char * const *attrs; 46 46 const struct dsdb_schema *schema; 47 bool sd; 48 bool instance_type; 49 bool object_sid; 47 uint32_t sd_flags; 48 bool added_nTSecurityDescriptor; 49 bool added_instanceType; 50 bool added_objectSid; 51 bool added_objectClass; 52 bool indirsync; 50 53 }; 51 54 … … 55 58 56 59 static void aclread_mark_inaccesslible(struct ldb_message_element *el) { 57 60 el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE; 58 61 } 59 62 … … 64 67 static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares) 65 68 { 66 struct ldb_context *ldb; 67 struct aclread_context *ac; 68 struct ldb_message *ret_msg; 69 struct ldb_message *msg; 70 int ret, num_of_attrs = 0; 71 unsigned int i, k = 0; 72 struct security_descriptor *sd; 73 struct dom_sid *sid = NULL; 74 TALLOC_CTX *tmp_ctx; 75 uint32_t instanceType; 76 77 ac = talloc_get_type(req->context, struct aclread_context); 78 ldb = ldb_module_get_ctx(ac->module); 79 if (!ares) { 80 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR ); 81 } 82 if (ares->error != LDB_SUCCESS) { 83 return ldb_module_done(ac->req, ares->controls, 84 ares->response, ares->error); 85 } 86 tmp_ctx = talloc_new(ac); 87 switch (ares->type) { 88 case LDB_REPLY_ENTRY: 89 msg = ares->message; 90 ret = dsdb_get_sd_from_ldb_message(ldb, tmp_ctx, msg, &sd); 91 if (ret != LDB_SUCCESS) { 92 DEBUG(10, ("acl_read: cannot get descriptor\n")); 93 ret = LDB_ERR_OPERATIONS_ERROR; 94 goto fail; 95 } 96 sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid"); 97 /* get the object instance type */ 98 instanceType = ldb_msg_find_attr_as_uint(msg, 69 struct ldb_context *ldb; 70 struct aclread_context *ac; 71 struct ldb_message *ret_msg; 72 struct ldb_message *msg; 73 int ret, num_of_attrs = 0; 74 unsigned int i, k = 0; 75 struct security_descriptor *sd; 76 struct dom_sid *sid = NULL; 77 TALLOC_CTX *tmp_ctx; 78 uint32_t instanceType; 79 const struct dsdb_class *objectclass; 80 81 ac = talloc_get_type(req->context, struct aclread_context); 82 ldb = ldb_module_get_ctx(ac->module); 83 if (!ares) { 84 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR ); 85 } 86 if (ares->error != LDB_SUCCESS) { 87 return ldb_module_done(ac->req, ares->controls, 88 ares->response, ares->error); 89 } 90 tmp_ctx = talloc_new(ac); 91 switch (ares->type) { 92 case LDB_REPLY_ENTRY: 93 msg = ares->message; 94 ret = dsdb_get_sd_from_ldb_message(ldb, tmp_ctx, msg, &sd); 95 if (ret != LDB_SUCCESS) { 96 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 97 "acl_read: cannot get descriptor of %s: %s\n", 98 ldb_dn_get_linearized(msg->dn), ldb_strerror(ret)); 99 ret = LDB_ERR_OPERATIONS_ERROR; 100 goto fail; 101 } else if (sd == NULL) { 102 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 103 "acl_read: cannot get descriptor of %s (attribute not found)\n", 104 ldb_dn_get_linearized(msg->dn)); 105 ret = LDB_ERR_OPERATIONS_ERROR; 106 goto fail; 107 } 108 /* 109 * Get the most specific structural object class for the ACL check 110 */ 111 objectclass = dsdb_get_structural_oc_from_msg(ac->schema, msg); 112 if (objectclass == NULL) { 113 ldb_asprintf_errstring(ldb, "acl_read: Failed to find a structural class for %s", 114 ldb_dn_get_linearized(msg->dn)); 115 ret = LDB_ERR_OPERATIONS_ERROR; 116 goto fail; 117 } 118 119 sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid"); 120 /* get the object instance type */ 121 instanceType = ldb_msg_find_attr_as_uint(msg, 99 122 "instanceType", 0); 100 101 123 if (!ldb_dn_is_null(msg->dn) && !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) 124 { 102 125 /* the object has a parent, so we have to check for visibility */ 103 126 struct ldb_dn *parent_dn = ldb_dn_get_parent(tmp_ctx, msg->dn); 127 104 128 ret = dsdb_module_check_access_on_dn(ac->module, 105 129 tmp_ctx, … … 111 135 return LDB_SUCCESS; 112 136 } else if (ret != LDB_SUCCESS) { 137 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 138 "acl_read: %s check parent %s - %s\n", 139 ldb_dn_get_linearized(msg->dn), 140 ldb_strerror(ret), 141 ldb_errstring(ldb)); 113 142 goto fail; 114 143 } 115 } 116 /* for every element in the message check RP */ 117 for (i=0; i < msg->num_elements; i++) { 118 const struct dsdb_attribute *attr; 119 bool is_sd, is_objectsid, is_instancetype; 120 uint32_t access_mask; 121 attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, 122 msg->elements[i].name); 123 if (!attr) { 124 DEBUG(2, ("acl_read: cannot find attribute %s in schema\n", 125 msg->elements[i].name)); 126 ret = LDB_ERR_OPERATIONS_ERROR; 127 goto fail; 128 } 129 is_sd = ldb_attr_cmp("nTSecurityDescriptor", 144 } 145 146 /* for every element in the message check RP */ 147 for (i=0; i < msg->num_elements; i++) { 148 const struct dsdb_attribute *attr; 149 bool is_sd, is_objectsid, is_instancetype, is_objectclass; 150 uint32_t access_mask; 151 attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, 152 msg->elements[i].name); 153 if (!attr) { 154 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 155 "acl_read: %s cannot find attr[%s] in of schema\n", 156 ldb_dn_get_linearized(msg->dn), 157 msg->elements[i].name); 158 ret = LDB_ERR_OPERATIONS_ERROR; 159 goto fail; 160 } 161 is_sd = ldb_attr_cmp("nTSecurityDescriptor", 130 162 msg->elements[i].name) == 0; 131 is_objectsid = ldb_attr_cmp("objectSid", 132 msg->elements[i].name) == 0; 133 is_instancetype = ldb_attr_cmp("instanceType", 134 msg->elements[i].name) == 0; 135 /* these attributes were added to perform access checks and must be removed */ 136 if (is_objectsid && ac->object_sid) { 137 aclread_mark_inaccesslible(&msg->elements[i]); 138 continue; 139 } 140 if (is_instancetype && ac->instance_type) { 141 aclread_mark_inaccesslible(&msg->elements[i]); 142 continue; 143 } 144 if (is_sd && ac->sd) { 145 aclread_mark_inaccesslible(&msg->elements[i]); 146 continue; 147 } 148 /* nTSecurityDescriptor is a special case */ 149 if (is_sd) { 150 access_mask = SEC_FLAG_SYSTEM_SECURITY|SEC_STD_READ_CONTROL; 151 } else { 152 access_mask = SEC_ADS_READ_PROP; 153 } 154 ret = acl_check_access_on_attribute(ac->module, 155 tmp_ctx, 156 sd, 157 sid, 158 access_mask, 159 attr); 160 161 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { 162 /* do not return this entry if attribute is 163 part of the search filter */ 164 if (dsdb_attr_in_parse_tree(ac->req->op.search.tree, 165 msg->elements[i].name)) { 166 talloc_free(tmp_ctx); 167 return LDB_SUCCESS; 168 } 169 aclread_mark_inaccesslible(&msg->elements[i]); 170 } else if (ret != LDB_SUCCESS) { 171 goto fail; 172 } 173 } 174 for (i=0; i < msg->num_elements; i++) { 175 if (!aclread_is_inaccessible(&msg->elements[i])) { 176 num_of_attrs++; 177 } 178 } 179 /*create a new message to return*/ 180 ret_msg = ldb_msg_new(ac->req); 181 ret_msg->dn = msg->dn; 182 talloc_steal(ret_msg, msg->dn); 183 ret_msg->num_elements = num_of_attrs; 184 if (num_of_attrs > 0) { 185 ret_msg->elements = talloc_array(ret_msg, 186 struct ldb_message_element, 187 num_of_attrs); 188 if (ret_msg->elements == NULL) { 189 return ldb_oom(ldb); 190 } 191 for (i=0; i < msg->num_elements; i++) { 192 bool to_remove = aclread_is_inaccessible(&msg->elements[i]); 193 if (!to_remove) { 194 ret_msg->elements[k] = msg->elements[i]; 195 talloc_steal(ret_msg->elements, msg->elements[i].values); 196 k++; 197 } 198 } 199 } else { 200 ret_msg->elements = NULL; 201 } 202 talloc_free(tmp_ctx); 203 204 return ldb_module_send_entry(ac->req, ret_msg, ares->controls); 205 case LDB_REPLY_REFERRAL: 206 return ldb_module_send_referral(ac->req, ares->referral); 207 case LDB_REPLY_DONE: 208 return ldb_module_done(ac->req, ares->controls, 163 is_objectsid = ldb_attr_cmp("objectSid", 164 msg->elements[i].name) == 0; 165 is_instancetype = ldb_attr_cmp("instanceType", 166 msg->elements[i].name) == 0; 167 is_objectclass = ldb_attr_cmp("objectClass", 168 msg->elements[i].name) == 0; 169 /* these attributes were added to perform access checks and must be removed */ 170 if (is_objectsid && ac->added_objectSid) { 171 aclread_mark_inaccesslible(&msg->elements[i]); 172 continue; 173 } 174 if (is_instancetype && ac->added_instanceType) { 175 aclread_mark_inaccesslible(&msg->elements[i]); 176 continue; 177 } 178 if (is_objectclass && ac->added_objectClass) { 179 aclread_mark_inaccesslible(&msg->elements[i]); 180 continue; 181 } 182 if (is_sd && ac->added_nTSecurityDescriptor) { 183 aclread_mark_inaccesslible(&msg->elements[i]); 184 continue; 185 } 186 /* nTSecurityDescriptor is a special case */ 187 if (is_sd) { 188 access_mask = 0; 189 190 if (ac->sd_flags & (SECINFO_OWNER|SECINFO_GROUP)) { 191 access_mask |= SEC_STD_READ_CONTROL; 192 } 193 if (ac->sd_flags & SECINFO_DACL) { 194 access_mask |= SEC_STD_READ_CONTROL; 195 } 196 if (ac->sd_flags & SECINFO_SACL) { 197 access_mask |= SEC_FLAG_SYSTEM_SECURITY; 198 } 199 } else { 200 access_mask = SEC_ADS_READ_PROP; 201 } 202 203 if (attr->searchFlags & SEARCH_FLAG_CONFIDENTIAL) { 204 access_mask |= SEC_ADS_CONTROL_ACCESS; 205 } 206 207 if (access_mask == 0) { 208 aclread_mark_inaccesslible(&msg->elements[i]); 209 continue; 210 } 211 212 ret = acl_check_access_on_attribute(ac->module, 213 tmp_ctx, 214 sd, 215 sid, 216 access_mask, 217 attr, 218 objectclass); 219 220 /* 221 * Dirsync control needs the replpropertymetadata attribute 222 * so return it as it will be removed by the control 223 * in anycase. 224 */ 225 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { 226 if (!ac->indirsync) { 227 /* 228 * do not return this entry if attribute is 229 * part of the search filter 230 */ 231 if (dsdb_attr_in_parse_tree(ac->req->op.search.tree, 232 msg->elements[i].name)) { 233 talloc_free(tmp_ctx); 234 return LDB_SUCCESS; 235 } 236 aclread_mark_inaccesslible(&msg->elements[i]); 237 } else { 238 /* 239 * We are doing dirysnc answers 240 * and the object shouldn't be returned (normally) 241 * but we will return it without replPropertyMetaData 242 * so that the dirysync module will do what is needed 243 * (remove the object if it is not deleted, or return 244 * just the objectGUID if it's deleted). 245 */ 246 if (dsdb_attr_in_parse_tree(ac->req->op.search.tree, 247 msg->elements[i].name)) { 248 ldb_msg_remove_attr(msg, "replPropertyMetaData"); 249 break; 250 } else { 251 aclread_mark_inaccesslible(&msg->elements[i]); 252 } 253 } 254 } else if (ret != LDB_SUCCESS) { 255 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 256 "acl_read: %s check attr[%s] gives %s - %s\n", 257 ldb_dn_get_linearized(msg->dn), 258 msg->elements[i].name, 259 ldb_strerror(ret), 260 ldb_errstring(ldb)); 261 goto fail; 262 } 263 } 264 for (i=0; i < msg->num_elements; i++) { 265 if (!aclread_is_inaccessible(&msg->elements[i])) { 266 num_of_attrs++; 267 } 268 } 269 /*create a new message to return*/ 270 ret_msg = ldb_msg_new(ac->req); 271 ret_msg->dn = msg->dn; 272 talloc_steal(ret_msg, msg->dn); 273 ret_msg->num_elements = num_of_attrs; 274 if (num_of_attrs > 0) { 275 ret_msg->elements = talloc_array(ret_msg, 276 struct ldb_message_element, 277 num_of_attrs); 278 if (ret_msg->elements == NULL) { 279 return ldb_oom(ldb); 280 } 281 for (i=0; i < msg->num_elements; i++) { 282 bool to_remove = aclread_is_inaccessible(&msg->elements[i]); 283 if (!to_remove) { 284 ret_msg->elements[k] = msg->elements[i]; 285 talloc_steal(ret_msg->elements, msg->elements[i].name); 286 talloc_steal(ret_msg->elements, msg->elements[i].values); 287 k++; 288 } 289 } 290 /* 291 * This should not be needed, but some modules 292 * may allocate values on the wrong context... 293 */ 294 talloc_steal(ret_msg->elements, msg); 295 } else { 296 ret_msg->elements = NULL; 297 } 298 talloc_free(tmp_ctx); 299 300 return ldb_module_send_entry(ac->req, ret_msg, ares->controls); 301 case LDB_REPLY_REFERRAL: 302 return ldb_module_send_referral(ac->req, ares->referral); 303 case LDB_REPLY_DONE: 304 return ldb_module_done(ac->req, ares->controls, 209 305 ares->response, LDB_SUCCESS); 210 306 211 212 307 } 308 return LDB_SUCCESS; 213 309 fail: 214 215 310 talloc_free(tmp_ctx); 311 return ldb_module_done(ac->req, NULL, NULL, ret); 216 312 } 217 313 … … 224 320 struct ldb_request *down_req; 225 321 struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID); 322 uint32_t flags = ldb_req_get_custom_flags(req); 226 323 struct ldb_result *res; 227 324 struct aclread_private *p; 325 bool need_sd = false; 326 bool explicit_sd_flags = false; 228 327 bool is_untrusted = ldb_req_is_untrusted(req); 328 static const char * const _all_attrs[] = { "*", NULL }; 329 bool all_attrs = false; 229 330 const char * const *attrs = NULL; 230 331 uint32_t instanceType; 231 332 static const char *acl_attrs[] = { 232 233 333 "instanceType", 334 NULL 234 335 }; 235 336 … … 254 355 acl_attrs, 255 356 DSDB_FLAG_NEXT_MODULE | 256 DSDB_SEARCH_SHOW_DELETED, req); 357 DSDB_FLAG_AS_SYSTEM | 358 DSDB_SEARCH_SHOW_RECYCLED, 359 req); 257 360 if (ret != LDB_SUCCESS) { 258 361 return ldb_error(ldb, ret, 259 362 "acl_read: Error retrieving instanceType for base."); 260 363 } 261 364 instanceType = ldb_msg_find_attr_as_uint(res->msgs[0], 262 365 "instanceType", 0); 263 366 if (instanceType != 0 && !(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) 264 367 { … … 284 387 ac->req = req; 285 388 ac->schema = dsdb_get_schema(ldb, req); 389 if (flags & DSDB_ACL_CHECKS_DIRSYNC_FLAG) { 390 ac->indirsync = true; 391 } else { 392 ac->indirsync = false; 393 } 286 394 if (!ac->schema) { 287 395 return ldb_operr(ldb); 288 396 } 289 ac->sd = !(ldb_attr_in_list(req->op.search.attrs, "nTSecurityDescriptor")); 290 if (req->op.search.attrs && !ldb_attr_in_list(req->op.search.attrs, "*")) { 291 if (!ldb_attr_in_list(req->op.search.attrs, "instanceType")) { 292 ac->instance_type = true; 293 attrs = ldb_attr_list_copy_add(ac, req->op.search.attrs, "instanceType"); 294 } else { 295 attrs = req->op.search.attrs; 397 398 attrs = req->op.search.attrs; 399 if (attrs == NULL) { 400 all_attrs = true; 401 attrs = _all_attrs; 402 } else if (attrs[0] == NULL) { 403 all_attrs = true; 404 attrs = _all_attrs; 405 } else if (ldb_attr_in_list(attrs, "*")) { 406 all_attrs = true; 407 } 408 409 /* 410 * In theory we should also check for the SD control but control verification is 411 * expensive so we'd better had the ntsecuritydescriptor to the list of 412 * searched attribute and then remove it ! 413 */ 414 ac->sd_flags = dsdb_request_sd_flags(ac->req, &explicit_sd_flags); 415 416 if (ldb_attr_in_list(attrs, "nTSecurityDescriptor")) { 417 need_sd = false; 418 } else if (explicit_sd_flags && all_attrs) { 419 need_sd = false; 420 } else { 421 need_sd = true; 422 } 423 424 if (!all_attrs) { 425 if (!ldb_attr_in_list(attrs, "instanceType")) { 426 attrs = ldb_attr_list_copy_add(ac, attrs, "instanceType"); 427 if (attrs == NULL) { 428 return ldb_oom(ldb); 429 } 430 ac->added_instanceType = true; 296 431 } 297 432 if (!ldb_attr_in_list(req->op.search.attrs, "objectSid")) { 298 ac->object_sid = true;299 433 attrs = ldb_attr_list_copy_add(ac, attrs, "objectSid"); 300 } 301 } 302 303 if (ac->sd) { 304 /* avoid replacing all attributes with nTSecurityDescriptor 305 * if attribute list is empty */ 306 if (!attrs) { 307 attrs = ldb_attr_list_copy_add(ac, attrs, "*"); 308 } 434 if (attrs == NULL) { 435 return ldb_oom(ldb); 436 } 437 ac->added_objectSid = true; 438 } 439 if (!ldb_attr_in_list(req->op.search.attrs, "objectClass")) { 440 attrs = ldb_attr_list_copy_add(ac, attrs, "objectClass"); 441 if (attrs == NULL) { 442 return ldb_oom(ldb); 443 } 444 ac->added_objectClass = true; 445 } 446 } 447 448 if (need_sd) { 309 449 attrs = ldb_attr_list_copy_add(ac, attrs, "nTSecurityDescriptor"); 310 } 450 if (attrs == NULL) { 451 return ldb_oom(ldb); 452 } 453 ac->added_nTSecurityDescriptor = true; 454 } 455 311 456 ac->attrs = req->op.search.attrs; 312 457 ret = ldb_build_search_req_ex(&down_req, … … 334 479 return ldb_module_oom(module); 335 480 } 336 p->enabled = lpcfg_parm_bool(ldb_get_opaque(ldb, "loadparm"), NULL, "acl", "search", false);481 p->enabled = lpcfg_parm_bool(ldb_get_opaque(ldb, "loadparm"), NULL, "acl", "search", true); 337 482 ldb_module_set_private(module, p); 338 483 return ldb_next_init(module); -
vendor/current/source4/dsdb/samdb/ldb_modules/acl_util.c
r740 r988 75 75 acl_attrs, 76 76 DSDB_FLAG_NEXT_MODULE | 77 DSDB_FLAG_AS_SYSTEM | 77 78 DSDB_SEARCH_SHOW_RECYCLED, 78 79 parent); 79 80 if (ret != LDB_SUCCESS) { 80 DEBUG(0,("access_check: failed to find object %s\n", ldb_dn_get_linearized(dn))); 81 ldb_asprintf_errstring(ldb_module_get_ctx(module), 82 "access_check: failed to find object %s\n", 83 ldb_dn_get_linearized(dn)); 81 84 return ret; 82 85 } … … 89 92 } 90 93 91 int dsdb_module_check_access_on_guid(struct ldb_module *module,92 TALLOC_CTX *mem_ctx,93 struct GUID *guid,94 uint32_t access_mask,95 const struct GUID *oc_guid,96 struct ldb_request *parent)97 {98 int ret;99 struct ldb_result *acl_res;100 static const char *acl_attrs[] = {101 "nTSecurityDescriptor",102 "objectSid",103 NULL104 };105 struct ldb_context *ldb = ldb_module_get_ctx(module);106 struct auth_session_info *session_info107 = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");108 if(!session_info) {109 return ldb_operr(ldb);110 }111 ret = dsdb_module_search(module, mem_ctx, &acl_res, NULL, LDB_SCOPE_SUBTREE,112 acl_attrs,113 DSDB_FLAG_NEXT_MODULE |114 DSDB_SEARCH_SHOW_RECYCLED,115 parent,116 "objectGUID=%s", GUID_string(mem_ctx, guid));117 118 if (ret != LDB_SUCCESS || acl_res->count == 0) {119 DEBUG(0,("access_check: failed to find object %s\n", GUID_string(mem_ctx, guid)));120 return ret;121 }122 return dsdb_check_access_on_dn_internal(ldb, acl_res,123 mem_ctx,124 session_info->security_token,125 acl_res->msgs[0]->dn,126 access_mask,127 oc_guid);128 }129 130 94 int acl_check_access_on_attribute(struct ldb_module *module, 131 95 TALLOC_CTX *mem_ctx, … … 133 97 struct dom_sid *rp_sid, 134 98 uint32_t access_mask, 135 const struct dsdb_attribute *attr) 99 const struct dsdb_attribute *attr, 100 const struct dsdb_class *objectclass) 136 101 { 137 102 int ret; … … 142 107 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 143 108 struct security_token *token = acl_user_token(module); 144 if (attr) { 145 if (!GUID_all_zero(&attr->attributeSecurityGUID)) {146 if (!insert_in_object_tree(tmp_ctx,147 &attr->attributeSecurityGUID,148 access_mask, &root,149 &new_node)) {150 DEBUG(10, ("acl_search: cannot add to object tree securityGUID\n"));151 goto fail;152 }153 154 if (!insert_in_object_tree(tmp_ctx,155 &attr->schemaIDGUID,156 access_mask, &new_node,157 &new_node)) {158 DEBUG(10, ("acl_search: cannot add to object tree attributeGUID\n"));159 goto fail;160 }109 110 if (!insert_in_object_tree(tmp_ctx, 111 &objectclass->schemaIDGUID, 112 access_mask, NULL, 113 &root)) { 114 DEBUG(10, ("acl_search: cannot add to object tree class schemaIDGUID\n")); 115 goto fail; 116 } 117 new_node = root; 118 119 if (!GUID_all_zero(&attr->attributeSecurityGUID)) { 120 if (!insert_in_object_tree(tmp_ctx, 121 &attr->attributeSecurityGUID, 122 access_mask, new_node, 123 &new_node)) { 124 DEBUG(10, ("acl_search: cannot add to object tree securityGUID\n")); 125 goto fail; 161 126 } 162 else {163 if (!insert_in_object_tree(tmp_ctx, 164 &attr->schemaIDGUID,165 access_mask, &root,166 &new_node)) {167 DEBUG(10, ("acl_search: cannot add to object tree attributeGUID\n"));168 goto fail;169 }170 171 } 127 } 128 129 if (!insert_in_object_tree(tmp_ctx, 130 &attr->schemaIDGUID, 131 access_mask, new_node, 132 &new_node)) { 133 DEBUG(10, ("acl_search: cannot add to object tree attributeGUID\n")); 134 goto fail; 135 } 136 172 137 status = sec_access_check_ds(sd, token, 173 138 access_mask, … … 188 153 } 189 154 155 int acl_check_access_on_objectclass(struct ldb_module *module, 156 TALLOC_CTX *mem_ctx, 157 struct security_descriptor *sd, 158 struct dom_sid *rp_sid, 159 uint32_t access_mask, 160 const struct dsdb_class *objectclass) 161 { 162 int ret; 163 NTSTATUS status; 164 uint32_t access_granted; 165 struct object_tree *root = NULL; 166 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 167 struct security_token *token = acl_user_token(module); 168 169 if (!insert_in_object_tree(tmp_ctx, 170 &objectclass->schemaIDGUID, 171 access_mask, NULL, 172 &root)) { 173 DEBUG(10, ("acl_search: cannot add to object tree class schemaIDGUID\n")); 174 goto fail; 175 } 176 177 status = sec_access_check_ds(sd, token, 178 access_mask, 179 &access_granted, 180 root, 181 rp_sid); 182 if (!NT_STATUS_IS_OK(status)) { 183 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; 184 } else { 185 ret = LDB_SUCCESS; 186 } 187 talloc_free(tmp_ctx); 188 return ret; 189 fail: 190 talloc_free(tmp_ctx); 191 return ldb_operr(ldb_module_get_ctx(module)); 192 } 190 193 191 194 /* checks for validated writes */ … … 201 204 uint32_t access_granted; 202 205 struct object_tree *root = NULL; 203 struct object_tree *new_node = NULL;204 206 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 205 207 … … 207 209 208 210 if (!insert_in_object_tree(tmp_ctx, &right, right_type, 209 &root, &new_node)) {211 NULL, &root)) { 210 212 DEBUG(10, ("acl_ext_right: cannot add to object tree\n")); 211 213 talloc_free(tmp_ctx); … … 239 241 session_info->info->account_name); 240 242 } 243 244 uint32_t dsdb_request_sd_flags(struct ldb_request *req, bool *explicit) 245 { 246 struct ldb_control *sd_control; 247 uint32_t sd_flags = 0; 248 249 if (explicit) { 250 *explicit = false; 251 } 252 253 sd_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID); 254 if (sd_control) { 255 struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_control->data; 256 257 sd_flags = sdctr->secinfo_flags; 258 259 if (explicit) { 260 *explicit = true; 261 } 262 263 /* mark it as handled */ 264 sd_control->critical = 0; 265 } 266 267 /* we only care for the last 4 bits */ 268 sd_flags &= 0x0000000F; 269 270 /* 271 * MS-ADTS 3.1.1.3.4.1.11 says that no bits 272 * equals all 4 bits 273 */ 274 if (sd_flags == 0) { 275 sd_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_SACL; 276 } 277 278 return sd_flags; 279 } 280 281 int dsdb_module_schedule_sd_propagation(struct ldb_module *module, 282 struct ldb_dn *nc_root, 283 struct ldb_dn *dn, 284 bool include_self) 285 { 286 struct ldb_context *ldb = ldb_module_get_ctx(module); 287 struct dsdb_extended_sec_desc_propagation_op *op; 288 int ret; 289 290 op = talloc_zero(module, struct dsdb_extended_sec_desc_propagation_op); 291 if (op == NULL) { 292 return ldb_oom(ldb); 293 } 294 295 op->nc_root = nc_root; 296 op->dn = dn; 297 op->include_self = include_self; 298 299 ret = dsdb_module_extended(module, op, NULL, 300 DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID, 301 op, 302 DSDB_FLAG_TOP_MODULE | 303 DSDB_FLAG_AS_SYSTEM | 304 DSDB_FLAG_TRUSTED, 305 NULL); 306 TALLOC_FREE(op); 307 return ret; 308 } -
vendor/current/source4/dsdb/samdb/ldb_modules/descriptor.c
r740 r988 40 40 #include "librpc/gen_ndr/ndr_security.h" 41 41 #include "libcli/security/security.h" 42 #include "dsdb/samdb/ldb_modules/schema.h"43 42 #include "auth/auth.h" 44 43 #include "param/param.h" 45 #include "util.h" 44 #include "dsdb/samdb/ldb_modules/util.h" 45 #include "lib/util/binsearch.h" 46 47 struct descriptor_changes { 48 struct descriptor_changes *prev, *next; 49 struct descriptor_changes *children; 50 struct ldb_dn *nc_root; 51 struct ldb_dn *dn; 52 bool force_self; 53 bool force_children; 54 struct ldb_dn *stopped_dn; 55 }; 46 56 47 57 struct descriptor_data { 48 int _dummy; 58 TALLOC_CTX *trans_mem; 59 struct descriptor_changes *changes; 49 60 }; 50 61 … … 58 69 struct ldb_message_element *sd_element; 59 70 struct ldb_val *sd_val; 71 uint32_t sd_flags; 60 72 int (*step_fn)(struct descriptor_context *); 61 73 }; 62 74 63 st ruct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,75 static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx, 64 76 struct ldb_dn *dn, 65 77 struct security_token *token, … … 88 100 } else if (security_token_has_sid(token, da_sid)) { 89 101 dag_sid = dom_sid_dup(mem_ctx, da_sid); 102 } else if (security_token_is_system(token)) { 103 dag_sid = dom_sid_dup(mem_ctx, sa_sid); 90 104 } else { 91 105 dag_sid = NULL; … … 96 110 } else if (security_token_has_sid(token, da_sid)) { 97 111 dag_sid = dom_sid_dup(mem_ctx, da_sid); 112 } else if (security_token_is_system(token)) { 113 dag_sid = dom_sid_dup(mem_ctx, ea_sid); 98 114 } else { 99 115 dag_sid = NULL; … … 104 120 } else if (security_token_has_sid(token, ea_sid)) { 105 121 dag_sid = dom_sid_dup(mem_ctx, ea_sid); 122 } else if (security_token_is_system(token)) { 123 dag_sid = dom_sid_dup(mem_ctx, da_sid); 106 124 } else { 107 125 dag_sid = NULL; … … 136 154 struct dom_sid *dag) 137 155 { 138 if (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008) { 139 return dag; 140 } 141 142 return NULL; 156 /* 157 * This depends on the function level of the DC 158 * which is 2008R2 in our case. Which means it is 159 * higher than 2003 and we should use the 160 * "default administrator group" also as owning group. 161 * 162 * This matches dcpromo for a 2003 domain 163 * on a Windows 2008R2 DC. 164 */ 165 return dag; 143 166 } 144 167 … … 159 182 160 183 if (sd_flags & (SECINFO_OWNER)) { 161 final_sd->owner_sid = talloc_memdup(mem_ctx, new_sd->owner_sid, sizeof(struct dom_sid)); 184 if (new_sd->owner_sid) { 185 final_sd->owner_sid = talloc_memdup(mem_ctx, new_sd->owner_sid, sizeof(struct dom_sid)); 186 } 162 187 final_sd->type |= new_sd->type & SEC_DESC_OWNER_DEFAULTED; 163 188 } 164 189 else if (old_sd) { 165 final_sd->owner_sid = talloc_memdup(mem_ctx, old_sd->owner_sid, sizeof(struct dom_sid)); 190 if (old_sd->owner_sid) { 191 final_sd->owner_sid = talloc_memdup(mem_ctx, old_sd->owner_sid, sizeof(struct dom_sid)); 192 } 166 193 final_sd->type |= old_sd->type & SEC_DESC_OWNER_DEFAULTED; 167 194 } 168 195 169 196 if (sd_flags & (SECINFO_GROUP)) { 170 final_sd->group_sid = talloc_memdup(mem_ctx, new_sd->group_sid, sizeof(struct dom_sid)); 197 if (new_sd->group_sid) { 198 final_sd->group_sid = talloc_memdup(mem_ctx, new_sd->group_sid, sizeof(struct dom_sid)); 199 } 171 200 final_sd->type |= new_sd->type & SEC_DESC_GROUP_DEFAULTED; 172 201 } 173 202 else if (old_sd) { 174 final_sd->group_sid = talloc_memdup(mem_ctx, old_sd->group_sid, sizeof(struct dom_sid)); 203 if (old_sd->group_sid) { 204 final_sd->group_sid = talloc_memdup(mem_ctx, old_sd->group_sid, sizeof(struct dom_sid)); 205 } 175 206 final_sd->type |= old_sd->type & SEC_DESC_GROUP_DEFAULTED; 176 207 } … … 231 262 struct dom_sid *default_owner; 232 263 struct dom_sid *default_group; 264 struct security_descriptor *default_descriptor = NULL; 265 struct GUID *object_list = NULL; 266 267 if (objectclass != NULL) { 268 default_descriptor = get_sd_unpacked(module, mem_ctx, objectclass); 269 object_list = talloc_zero_array(mem_ctx, struct GUID, 2); 270 if (object_list == NULL) { 271 return NULL; 272 } 273 object_list[0] = objectclass->schemaIDGUID; 274 } 233 275 234 276 if (object) { … … 246 288 } 247 289 } else { 248 user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);290 user_descriptor = default_descriptor; 249 291 } 250 292 … … 279 321 } 280 322 323 if (user_descriptor && default_descriptor && 324 (user_descriptor->dacl == NULL)) 325 { 326 user_descriptor->dacl = default_descriptor->dacl; 327 user_descriptor->type |= default_descriptor->type & ( 328 SEC_DESC_DACL_PRESENT | 329 SEC_DESC_DACL_DEFAULTED|SEC_DESC_DACL_AUTO_INHERIT_REQ | 330 SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_PROTECTED | 331 SEC_DESC_DACL_TRUSTED); 332 } 333 334 if (user_descriptor && default_descriptor && 335 (user_descriptor->sacl == NULL)) 336 { 337 user_descriptor->sacl = default_descriptor->sacl; 338 user_descriptor->type |= default_descriptor->type & ( 339 SEC_DESC_SACL_PRESENT | 340 SEC_DESC_SACL_DEFAULTED|SEC_DESC_SACL_AUTO_INHERIT_REQ | 341 SEC_DESC_SACL_AUTO_INHERITED|SEC_DESC_SACL_PROTECTED | 342 SEC_DESC_SERVER_SECURITY); 343 } 344 345 346 if (!(sd_flags & SECINFO_OWNER) && user_descriptor) { 347 user_descriptor->owner_sid = NULL; 348 349 /* 350 * We need the correct owner sid 351 * when calculating the DACL or SACL 352 */ 353 if (old_descriptor) { 354 user_descriptor->owner_sid = old_descriptor->owner_sid; 355 } 356 } 357 if (!(sd_flags & SECINFO_GROUP) && user_descriptor) { 358 user_descriptor->group_sid = NULL; 359 360 /* 361 * We need the correct group sid 362 * when calculating the DACL or SACL 363 */ 364 if (old_descriptor) { 365 user_descriptor->group_sid = old_descriptor->group_sid; 366 } 367 } 368 if (!(sd_flags & SECINFO_DACL) && user_descriptor) { 369 user_descriptor->dacl = NULL; 370 371 /* 372 * We add SEC_DESC_DACL_PROTECTED so that 373 * create_security_descriptor() skips 374 * the unused inheritance calculation 375 */ 376 user_descriptor->type |= SEC_DESC_DACL_PROTECTED; 377 } 378 if (!(sd_flags & SECINFO_SACL) && user_descriptor) { 379 user_descriptor->sacl = NULL; 380 381 /* 382 * We add SEC_DESC_SACL_PROTECTED so that 383 * create_security_descriptor() skips 384 * the unused inheritance calculation 385 */ 386 user_descriptor->type |= SEC_DESC_SACL_PROTECTED; 387 } 388 281 389 default_owner = get_default_ag(mem_ctx, dn, 282 390 session_info->security_token, ldb); 283 391 default_group = get_default_group(mem_ctx, ldb, default_owner); 284 new_sd = create_security_descriptor(mem_ctx, parent_descriptor, user_descriptor, true, 285 NULL, SEC_DACL_AUTO_INHERIT|SEC_SACL_AUTO_INHERIT, 392 new_sd = create_security_descriptor(mem_ctx, 393 parent_descriptor, 394 user_descriptor, 395 true, 396 object_list, 397 SEC_DACL_AUTO_INHERIT | 398 SEC_SACL_AUTO_INHERIT, 286 399 session_info->security_token, 287 400 default_owner, default_group, … … 386 499 { 387 500 struct descriptor_context *ac; 388 struct ldb_control *sd_control;389 501 struct ldb_val *sd_val = NULL; 390 502 struct ldb_message_element *sd_el; 391 503 DATA_BLOB *show_sd; 392 int ret; 393 uint32_t sd_flags = 0; 504 int ret = LDB_SUCCESS; 394 505 395 506 ac = talloc_get_type(req->context, struct descriptor_context); … … 404 515 } 405 516 406 sd_control = ldb_request_get_control(ac->req, LDB_CONTROL_SD_FLAGS_OID);407 if (sd_control) {408 struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_control->data;409 sd_flags = sdctr->secinfo_flags;410 /* we only care for the last 4 bits */411 sd_flags = sd_flags & 0x0000000F;412 if (sd_flags == 0) {413 /* MS-ADTS 3.1.1.3.4.1.11 says that no bits414 equals all 4 bits */415 sd_flags = 0xF;416 }417 }418 419 517 switch (ares->type) { 420 518 case LDB_REPLY_ENTRY: 421 if (sd_flags != 0) { 422 sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor"); 423 if (sd_el) { 424 sd_val = sd_el->values; 425 } 426 } 519 sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor"); 520 if (sd_el) { 521 sd_val = sd_el->values; 522 } 523 427 524 if (sd_val) { 428 525 show_sd = descr_get_descriptor_to_show(ac->module, ac->req, 429 sd_val, sd_flags);526 sd_val, ac->sd_flags); 430 527 if (!show_sd) { 431 528 ret = LDB_ERR_OPERATIONS_ERROR; … … 455 552 static int descriptor_add(struct ldb_module *module, struct ldb_request *req) 456 553 { 457 struct ldb_context *ldb ;554 struct ldb_context *ldb = ldb_module_get_ctx(module); 458 555 struct ldb_request *add_req; 459 556 struct ldb_message *msg; … … 461 558 const struct ldb_val *parent_sd = NULL; 462 559 const struct ldb_val *user_sd; 463 struct ldb_dn *parent_dn, *dn, *nc_root; 560 struct ldb_dn *dn = req->op.add.message->dn; 561 struct ldb_dn *parent_dn, *nc_root; 464 562 struct ldb_message_element *objectclass_element, *sd_element; 465 563 int ret; … … 468 566 const struct dsdb_class *objectclass; 469 567 static const char * const parent_attrs[] = { "nTSecurityDescriptor", NULL }; 470 471 ldb = ldb_module_get_ctx(module); 472 dn = req->op.add.message->dn; 568 uint32_t instanceType; 569 bool isNC = false; 570 uint32_t sd_flags = dsdb_request_sd_flags(req, NULL); 571 572 /* do not manipulate our control entries */ 573 if (ldb_dn_is_special(dn)) { 574 return ldb_next_request(module, req); 575 } 576 473 577 user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor"); 474 578 sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor"); … … 480 584 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn)); 481 585 482 /* do not manipulate our control entries */ 483 if (ldb_dn_is_special(dn)) { 484 return ldb_next_request(module, req); 485 } 486 487 /* if the object has a parent, retrieve its SD to 488 * use for calculation. Unfortunately we do not yet have 489 * instanceType, so we use dsdb_find_nc_root. */ 490 parent_dn = ldb_dn_get_parent(req, dn); 491 if (parent_dn == NULL) { 492 return ldb_oom(ldb); 493 } 494 495 ret = dsdb_find_nc_root(ldb, req, dn, &nc_root); 496 if (ret != LDB_SUCCESS) { 497 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n", 498 ldb_dn_get_linearized(dn)); 499 return ret; 500 } 501 502 if (ldb_dn_compare(dn, nc_root) != 0) { 586 instanceType = ldb_msg_find_attr_as_uint(req->op.add.message, "instanceType", 0); 587 588 if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) { 589 isNC = true; 590 } 591 592 if (!isNC) { 593 ret = dsdb_find_nc_root(ldb, req, dn, &nc_root); 594 if (ret != LDB_SUCCESS) { 595 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: Could not find NC root for %s\n", 596 ldb_dn_get_linearized(dn)); 597 return ret; 598 } 599 600 if (ldb_dn_compare(dn, nc_root) == 0) { 601 DEBUG(0, ("Found DN %s being a NC by the old method\n", ldb_dn_get_linearized(dn))); 602 isNC = true; 603 } 604 } 605 606 if (isNC) { 607 DEBUG(2, ("DN: %s is a NC\n", ldb_dn_get_linearized(dn))); 608 } 609 if (!isNC) { 610 /* if the object has a parent, retrieve its SD to 611 * use for calculation. Unfortunately we do not yet have 612 * instanceType, so we use dsdb_find_nc_root. */ 613 614 parent_dn = ldb_dn_get_parent(req, dn); 615 if (parent_dn == NULL) { 616 return ldb_oom(ldb); 617 } 618 503 619 /* we aren't any NC */ 504 620 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn, 505 621 parent_attrs, 506 DSDB_FLAG_NEXT_MODULE, 622 DSDB_FLAG_NEXT_MODULE | 623 DSDB_FLAG_AS_SYSTEM | 624 DSDB_SEARCH_SHOW_RECYCLED, 507 625 req); 508 626 if (ret != LDB_SUCCESS) { … … 524 642 } 525 643 526 objectclass = get_last_structural_class(schema, objectclass_element, req); 644 objectclass = dsdb_get_last_structural_class(schema, 645 objectclass_element); 527 646 if (objectclass == NULL) { 528 647 return ldb_operr(ldb); 529 648 } 530 649 650 /* 651 * The SD_FLAG control is ignored on add 652 * and we default to all bits set. 653 */ 654 sd_flags = SECINFO_OWNER|SECINFO_GROUP|SECINFO_SACL|SECINFO_DACL; 655 531 656 sd = get_new_descriptor(module, dn, req, 532 657 objectclass, parent_sd, 533 user_sd, NULL, 0); 658 user_sd, NULL, sd_flags); 659 if (sd == NULL) { 660 return ldb_operr(ldb); 661 } 534 662 msg = ldb_msg_copy_shallow(req, req->op.add.message); 535 if (sd != NULL) { 536 if (sd_element != NULL) { 537 sd_element->values[0] = *sd; 538 } else { 539 ret = ldb_msg_add_steal_value(msg, 540 "nTSecurityDescriptor", 541 sd); 542 if (ret != LDB_SUCCESS) { 543 return ret; 544 } 663 if (msg == NULL) { 664 return ldb_oom(ldb); 665 } 666 if (sd_element != NULL) { 667 sd_element->values[0] = *sd; 668 } else { 669 ret = ldb_msg_add_steal_value(msg, 670 "nTSecurityDescriptor", 671 sd); 672 if (ret != LDB_SUCCESS) { 673 return ret; 545 674 } 546 675 } … … 562 691 static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) 563 692 { 564 struct ldb_context *ldb; 565 struct ldb_control *sd_recalculate_control, *sd_flags_control; 693 struct ldb_context *ldb = ldb_module_get_ctx(module); 566 694 struct ldb_request *mod_req; 567 695 struct ldb_message *msg; … … 570 698 const struct ldb_val *parent_sd = NULL; 571 699 const struct ldb_val *user_sd; 572 struct ldb_dn *parent_dn, *dn; 573 struct ldb_message_element *objectclass_element; 700 struct ldb_dn *dn = req->op.mod.message->dn; 701 struct ldb_dn *parent_dn; 702 struct ldb_message_element *objectclass_element, *sd_element; 574 703 int ret; 575 uint32_t instanceType, sd_flags = 0; 704 uint32_t instanceType; 705 bool explicit_sd_flags = false; 706 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags); 576 707 const struct dsdb_schema *schema; 577 708 DATA_BLOB *sd; … … 581 712 "instanceType", 582 713 "objectClass", NULL }; 583 ldb = ldb_module_get_ctx(module); 584 dn = req->op.mod.message->dn; 585 user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor"); 586 /* This control forces the recalculation of the SD also when 587 * no modification is performed. */ 588 sd_recalculate_control = ldb_request_get_control(req, 589 LDB_CONTROL_RECALCULATE_SD_OID); 590 if (!user_sd && !sd_recalculate_control) { 591 return ldb_next_request(module, req); 592 } 593 594 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn)); 714 struct ldb_control *sd_propagation_control; 715 int cmp_ret = -1; 595 716 596 717 /* do not manipulate our control entries */ … … 599 720 } 600 721 722 sd_propagation_control = ldb_request_get_control(req, 723 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); 724 if (sd_propagation_control != NULL) { 725 if (sd_propagation_control->data != module) { 726 return ldb_operr(ldb); 727 } 728 if (req->op.mod.message->num_elements != 0) { 729 return ldb_operr(ldb); 730 } 731 if (explicit_sd_flags) { 732 return ldb_operr(ldb); 733 } 734 if (sd_flags != 0xF) { 735 return ldb_operr(ldb); 736 } 737 if (sd_propagation_control->critical == 0) { 738 return ldb_operr(ldb); 739 } 740 741 sd_propagation_control->critical = 0; 742 } 743 744 sd_element = ldb_msg_find_element(req->op.mod.message, "nTSecurityDescriptor"); 745 if (sd_propagation_control == NULL && sd_element == NULL) { 746 return ldb_next_request(module, req); 747 } 748 749 /* 750 * nTSecurityDescriptor with DELETE is not supported yet. 751 * TODO: handle this correctly. 752 */ 753 if (sd_propagation_control == NULL && 754 LDB_FLAG_MOD_TYPE(sd_element->flags) == LDB_FLAG_MOD_DELETE) 755 { 756 return ldb_module_error(module, 757 LDB_ERR_UNWILLING_TO_PERFORM, 758 "MOD_DELETE for nTSecurityDescriptor " 759 "not supported yet"); 760 } 761 762 user_sd = ldb_msg_find_ldb_val(req->op.mod.message, "nTSecurityDescriptor"); 763 /* nTSecurityDescriptor without a value is an error, letting through so it is handled */ 764 if (sd_propagation_control == NULL && user_sd == NULL) { 765 return ldb_next_request(module, req); 766 } 767 768 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_modify: %s\n", ldb_dn_get_linearized(dn)); 769 601 770 ret = dsdb_module_search_dn(module, req, ¤t_res, dn, 602 771 current_attrs, 603 DSDB_FLAG_NEXT_MODULE, 772 DSDB_FLAG_NEXT_MODULE | 773 DSDB_FLAG_AS_SYSTEM | 774 DSDB_SEARCH_SHOW_RECYCLED, 604 775 req); 605 776 if (ret != LDB_SUCCESS) { … … 621 792 ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn, 622 793 parent_attrs, 623 DSDB_FLAG_NEXT_MODULE, 794 DSDB_FLAG_NEXT_MODULE | 795 DSDB_FLAG_AS_SYSTEM | 796 DSDB_SEARCH_SHOW_RECYCLED, 624 797 req); 625 798 if (ret != LDB_SUCCESS) { … … 633 806 parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor"); 634 807 } 635 sd_flags_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);636 808 637 809 schema = dsdb_get_schema(ldb, req); … … 642 814 } 643 815 644 objectclass = get_last_structural_class(schema, objectclass_element, req); 816 objectclass = dsdb_get_last_structural_class(schema, 817 objectclass_element); 645 818 if (objectclass == NULL) { 646 819 return ldb_operr(ldb); 647 820 } 648 821 649 if (sd_flags_control) { 650 struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_flags_control->data; 651 sd_flags = sdctr->secinfo_flags; 652 /* we only care for the last 4 bits */ 653 sd_flags = sd_flags & 0x0000000F; 654 } 655 if (sd_flags != 0) { 656 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor"); 822 old_sd = ldb_msg_find_ldb_val(current_res->msgs[0], "nTSecurityDescriptor"); 823 if (old_sd == NULL) { 824 return ldb_operr(ldb); 825 } 826 827 if (sd_propagation_control != NULL) { 828 /* 829 * This just triggers a recalculation of the 830 * inherited aces. 831 */ 832 user_sd = old_sd; 657 833 } 658 834 … … 660 836 objectclass, parent_sd, 661 837 user_sd, old_sd, sd_flags); 838 if (sd == NULL) { 839 return ldb_operr(ldb); 840 } 662 841 msg = ldb_msg_copy_shallow(req, req->op.mod.message); 663 if (sd != NULL) { 664 struct ldb_message_element *sd_element; 665 if (user_sd != NULL) { 666 sd_element = ldb_msg_find_element(msg, 667 "nTSecurityDescriptor"); 668 sd_element->values[0] = *sd; 669 } else if (sd_recalculate_control != NULL) { 670 /* In this branch we really do force the recalculation 671 * of the SD */ 672 ldb_msg_remove_attr(msg, "nTSecurityDescriptor"); 673 674 ret = ldb_msg_add_steal_value(msg, 675 "nTSecurityDescriptor", 676 sd); 677 if (ret != LDB_SUCCESS) { 678 return ldb_error(ldb, ret, 679 "descriptor_modify: Could not replace SD value in message."); 680 } 681 sd_element = ldb_msg_find_element(msg, 682 "nTSecurityDescriptor"); 683 sd_element->flags = LDB_FLAG_MOD_REPLACE; 684 } 685 } 686 687 /* mark the controls as non-critical since we've handled them */ 688 if (sd_flags_control != NULL) { 689 sd_flags_control->critical = 0; 690 } 691 if (sd_recalculate_control != NULL) { 692 sd_recalculate_control->critical = 0; 842 if (msg == NULL) { 843 return ldb_oom(ldb); 844 } 845 cmp_ret = data_blob_cmp(old_sd, sd); 846 if (sd_propagation_control != NULL) { 847 if (cmp_ret == 0) { 848 /* 849 * The nTSecurityDescriptor is unchanged, 850 * which means we can stop the processing. 851 * 852 * We mark the control as critical again, 853 * as we have not processed it, so the caller 854 * can tell that the descriptor was unchanged. 855 */ 856 sd_propagation_control->critical = 1; 857 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); 858 } 859 860 ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor", 861 LDB_FLAG_MOD_REPLACE, 862 &sd_element); 863 if (ret != LDB_SUCCESS) { 864 return ldb_oom(ldb); 865 } 866 ret = ldb_msg_add_value(msg, "nTSecurityDescriptor", 867 sd, NULL); 868 if (ret != LDB_SUCCESS) { 869 return ldb_oom(ldb); 870 } 871 } else if (cmp_ret != 0) { 872 struct ldb_dn *nc_root; 873 874 ret = dsdb_find_nc_root(ldb, msg, dn, &nc_root); 875 if (ret != LDB_SUCCESS) { 876 return ldb_oom(ldb); 877 } 878 879 ret = dsdb_module_schedule_sd_propagation(module, nc_root, 880 dn, false); 881 if (ret != LDB_SUCCESS) { 882 return ldb_operr(ldb); 883 } 884 sd_element->values[0] = *sd; 885 } else { 886 sd_element->values[0] = *sd; 693 887 } 694 888 … … 711 905 int ret; 712 906 struct ldb_context *ldb; 713 struct ldb_control *sd_control;714 907 struct ldb_request *down_req; 715 908 struct descriptor_context *ac; 716 717 sd_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID); 718 if (!sd_control) { 909 bool explicit_sd_flags = false; 910 uint32_t sd_flags = dsdb_request_sd_flags(req, &explicit_sd_flags); 911 bool show_sd = explicit_sd_flags; 912 913 if (!show_sd && 914 ldb_attr_in_list(req->op.search.attrs, "nTSecurityDescriptor")) 915 { 916 show_sd = true; 917 } 918 919 if (!show_sd) { 719 920 return ldb_next_request(module, req); 720 921 } … … 725 926 return ldb_operr(ldb); 726 927 } 928 ac->sd_flags = sd_flags; 727 929 728 930 ret = ldb_build_search_req_ex(&down_req, ldb, ac, … … 738 940 return ret; 739 941 } 740 /* mark it as handled */741 if (sd_control) {742 sd_control->critical = 0;743 }744 942 745 943 return ldb_next_request(ac->module, down_req); 746 944 } 747 /* TODO */ 945 748 946 static int descriptor_rename(struct ldb_module *module, struct ldb_request *req) 749 947 { 750 948 struct ldb_context *ldb = ldb_module_get_ctx(module); 751 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn)); 949 struct ldb_dn *olddn = req->op.rename.olddn; 950 struct ldb_dn *newdn = req->op.rename.newdn; 951 int ret; 752 952 753 953 /* do not manipulate our control entries */ … … 756 956 } 757 957 958 ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_rename: %s\n", 959 ldb_dn_get_linearized(olddn)); 960 961 if (ldb_dn_compare(olddn, newdn) != 0) { 962 struct ldb_dn *nc_root; 963 964 ret = dsdb_find_nc_root(ldb, req, newdn, &nc_root); 965 if (ret != LDB_SUCCESS) { 966 return ldb_oom(ldb); 967 } 968 969 ret = dsdb_module_schedule_sd_propagation(module, nc_root, 970 newdn, true); 971 if (ret != LDB_SUCCESS) { 972 return ldb_operr(ldb); 973 } 974 } 975 758 976 return ldb_next_request(module, req); 759 977 } 760 978 979 static int descriptor_extended_sec_desc_propagation(struct ldb_module *module, 980 struct ldb_request *req) 981 { 982 struct descriptor_data *descriptor_private = 983 talloc_get_type_abort(ldb_module_get_private(module), 984 struct descriptor_data); 985 struct ldb_context *ldb = ldb_module_get_ctx(module); 986 struct dsdb_extended_sec_desc_propagation_op *op; 987 TALLOC_CTX *parent_mem = NULL; 988 struct descriptor_changes *parent_change = NULL; 989 struct descriptor_changes *c; 990 int ret; 991 992 op = talloc_get_type(req->op.extended.data, 993 struct dsdb_extended_sec_desc_propagation_op); 994 if (op == NULL) { 995 ldb_debug(ldb, LDB_DEBUG_FATAL, 996 "descriptor_extended_sec_desc_propagation: " 997 "invalid extended data\n"); 998 return LDB_ERR_PROTOCOL_ERROR; 999 } 1000 1001 if (descriptor_private->trans_mem == NULL) { 1002 return ldb_module_operr(module); 1003 } 1004 1005 parent_mem = descriptor_private->trans_mem; 1006 1007 for (c = descriptor_private->changes; c; c = c->next) { 1008 ret = ldb_dn_compare(c->nc_root, op->nc_root); 1009 if (ret != 0) { 1010 continue; 1011 } 1012 1013 ret = ldb_dn_compare(c->dn, op->dn); 1014 if (ret == 0) { 1015 if (op->include_self) { 1016 c->force_self = true; 1017 } else { 1018 c->force_children = true; 1019 } 1020 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); 1021 } 1022 1023 ret = ldb_dn_compare_base(c->dn, op->dn); 1024 if (ret != 0) { 1025 continue; 1026 } 1027 1028 parent_mem = c; 1029 parent_change = c; 1030 break; 1031 } 1032 1033 c = talloc_zero(parent_mem, struct descriptor_changes); 1034 if (c == NULL) { 1035 return ldb_module_oom(module); 1036 } 1037 c->nc_root = ldb_dn_copy(c, op->nc_root); 1038 if (c->nc_root == NULL) { 1039 return ldb_module_oom(module); 1040 } 1041 c->dn = ldb_dn_copy(c, op->dn); 1042 if (c->dn == NULL) { 1043 return ldb_module_oom(module); 1044 } 1045 if (op->include_self) { 1046 c->force_self = true; 1047 } else { 1048 c->force_children = true; 1049 } 1050 1051 if (parent_change != NULL) { 1052 DLIST_ADD_END(parent_change->children, c); 1053 } else { 1054 DLIST_ADD_END(descriptor_private->changes, c); 1055 } 1056 1057 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); 1058 } 1059 1060 static int descriptor_extended(struct ldb_module *module, struct ldb_request *req) 1061 { 1062 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID) == 0) { 1063 return descriptor_extended_sec_desc_propagation(module, req); 1064 } 1065 1066 return ldb_next_request(module, req); 1067 } 1068 761 1069 static int descriptor_init(struct ldb_module *module) 762 1070 { 763 int ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);764 1071 struct ldb_context *ldb = ldb_module_get_ctx(module); 1072 int ret; 1073 struct descriptor_data *descriptor_private; 1074 1075 ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID); 765 1076 if (ret != LDB_SUCCESS) { 766 1077 ldb_debug(ldb, LDB_DEBUG_ERROR, … … 768 1079 return ldb_operr(ldb); 769 1080 } 1081 1082 descriptor_private = talloc_zero(module, struct descriptor_data); 1083 if (descriptor_private == NULL) { 1084 ldb_oom(ldb); 1085 return LDB_ERR_OPERATIONS_ERROR; 1086 } 1087 ldb_module_set_private(module, descriptor_private); 1088 770 1089 return ldb_next_init(module); 771 1090 } 772 1091 1092 static int descriptor_sd_propagation_object(struct ldb_module *module, 1093 struct ldb_message *msg, 1094 bool *stop) 1095 { 1096 struct ldb_context *ldb = ldb_module_get_ctx(module); 1097 struct ldb_request *sub_req; 1098 struct ldb_result *mod_res; 1099 struct ldb_control *sd_propagation_control; 1100 int ret; 1101 1102 *stop = false; 1103 1104 mod_res = talloc_zero(msg, struct ldb_result); 1105 if (mod_res == NULL) { 1106 return ldb_module_oom(module); 1107 } 1108 1109 ret = ldb_build_mod_req(&sub_req, ldb, mod_res, 1110 msg, 1111 NULL, 1112 mod_res, 1113 ldb_modify_default_callback, 1114 NULL); 1115 LDB_REQ_SET_LOCATION(sub_req); 1116 if (ret != LDB_SUCCESS) { 1117 return ldb_module_operr(module); 1118 } 1119 1120 ldb_req_mark_trusted(sub_req); 1121 1122 ret = ldb_request_add_control(sub_req, 1123 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID, 1124 true, module); 1125 if (ret != LDB_SUCCESS) { 1126 return ldb_module_operr(module); 1127 } 1128 1129 sd_propagation_control = ldb_request_get_control(sub_req, 1130 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); 1131 if (sd_propagation_control == NULL) { 1132 return ldb_module_operr(module); 1133 } 1134 1135 ret = dsdb_request_add_controls(sub_req, 1136 DSDB_FLAG_AS_SYSTEM | 1137 DSDB_SEARCH_SHOW_RECYCLED); 1138 if (ret != LDB_SUCCESS) { 1139 return ldb_module_operr(module); 1140 } 1141 1142 ret = descriptor_modify(module, sub_req); 1143 if (ret == LDB_SUCCESS) { 1144 ret = ldb_wait(sub_req->handle, LDB_WAIT_ALL); 1145 } 1146 if (ret != LDB_SUCCESS) { 1147 return ldb_module_operr(module); 1148 } 1149 1150 if (sd_propagation_control->critical != 0) { 1151 *stop = true; 1152 } 1153 1154 talloc_free(mod_res); 1155 1156 return LDB_SUCCESS; 1157 } 1158 1159 static int descriptor_sd_propagation_msg_sort(struct ldb_message **m1, 1160 struct ldb_message **m2) 1161 { 1162 struct ldb_dn *dn1 = (*m1)->dn; 1163 struct ldb_dn *dn2 = (*m2)->dn; 1164 1165 /* 1166 * This sorts in tree order, parents first 1167 */ 1168 return ldb_dn_compare(dn2, dn1); 1169 } 1170 1171 static int descriptor_sd_propagation_dn_sort(struct ldb_dn *dn1, 1172 struct ldb_dn *dn2) 1173 { 1174 /* 1175 * This sorts in tree order, parents first 1176 */ 1177 return ldb_dn_compare(dn2, dn1); 1178 } 1179 1180 static int descriptor_sd_propagation_recursive(struct ldb_module *module, 1181 struct descriptor_changes *change) 1182 { 1183 struct ldb_context *ldb = ldb_module_get_ctx(module); 1184 struct ldb_result *res = NULL; 1185 unsigned int i; 1186 const char * const no_attrs[] = { "@__NONE__", NULL }; 1187 struct descriptor_changes *c; 1188 struct descriptor_changes *stopped_stack = NULL; 1189 enum ldb_scope scope; 1190 int ret; 1191 1192 /* 1193 * First confirm this object has children, or exists (depending on change->force_self) 1194 * 1195 * LDB_SCOPE_SUBTREE searches are expensive. 1196 * 1197 * Note: that we do not search for deleted/recycled objects 1198 */ 1199 ret = dsdb_module_search(module, 1200 change, 1201 &res, 1202 change->dn, 1203 LDB_SCOPE_ONELEVEL, 1204 no_attrs, 1205 DSDB_FLAG_NEXT_MODULE | 1206 DSDB_FLAG_AS_SYSTEM, 1207 NULL, /* parent_req */ 1208 "(objectClass=*)"); 1209 if (ret != LDB_SUCCESS) { 1210 return ret; 1211 } 1212 1213 if (res->count == 0 && !change->force_self) { 1214 TALLOC_FREE(res); 1215 return LDB_SUCCESS; 1216 } else if (res->count == 0 && change->force_self) { 1217 scope = LDB_SCOPE_BASE; 1218 } else { 1219 scope = LDB_SCOPE_SUBTREE; 1220 } 1221 1222 /* 1223 * Note: that we do not search for deleted/recycled objects 1224 */ 1225 ret = dsdb_module_search(module, 1226 change, 1227 &res, 1228 change->dn, 1229 scope, 1230 no_attrs, 1231 DSDB_FLAG_NEXT_MODULE | 1232 DSDB_FLAG_AS_SYSTEM, 1233 NULL, /* parent_req */ 1234 "(objectClass=*)"); 1235 if (ret != LDB_SUCCESS) { 1236 return ret; 1237 } 1238 1239 TYPESAFE_QSORT(res->msgs, res->count, 1240 descriptor_sd_propagation_msg_sort); 1241 1242 for (c = change->children; c; c = c->next) { 1243 struct ldb_message *msg = NULL; 1244 1245 BINARY_ARRAY_SEARCH_P(res->msgs, res->count, dn, c->dn, 1246 descriptor_sd_propagation_dn_sort, 1247 msg); 1248 1249 if (msg == NULL) { 1250 ldb_debug(ldb, LDB_DEBUG_WARNING, 1251 "descriptor_sd_propagation_recursive: " 1252 "%s not found under %s", 1253 ldb_dn_get_linearized(c->dn), 1254 ldb_dn_get_linearized(change->dn)); 1255 continue; 1256 } 1257 1258 msg->elements = (struct ldb_message_element *)c; 1259 } 1260 1261 DLIST_ADD(stopped_stack, change); 1262 1263 if (change->force_self) { 1264 i = 0; 1265 } else { 1266 i = 1; 1267 } 1268 1269 for (; i < res->count; i++) { 1270 struct descriptor_changes *cur; 1271 bool stop = false; 1272 1273 cur = talloc_get_type(res->msgs[i]->elements, 1274 struct descriptor_changes); 1275 res->msgs[i]->elements = NULL; 1276 res->msgs[i]->num_elements = 0; 1277 1278 if (cur != NULL) { 1279 DLIST_REMOVE(change->children, cur); 1280 } 1281 1282 for (c = stopped_stack; c; c = stopped_stack) { 1283 ret = ldb_dn_compare_base(c->dn, 1284 res->msgs[i]->dn); 1285 if (ret == 0) { 1286 break; 1287 } 1288 1289 c->stopped_dn = NULL; 1290 DLIST_REMOVE(stopped_stack, c); 1291 } 1292 1293 if (cur != NULL) { 1294 DLIST_ADD(stopped_stack, cur); 1295 } 1296 1297 if (stopped_stack->stopped_dn != NULL) { 1298 ret = ldb_dn_compare_base(stopped_stack->stopped_dn, 1299 res->msgs[i]->dn); 1300 if (ret == 0) { 1301 continue; 1302 } 1303 stopped_stack->stopped_dn = NULL; 1304 } 1305 1306 ret = descriptor_sd_propagation_object(module, res->msgs[i], 1307 &stop); 1308 if (ret != LDB_SUCCESS) { 1309 return ret; 1310 } 1311 1312 if (cur != NULL && cur->force_children) { 1313 continue; 1314 } 1315 1316 if (stop) { 1317 stopped_stack->stopped_dn = res->msgs[i]->dn; 1318 continue; 1319 } 1320 } 1321 1322 TALLOC_FREE(res); 1323 return LDB_SUCCESS; 1324 } 1325 1326 static int descriptor_start_transaction(struct ldb_module *module) 1327 { 1328 struct descriptor_data *descriptor_private = 1329 talloc_get_type_abort(ldb_module_get_private(module), 1330 struct descriptor_data); 1331 1332 if (descriptor_private->trans_mem != NULL) { 1333 return ldb_module_operr(module); 1334 } 1335 1336 descriptor_private->trans_mem = talloc_new(descriptor_private); 1337 if (descriptor_private->trans_mem == NULL) { 1338 return ldb_module_oom(module); 1339 } 1340 descriptor_private->changes = NULL; 1341 1342 return ldb_next_start_trans(module); 1343 } 1344 1345 static int descriptor_prepare_commit(struct ldb_module *module) 1346 { 1347 struct descriptor_data *descriptor_private = 1348 talloc_get_type_abort(ldb_module_get_private(module), 1349 struct descriptor_data); 1350 struct descriptor_changes *c, *n; 1351 int ret; 1352 1353 for (c = descriptor_private->changes; c; c = n) { 1354 n = c->next; 1355 DLIST_REMOVE(descriptor_private->changes, c); 1356 1357 ret = descriptor_sd_propagation_recursive(module, c); 1358 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 1359 continue; 1360 } 1361 if (ret != LDB_SUCCESS) { 1362 return ret; 1363 } 1364 } 1365 1366 return ldb_next_prepare_commit(module); 1367 } 1368 1369 static int descriptor_end_transaction(struct ldb_module *module) 1370 { 1371 struct descriptor_data *descriptor_private = 1372 talloc_get_type_abort(ldb_module_get_private(module), 1373 struct descriptor_data); 1374 1375 TALLOC_FREE(descriptor_private->trans_mem); 1376 descriptor_private->changes = NULL; 1377 1378 return ldb_next_end_trans(module); 1379 } 1380 1381 static int descriptor_del_transaction(struct ldb_module *module) 1382 { 1383 struct descriptor_data *descriptor_private = 1384 talloc_get_type_abort(ldb_module_get_private(module), 1385 struct descriptor_data); 1386 1387 TALLOC_FREE(descriptor_private->trans_mem); 1388 descriptor_private->changes = NULL; 1389 1390 return ldb_next_del_trans(module); 1391 } 773 1392 774 1393 static const struct ldb_module_ops ldb_descriptor_module_ops = { 775 .name = "descriptor", 776 .search = descriptor_search, 777 .add = descriptor_add, 778 .modify = descriptor_modify, 779 .rename = descriptor_rename, 780 .init_context = descriptor_init 1394 .name = "descriptor", 1395 .search = descriptor_search, 1396 .add = descriptor_add, 1397 .modify = descriptor_modify, 1398 .rename = descriptor_rename, 1399 .init_context = descriptor_init, 1400 .extended = descriptor_extended, 1401 .start_transaction = descriptor_start_transaction, 1402 .prepare_commit = descriptor_prepare_commit, 1403 .end_transaction = descriptor_end_transaction, 1404 .del_transaction = descriptor_del_transaction, 781 1405 }; 782 1406 -
vendor/current/source4/dsdb/samdb/ldb_modules/extended_dn_in.c
r740 r988 34 34 #include <ldb_errors.h> 35 35 #include <ldb_module.h> 36 #include "dsdb/samdb/samdb.h" 37 #include "dsdb/samdb/ldb_modules/util.h" 38 #include "lib/ldb-samba/ldb_matching_rules.h" 36 39 37 40 /* … … 45 48 struct ldb_request *req; 46 49 struct ldb_dn *basedn; 50 struct ldb_dn *dn; 47 51 char *wellknown_object; 48 52 int extended_type; 49 53 }; 54 55 static const char *wkattr[] = { 56 "wellKnownObjects", 57 "otherWellKnownObjects", 58 NULL 59 }; 60 61 static const struct ldb_module_ops ldb_extended_dn_in_openldap_module_ops; 50 62 51 63 /* An extra layer of indirection because LDB does not allow the original request to be altered */ … … 86 98 struct ldb_message_element *el; 87 99 int ret; 88 unsigned int i ;100 unsigned int i, j; 89 101 size_t wkn_len = 0; 90 102 char *valstr = NULL; … … 104 116 switch (ares->type) { 105 117 case LDB_REPLY_ENTRY: 118 if (ac->basedn) { 119 /* we have more than one match! This can 120 happen as S-1-5-17 appears twice in a 121 normal provision. We need to return 122 NO_SUCH_OBJECT */ 123 const char *str = talloc_asprintf(req, "Duplicate base-DN matches found for '%s'", 124 ldb_dn_get_extended_linearized(req, ac->dn, 1)); 125 ldb_set_errstring(ldb_module_get_ctx(ac->module), str); 126 return ldb_module_done(ac->req, NULL, NULL, 127 LDB_ERR_NO_SUCH_OBJECT); 128 } 129 106 130 if (!ac->wellknown_object) { 107 131 ac->basedn = talloc_steal(ac, ares->message->dn); … … 111 135 wkn_len = strlen(ac->wellknown_object); 112 136 113 el = ldb_msg_find_element(ares->message, "wellKnownObjects"); 114 if (!el) { 115 ac->basedn = NULL; 116 break; 117 } 118 119 for (i=0; i < el->num_values; i++) { 120 valstr = talloc_strndup(ac, 121 (const char *)el->values[i].data, 122 el->values[i].length); 123 if (!valstr) { 124 ldb_oom(ldb_module_get_ctx(ac->module)); 125 return ldb_module_done(ac->req, NULL, NULL, 126 LDB_ERR_OPERATIONS_ERROR); 127 } 128 129 if (strncasecmp(valstr, ac->wellknown_object, wkn_len) != 0) { 130 talloc_free(valstr); 137 for (j=0; wkattr[j]; j++) { 138 139 el = ldb_msg_find_element(ares->message, wkattr[j]); 140 if (!el) { 141 ac->basedn = NULL; 131 142 continue; 132 143 } 133 144 134 found = &valstr[wkn_len]; 135 break; 145 for (i=0; i < el->num_values; i++) { 146 valstr = talloc_strndup(ac, 147 (const char *)el->values[i].data, 148 el->values[i].length); 149 if (!valstr) { 150 ldb_oom(ldb_module_get_ctx(ac->module)); 151 return ldb_module_done(ac->req, NULL, NULL, 152 LDB_ERR_OPERATIONS_ERROR); 153 } 154 155 if (strncasecmp(valstr, ac->wellknown_object, wkn_len) != 0) { 156 talloc_free(valstr); 157 continue; 158 } 159 160 found = &valstr[wkn_len]; 161 break; 162 } 163 if (found) { 164 break; 165 } 136 166 } 137 167 … … 157 187 if (!ac->basedn) { 158 188 const char *str = talloc_asprintf(req, "Base-DN '%s' not found", 159 ldb_dn_get_extended_linearized(req, ac-> req->op.search.base, 1));189 ldb_dn_get_extended_linearized(req, ac->dn, 1)); 160 190 ldb_set_errstring(ldb_module_get_ctx(ac->module), str); 161 191 return ldb_module_done(ac->req, NULL, NULL, … … 249 279 } 250 280 281 282 /* 283 windows ldap searchs don't allow a baseDN with more 284 than one extended component, or an extended 285 component and a string DN 286 287 We only enforce this over ldap, not for internal 288 use, as there are just too many places where we 289 internally want to use a DN that has come from a 290 search with extended DN enabled, or comes from a DRS 291 naming context. 292 293 Enforcing this would also make debugging samba much 294 harder, as we'd need to use ldb_dn_minimise() in a 295 lot of places, and that would lose the DN string 296 which is so useful for working out what a request is 297 for 298 */ 299 static bool ldb_dn_match_allowed(struct ldb_dn *dn, struct ldb_request *req) 300 { 301 int num_components = ldb_dn_get_comp_num(dn); 302 int num_ex_components = ldb_dn_get_extended_comp_num(dn); 303 304 if (num_ex_components == 0) { 305 return true; 306 } 307 308 if ((num_components != 0 || num_ex_components != 1) && 309 ldb_req_is_untrusted(req)) { 310 return false; 311 } 312 return true; 313 } 314 315 316 struct extended_dn_filter_ctx { 317 bool test_only; 318 bool matched; 319 struct ldb_module *module; 320 struct ldb_request *req; 321 struct dsdb_schema *schema; 322 uint32_t dsdb_flags; 323 }; 324 325 /* 326 create a always non-matching node from a equality node 327 */ 328 static void set_parse_tree_false(struct ldb_parse_tree *tree) 329 { 330 const char *attr = tree->u.equality.attr; 331 struct ldb_val value = tree->u.equality.value; 332 tree->operation = LDB_OP_EXTENDED; 333 tree->u.extended.attr = attr; 334 tree->u.extended.value = value; 335 tree->u.extended.rule_id = SAMBA_LDAP_MATCH_ALWAYS_FALSE; 336 tree->u.extended.dnAttributes = 0; 337 } 338 339 /* 340 called on all nodes in the parse tree 341 */ 342 static int extended_dn_filter_callback(struct ldb_parse_tree *tree, void *private_context) 343 { 344 struct extended_dn_filter_ctx *filter_ctx; 345 int ret; 346 struct ldb_dn *dn = NULL; 347 const struct ldb_val *sid_val, *guid_val; 348 const char *no_attrs[] = { NULL }; 349 struct ldb_result *res; 350 const struct dsdb_attribute *attribute = NULL; 351 bool has_extended_component = false; 352 enum ldb_scope scope; 353 struct ldb_dn *base_dn; 354 const char *expression; 355 uint32_t dsdb_flags; 356 357 if (tree->operation != LDB_OP_EQUALITY && tree->operation != LDB_OP_EXTENDED) { 358 return LDB_SUCCESS; 359 } 360 361 filter_ctx = talloc_get_type_abort(private_context, struct extended_dn_filter_ctx); 362 363 if (filter_ctx->test_only && filter_ctx->matched) { 364 /* the tree already matched */ 365 return LDB_SUCCESS; 366 } 367 368 if (!filter_ctx->schema) { 369 /* Schema not setup yet */ 370 return LDB_SUCCESS; 371 } 372 if (tree->operation == LDB_OP_EQUALITY) { 373 attribute = dsdb_attribute_by_lDAPDisplayName(filter_ctx->schema, tree->u.equality.attr); 374 } else if (tree->operation == LDB_OP_EXTENDED) { 375 attribute = dsdb_attribute_by_lDAPDisplayName(filter_ctx->schema, tree->u.extended.attr); 376 } 377 if (attribute == NULL) { 378 return LDB_SUCCESS; 379 } 380 381 if (attribute->dn_format != DSDB_NORMAL_DN) { 382 return LDB_SUCCESS; 383 } 384 385 if (tree->operation == LDB_OP_EQUALITY) { 386 has_extended_component = (memchr(tree->u.equality.value.data, '<', 387 tree->u.equality.value.length) != NULL); 388 } else if (tree->operation == LDB_OP_EXTENDED) { 389 has_extended_component = (memchr(tree->u.extended.value.data, '<', 390 tree->u.extended.value.length) != NULL); 391 } 392 393 /* 394 * Don't turn it into an extended DN if we're talking to OpenLDAP. 395 * We just check the module_ops pointer instead of adding a private 396 * pointer and a boolean to tell us the exact same thing. 397 */ 398 if (!has_extended_component) { 399 if (!attribute->one_way_link) { 400 return LDB_SUCCESS; 401 } 402 403 if (ldb_module_get_ops(filter_ctx->module) == &ldb_extended_dn_in_openldap_module_ops) { 404 return LDB_SUCCESS; 405 } 406 } 407 408 if (tree->operation == LDB_OP_EQUALITY) { 409 dn = ldb_dn_from_ldb_val(filter_ctx, ldb_module_get_ctx(filter_ctx->module), &tree->u.equality.value); 410 } else if (tree->operation == LDB_OP_EXTENDED 411 && (strcmp(tree->u.extended.rule_id, SAMBA_LDAP_MATCH_RULE_TRANSITIVE_EVAL) == 0)) { 412 dn = ldb_dn_from_ldb_val(filter_ctx, ldb_module_get_ctx(filter_ctx->module), &tree->u.extended.value); 413 } 414 if (dn == NULL) { 415 /* testing against windows shows that we don't raise 416 an error here */ 417 return LDB_SUCCESS; 418 } 419 420 guid_val = ldb_dn_get_extended_component(dn, "GUID"); 421 sid_val = ldb_dn_get_extended_component(dn, "SID"); 422 423 if (!guid_val && !sid_val && (attribute->searchFlags & SEARCH_FLAG_ATTINDEX)) { 424 /* if it is indexed, then fixing the string DN will do 425 no good here, as we will not find the attribute in 426 the index. So for now fall through to a standard DN 427 component comparison */ 428 return LDB_SUCCESS; 429 } 430 431 if (filter_ctx->test_only) { 432 /* we need to copy the tree */ 433 filter_ctx->matched = true; 434 return LDB_SUCCESS; 435 } 436 437 if (!ldb_dn_match_allowed(dn, filter_ctx->req)) { 438 /* we need to make this element of the filter always 439 be false */ 440 set_parse_tree_false(tree); 441 return LDB_SUCCESS; 442 } 443 444 dsdb_flags = filter_ctx->dsdb_flags | DSDB_FLAG_NEXT_MODULE; 445 446 if (guid_val) { 447 expression = talloc_asprintf(filter_ctx, "objectGUID=%s", ldb_binary_encode(filter_ctx, *guid_val)); 448 scope = LDB_SCOPE_SUBTREE; 449 base_dn = NULL; 450 dsdb_flags |= DSDB_SEARCH_SEARCH_ALL_PARTITIONS; 451 } else if (sid_val) { 452 expression = talloc_asprintf(filter_ctx, "objectSID=%s", ldb_binary_encode(filter_ctx, *sid_val)); 453 scope = LDB_SCOPE_SUBTREE; 454 base_dn = NULL; 455 dsdb_flags |= DSDB_SEARCH_SEARCH_ALL_PARTITIONS; 456 } else { 457 /* fallback to searching using the string DN as the base DN */ 458 expression = "objectClass=*"; 459 base_dn = dn; 460 scope = LDB_SCOPE_BASE; 461 } 462 463 ret = dsdb_module_search(filter_ctx->module, 464 filter_ctx, 465 &res, 466 base_dn, 467 scope, 468 no_attrs, 469 dsdb_flags, 470 filter_ctx->req, 471 "%s", expression); 472 if (scope == LDB_SCOPE_BASE && ret == LDB_ERR_NO_SUCH_OBJECT) { 473 /* note that this will need to change for multi-domain 474 support */ 475 set_parse_tree_false(tree); 476 return LDB_SUCCESS; 477 } 478 479 if (ret != LDB_SUCCESS) { 480 return LDB_SUCCESS; 481 } 482 483 484 if (res->count != 1) { 485 return LDB_SUCCESS; 486 } 487 488 /* replace the search expression element with the matching DN */ 489 if (tree->operation == LDB_OP_EQUALITY) { 490 tree->u.equality.value.data = 491 (uint8_t *)talloc_strdup(tree, ldb_dn_get_extended_linearized(tree, res->msgs[0]->dn, 1)); 492 if (tree->u.equality.value.data == NULL) { 493 return ldb_oom(ldb_module_get_ctx(filter_ctx->module)); 494 } 495 tree->u.equality.value.length = strlen((const char *)tree->u.equality.value.data); 496 } else if (tree->operation == LDB_OP_EXTENDED) { 497 tree->u.extended.value.data = 498 (uint8_t *)talloc_strdup(tree, ldb_dn_get_extended_linearized(tree, res->msgs[0]->dn, 1)); 499 if (tree->u.extended.value.data == NULL) { 500 return ldb_oom(ldb_module_get_ctx(filter_ctx->module)); 501 } 502 tree->u.extended.value.length = strlen((const char *)tree->u.extended.value.data); 503 } 504 talloc_free(res); 505 506 filter_ctx->matched = true; 507 return LDB_SUCCESS; 508 } 509 510 /* 511 fix the parse tree to change any extended DN components to their 512 caconical form 513 */ 514 static int extended_dn_fix_filter(struct ldb_module *module, 515 struct ldb_request *req, 516 uint32_t default_dsdb_flags) 517 { 518 struct extended_dn_filter_ctx *filter_ctx; 519 int ret; 520 521 filter_ctx = talloc_zero(req, struct extended_dn_filter_ctx); 522 if (filter_ctx == NULL) { 523 return ldb_module_oom(module); 524 } 525 526 /* first pass through the existing tree to see if anything 527 needs to be modified. Filtering DNs on the input side is rare, 528 so this avoids copying the parse tree in most cases */ 529 filter_ctx->test_only = true; 530 filter_ctx->matched = false; 531 filter_ctx->module = module; 532 filter_ctx->req = req; 533 filter_ctx->schema = dsdb_get_schema(ldb_module_get_ctx(module), filter_ctx); 534 filter_ctx->dsdb_flags= default_dsdb_flags; 535 536 ret = ldb_parse_tree_walk(req->op.search.tree, extended_dn_filter_callback, filter_ctx); 537 if (ret != LDB_SUCCESS) { 538 talloc_free(filter_ctx); 539 return ret; 540 } 541 542 if (!filter_ctx->matched) { 543 /* nothing matched, no need for a new parse tree */ 544 talloc_free(filter_ctx); 545 return LDB_SUCCESS; 546 } 547 548 filter_ctx->test_only = false; 549 filter_ctx->matched = false; 550 551 req->op.search.tree = ldb_parse_tree_copy_shallow(req, req->op.search.tree); 552 if (req->op.search.tree == NULL) { 553 return ldb_oom(ldb_module_get_ctx(module)); 554 } 555 556 ret = ldb_parse_tree_walk(req->op.search.tree, extended_dn_filter_callback, filter_ctx); 557 if (ret != LDB_SUCCESS) { 558 talloc_free(filter_ctx); 559 return ret; 560 } 561 562 talloc_free(filter_ctx); 563 return LDB_SUCCESS; 564 } 565 566 /* 567 fix DNs and filter expressions to cope with the semantics of 568 extended DNs 569 */ 251 570 static int extended_dn_in_fix(struct ldb_module *module, struct ldb_request *req, struct ldb_dn *dn) 252 571 { … … 262 581 NULL 263 582 }; 264 static const char *wkattr[] = { 265 "wellKnownObjects", 266 NULL 267 }; 268 bool all_partitions = false; 583 uint32_t dsdb_flags = DSDB_FLAG_AS_SYSTEM | DSDB_SEARCH_SHOW_EXTENDED_DN; 584 585 if (ldb_request_get_control(req, LDB_CONTROL_SHOW_DELETED_OID)) { 586 dsdb_flags |= DSDB_SEARCH_SHOW_DELETED; 587 } 588 if (ldb_request_get_control(req, LDB_CONTROL_SHOW_RECYCLED_OID)) { 589 dsdb_flags |= DSDB_SEARCH_SHOW_RECYCLED; 590 } 591 if (ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) { 592 dsdb_flags |= DSDB_SEARCH_SHOW_RECYCLED; 593 } 594 595 if (req->operation == LDB_SEARCH) { 596 ret = extended_dn_fix_filter(module, req, dsdb_flags); 597 if (ret != LDB_SUCCESS) { 598 return ret; 599 } 600 } 269 601 270 602 if (!ldb_dn_has_extended(dn)) { … … 274 606 /* It looks like we need to map the DN */ 275 607 const struct ldb_val *sid_val, *guid_val, *wkguid_val; 276 int num_components = ldb_dn_get_comp_num(dn); 277 int num_ex_components = ldb_dn_get_extended_comp_num(dn); 278 279 /* 280 windows ldap searchs don't allow a baseDN with more 281 than one extended component, or an extended 282 component and a string DN 283 284 We only enforce this over ldap, not for internal 285 use, as there are just too many places where we 286 internally want to use a DN that has come from a 287 search with extended DN enabled, or comes from a DRS 288 naming context. 289 290 Enforcing this would also make debugging samba much 291 harder, as we'd need to use ldb_dn_minimise() in a 292 lot of places, and that would lose the DN string 293 which is so useful for working out what a request is 294 for 295 */ 296 if ((num_components != 0 || num_ex_components != 1) && 297 ldb_req_is_untrusted(req)) { 608 609 if (!ldb_dn_match_allowed(dn, req)) { 298 610 return ldb_error(ldb_module_get_ctx(module), 299 611 LDB_ERR_INVALID_DN_SYNTAX, "invalid number of DN components"); … … 304 616 wkguid_val = ldb_dn_get_extended_component(dn, "WKGUID"); 305 617 306 if (sid_val) { 307 all_partitions = true; 308 base_dn = ldb_get_default_basedn(ldb_module_get_ctx(module)); 309 base_dn_filter = talloc_asprintf(req, "(objectSid=%s)", 618 /* 619 prioritise the GUID - we have had instances of 620 duplicate SIDs in the database in the 621 ForeignSecurityPrinciples due to provision errors 622 */ 623 if (guid_val) { 624 dsdb_flags |= DSDB_SEARCH_SEARCH_ALL_PARTITIONS; 625 base_dn = NULL; 626 base_dn_filter = talloc_asprintf(req, "(objectGUID=%s)", 627 ldb_binary_encode(req, *guid_val)); 628 if (!base_dn_filter) { 629 return ldb_oom(ldb_module_get_ctx(module)); 630 } 631 base_dn_scope = LDB_SCOPE_SUBTREE; 632 base_dn_attrs = no_attr; 633 634 } else if (sid_val) { 635 dsdb_flags |= DSDB_SEARCH_SEARCH_ALL_PARTITIONS; 636 base_dn = NULL; 637 base_dn_filter = talloc_asprintf(req, "(objectSid=%s)", 310 638 ldb_binary_encode(req, *sid_val)); 311 639 if (!base_dn_filter) { … … 314 642 base_dn_scope = LDB_SCOPE_SUBTREE; 315 643 base_dn_attrs = no_attr; 316 317 } else if (guid_val) {318 319 all_partitions = true;320 base_dn = ldb_get_default_basedn(ldb_module_get_ctx(module));321 base_dn_filter = talloc_asprintf(req, "(objectGUID=%s)",322 ldb_binary_encode(req, *guid_val));323 if (!base_dn_filter) {324 return ldb_oom(ldb_module_get_ctx(module));325 }326 base_dn_scope = LDB_SCOPE_SUBTREE;327 base_dn_attrs = no_attr;328 329 644 330 645 } else if (wkguid_val) { … … 374 689 ac->module = module; 375 690 ac->req = req; 691 ac->dn = dn; 376 692 ac->basedn = NULL; /* Filled in if the search finds the DN by SID/GUID etc */ 377 693 ac->wellknown_object = wellknown_object; … … 386 702 base_dn_filter, 387 703 base_dn_attrs, 388 req->controls,704 NULL, 389 705 ac, extended_base_callback, 390 706 req); … … 394 710 } 395 711 396 if (all_partitions) { 397 struct ldb_search_options_control *control; 398 control = talloc(down_req, struct ldb_search_options_control); 399 control->search_options = 2; 400 ret = ldb_request_replace_control(down_req, 401 LDB_CONTROL_SEARCH_OPTIONS_OID, 402 true, control); 403 if (ret != LDB_SUCCESS) { 404 ldb_oom(ldb_module_get_ctx(module)); 405 return ret; 406 } 712 ret = dsdb_request_add_controls(down_req, dsdb_flags); 713 if (ret != LDB_SUCCESS) { 714 return ret; 407 715 } 408 716 … … 440 748 }; 441 749 750 static const struct ldb_module_ops ldb_extended_dn_in_openldap_module_ops = { 751 .name = "extended_dn_in_openldap", 752 .search = extended_dn_in_search, 753 .modify = extended_dn_in_modify, 754 .del = extended_dn_in_del, 755 .rename = extended_dn_in_rename, 756 }; 757 442 758 int ldb_extended_dn_in_module_init(const char *version) 443 759 { 760 int ret; 444 761 LDB_MODULE_CHECK_VERSION(version); 762 ret = ldb_register_module(&ldb_extended_dn_in_openldap_module_ops); 763 if (ret != LDB_SUCCESS) { 764 return ret; 765 } 445 766 return ldb_register_module(&ldb_extended_dn_in_module_ops); 446 767 } -
vendor/current/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
r740 r988 41 41 #include "librpc/ndr/libndr.h" 42 42 #include "dsdb/samdb/samdb.h" 43 #include " util.h"43 #include "dsdb/samdb/ldb_modules/util.h" 44 44 45 45 struct extended_dn_out_private { … … 77 77 78 78 for (cur = schema->attributes; cur; cur = cur->next) { 79 if ( dsdb_dn_oid_to_format(cur->syntax->ldap_oid)!= DSDB_NORMAL_DN) {79 if (cur->dn_format != DSDB_NORMAL_DN) { 80 80 continue; 81 81 } … … 83 83 = talloc_realloc(p, dereference_control->dereference, 84 84 struct dsdb_openldap_dereference *, i + 2); 85 if (!dereference_control ) {85 if (!dereference_control->dereference) { 86 86 return ldb_oom(ldb); 87 87 } … … 139 139 140 140 return true; 141 }142 143 /* Fix the DN so that the relative attribute names are in upper case so that the DN:144 cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes145 CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com146 */147 148 149 static int fix_dn(struct ldb_context *ldb, struct ldb_dn *dn)150 {151 int i, ret;152 char *upper_rdn_attr;153 154 for (i=0; i < ldb_dn_get_comp_num(dn); i++) {155 /* We need the attribute name in upper case */156 upper_rdn_attr = strupper_talloc(dn,157 ldb_dn_get_component_name(dn, i));158 if (!upper_rdn_attr) {159 return ldb_oom(ldb);160 }161 162 /* And replace it with CN=foo (we need the attribute in upper case */163 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,164 *ldb_dn_get_component_val(dn, i));165 talloc_free(upper_rdn_attr);166 if (ret != LDB_SUCCESS) {167 return ret;168 }169 }170 return LDB_SUCCESS;171 141 } 172 142 … … 350 320 }; 351 321 322 323 /* 324 fix one-way links to have the right string DN, to cope with 325 renames of the target 326 */ 327 static int fix_one_way_link(struct extended_search_context *ac, struct ldb_dn *dn, 328 bool is_deleted_objects, bool *remove_value) 329 { 330 struct GUID guid; 331 NTSTATUS status; 332 int ret; 333 struct ldb_dn *real_dn; 334 uint32_t search_flags; 335 TALLOC_CTX *tmp_ctx = talloc_new(ac); 336 const char *attrs[] = { NULL }; 337 struct ldb_result *res; 338 339 (*remove_value) = false; 340 341 status = dsdb_get_extended_dn_guid(dn, &guid, "GUID"); 342 if (!NT_STATUS_IS_OK(status)) { 343 /* this is a strange DN that doesn't have a GUID! just 344 return the current DN string?? */ 345 talloc_free(tmp_ctx); 346 return LDB_SUCCESS; 347 } 348 349 search_flags = DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SEARCH_ALL_PARTITIONS | DSDB_SEARCH_ONE_ONLY; 350 351 if (ldb_request_get_control(ac->req, LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID) || 352 is_deleted_objects) { 353 search_flags |= DSDB_SEARCH_SHOW_DELETED; 354 } 355 356 ret = dsdb_module_search(ac->module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs, 357 search_flags, ac->req, "objectguid=%s", GUID_string(tmp_ctx, &guid)); 358 if (ret != LDB_SUCCESS || res->count != 1) { 359 /* if we can't resolve this GUID, then we don't 360 display the link. This could be a link to a NC that we don't 361 have, or it could be a link to a deleted object 362 */ 363 (*remove_value) = true; 364 talloc_free(tmp_ctx); 365 return LDB_SUCCESS; 366 } 367 real_dn = res->msgs[0]->dn; 368 369 if (strcmp(ldb_dn_get_linearized(dn), ldb_dn_get_linearized(real_dn)) == 0) { 370 /* its already correct */ 371 talloc_free(tmp_ctx); 372 return LDB_SUCCESS; 373 } 374 375 /* fix the DN by replacing its components with those from the 376 * real DN 377 */ 378 if (!ldb_dn_replace_components(dn, real_dn)) { 379 talloc_free(tmp_ctx); 380 return ldb_operr(ldb_module_get_ctx(ac->module)); 381 } 382 talloc_free(tmp_ctx); 383 384 return LDB_SUCCESS; 385 } 386 387 388 /* 389 this is called to post-process the results from the search 390 */ 352 391 static int extended_callback(struct ldb_request *req, struct ldb_reply *ares, 353 392 int (*handle_dereference)(struct ldb_dn *dn, … … 391 430 392 431 if (p && p->normalise) { 393 ret = fix_dn(ldb, ares->message->dn);432 ret = dsdb_fix_dn_rdncase(ldb, ares->message->dn); 394 433 if (ret != LDB_SUCCESS) { 395 434 return ldb_module_done(ac->req, NULL, NULL, ret); … … 439 478 bool make_extended_dn; 440 479 const struct dsdb_attribute *attribute; 480 441 481 attribute = dsdb_attribute_by_lDAPDisplayName(ac->schema, msg->elements[i].name); 442 482 if (!attribute) { … … 461 501 462 502 /* Look to see if this attributeSyntax is a DN */ 463 if ( dsdb_dn_oid_to_format(attribute->syntax->ldap_oid)== DSDB_INVALID_DN) {503 if (attribute->dn_format == DSDB_INVALID_DN) { 464 504 continue; 465 505 } … … 477 517 struct dsdb_dn *dsdb_dn = NULL; 478 518 struct ldb_val *plain_dn = &msg->elements[i].values[j]; 519 bool is_deleted_objects = false; 479 520 480 521 if (!checked_reveal_control) { … … 512 553 dn = dsdb_dn->dn; 513 554 555 /* we need to know if this is a link to the 556 deleted objects container for fixing one way 557 links */ 558 if (dsdb_dn->extra_part.length == 16) { 559 char *hex_string = data_blob_hex_string_upper(req, &dsdb_dn->extra_part); 560 if (hex_string && strcmp(hex_string, DS_GUID_DELETED_OBJECTS_CONTAINER) == 0) { 561 is_deleted_objects = true; 562 } 563 talloc_free(hex_string); 564 } 565 514 566 /* don't let users see the internal extended 515 567 GUID components */ 516 568 if (!have_reveal_control) { 517 const char *accept[] = { "GUID", "SID", "WKGUID",NULL };569 const char *accept[] = { "GUID", "SID", NULL }; 518 570 ldb_dn_extended_filter(dn, accept); 519 571 } 520 572 521 573 if (p->normalise) { 522 ret = fix_dn(ldb, dn);574 ret = dsdb_fix_dn_rdncase(ldb, dn); 523 575 if (ret != LDB_SUCCESS) { 524 576 talloc_free(dsdb_dn); … … 545 597 } 546 598 } 599 600 /* note that we don't fixup objectCategory as 601 it should not be possible to move 602 objectCategory elements in the schema */ 603 if (attribute->one_way_link && 604 strcasecmp(attribute->lDAPDisplayName, "objectCategory") != 0) { 605 bool remove_value; 606 ret = fix_one_way_link(ac, dn, is_deleted_objects, &remove_value); 607 if (ret != LDB_SUCCESS) { 608 talloc_free(dsdb_dn); 609 return ldb_module_done(ac->req, NULL, NULL, ret); 610 } 611 if (remove_value && 612 !ldb_request_get_control(req, LDB_CONTROL_REVEAL_INTERNALS)) { 613 /* we show these with REVEAL 614 to allow dbcheck to find and 615 cleanup these orphaned links */ 616 memmove(&msg->elements[i].values[j], 617 &msg->elements[i].values[j+1], 618 (msg->elements[i].num_values-(j+1))*sizeof(struct ldb_val)); 619 msg->elements[i].num_values--; 620 j--; 621 continue; 622 } 623 } 547 624 548 625 if (make_extended_dn) { … … 602 679 struct ldb_context *ldb = ldb_module_get_ctx(module); 603 680 int ret; 604 bool critical;605 681 606 682 struct extended_dn_out_private *p = talloc_get_type(ldb_module_get_private(module), struct extended_dn_out_private); … … 701 777 /* mark extended DN and storage format controls as done */ 702 778 if (control) { 703 critical = control->critical;704 779 control->critical = 0; 705 780 } -
vendor/current/source4/dsdb/samdb/ldb_modules/extended_dn_store.c
r740 r988 277 277 278 278 ret = dsdb_request_add_controls(os->search_req, 279 DSDB_SEARCH_SHOW_RECYCLED|DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT); 279 DSDB_FLAG_AS_SYSTEM | 280 DSDB_SEARCH_SHOW_RECYCLED | 281 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT); 280 282 if (ret != LDB_SUCCESS) { 281 283 talloc_free(os); … … 326 328 327 329 /* We only setup an extended DN GUID on DN elements */ 328 if ( dsdb_dn_oid_to_format(schema_attr->syntax->ldap_oid)== DSDB_INVALID_DN) {330 if (schema_attr->dn_format == DSDB_INVALID_DN) { 329 331 continue; 330 332 } … … 401 403 402 404 /* We only setup an extended DN GUID on these particular DN objects */ 403 if ( dsdb_dn_oid_to_format(schema_attr->syntax->ldap_oid)== DSDB_INVALID_DN) {405 if (schema_attr->dn_format == DSDB_INVALID_DN) { 404 406 continue; 405 407 } -
vendor/current/source4/dsdb/samdb/ldb_modules/instancetype.c
r740 r988 78 78 /* 79 79 * If we have a NC add operation then we need also the 80 * "TYPE_WRITE" flag in order to succeed. 81 */ 82 if (!(instanceType & INSTANCE_TYPE_WRITE)) { 83 ldb_set_errstring(ldb, "instancetype: if TYPE_IS_NC_HEAD was set, then also TYPE_WRITE is requested!"); 84 return LDB_ERR_UNWILLING_TO_PERFORM; 80 * "TYPE_WRITE" flag in order to succeed, 81 * unless this NC is not instantiated 82 */ 83 if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) { 84 if (!(instanceType & INSTANCE_TYPE_UNINSTANT)) { 85 ldb_set_errstring(ldb, "instancetype: if TYPE_IS_NC_HEAD " 86 "was set, and we are creating a new NC " 87 "over DsAddEntry then also TYPE_UNINSTANT is requested!"); 88 return LDB_ERR_UNWILLING_TO_PERFORM; 89 } 90 } else { 91 if (!(instanceType & INSTANCE_TYPE_WRITE)) { 92 ldb_set_errstring(ldb, "instancetype: if TYPE_IS_NC_HEAD " 93 "was set, then also TYPE_WRITE is requested!"); 94 return LDB_ERR_UNWILLING_TO_PERFORM; 95 } 85 96 } 97 98 /* 99 * TODO: Confirm we are naming master or start 100 * a remote call to the naming master to 101 * create the crossRef object 102 */ 86 103 } 87 104 … … 135 152 el = ldb_msg_find_element(req->op.mod.message, "instanceType"); 136 153 if (el != NULL) { 137 ldb_set_errstring(ldb, "instancetype: the 'instanceType' attribute can never be changed!"); 138 return LDB_ERR_CONSTRAINT_VIOLATION; 154 /* Except to allow dbcheck to fix things, this must never be modified */ 155 if (!ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) { 156 ldb_set_errstring(ldb, "instancetype: the 'instanceType' attribute can never be changed!"); 157 return LDB_ERR_CONSTRAINT_VIOLATION; 158 } 139 159 } 140 141 160 return ldb_next_request(module, req); 142 161 } -
vendor/current/source4/dsdb/samdb/ldb_modules/linked_attributes.c
r740 r988 4 4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007 5 5 Copyright (C) Simo Sorce <idra@samba.org> 2008 6 Copyright (C) Matthieu Patou <mat@matws.net> 2011 7 Copyright (C) Andrew Tridgell 2009 6 8 7 9 This program is free software; you can redistribute it and/or modify … … 46 48 struct GUID guid; 47 49 char *name; 48 char *value;49 50 }; 50 51 … … 60 61 struct ldb_module *module; 61 62 struct ldb_request *req; 62 struct ldb_dn *add_dn; 63 struct ldb_dn *del_dn; 63 struct ldb_dn *mod_dn; 64 64 struct replace_context *rc; 65 65 struct la_op_store *ops; 66 66 struct ldb_extended *op_response; 67 67 struct ldb_control **op_controls; 68 /* 69 * For futur use 70 * will tell which GC to use for resolving links 71 */ 72 char *gc_dns_name; 68 73 }; 74 75 76 static int handle_verify_name_control(TALLOC_CTX *ctx, struct ldb_context *ldb, 77 struct ldb_control *control, struct la_context *ac) 78 { 79 /* 80 * If we are a GC let's remove the control, 81 * if there is a specified GC check that is us. 82 */ 83 struct ldb_verify_name_control *lvnc = (struct ldb_verify_name_control *)control->data; 84 if (samdb_is_gc(ldb)) { 85 /* Because we can't easily talloc a struct ldb_dn*/ 86 struct ldb_dn **dn = talloc_array(ctx, struct ldb_dn *, 1); 87 int ret = samdb_server_reference_dn(ldb, ctx, dn); 88 const char *dns; 89 90 if (ret != LDB_SUCCESS) { 91 return ldb_operr(ldb); 92 } 93 94 dns = samdb_dn_to_dnshostname(ldb, ctx, *dn); 95 if (!dns) { 96 return ldb_operr(ldb); 97 } 98 if (!lvnc->gc || strcasecmp(dns, lvnc->gc) == 0) { 99 if (!ldb_save_controls(control, ctx, NULL)) { 100 return ldb_operr(ldb); 101 } 102 } else { 103 control->critical = true; 104 } 105 talloc_free(dn); 106 } else { 107 /* For the moment we don't remove the control is this case in order 108 * to fail the request. It's better than having the client thinking 109 * that we honnor its control. 110 * Hopefully only a very small set of usecase should hit this problem. 111 */ 112 if (lvnc->gc) { 113 ac->gc_dns_name = talloc_strdup(ac, lvnc->gc); 114 } 115 control->critical = true; 116 } 117 118 return LDB_SUCCESS; 119 } 69 120 70 121 static struct la_context *linked_attributes_init(struct ldb_module *module, … … 92 143 turn a DN into a GUID 93 144 */ 94 static int la_guid_from_dn(struct la_context *ac, struct ldb_dn *dn, struct GUID *guid) 145 static int la_guid_from_dn(struct ldb_module *module, 146 struct ldb_request *parent, 147 struct ldb_dn *dn, struct GUID *guid) 95 148 { 96 149 NTSTATUS status; … … 104 157 DEBUG(4,(__location__ ": Unable to parse GUID for dn %s\n", 105 158 ldb_dn_get_linearized(dn))); 106 return ldb_operr(ldb_module_get_ctx( ac->module));107 } 108 109 ret = dsdb_ find_guid_by_dn(ldb_module_get_ctx(ac->module), dn, guid);159 return ldb_operr(ldb_module_get_ctx(module)); 160 } 161 162 ret = dsdb_module_guid_by_dn(module, dn, guid, parent); 110 163 if (ret != LDB_SUCCESS) { 111 164 DEBUG(4,(__location__ ": Failed to find GUID for dn %s\n", … … 144 197 os->op = op; 145 198 146 ret = la_guid_from_dn(ac , op_dn, &os->guid);199 ret = la_guid_from_dn(ac->module, ac->req, op_dn, &os->guid); 147 200 talloc_free(op_dn); 148 201 if (ret == LDB_ERR_NO_SUCH_OBJECT && ac->req->operation == LDB_DELETE) { … … 167 220 /* Do deletes before adds */ 168 221 if (op == LA_OP_ADD) { 169 DLIST_ADD_END(ac->ops, os , struct la_op_store *);222 DLIST_ADD_END(ac->ops, os); 170 223 } else { 171 224 /* By adding to the head of the list, we do deletes before … … 191 244 struct ldb_control *ctrl; 192 245 unsigned int i, j; 246 struct ldb_control *control; 193 247 int ret; 194 248 … … 200 254 } 201 255 202 if (!(ctrl = ldb_request_get_control(req, DSDB_CONTROL_APPLY_LINKS))) {203 /* don't do anything special for linked attributes, repl_meta_data has done it */204 return ldb_next_request(module, req);205 }206 ctrl->critical = false;207 208 256 ac = linked_attributes_init(module, req); 209 257 if (!ac) { 210 258 return ldb_operr(ldb); 211 259 } 260 261 control = ldb_request_get_control(req, LDB_CONTROL_VERIFY_NAME_OID); 262 if (control != NULL && control->data != NULL) { 263 ret = handle_verify_name_control(req, ldb, control, ac); 264 if (ret != LDB_SUCCESS) { 265 return ldb_operr(ldb); 266 } 267 } 268 269 if (!(ctrl = ldb_request_get_control(req, DSDB_CONTROL_APPLY_LINKS))) { 270 /* don't do anything special for linked attributes, repl_meta_data has done it */ 271 talloc_free(ac); 272 return ldb_next_request(module, req); 273 } 274 ctrl->critical = false; 212 275 213 276 if (!ac->schema) { … … 216 279 return ldb_next_request(module, req); 217 280 } 281 218 282 219 283 /* Need to ensure we only have forward links being specified */ … … 229 293 return LDB_ERR_OBJECT_CLASS_VIOLATION; 230 294 } 231 /* We have a valid attribute, now find out if it is a forward link */ 232 if ((schema_attr->linkID == 0)) { 295 296 /* this could be a link with no partner, in which case 297 there is no special work to do */ 298 if (schema_attr->linkID == 0) { 233 299 continue; 234 300 } 235 301 236 if ((schema_attr->linkID & 1) == 1) { 237 unsigned int functional_level; 238 239 functional_level = dsdb_functional_level(ldb); 240 SMB_ASSERT(functional_level > DS_DOMAIN_FUNCTION_2000); 241 } 302 /* this part of the code should only be handling forward links */ 303 SMB_ASSERT((schema_attr->linkID & 1) == 0); 242 304 243 305 /* Even link IDs are for the originating attribute */ 244 target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID +1);306 target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID ^ 1); 245 307 if (!target_attr) { 246 308 /* … … 320 382 } 321 383 322 ac-> add_dn = ac->del_dn = talloc_steal(ac, ares->message->dn);384 ac->mod_dn = talloc_steal(ac, ares->message->dn); 323 385 324 386 /* We don't populate 'rc' for ADD - it can't be deleting elements anyway */ … … 346 408 } 347 409 348 target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID +1);410 target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID ^ 1); 349 411 if (!target_attr) { 350 412 /* … … 413 475 /* Apply the modify to the linked entry */ 414 476 477 struct ldb_control *control; 415 478 struct ldb_context *ldb; 416 479 unsigned int i, j; … … 428 491 } 429 492 430 if (!(ctrl = ldb_request_get_control(req, DSDB_CONTROL_APPLY_LINKS))) {431 /* don't do anything special for linked attributes, repl_meta_data has done it */432 return ldb_next_request(module, req);433 }434 ctrl->critical = false;435 436 493 ac = linked_attributes_init(module, req); 437 494 if (!ac) { 438 495 return ldb_operr(ldb); 439 496 } 497 498 control = ldb_request_get_control(req, LDB_CONTROL_VERIFY_NAME_OID); 499 if (control != NULL && control->data != NULL) { 500 ret = handle_verify_name_control(req, ldb, control, ac); 501 if (ret != LDB_SUCCESS) { 502 return ldb_operr(ldb); 503 } 504 } 505 506 if (!(ctrl = ldb_request_get_control(req, DSDB_CONTROL_APPLY_LINKS))) { 507 /* don't do anything special for linked attributes, repl_meta_data has done it */ 508 talloc_free(ac); 509 return ldb_next_request(module, req); 510 } 511 ctrl->critical = false; 440 512 441 513 if (!ac->schema) { … … 469 541 } 470 542 471 if ((schema_attr->linkID & 1) == 1) { 472 unsigned int functional_level; 473 474 functional_level = dsdb_functional_level(ldb); 475 SMB_ASSERT(functional_level > DS_DOMAIN_FUNCTION_2000); 476 } 543 /* this part of the code should only be handling forward links */ 544 SMB_ASSERT((schema_attr->linkID & 1) == 0); 545 477 546 /* Now find the target attribute */ 478 target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID +1);547 target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID ^ 1); 479 548 if (!target_attr) { 480 549 /* … … 573 642 /* We need to figure out our own extended DN, to fill in as the backlink target */ 574 643 if (ret == LDB_SUCCESS) { 575 ret = ldb_request_add_control(search_req,576 LDB_CONTROL_EXTENDED_DN_OID,577 false, NULL);644 ret = dsdb_request_add_controls(search_req, 645 DSDB_SEARCH_SHOW_RECYCLED | 646 DSDB_SEARCH_SHOW_EXTENDED_DN); 578 647 } 579 648 if (ret == LDB_SUCCESS) { … … 593 662 594 663 static int linked_attributes_fix_links(struct ldb_module *module, 664 struct GUID self_guid, 595 665 struct ldb_dn *old_dn, struct ldb_dn *new_dn, 596 666 struct ldb_message_element *el, struct dsdb_schema *schema, … … 619 689 struct ldb_message *msg; 620 690 struct ldb_message_element *el2; 691 struct GUID link_guid; 621 692 622 693 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &el->values[i], schema_attr->syntax->ldap_oid); … … 626 697 } 627 698 628 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dsdb_dn->dn, 629 attrs, 630 DSDB_FLAG_NEXT_MODULE | 631 DSDB_SEARCH_SHOW_RECYCLED | 632 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT | 633 DSDB_SEARCH_REVEAL_INTERNALS, parent); 699 ret = la_guid_from_dn(module, parent, dsdb_dn->dn, &link_guid); 634 700 if (ret != LDB_SUCCESS) { 635 ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - remotenot found - %s",701 ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - GUID not found - %s", 636 702 el->name, target->lDAPDisplayName, 637 703 ldb_dn_get_linearized(old_dn), … … 641 707 return ret; 642 708 } 709 710 /* 711 * get the existing message from the db for the object with 712 * this GUID, returning attribute being modified. We will then 713 * use this msg as the basis for a modify call 714 */ 715 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs, 716 DSDB_FLAG_NEXT_MODULE | 717 DSDB_SEARCH_SEARCH_ALL_PARTITIONS | 718 DSDB_SEARCH_SHOW_RECYCLED | 719 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT | 720 DSDB_SEARCH_REVEAL_INTERNALS, 721 parent, 722 "objectGUID=%s", GUID_string(tmp_ctx, &link_guid)); 723 if (ret != LDB_SUCCESS) { 724 ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - target GUID %s not found - %s", 725 el->name, target->lDAPDisplayName, 726 ldb_dn_get_linearized(old_dn), 727 ldb_dn_get_linearized(dsdb_dn->dn), 728 GUID_string(tmp_ctx, &link_guid), 729 ldb_errstring(ldb)); 730 talloc_free(tmp_ctx); 731 return ret; 732 } 733 if (res->count == 0) { 734 /* Forward link without backlink object remaining - nothing to do here */ 735 continue; 736 } 737 if (res->count != 1) { 738 ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - target GUID %s found more than once!", 739 el->name, target->lDAPDisplayName, 740 ldb_dn_get_linearized(old_dn), 741 ldb_dn_get_linearized(dsdb_dn->dn), 742 GUID_string(tmp_ctx, &link_guid)); 743 talloc_free(tmp_ctx); 744 return LDB_ERR_OPERATIONS_ERROR; 745 } 746 643 747 msg = res->msgs[0]; 644 748 … … 664 768 for (j=0; j<el2->num_values; j++) { 665 769 struct dsdb_dn *dsdb_dn2; 770 struct GUID link_guid2; 771 666 772 dsdb_dn2 = dsdb_dn_parse(msg, ldb, &el2->values[j], target->syntax->ldap_oid); 667 773 if (dsdb_dn2 == NULL) { … … 669 775 return LDB_ERR_INVALID_DN_SYNTAX; 670 776 } 671 if (ldb_dn_compare(old_dn, dsdb_dn2->dn) != 0) { 777 778 ret = la_guid_from_dn(module, parent, dsdb_dn2->dn, &link_guid2); 779 if (ret != LDB_SUCCESS) { 780 talloc_free(tmp_ctx); 781 return ret; 782 } 783 784 /* 785 * By comparing using the GUID we ensure that 786 * even if somehow the name has got out of 787 * sync, this rename will fix it. 788 * 789 * If somehow we don't have a GUID on the DN 790 * in the DB, the la_guid_from_dn call will be 791 * more costly, but still give us a GUID. 792 * dbcheck will fix this if run. 793 */ 794 if (!GUID_equal(&self_guid, &link_guid2)) { 672 795 continue; 673 796 } 797 674 798 ret = ldb_dn_update_components(dsdb_dn2->dn, new_dn); 675 799 if (ret != LDB_SUCCESS) { … … 718 842 struct dsdb_schema *schema; 719 843 int ret; 844 struct GUID guid; 845 720 846 /* 721 847 - load the current msg … … 727 853 NULL, 728 854 DSDB_FLAG_NEXT_MODULE | 855 DSDB_SEARCH_SHOW_EXTENDED_DN | 729 856 DSDB_SEARCH_SHOW_RECYCLED, req); 730 857 if (ret != LDB_SUCCESS) { … … 738 865 739 866 msg = res->msgs[0]; 867 868 ret = la_guid_from_dn(module, req, msg->dn, &guid); 869 if (ret != LDB_SUCCESS) { 870 return ret; 871 } 740 872 741 873 for (i=0; i<msg->num_elements; i++) { … … 746 878 continue; 747 879 } 748 ret = linked_attributes_fix_links(module, msg->dn, req->op.rename.newdn, el,880 ret = linked_attributes_fix_links(module, guid, msg->dn, req->op.rename.newdn, el, 749 881 schema, schema_attr, req); 750 882 if (ret != LDB_SUCCESS) { … … 868 1000 869 1001 if (ret == LDB_SUCCESS) { 870 ret = ldb_request_add_control(search_req,871 LDB_CONTROL_EXTENDED_DN_OID,872 false, NULL);1002 ret = dsdb_request_add_controls(search_req, 1003 DSDB_SEARCH_SHOW_RECYCLED | 1004 DSDB_SEARCH_SHOW_EXTENDED_DN); 873 1005 } 874 1006 if (ret != LDB_SUCCESS) { … … 931 1063 struct GUID *guid, struct ldb_dn **dn) 932 1064 { 933 return dsdb_ find_dn_by_guid(ldb_module_get_ctx(ac->module), ac, guid, dn);1065 return dsdb_module_dn_by_guid(ac->module, ac, guid, dn, ac->req); 934 1066 } 935 1067 … … 941 1073 struct ldb_context *ldb; 942 1074 int ret; 1075 1076 if (ac->mod_dn == NULL) { 1077 /* we didn't find the DN that we searched for */ 1078 return LDB_SUCCESS; 1079 } 943 1080 944 1081 ldb = ldb_module_get_ctx(ac->module); … … 970 1107 } 971 1108 ret_el->num_values = 1; 972 if (op->op == LA_OP_ADD) { 973 ret_el->values[0] = data_blob_string_const(ldb_dn_get_extended_linearized(new_msg, ac->add_dn, 1)); 974 } else { 975 ret_el->values[0] = data_blob_string_const(ldb_dn_get_extended_linearized(new_msg, ac->del_dn, 1)); 976 } 1109 ret_el->values[0] = data_blob_string_const(ldb_dn_get_extended_linearized(new_msg, ac->mod_dn, 1)); 977 1110 978 1111 /* a backlink should never be single valued. Unfortunately the … … 997 1130 ret = dsdb_module_modify(module, new_msg, DSDB_FLAG_NEXT_MODULE, ac->req); 998 1131 if (ret != LDB_SUCCESS) { 999 ldb_debug(ldb, LDB_DEBUG_WARNING, "Failed to apply linked attribute change '%s'\n%s\n",1132 ldb_debug(ldb, LDB_DEBUG_WARNING, __location__ ": failed to apply linked attribute change '%s'\n%s\n", 1000 1133 ldb_errstring(ldb), 1001 1134 ldb_ldif_message_string(ldb, op, LDB_CHANGETYPE_MODIFY, new_msg)); … … 1095 1228 } 1096 1229 1230 static int linked_attributes_ldb_init(struct ldb_module *module) 1231 { 1232 int ret; 1233 1234 ret = ldb_mod_register_control(module, LDB_CONTROL_VERIFY_NAME_OID); 1235 if (ret != LDB_SUCCESS) { 1236 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR, 1237 "verify_name: Unable to register control with rootdse!\n"); 1238 return ldb_operr(ldb_module_get_ctx(module)); 1239 } 1240 1241 return ldb_next_init(module); 1242 } 1243 1097 1244 1098 1245 static const struct ldb_module_ops ldb_linked_attributes_module_ops = { … … 1101 1248 .modify = linked_attributes_modify, 1102 1249 .rename = linked_attributes_rename, 1250 .init_context = linked_attributes_ldb_init, 1103 1251 .start_transaction = linked_attributes_start_transaction, 1104 1252 .prepare_commit = linked_attributes_prepare_commit, -
vendor/current/source4/dsdb/samdb/ldb_modules/local_password.c
r740 r988 44 44 45 45 This allows the password database to be synchronised in a multi-master 46 fashion, sep erate to the more difficult concerns of the main46 fashion, separate to the more difficult concerns of the main 47 47 database. (With passwords, the last writer always wins) 48 48 … … 182 182 } 183 183 184 remote_message = ldb_msg_copy_shallow( remote_req, req->op.add.message);184 remote_message = ldb_msg_copy_shallow(ac, req->op.add.message); 185 185 if (remote_message == NULL) { 186 186 return ldb_operr(ldb); -
vendor/current/source4/dsdb/samdb/ldb_modules/new_partition.c
r740 r988 37 37 #include "dsdb/samdb/samdb.h" 38 38 #include "../libds/common/flags.h" 39 #include "dsdb/common/util.h" 39 40 40 41 struct np_context { … … 65 66 66 67 if (ares->type != LDB_REPLY_DONE) { 67 ldb_ set_errstring(ldb, "Invalid reply type!");68 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type); 68 69 return ldb_module_done(ac->req, NULL, NULL, 69 70 LDB_ERR_OPERATIONS_ERROR); … … 123 124 ldb, ac, DSDB_EXTENDED_CREATE_PARTITION_OID, ex_op, 124 125 NULL, ac, np_part_mod_callback, req); 126 127 /* if the parent was asking for a partial replica, then we 128 * need the extended operation to also ask for a partial 129 * replica */ 130 if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) { 131 ret = dsdb_request_add_controls(ac->part_add, DSDB_MODIFY_PARTIAL_REPLICA); 132 if (ret != LDB_SUCCESS) { 133 return ret; 134 } 135 } 136 125 137 126 138 LDB_REQ_SET_LOCATION(ac->part_add); … … 154 166 155 167 if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) { 156 return ldb_next_request(module, req);157 }158 159 if (instanceType & INSTANCE_TYPE_UNINSTANT) {160 DEBUG(0,(__location__ ": Skipping uninstantiated partition %s\n",161 ldb_dn_get_linearized(req->op.add.message->dn)));162 168 return ldb_next_request(module, req); 163 169 } -
vendor/current/source4/dsdb/samdb/ldb_modules/objectclass.c
r740 r988 4 4 Copyright (C) Simo Sorce 2006-2008 5 5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2009 6 Copyright (C) Matthias Dieter Wallnöfer 2010 6 Copyright (C) Matthias Dieter Wallnöfer 2010-2011 7 7 8 8 This program is free software; you can redistribute it and/or modify … … 38 38 #include "includes.h" 39 39 #include "ldb_module.h" 40 #include "util/dlinklist.h"41 40 #include "dsdb/samdb/samdb.h" 42 41 #include "librpc/ndr/libndr.h" … … 46 45 #include "param/param.h" 47 46 #include "../libds/common/flags.h" 48 #include "dsdb/samdb/ldb_modules/schema.h" 49 #include "util.h" 47 #include "dsdb/samdb/ldb_modules/util.h" 50 48 51 49 struct oc_context { … … 59 57 60 58 int (*step_fn)(struct oc_context *); 61 };62 63 struct class_list {64 struct class_list *prev, *next;65 const struct dsdb_class *objectclass;66 59 }; 67 60 … … 89 82 static int objectclass_do_add(struct oc_context *ac); 90 83 91 /* Sort objectClasses into correct order, and validate that all 92 * objectClasses specified actually exist in the schema 84 /* 85 * This checks if we have unrelated object classes in our entry's "objectClass" 86 * attribute. That means "unsatisfied" abstract classes (no concrete subclass) 87 * or two or more disjunct structural ones. 88 * If one of these conditions are true, blame. 93 89 */ 94 95 static int objectclass_sort(struct ldb_module *module, 96 const struct dsdb_schema *schema, 97 TALLOC_CTX *mem_ctx, 98 struct ldb_message_element *objectclass_element, 99 struct class_list **sorted_out) 100 { 101 struct ldb_context *ldb; 102 unsigned int i, lowest; 103 struct class_list *unsorted = NULL, *sorted = NULL, *current = NULL, *poss_parent = NULL, *new_parent = NULL, *current_lowest = NULL; 104 105 ldb = ldb_module_get_ctx(module); 106 107 /* DESIGN: 108 * 109 * We work on 4 different 'bins' (implemented here as linked lists): 110 * 111 * * sorted: the eventual list, in the order we wish to push 112 * into the database. This is the only ordered list. 113 * 114 * * parent_class: The current parent class 'bin' we are 115 * trying to find subclasses for 116 * 117 * * subclass: The subclasses we have found so far 118 * 119 * * unsorted: The remaining objectClasses 120 * 121 * The process is a matter of filtering objectClasses up from 122 * unsorted into sorted. Order is irrelevent in the later 3 'bins'. 123 * 124 * We start with 'top' (found and promoted to parent_class 125 * initially). Then we find (in unsorted) all the direct 126 * subclasses of 'top'. parent_classes is concatenated onto 127 * the end of 'sorted', and subclass becomes the list in 128 * parent_class. 129 * 130 * We then repeat, until we find no more subclasses. Any left 131 * over classes are added to the end. 132 * 133 */ 134 135 /* Firstly, dump all the objectClass elements into the 136 * unsorted bin, except for 'top', which is special */ 137 for (i=0; i < objectclass_element->num_values; i++) { 138 current = talloc(mem_ctx, struct class_list); 139 if (!current) { 140 return ldb_oom(ldb); 141 } 142 current->objectclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &objectclass_element->values[i]); 143 if (!current->objectclass) { 144 ldb_asprintf_errstring(ldb, "objectclass %.*s is not a valid objectClass in schema", 145 (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data); 146 /* This looks weird, but windows apparently returns this for invalid objectClass values */ 147 return LDB_ERR_NO_SUCH_ATTRIBUTE; 148 } else if (current->objectclass->isDefunct) { 149 ldb_asprintf_errstring(ldb, "objectclass %.*s marked as isDefunct objectClass in schema - not valid for new objects", 150 (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data); 151 /* This looks weird, but windows apparently returns this for invalid objectClass values */ 152 return LDB_ERR_NO_SUCH_ATTRIBUTE; 153 } 154 155 /* Don't add top to list, we will do that later */ 156 if (ldb_attr_cmp("top", current->objectclass->lDAPDisplayName) != 0) { 157 DLIST_ADD_END(unsorted, current, struct class_list *); 158 } 159 } 160 161 /* Add top here, to prevent duplicates */ 162 current = talloc(mem_ctx, struct class_list); 163 current->objectclass = dsdb_class_by_lDAPDisplayName(schema, "top"); 164 DLIST_ADD_END(sorted, current, struct class_list *); 165 166 167 /* For each object: find parent chain */ 168 for (current = unsorted; schema && current; current = current->next) { 169 for (poss_parent = unsorted; poss_parent; poss_parent = poss_parent->next) { 170 if (ldb_attr_cmp(poss_parent->objectclass->lDAPDisplayName, current->objectclass->subClassOf) == 0) { 171 break; 172 } 173 } 174 /* If we didn't get to the end of the list, we need to add this parent */ 175 if (poss_parent || (ldb_attr_cmp("top", current->objectclass->subClassOf) == 0)) { 90 static int check_unrelated_objectclasses(struct ldb_module *module, 91 const struct dsdb_schema *schema, 92 const struct dsdb_class *struct_objectclass, 93 struct ldb_message_element *objectclass_element) 94 { 95 struct ldb_context *ldb = ldb_module_get_ctx(module); 96 unsigned int i; 97 bool found; 98 99 if (schema == NULL) { 100 return LDB_SUCCESS; 101 } 102 103 for (i = 0; i < objectclass_element->num_values; i++) { 104 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, 105 &objectclass_element->values[i]); 106 const struct dsdb_class *tmp_class2 = struct_objectclass; 107 108 /* Pointer comparison can be used due to the same schema str. */ 109 if (tmp_class == NULL || 110 tmp_class == struct_objectclass || 111 tmp_class->objectClassCategory > 2 || 112 ldb_attr_cmp(tmp_class->lDAPDisplayName, "top") == 0) { 176 113 continue; 177 114 } 178 115 179 new_parent = talloc(mem_ctx, struct class_list); 180 new_parent->objectclass = dsdb_class_by_lDAPDisplayName(schema, current->objectclass->subClassOf); 181 DLIST_ADD_END(unsorted, new_parent, struct class_list *); 182 } 183 184 do 185 { 186 lowest = UINT_MAX; 187 current_lowest = NULL; 188 for (current = unsorted; schema && current; current = current->next) { 189 if(current->objectclass->subClass_order < lowest) { 190 current_lowest = current; 191 lowest = current->objectclass->subClass_order; 192 } 193 } 194 195 if(current_lowest != NULL) { 196 DLIST_REMOVE(unsorted,current_lowest); 197 DLIST_ADD_END(sorted,current_lowest, struct class_list *); 198 } 199 } while(unsorted); 200 201 202 if (!unsorted) { 203 *sorted_out = sorted; 204 return LDB_SUCCESS; 205 } 206 207 if (!schema) { 208 /* If we don't have schema yet, then just merge the lists again */ 209 DLIST_CONCATENATE(sorted, unsorted, struct class_list *); 210 *sorted_out = sorted; 211 return LDB_SUCCESS; 212 } 213 214 /* This shouldn't happen, and would break MMC, perhaps there 215 * was no 'top', a conflict in the objectClasses or some other 216 * schema error? 217 */ 218 ldb_asprintf_errstring(ldb, "objectclass %s is not a valid objectClass in objectClass chain", unsorted->objectclass->lDAPDisplayName); 219 return LDB_ERR_OBJECT_CLASS_VIOLATION; 116 found = false; 117 while (!found && 118 ldb_attr_cmp(tmp_class2->lDAPDisplayName, "top") != 0) { 119 tmp_class2 = dsdb_class_by_lDAPDisplayName(schema, 120 tmp_class2->subClassOf); 121 if (tmp_class2 == tmp_class) { 122 found = true; 123 } 124 } 125 if (found) { 126 continue; 127 } 128 129 ldb_asprintf_errstring(ldb, 130 "objectclass: the objectclass '%s' seems to be unrelated to %s!", 131 tmp_class->lDAPDisplayName, 132 struct_objectclass->lDAPDisplayName); 133 return LDB_ERR_OBJECT_CLASS_VIOLATION; 134 } 135 136 return LDB_SUCCESS; 220 137 } 221 138 … … 270 187 } 271 188 272 static int oc_op_callback(struct ldb_request *req, struct ldb_reply *ares)273 {274 struct oc_context *ac;275 276 ac = talloc_get_type(req->context, struct oc_context);277 278 if (!ares) {279 return ldb_module_done(ac->req, NULL, NULL,280 LDB_ERR_OPERATIONS_ERROR);281 }282 283 if (ares->type == LDB_REPLY_REFERRAL) {284 return ldb_module_send_referral(ac->req, ares->referral);285 }286 287 if (ares->error != LDB_SUCCESS) {288 return ldb_module_done(ac->req, ares->controls,289 ares->response, ares->error);290 }291 292 if (ares->type != LDB_REPLY_DONE) {293 talloc_free(ares);294 return ldb_module_done(ac->req, NULL, NULL,295 LDB_ERR_OPERATIONS_ERROR);296 }297 298 return ldb_module_done(ac->req, ares->controls,299 ares->response, ares->error);300 }301 302 189 /* Fix up the DN to be in the standard form, taking particular care to match the parent DN 303 190 … … 355 242 356 243 357 /* And replace it with CN=foo (we need the attribute in upper case */244 /* And replace it with CN=foo (we need the attribute in upper case) */ 358 245 return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr, *rdn_val); 359 246 } 360 247 361 362 static int objectclass_do_add(struct oc_context *ac);363 248 364 249 static int objectclass_add(struct ldb_module *module, struct ldb_request *req) … … 436 321 } 437 322 323 ret = dsdb_request_add_controls(search_req, 324 DSDB_FLAG_AS_SYSTEM | 325 DSDB_SEARCH_SHOW_RECYCLED); 326 if (ret != LDB_SUCCESS) { 327 return ret; 328 } 329 438 330 ac->step_fn = objectclass_do_add; 439 331 … … 450 342 struct ldb_control *rodc_control; 451 343 452 if ( strcasecmp(objectclass->lDAPDisplayName, "nTDSDSA") != 0) {344 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSDSA") != 0) { 453 345 return false; 454 346 } … … 468 360 struct ldb_message_element *objectclass_element, *el; 469 361 struct ldb_message *msg; 470 TALLOC_CTX *mem_ctx;471 struct class_list *sorted, *current;472 362 const char *rdn_name = NULL; 473 363 char *value; … … 516 406 517 407 if (ac->schema != NULL) { 408 /* 409 * Notice: by the normalization function call in "ldb_request()" 410 * case "LDB_ADD" we have always only *one* "objectClass" 411 * attribute at this stage! 412 */ 413 518 414 objectclass_element = ldb_msg_find_element(msg, "objectClass"); 519 415 if (!objectclass_element) { … … 528 424 } 529 425 530 mem_ctx = talloc_new(ac); 531 if (mem_ctx == NULL) { 532 return ldb_module_oom(ac->module); 533 } 534 535 /* Here we do now get the "objectClass" list from the 536 * database. */ 537 ret = objectclass_sort(ac->module, ac->schema, mem_ctx, 538 objectclass_element, &sorted); 426 /* Now do the sorting */ 427 ret = dsdb_sort_objectClass_attr(ldb, ac->schema, 428 objectclass_element, msg, 429 objectclass_element); 539 430 if (ret != LDB_SUCCESS) { 540 talloc_free(mem_ctx);541 431 return ret; 542 432 } 543 544 ldb_msg_remove_element(msg, objectclass_element); 545 546 /* Well, now we shouldn't find any additional "objectClass" 547 * message element (required by the AD specification). */ 548 objectclass_element = ldb_msg_find_element(msg, "objectClass"); 549 if (objectclass_element != NULL) { 550 ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, only one 'objectclass' attribute specification is allowed!", 551 ldb_dn_get_linearized(msg->dn)); 552 talloc_free(mem_ctx); 553 return LDB_ERR_OBJECT_CLASS_VIOLATION; 554 } 555 556 /* We must completely replace the existing objectClass entry, 557 * because we need it sorted. */ 558 ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL); 559 if (ret != LDB_SUCCESS) { 560 talloc_free(mem_ctx); 561 return ret; 562 } 563 564 /* Move from the linked list back into an ldb msg */ 565 for (current = sorted; current; current = current->next) { 566 const char *objectclass_name = current->objectclass->lDAPDisplayName; 567 568 ret = ldb_msg_add_string(msg, "objectClass", objectclass_name); 569 if (ret != LDB_SUCCESS) { 570 ldb_set_errstring(ldb, 571 "objectclass: could not re-add sorted " 572 "objectclass to modify msg"); 573 talloc_free(mem_ctx); 574 return ret; 575 } 576 } 577 578 talloc_free(mem_ctx); 579 580 /* Retrive the message again so get_last_structural_class works */ 581 objectclass_element = ldb_msg_find_element(msg, "objectClass"); 582 583 /* Make sure its valid to add an object of this type */ 584 objectclass = get_last_structural_class(ac->schema, 585 objectclass_element, ac->req); 586 if(objectclass == NULL) { 433 434 /* 435 * Get the new top-most structural object class and check for 436 * unrelated structural classes 437 */ 438 objectclass = dsdb_get_last_structural_class(ac->schema, 439 objectclass_element); 440 if (objectclass == NULL) { 587 441 ldb_asprintf_errstring(ldb, 588 442 "Failed to find a structural class for %s", 589 443 ldb_dn_get_linearized(msg->dn)); 590 444 return LDB_ERR_UNWILLING_TO_PERFORM; 445 } 446 447 ret = check_unrelated_objectclasses(ac->module, ac->schema, 448 objectclass, 449 objectclass_element); 450 if (ret != LDB_SUCCESS) { 451 return ret; 591 452 } 592 453 … … 735 596 || ldb_attr_cmp(objectclass->lDAPDisplayName, "serversContainer") == 0 736 597 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSDSA") == 0) { 598 if (ldb_attr_cmp(objectclass->lDAPDisplayName, "site") == 0) 599 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME); 737 600 systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE); 738 739 601 } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0 602 || ldb_attr_cmp(objectclass->lDAPDisplayName, "subnet") == 0 740 603 || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0 741 604 || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) { 742 605 systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME); 743 606 } 744 745 607 /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */ 746 608 … … 763 625 } 764 626 765 ret = ldb_msg_sanity_check(ldb, msg);766 if (ret != LDB_SUCCESS) {767 return ret;768 }769 770 627 ret = ldb_build_add_req(&add_req, ldb, ac, 771 628 msg, 772 629 ac->req->controls, 773 ac , oc_op_callback,630 ac->req, dsdb_next_callback, 774 631 ac->req); 775 632 LDB_REQ_SET_LOCATION(add_req); … … 857 714 } 858 715 859 ret = ldb_build_mod_req(&down_req, ldb, ac, 860 msg, 861 req->controls, ac, 862 oc_changes ? oc_modify_callback : oc_op_callback, 863 req); 716 if (oc_changes) { 717 ret = ldb_build_mod_req(&down_req, ldb, ac, 718 msg, 719 req->controls, ac, 720 oc_modify_callback, 721 req); 722 } else { 723 ret = ldb_build_mod_req(&down_req, ldb, ac, 724 msg, 725 req->controls, req, 726 dsdb_next_callback, 727 req); 728 } 864 729 LDB_REQ_SET_LOCATION(down_req); 865 730 if (ret != LDB_SUCCESS) { … … 917 782 } 918 783 784 ret = dsdb_request_add_controls(search_req, 785 DSDB_FLAG_AS_SYSTEM | 786 DSDB_SEARCH_SHOW_RECYCLED); 787 if (ret != LDB_SUCCESS) { 788 return ldb_module_done(ac->req, NULL, NULL, ret); 789 } 790 919 791 ac->step_fn = objectclass_do_mod; 920 792 … … 931 803 struct ldb_context *ldb; 932 804 struct ldb_request *mod_req; 933 char *value;934 805 struct ldb_message_element *oc_el_entry, *oc_el_change; 935 806 struct ldb_val *vals; 936 807 struct ldb_message *msg; 937 TALLOC_CTX *mem_ctx;938 struct class_list *sorted, *current;939 808 const struct dsdb_class *objectclass; 940 809 unsigned int i, j, k; 941 bool found , replace = false;810 bool found; 942 811 int ret; 943 812 … … 963 832 964 833 msg->dn = ac->req->op.mod.message->dn; 965 966 mem_ctx = talloc_new(ac);967 if (mem_ctx == NULL) {968 return ldb_module_oom(ac->module);969 }970 834 971 835 /* We've to walk over all "objectClass" message elements */ … … 989 853 (int)oc_el_change->values[i].length, 990 854 (const char *)oc_el_change->values[i].data); 991 talloc_free(mem_ctx);992 855 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 993 856 } … … 999 862 oc_el_entry->num_values + 1); 1000 863 if (vals == NULL) { 1001 talloc_free(mem_ctx);1002 864 return ldb_module_oom(ac->module); 1003 865 } … … 1008 870 } 1009 871 1010 objectclass = get_last_structural_class(ac->schema,1011 oc_el_change, ac->req);1012 if (objectclass != NULL) {1013 ldb_asprintf_errstring(ldb,1014 "objectclass: cannot add a new top-most structural objectclass '%s'!",1015 objectclass->lDAPDisplayName);1016 talloc_free(mem_ctx);1017 return LDB_ERR_OBJECT_CLASS_VIOLATION;1018 }1019 1020 /* Now do the sorting */1021 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,1022 oc_el_entry, &sorted);1023 if (ret != LDB_SUCCESS) {1024 talloc_free(mem_ctx);1025 return ret;1026 }1027 1028 872 break; 1029 873 1030 874 case LDB_FLAG_MOD_REPLACE: 1031 /* Do the sorting for the change message element */ 1032 ret = objectclass_sort(ac->module, ac->schema, mem_ctx, 1033 oc_el_change, &sorted); 1034 if (ret != LDB_SUCCESS) { 1035 talloc_free(mem_ctx); 1036 return ret; 1037 } 1038 1039 /* this is a replace */ 1040 replace = true; 875 /* 876 * In this case the new "oc_el_entry" is simply 877 * "oc_el_change" 878 */ 879 oc_el_entry = oc_el_change; 1041 880 1042 881 break; 1043 882 1044 883 case LDB_FLAG_MOD_DELETE: 1045 /* get the actual top-most structural objectclass */1046 objectclass = get_last_structural_class(ac->schema,1047 oc_el_entry, ac->req);1048 if (objectclass == NULL) {1049 /* no structural objectclass? */1050 talloc_free(mem_ctx);1051 return ldb_operr(ldb);1052 }1053 1054 884 /* Merge the two message elements */ 1055 885 for (i = 0; i < oc_el_change->num_values; i++) { … … 1078 908 (int)oc_el_change->values[i].length, 1079 909 (const char *)oc_el_change->values[i].data); 1080 talloc_free(mem_ctx);1081 910 return LDB_ERR_NO_SUCH_ATTRIBUTE; 1082 911 } 1083 912 } 1084 913 1085 /* Make sure that the top-most structural object class1086 * hasn't been deleted */1087 found = false;1088 for (i = 0; i < oc_el_entry->num_values; i++) {1089 if (ldb_attr_cmp(objectclass->lDAPDisplayName,1090 (char *)oc_el_entry->values[i].data) == 0) {1091 found = true;1092 break;1093 }1094 }1095 if (!found) {1096 ldb_asprintf_errstring(ldb,1097 "objectclass: cannot delete the top-most structural objectclass '%s'!",1098 objectclass->lDAPDisplayName);1099 talloc_free(mem_ctx);1100 return LDB_ERR_OBJECT_CLASS_VIOLATION;1101 }1102 1103 /* Now do the sorting */1104 ret = objectclass_sort(ac->module, ac->schema, mem_ctx,1105 oc_el_entry, &sorted);1106 if (ret != LDB_SUCCESS) {1107 talloc_free(mem_ctx);1108 return ret;1109 }1110 1111 914 break; 1112 915 } 1113 916 1114 /* (Re)-add an empty "objectClass" attribute on the object 1115 * classes change message "msg". */ 1116 ldb_msg_remove_attr(msg, "objectClass"); 1117 ret = ldb_msg_add_empty(msg, "objectClass", 1118 LDB_FLAG_MOD_REPLACE, &oc_el_change); 917 /* Now do the sorting */ 918 ret = dsdb_sort_objectClass_attr(ldb, ac->schema, oc_el_entry, 919 msg, oc_el_entry); 1119 920 if (ret != LDB_SUCCESS) { 1120 talloc_free(mem_ctx);1121 921 return ret; 1122 922 } 1123 923 1124 /* Move from the linked list back into an ldb msg */ 1125 for (current = sorted; current; current = current->next) { 1126 value = talloc_strdup(msg, 1127 current->objectclass->lDAPDisplayName); 1128 if (value == NULL) { 1129 talloc_free(mem_ctx); 1130 return ldb_module_oom(ac->module); 1131 } 1132 ret = ldb_msg_add_string(msg, "objectClass", value); 1133 if (ret != LDB_SUCCESS) { 1134 ldb_set_errstring(ldb, 1135 "objectclass: could not re-add sorted objectclasses!"); 1136 talloc_free(mem_ctx); 1137 return ret; 1138 } 1139 } 1140 1141 if (replace) { 1142 /* Well, on replace we are nearly done: we have to test 1143 * if the change and entry message element are identical 1144 * ly. We can use "ldb_msg_element_compare" since now 1145 * the specified objectclasses match for sure in case. 1146 */ 1147 ret = ldb_msg_element_compare(oc_el_entry, 1148 oc_el_change); 1149 if (ret == 0) { 1150 ret = ldb_msg_element_compare(oc_el_change, 1151 oc_el_entry); 1152 } 1153 if (ret == 0) { 1154 /* they are the same so we are done in this 1155 * case */ 1156 talloc_free(mem_ctx); 1157 return ldb_module_done(ac->req, NULL, NULL, 1158 LDB_SUCCESS); 1159 } else { 1160 ldb_set_errstring(ldb, 1161 "objectclass: the specified objectclasses are not exactly the same as on the entry!"); 1162 talloc_free(mem_ctx); 1163 return LDB_ERR_OBJECT_CLASS_VIOLATION; 1164 } 1165 } 1166 1167 /* Now we've applied all changes from "oc_el_change" to 1168 * "oc_el_entry" therefore the new "oc_el_entry" will be 1169 * "oc_el_change". */ 1170 oc_el_entry = oc_el_change; 1171 } 1172 1173 talloc_free(mem_ctx); 924 /* 925 * Get the new top-most structural object class and check for 926 * unrelated structural classes 927 */ 928 objectclass = dsdb_get_last_structural_class(ac->schema, 929 oc_el_entry); 930 if (objectclass == NULL) { 931 ldb_set_errstring(ldb, 932 "objectclass: cannot delete all structural objectclasses!"); 933 return LDB_ERR_OBJECT_CLASS_VIOLATION; 934 } 935 936 /* Check for unrelated objectclasses */ 937 ret = check_unrelated_objectclasses(ac->module, ac->schema, 938 objectclass, 939 oc_el_entry); 940 if (ret != LDB_SUCCESS) { 941 return ret; 942 } 943 } 944 945 /* Now add the new object class attribute to the change message */ 946 ret = ldb_msg_add(msg, oc_el_entry, LDB_FLAG_MOD_REPLACE); 947 if (ret != LDB_SUCCESS) { 948 ldb_module_oom(ac->module); 949 return ret; 950 } 1174 951 1175 952 /* Now we have the real and definitive change left to do */ … … 1178 955 msg, 1179 956 ac->req->controls, 1180 ac , oc_op_callback,957 ac->req, dsdb_next_callback, 1181 958 ac->req); 1182 959 LDB_REQ_SET_LOCATION(mod_req); … … 1236 1013 deletes will be refused as we will think the target parent 1237 1014 does not exist */ 1238 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,1239 false, NULL);1240 1015 ret = dsdb_request_add_controls(search_req, 1016 DSDB_FLAG_AS_SYSTEM | 1017 DSDB_SEARCH_SHOW_RECYCLED); 1241 1018 if (ret != LDB_SUCCESS) { 1242 1019 return ret; … … 1286 1063 } 1287 1064 1065 ret = dsdb_request_add_controls(search_req, 1066 DSDB_FLAG_AS_SYSTEM | 1067 DSDB_SEARCH_SHOW_RECYCLED); 1068 if (ret != LDB_SUCCESS) { 1069 return ret; 1070 } 1071 1288 1072 ac->step_fn = objectclass_do_rename2; 1289 1073 … … 1322 1106 return ldb_operr(ldb); 1323 1107 } 1324 objectclass = get_last_structural_class(ac->schema, oc_el_entry, ac->req); 1108 objectclass = dsdb_get_last_structural_class(ac->schema, 1109 oc_el_entry); 1325 1110 if (objectclass == NULL) { 1326 1111 /* existing entry without a valid object class? */ … … 1408 1193 ac->req->op.rename.olddn, fixed_dn, 1409 1194 ac->req->controls, 1410 ac , oc_op_callback,1195 ac->req, dsdb_next_callback, 1411 1196 ac->req); 1412 1197 LDB_REQ_SET_LOCATION(rename_req); … … 1425 1210 static const char * const attrs[] = { "nCName", "objectClass", 1426 1211 "systemFlags", 1212 "isDeleted", 1427 1213 "isCriticalSystemObject", NULL }; 1428 1214 struct ldb_context *ldb; … … 1464 1250 } 1465 1251 1252 ret = dsdb_request_add_controls(search_req, 1253 DSDB_FLAG_AS_SYSTEM | 1254 DSDB_SEARCH_SHOW_RECYCLED); 1255 if (ret != LDB_SUCCESS) { 1256 return ret; 1257 } 1258 1466 1259 ac->step_fn = objectclass_do_delete; 1467 1260 … … 1488 1281 1489 1282 /* DC's ntDSDSA object */ 1490 if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb )) == 0) {1283 if (ldb_dn_compare(ac->req->op.del.dn, samdb_ntds_settings_dn(ldb, ac)) == 0) { 1491 1284 ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!", 1492 1285 ldb_dn_get_linearized(ac->req->op.del.dn)); … … 1496 1289 /* DC's rIDSet object */ 1497 1290 /* Perform this check only when it does exist - this is needed in order 1498 * to don't let existing provisions break . */1291 * to don't let existing provisions break, and to delete . */ 1499 1292 ret = samdb_rid_set_dn(ldb, ac, &dn); 1500 if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) { 1293 if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_ATTRIBUTE) 1294 && (ret != LDB_ERR_NO_SUCH_OBJECT)) { 1295 ldb_asprintf_errstring(ldb, "objectclass: Unable to determine if %s, is this DC's rIDSet object: %s ", 1296 ldb_dn_get_linearized(ac->req->op.del.dn), 1297 ldb_errstring(ldb)); 1501 1298 return ret; 1502 1299 } … … 1509 1306 } 1510 1307 talloc_free(dn); 1308 } 1309 1310 /* Only trusted request from system account are allowed to delete 1311 * deleted objects. 1312 */ 1313 if (ldb_msg_check_string_attribute(ac->search_res->message, "isDeleted", "TRUE") && 1314 (ldb_req_is_untrusted(ac->req) || 1315 !dsdb_module_am_system(ac->module))) { 1316 ldb_asprintf_errstring(ldb, "Delete of '%s' failed", 1317 ldb_dn_get_linearized(ac->req->op.del.dn)); 1318 return LDB_ERR_UNWILLING_TO_PERFORM; 1511 1319 } 1512 1320 … … 1550 1358 "isCriticalSystemObject", false); 1551 1359 if (isCriticalSystemObject) { 1552 ldb_asprintf_errstring(ldb, 1360 /* 1361 * Following the explaination from Microsoft 1362 * https://lists.samba.org/archive/cifs-protocol/2011-August/002046.html 1363 * "I finished the investigation on this behavior. 1364 * As per MS-ADTS 3.1.5.5.7.2 , when a tree deletion is performed , 1365 * every object in the tree will be checked to see if it has isCriticalSystemObject 1366 * set to TRUE, including the root node on which the delete operation is performed 1367 * But there is an exception if the root object is a SAM specific objects(3.1.1.5.2.3 MS-ADTS) 1368 * Its deletion is done through SAM manger and isCriticalSystemObject attribute is not checked 1369 * The root node of the tree delete in your case is CN=ARES,OU=Domain Controllers,DC=w2k8r2,DC=home,DC=matws,DC=net 1370 * which is a SAM object with user class. Therefore the tree deletion is performed without any error 1371 */ 1372 1373 if (samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "group") == NULL && 1374 samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "samDomain") == NULL && 1375 samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "samServer") == NULL && 1376 samdb_find_attribute(ldb, ac->search_res->message, "objectClass", "user") == NULL) { 1377 ldb_asprintf_errstring(ldb, 1553 1378 "objectclass: Cannot tree-delete %s, it's a critical system object!", 1554 1379 ldb_dn_get_linearized(ac->req->op.del.dn)); 1555 1380 return LDB_ERR_UNWILLING_TO_PERFORM; 1381 } 1556 1382 } 1557 1383 } -
vendor/current/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
r740 r988 73 73 static int oc_op_callback(struct ldb_request *req, struct ldb_reply *ares); 74 74 75 /* checks correctness of dSHeuristics attribute 76 * as described in MS-ADTS 7.1.1.2.4.1.2 dSHeuristics */ 75 /* 76 * Checks the correctness of the "dSHeuristics" attribute as described in both 77 * MS-ADTS 7.1.1.2.4.1.2 dSHeuristics and MS-ADTS 3.1.1.5.3.2 Constraints 78 */ 77 79 static int oc_validate_dsheuristics(struct ldb_message_element *el) 78 80 { 79 81 if (el->num_values > 0) { 80 if (el->values[0].length > DS_HR_LDAP_BYPASS_UPPER_LIMIT_BOUNDS) { 81 return LDB_ERR_CONSTRAINT_VIOLATION; 82 } else if (el->values[0].length >= DS_HR_TENTH_CHAR 83 && el->values[0].data[DS_HR_TENTH_CHAR-1] != '1') { 84 return LDB_ERR_CONSTRAINT_VIOLATION; 85 } 86 } 87 82 if ((el->values[0].length >= DS_HR_NINETIETH_CHAR) && 83 (el->values[0].data[DS_HR_NINETIETH_CHAR-1] != '9')) { 84 return LDB_ERR_CONSTRAINT_VIOLATION; 85 } 86 if ((el->values[0].length >= DS_HR_EIGHTIETH_CHAR) && 87 (el->values[0].data[DS_HR_EIGHTIETH_CHAR-1] != '8')) { 88 return LDB_ERR_CONSTRAINT_VIOLATION; 89 } 90 if ((el->values[0].length >= DS_HR_SEVENTIETH_CHAR) && 91 (el->values[0].data[DS_HR_SEVENTIETH_CHAR-1] != '7')) { 92 return LDB_ERR_CONSTRAINT_VIOLATION; 93 } 94 if ((el->values[0].length >= DS_HR_SIXTIETH_CHAR) && 95 (el->values[0].data[DS_HR_SIXTIETH_CHAR-1] != '6')) { 96 return LDB_ERR_CONSTRAINT_VIOLATION; 97 } 98 if ((el->values[0].length >= DS_HR_FIFTIETH_CHAR) && 99 (el->values[0].data[DS_HR_FIFTIETH_CHAR-1] != '5')) { 100 return LDB_ERR_CONSTRAINT_VIOLATION; 101 } 102 if ((el->values[0].length >= DS_HR_FOURTIETH_CHAR) && 103 (el->values[0].data[DS_HR_FOURTIETH_CHAR-1] != '4')) { 104 return LDB_ERR_CONSTRAINT_VIOLATION; 105 } 106 if ((el->values[0].length >= DS_HR_THIRTIETH_CHAR) && 107 (el->values[0].data[DS_HR_THIRTIETH_CHAR-1] != '3')) { 108 return LDB_ERR_CONSTRAINT_VIOLATION; 109 } 110 if ((el->values[0].length >= DS_HR_TWENTIETH_CHAR) && 111 (el->values[0].data[DS_HR_TWENTIETH_CHAR-1] != '2')) { 112 return LDB_ERR_CONSTRAINT_VIOLATION; 113 } 114 if ((el->values[0].length >= DS_HR_TENTH_CHAR) && 115 (el->values[0].data[DS_HR_TENTH_CHAR-1] != '1')) { 116 return LDB_ERR_CONSTRAINT_VIOLATION; 117 } 118 } 119 120 return LDB_SUCCESS; 121 } 122 123 /* 124 auto normalise values on input 125 */ 126 static int oc_auto_normalise(struct ldb_context *ldb, const struct dsdb_attribute *attr, 127 struct ldb_message *msg, struct ldb_message_element *el) 128 { 129 int i; 130 bool values_copied = false; 131 132 for (i=0; i<el->num_values; i++) { 133 struct ldb_val v; 134 int ret; 135 ret = attr->ldb_schema_attribute->syntax->canonicalise_fn(ldb, el->values, &el->values[i], &v); 136 if (ret != LDB_SUCCESS) { 137 return ret; 138 } 139 if (data_blob_cmp(&v, &el->values[i]) == 0) { 140 /* no need to replace it */ 141 talloc_free(v.data); 142 continue; 143 } 144 145 /* we need to copy the values array on the first change */ 146 if (!values_copied) { 147 struct ldb_val *v2; 148 v2 = talloc_array(msg->elements, struct ldb_val, el->num_values); 149 if (v2 == NULL) { 150 return ldb_oom(ldb); 151 } 152 memcpy(v2, el->values, sizeof(struct ldb_val) * el->num_values); 153 el->values = v2; 154 values_copied = true; 155 } 156 157 el->values[i] = v; 158 } 88 159 return LDB_SUCCESS; 89 160 } … … 122 193 msg->elements[i].name); 123 194 if (attr == NULL) { 195 if (ldb_request_get_control(ac->req, DSDB_CONTROL_DBCHECK) && 196 ac->req->operation != LDB_ADD) { 197 /* we allow this for dbcheck to fix 198 broken attributes */ 199 goto no_attribute; 200 } 124 201 ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' was not found in the schema!", 125 202 msg->elements[i].name, … … 128 205 } 129 206 130 if ((attr->linkID & 1) == 1) { 207 if ((attr->linkID & 1) == 1 && 208 !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) && 209 !ldb_request_get_control(ac->req, DSDB_CONTROL_DBCHECK)) { 131 210 /* Odd is for the target. Illegal to modify */ 132 211 ldb_asprintf_errstring(ldb, … … 140 219 werr = attr->syntax->validate_ldb(&syntax_ctx, attr, 141 220 &msg->elements[i]); 142 if (!W_ERROR_IS_OK(werr)) { 221 if (!W_ERROR_IS_OK(werr) && 222 !ldb_request_get_control(ac->req, DSDB_CONTROL_DBCHECK)) { 143 223 ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' contains at least one invalid value!", 144 224 msg->elements[i].name, … … 167 247 } 168 248 249 /* auto normalise some attribute values */ 250 if (attr->syntax->auto_normalise) { 251 ret = oc_auto_normalise(ldb, attr, msg, &msg->elements[i]); 252 if (ret != LDB_SUCCESS) { 253 return ret; 254 } 255 } 256 169 257 /* Substitute the attribute name to match in case */ 170 258 msg->elements[i].name = attr->lDAPDisplayName; 171 259 } 172 260 261 no_attribute: 173 262 if (ac->req->operation == LDB_ADD) { 174 263 ret = ldb_build_add_req(&child_req, ldb, ac, … … 211 300 unsigned int i; 212 301 bool found; 302 bool isSchemaAttr = false; 213 303 214 304 ldb = ldb_module_get_ctx(ac->module); … … 241 331 * manipulated by client machines over the LDAPv3 transport." 242 332 */ 243 if (ldb_req_is_untrusted(ac->req)) { 244 for (i = 0; i < oc_element->num_values; i++) { 245 if ((strcmp((char *)oc_element->values[i].data, 246 "secret") == 0) || 247 (strcmp((char *)oc_element->values[i].data, 248 "trustedDomain") == 0)) { 333 for (i = 0; i < oc_element->num_values; i++) { 334 char * attname = (char *)oc_element->values[i].data; 335 if (ldb_req_is_untrusted(ac->req)) { 336 if (strcmp(attname, "secret") == 0 || 337 strcmp(attname, "trustedDomain") == 0) { 249 338 ldb_asprintf_errstring(ldb, "objectclass_attrs: LSA objectclasses (entry '%s') cannot be created or changed over LDAP!", 250 339 ldb_dn_get_linearized(ac->search_res->message->dn)); 251 340 return LDB_ERR_UNWILLING_TO_PERFORM; 252 341 } 342 } 343 if (strcmp(attname, "attributeSchema") == 0) { 344 isSchemaAttr = true; 253 345 } 254 346 } … … 296 388 msg->elements[i].name); 297 389 if (attr == NULL) { 390 if (ldb_request_get_control(ac->req, DSDB_CONTROL_DBCHECK)) { 391 /* allow this to make it possible for dbcheck 392 to remove bad attributes */ 393 continue; 394 } 298 395 return ldb_operr(ldb); 299 396 } … … 312 409 } 313 410 if (!found) { 314 ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' does not exist in the specified objectclasses!", 315 msg->elements[i].name, 316 ldb_dn_get_linearized(msg->dn)); 317 return LDB_ERR_OBJECT_CLASS_VIOLATION; 318 } 319 } 320 321 if (found_must_contain[0] != NULL) { 411 /* we allow this for dbcheck to fix the rest of this broken entry */ 412 if (!ldb_request_get_control(ac->req, DSDB_CONTROL_DBCHECK) || 413 ac->req->operation == LDB_ADD) { 414 ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' does not exist in the specified objectclasses!", 415 msg->elements[i].name, 416 ldb_dn_get_linearized(msg->dn)); 417 return LDB_ERR_OBJECT_CLASS_VIOLATION; 418 } 419 } 420 } 421 422 if (found_must_contain[0] != NULL && 423 ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE") == 0) { 322 424 ldb_asprintf_errstring(ldb, "objectclass_attrs: at least one mandatory attribute ('%s') on entry '%s' wasn't specified!", 323 425 found_must_contain[0], … … 326 428 } 327 429 430 if (isSchemaAttr) { 431 /* Before really adding an attribute in the database, 432 * let's check that we can translate it into a dbsd_attribute and 433 * that we can find a valid syntax object. 434 * If not it's better to reject this attribute than not be able 435 * to start samba next time due to schema being unloadable. 436 */ 437 struct dsdb_attribute *att = talloc(ac, struct dsdb_attribute); 438 const struct dsdb_syntax *attrSyntax; 439 WERROR status; 440 441 status= dsdb_attribute_from_ldb(ac->schema, msg, att); 442 if (!W_ERROR_IS_OK(status)) { 443 ldb_set_errstring(ldb, 444 "objectclass: failed to translate the schemaAttribute to a dsdb_attribute"); 445 return LDB_ERR_UNWILLING_TO_PERFORM; 446 } 447 448 attrSyntax = dsdb_syntax_for_attribute(att); 449 if (!attrSyntax) { 450 ldb_set_errstring(ldb, 451 "objectclass: unknown attribute syntax"); 452 return LDB_ERR_UNWILLING_TO_PERFORM; 453 } 454 } 328 455 return ldb_module_done(ac->req, ac->mod_ares->controls, 329 456 ac->mod_ares->response, LDB_SUCCESS); … … 474 601 { 475 602 struct ldb_context *ldb; 603 struct ldb_control *sd_propagation_control; 604 int ret; 605 476 606 struct oc_context *ac; 477 607 … … 482 612 /* do not manipulate our control entries */ 483 613 if (ldb_dn_is_special(req->op.mod.message->dn)) { 614 return ldb_next_request(module, req); 615 } 616 617 sd_propagation_control = ldb_request_get_control(req, 618 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); 619 if (sd_propagation_control != NULL) { 620 if (req->op.mod.message->num_elements != 1) { 621 return ldb_module_operr(module); 622 } 623 ret = strcmp(req->op.mod.message->elements[0].name, 624 "nTSecurityDescriptor"); 625 if (ret != 0) { 626 return ldb_module_operr(module); 627 } 628 484 629 return ldb_next_request(module, req); 485 630 } -
vendor/current/source4/dsdb/samdb/ldb_modules/operational.c
r740 r988 85 85 }; 86 86 87 enum search_type { 88 TOKEN_GROUPS, 89 TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL, 90 TOKEN_GROUPS_NO_GC_ACCEPTABLE 91 }; 92 87 93 /* 88 94 construct a canonical name from a message … … 128 134 construct the token groups for SAM objects from a message 129 135 */ 130 static int construct_token_groups(struct ldb_module *module, 131 struct ldb_message *msg, enum ldb_scope scope, 132 struct ldb_request *parent) 133 { 134 struct ldb_context *ldb = ldb_module_get_ctx(module);; 136 static int construct_generic_token_groups(struct ldb_module *module, 137 struct ldb_message *msg, enum ldb_scope scope, 138 struct ldb_request *parent, 139 const char *attribute_string, 140 enum search_type type) 141 { 142 struct ldb_context *ldb = ldb_module_get_ctx(module); 135 143 TALLOC_CTX *tmp_ctx = talloc_new(msg); 136 144 unsigned int i; 137 145 int ret; 138 const char *filter ;146 const char *filter = NULL; 139 147 140 148 NTSTATUS status; … … 190 198 191 199 /* only return security groups */ 192 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))", 193 GROUP_TYPE_SECURITY_ENABLED); 200 switch(type) { 201 case TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL: 202 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u)(|(groupType:1.2.840.113556.1.4.803:=%u)(groupType:1.2.840.113556.1.4.803:=%u)))", 203 GROUP_TYPE_SECURITY_ENABLED, GROUP_TYPE_ACCOUNT_GROUP, GROUP_TYPE_UNIVERSAL_GROUP); 204 break; 205 case TOKEN_GROUPS_NO_GC_ACCEPTABLE: 206 case TOKEN_GROUPS: 207 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))", 208 GROUP_TYPE_SECURITY_ENABLED); 209 break; 210 } 211 194 212 if (!filter) { 195 213 talloc_free(tmp_ctx); … … 254 272 255 273 for (i=0; i < num_groupSIDs; i++) { 256 ret = samdb_msg_add_dom_sid(ldb, msg, msg, "tokenGroups", &groupSIDs[i]);274 ret = samdb_msg_add_dom_sid(ldb, msg, msg, attribute_string, &groupSIDs[i]); 257 275 if (ret) { 258 276 talloc_free(tmp_ctx); … … 264 282 } 265 283 284 static int construct_token_groups(struct ldb_module *module, 285 struct ldb_message *msg, enum ldb_scope scope, 286 struct ldb_request *parent) 287 { 288 /** 289 * TODO: Add in a limiting domain when we start to support 290 * trusted domains. 291 */ 292 return construct_generic_token_groups(module, msg, scope, parent, 293 "tokenGroups", 294 TOKEN_GROUPS); 295 } 296 297 static int construct_token_groups_no_gc(struct ldb_module *module, 298 struct ldb_message *msg, enum ldb_scope scope, 299 struct ldb_request *parent) 300 { 301 /** 302 * TODO: Add in a limiting domain when we start to support 303 * trusted domains. 304 */ 305 return construct_generic_token_groups(module, msg, scope, parent, 306 "tokenGroupsNoGCAcceptable", 307 TOKEN_GROUPS); 308 } 309 310 static int construct_global_universal_token_groups(struct ldb_module *module, 311 struct ldb_message *msg, enum ldb_scope scope, 312 struct ldb_request *parent) 313 { 314 return construct_generic_token_groups(module, msg, scope, parent, 315 "tokenGroupsGlobalAndUniversal", 316 TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL); 317 } 266 318 /* 267 319 construct the parent GUID for an entry from a message … … 284 336 DSDB_FLAG_NEXT_MODULE | 285 337 DSDB_SEARCH_SHOW_RECYCLED, parent); 338 if (ret != LDB_SUCCESS) { 339 return ret; 340 } 286 341 287 342 instanceType = ldb_msg_find_attr_as_uint(res->msgs[0], … … 307 362 /* not NC, so the object should have a parent*/ 308 363 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 309 DEBUG(4,(__location__ ": Parent dn for %s does not exist \n",310 ldb_dn_get_linearized(msg->dn)));311 return ldb_operr(ldb_module_get_ctx(module));364 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_OPERATIONS_ERROR, 365 talloc_asprintf(msg, "Parent dn for %s does not exist", 366 ldb_dn_get_linearized(msg->dn))); 312 367 } else if (ret != LDB_SUCCESS) { 313 368 return ret; … … 320 375 } 321 376 322 v = data_blob_dup_talloc(parent_res, parent_guid);377 v = data_blob_dup_talloc(parent_res, *parent_guid); 323 378 if (!v.data) { 324 379 talloc_free(parent_res); … … 328 383 talloc_free(parent_res); 329 384 return ret; 385 } 386 387 static int construct_modifyTimeStamp(struct ldb_module *module, 388 struct ldb_message *msg, enum ldb_scope scope, 389 struct ldb_request *parent) 390 { 391 struct operational_data *data = talloc_get_type(ldb_module_get_private(module), struct operational_data); 392 struct ldb_context *ldb = ldb_module_get_ctx(module); 393 394 /* We may be being called before the init function has finished */ 395 if (!data) { 396 return LDB_SUCCESS; 397 } 398 399 /* Try and set this value up, if possible. Don't worry if it 400 * fails, we may not have the DB set up yet. 401 */ 402 if (!data->aggregate_dn) { 403 data->aggregate_dn = samdb_aggregate_schema_dn(ldb, data); 404 } 405 406 if (data->aggregate_dn && ldb_dn_compare(data->aggregate_dn, msg->dn) == 0) { 407 /* 408 * If we have the DN for the object with common name = Aggregate and 409 * the request is for this DN then let's do the following: 410 * 1) search the object which changedUSN correspond to the one of the loaded 411 * schema. 412 * 2) Get the whenChanged attribute 413 * 3) Generate the modifyTimestamp out of the whenChanged attribute 414 */ 415 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL); 416 char *value = ldb_timestring(msg, schema->ts_last_change); 417 418 return ldb_msg_add_string(msg, "modifyTimeStamp", value); 419 } 420 return ldb_msg_copy_attr(msg, "whenChanged", "modifyTimeStamp"); 330 421 } 331 422 … … 372 463 if (!ldb) { 373 464 DEBUG(4, (__location__ ": Failed to get ldb \n")); 374 return ldb_operr(ldb);465 return LDB_ERR_OPERATIONS_ERROR; 375 466 } 376 467 … … 527 618 return LDB_SUCCESS; 528 619 } 529 if (!omd_value) {530 return LDB_SUCCESS;531 }532 620 533 621 omd = talloc(msg, struct replPropertyMetaDataBlob); … … 568 656 } 569 657 658 #define _UF_TRUST_ACCOUNTS ( \ 659 UF_WORKSTATION_TRUST_ACCOUNT | \ 660 UF_SERVER_TRUST_ACCOUNT | \ 661 UF_INTERDOMAIN_TRUST_ACCOUNT \ 662 ) 663 #define _UF_NO_EXPIRY_ACCOUNTS ( \ 664 UF_SMARTCARD_REQUIRED | \ 665 UF_DONT_EXPIRE_PASSWD | \ 666 _UF_TRUST_ACCOUNTS \ 667 ) 668 669 /* 670 calculate msDS-UserPasswordExpiryTimeComputed 671 */ 672 static NTTIME get_msds_user_password_expiry_time_computed(struct ldb_module *module, 673 struct ldb_message *msg, 674 struct ldb_dn *domain_dn) 675 { 676 int64_t pwdLastSet, maxPwdAge; 677 uint32_t userAccountControl; 678 NTTIME ret; 679 680 userAccountControl = ldb_msg_find_attr_as_uint(msg, 681 "userAccountControl", 682 0); 683 if (userAccountControl & _UF_NO_EXPIRY_ACCOUNTS) { 684 return 0x7FFFFFFFFFFFFFFFULL; 685 } 686 687 pwdLastSet = ldb_msg_find_attr_as_int64(msg, "pwdLastSet", 0); 688 if (pwdLastSet == 0) { 689 return 0; 690 } 691 692 if (pwdLastSet <= -1) { 693 /* 694 * This can't really happen... 695 */ 696 return 0x7FFFFFFFFFFFFFFFULL; 697 } 698 699 if (pwdLastSet >= 0x7FFFFFFFFFFFFFFFULL) { 700 /* 701 * Somethings wrong with the clock... 702 */ 703 return 0x7FFFFFFFFFFFFFFFULL; 704 } 705 706 /* 707 * Note that maxPwdAge is a stored as negative value. 708 * 709 * Possible values are in the range of: 710 * 711 * maxPwdAge: -864000000001 712 * to 713 * maxPwdAge: -9223372036854775808 (-0x8000000000000000ULL) 714 * 715 */ 716 maxPwdAge = samdb_search_int64(ldb_module_get_ctx(module), msg, 0, 717 domain_dn, "maxPwdAge", NULL); 718 if (maxPwdAge >= -864000000000) { 719 /* 720 * This is not really possible... 721 */ 722 return 0x7FFFFFFFFFFFFFFFULL; 723 } 724 725 if (maxPwdAge == -0x8000000000000000ULL) { 726 return 0x7FFFFFFFFFFFFFFFULL; 727 } 728 729 /* 730 * Note we already catched maxPwdAge == -0x8000000000000000ULL 731 * and pwdLastSet >= 0x7FFFFFFFFFFFFFFFULL above. 732 * 733 * Remember maxPwdAge is a negative number, 734 * so it results in the following. 735 * 736 * 0x7FFFFFFFFFFFFFFEULL + 0x7FFFFFFFFFFFFFFFULL 737 * = 738 * 0xFFFFFFFFFFFFFFFFULL 739 */ 740 ret = pwdLastSet - maxPwdAge; 741 if (ret >= 0x7FFFFFFFFFFFFFFFULL) { 742 return 0x7FFFFFFFFFFFFFFFULL; 743 } 744 745 return ret; 746 } 747 748 749 /* 750 construct msDS-User-Account-Control-Computed attr 751 */ 752 static int construct_msds_user_account_control_computed(struct ldb_module *module, 753 struct ldb_message *msg, enum ldb_scope scope, 754 struct ldb_request *parent) 755 { 756 uint32_t userAccountControl; 757 uint32_t msDS_User_Account_Control_Computed = 0; 758 struct ldb_context *ldb = ldb_module_get_ctx(module); 759 NTTIME now; 760 struct ldb_dn *nc_root; 761 int ret; 762 763 ret = dsdb_find_nc_root(ldb, msg, msg->dn, &nc_root); 764 if (ret != 0) { 765 ldb_asprintf_errstring(ldb, 766 "Failed to find NC root of DN: %s: %s", 767 ldb_dn_get_linearized(msg->dn), 768 ldb_errstring(ldb_module_get_ctx(module))); 769 return ret; 770 } 771 if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) != 0) { 772 /* Only calculate this on our default NC */ 773 return 0; 774 } 775 /* Test account expire time */ 776 unix_to_nt_time(&now, time(NULL)); 777 778 userAccountControl = ldb_msg_find_attr_as_uint(msg, 779 "userAccountControl", 780 0); 781 if (!(userAccountControl & _UF_TRUST_ACCOUNTS)) { 782 783 int64_t lockoutTime = ldb_msg_find_attr_as_int64(msg, "lockoutTime", 0); 784 if (lockoutTime != 0) { 785 int64_t lockoutDuration = samdb_search_int64(ldb, 786 msg, 0, nc_root, 787 "lockoutDuration", NULL); 788 if (lockoutDuration >= 0) { 789 msDS_User_Account_Control_Computed |= UF_LOCKOUT; 790 } else if (lockoutTime - lockoutDuration >= now) { 791 msDS_User_Account_Control_Computed |= UF_LOCKOUT; 792 } 793 } 794 } 795 796 if (!(userAccountControl & _UF_NO_EXPIRY_ACCOUNTS)) { 797 NTTIME must_change_time 798 = get_msds_user_password_expiry_time_computed(module, 799 msg, nc_root); 800 /* check for expired password */ 801 if (must_change_time < now) { 802 msDS_User_Account_Control_Computed |= UF_PASSWORD_EXPIRED; 803 } 804 } 805 806 return samdb_msg_add_int64(ldb, 807 msg->elements, msg, 808 "msDS-User-Account-Control-Computed", 809 msDS_User_Account_Control_Computed); 810 } 811 812 /* 813 construct msDS-UserPasswordExpiryTimeComputed 814 */ 815 static int construct_msds_user_password_expiry_time_computed(struct ldb_module *module, 816 struct ldb_message *msg, enum ldb_scope scope, 817 struct ldb_request *parent) 818 { 819 struct ldb_context *ldb = ldb_module_get_ctx(module); 820 struct ldb_dn *nc_root; 821 int64_t password_expiry_time; 822 int ret; 823 824 ret = dsdb_find_nc_root(ldb, msg, msg->dn, &nc_root); 825 if (ret != 0) { 826 ldb_asprintf_errstring(ldb, 827 "Failed to find NC root of DN: %s: %s", 828 ldb_dn_get_linearized(msg->dn), 829 ldb_errstring(ldb)); 830 return ret; 831 } 832 833 if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) != 0) { 834 /* Only calculate this on our default NC */ 835 return 0; 836 } 837 838 password_expiry_time 839 = get_msds_user_password_expiry_time_computed(module, msg, 840 nc_root); 841 842 return samdb_msg_add_int64(ldb, 843 msg->elements, msg, 844 "msDS-UserPasswordExpiryTimeComputed", 845 password_expiry_time); 846 } 847 848 570 849 struct op_controls_flags { 571 850 bool sd; … … 574 853 575 854 static bool check_keep_control_for_attribute(struct op_controls_flags* controls_flags, const char* attr) { 576 if ( ldb_attr_cmp(attr, "msDS-KeyVersionNumber") == 0 && controls_flags->bypassoperational) {855 if (controls_flags->bypassoperational && ldb_attr_cmp(attr, "msDS-KeyVersionNumber") == 0 ) { 577 856 return true; 578 857 } … … 593 872 594 873 874 struct op_attributes_replace { 875 const char *attr; 876 const char *replace; 877 const char * const *extra_attrs; 878 int (*constructor)(struct ldb_module *, struct ldb_message *, enum ldb_scope, struct ldb_request *); 879 }; 880 881 882 static const char *objectSid_attr[] = 883 { 884 "objectSid", 885 NULL 886 }; 887 888 889 static const char *objectCategory_attr[] = 890 { 891 "objectCategory", 892 NULL 893 }; 894 895 896 static const char *user_account_control_computed_attrs[] = 897 { 898 "lockoutTime", 899 "pwdLastSet", 900 NULL 901 }; 902 903 904 static const char *user_password_expiry_time_computed_attrs[] = 905 { 906 "pwdLastSet", 907 NULL 908 }; 909 910 595 911 /* 596 912 a list of attribute names that are hidden, but can be searched for 597 913 using another (non-hidden) name to produce the correct result 598 914 */ 599 static const struct { 600 const char *attr; 601 const char *replace; 602 const char *extra_attr; 603 int (*constructor)(struct ldb_module *, struct ldb_message *, enum ldb_scope, struct ldb_request *); 604 } search_sub[] = { 915 static const struct op_attributes_replace search_sub[] = { 605 916 { "createTimeStamp", "whenCreated", NULL , NULL }, 606 { "modifyTimeStamp", "whenChanged", NULL , NULL},917 { "modifyTimeStamp", "whenChanged", NULL , construct_modifyTimeStamp}, 607 918 { "structuralObjectClass", "objectClass", NULL , NULL }, 608 919 { "canonicalName", NULL, NULL , construct_canonical_name }, 609 { "primaryGroupToken", "objectClass", "objectSid", construct_primary_group_token }, 610 { "tokenGroups", "primaryGroupID", "objectSid", construct_token_groups }, 920 { "primaryGroupToken", "objectClass", objectSid_attr, construct_primary_group_token }, 921 { "tokenGroups", "primaryGroupID", objectSid_attr, construct_token_groups }, 922 { "tokenGroupsNoGCAcceptable", "primaryGroupID", objectSid_attr, construct_token_groups_no_gc}, 923 { "tokenGroupsGlobalAndUniversal", "primaryGroupID", objectSid_attr, construct_global_universal_token_groups }, 611 924 { "parentGUID", NULL, NULL, construct_parent_guid }, 612 925 { "subSchemaSubEntry", NULL, NULL, construct_subschema_subentry }, 613 { "msDS-isRODC", "objectClass", "objectCategory", construct_msds_isrodc }, 614 { "msDS-KeyVersionNumber", "replPropertyMetaData", NULL, construct_msds_keyversionnumber } 926 { "msDS-isRODC", "objectClass", objectCategory_attr, construct_msds_isrodc }, 927 { "msDS-KeyVersionNumber", "replPropertyMetaData", NULL, construct_msds_keyversionnumber }, 928 { "msDS-User-Account-Control-Computed", "userAccountControl", user_account_control_computed_attrs, 929 construct_msds_user_account_control_computed }, 930 { "msDS-UserPasswordExpiryTimeComputed", "userAccountControl", user_password_expiry_time_computed_attrs, 931 construct_msds_user_password_expiry_time_computed } 615 932 }; 616 933 … … 629 946 Some of these are attributes that were once stored, but are now calculated 630 947 */ 631 st atic const struct{948 struct op_attributes_operations { 632 949 const char *attr; 633 950 enum op_remove op; 634 } operational_remove[] = { 951 }; 952 953 static const struct op_attributes_operations operational_remove[] = { 635 954 { "nTSecurityDescriptor", OPERATIONAL_SD_FLAGS }, 636 955 { "msDS-KeyVersionNumber", OPERATIONAL_REMOVE_UNLESS_CONTROL }, … … 654 973 const char * const *attrs_searched_for, 655 974 struct op_controls_flags* controls_flags, 975 struct op_attributes_operations *list, 976 unsigned int list_size, 977 struct op_attributes_replace *list_replace, 978 unsigned int list_replace_size, 656 979 struct ldb_request *parent) 657 980 { … … 663 986 664 987 /* removed any attrs that should not be shown to the user */ 665 for (i=0; i<ARRAY_SIZE(operational_remove); i++) { 666 switch (operational_remove[i].op) { 667 case OPERATIONAL_REMOVE_UNASKED: 668 if (ldb_attr_in_list(attrs_from_user, operational_remove[i].attr)) { 669 continue; 670 } 671 if (ldb_attr_in_list(attrs_searched_for, operational_remove[i].attr)) { 672 continue; 673 } 674 case OPERATIONAL_REMOVE_ALWAYS: 675 ldb_msg_remove_attr(msg, operational_remove[i].attr); 676 break; 677 case OPERATIONAL_REMOVE_UNLESS_CONTROL: 678 if (!check_keep_control_for_attribute(controls_flags, operational_remove[i].attr)) { 679 ldb_msg_remove_attr(msg, operational_remove[i].attr); 680 break; 681 } else { 682 continue; 683 } 684 case OPERATIONAL_SD_FLAGS: 685 if (controls_flags->sd || 686 ldb_attr_in_list(attrs_from_user, operational_remove[i].attr)) { 687 continue; 688 } 689 ldb_msg_remove_attr(msg, operational_remove[i].attr); 690 break; 691 } 692 } 693 694 for (a=0;attrs_from_user && attrs_from_user[a];a++) { 695 if (check_keep_control_for_attribute(controls_flags, attrs_from_user[a])) { 988 for (i=0; i < list_size; i++) { 989 ldb_msg_remove_attr(msg, list[i].attr); 990 } 991 992 for (a=0; a < list_replace_size; a++) { 993 if (check_keep_control_for_attribute(controls_flags, 994 list_replace[a].attr)) { 696 995 continue; 697 996 } 698 for (i=0;i<ARRAY_SIZE(search_sub);i++) { 699 if (ldb_attr_cmp(attrs_from_user[a], search_sub[i].attr) != 0) { 700 continue; 701 } 702 703 /* construct the new attribute, using either a supplied 704 constructor or a simple copy */ 705 constructed_attributes = true; 706 if (search_sub[i].constructor != NULL) { 707 if (search_sub[i].constructor(module, msg, scope, parent) != LDB_SUCCESS) { 708 goto failed; 709 } 710 } else if (ldb_msg_copy_attr(msg, 711 search_sub[i].replace, 712 search_sub[i].attr) != LDB_SUCCESS) { 997 998 /* construct the new attribute, using either a supplied 999 constructor or a simple copy */ 1000 constructed_attributes = true; 1001 if (list_replace[a].constructor != NULL) { 1002 if (list_replace[a].constructor(module, msg, scope, parent) != LDB_SUCCESS) { 713 1003 goto failed; 714 1004 } 1005 } else if (ldb_msg_copy_attr(msg, 1006 list_replace[a].replace, 1007 list_replace[a].attr) != LDB_SUCCESS) { 1008 goto failed; 715 1009 } 716 1010 } … … 721 1015 */ 722 1016 if ((constructed_attributes) && (!ldb_attr_in_list(attrs_from_user, "*"))) { 723 for (i=0; i<ARRAY_SIZE(search_sub);i++) {1017 for (i=0; i < list_replace_size; i++) { 724 1018 /* remove the added search helper attributes, unless 725 1019 * they were asked for by the user */ 726 if (search_sub[i].replace != NULL && 727 !ldb_attr_in_list(attrs_from_user, search_sub[i].replace)) { 728 ldb_msg_remove_attr(msg, search_sub[i].replace); 729 } 730 if (search_sub[i].extra_attr != NULL && 731 !ldb_attr_in_list(attrs_from_user, search_sub[i].extra_attr)) { 732 ldb_msg_remove_attr(msg, search_sub[i].extra_attr); 1020 if (list_replace[i].replace != NULL && 1021 !ldb_attr_in_list(attrs_from_user, list_replace[i].replace)) { 1022 ldb_msg_remove_attr(msg, list_replace[i].replace); 1023 } 1024 if (list_replace[i].extra_attrs != NULL) { 1025 unsigned int j; 1026 for (j=0; list_replace[i].extra_attrs[j]; j++) { 1027 if (!ldb_attr_in_list(attrs_from_user, list_replace[i].extra_attrs[j])) { 1028 ldb_msg_remove_attr(msg, list_replace[i].extra_attrs[j]); 1029 } 1030 } 733 1031 } 734 1032 } … … 754 1052 const char * const *attrs; 755 1053 struct op_controls_flags* controls_flags; 1054 struct op_attributes_operations *list_operations; 1055 unsigned int list_operations_size; 1056 struct op_attributes_replace *attrs_to_replace; 1057 unsigned int attrs_to_replace_size; 756 1058 }; 757 1059 … … 781 1083 ac->attrs, 782 1084 req->op.search.attrs, 783 ac->controls_flags, req); 1085 ac->controls_flags, 1086 ac->list_operations, 1087 ac->list_operations_size, 1088 ac->attrs_to_replace, 1089 ac->attrs_to_replace_size, 1090 req); 784 1091 if (ret != 0) { 785 1092 return ldb_module_done(ac->req, NULL, NULL, … … 799 1106 talloc_free(ares); 800 1107 return LDB_SUCCESS; 1108 } 1109 1110 static struct op_attributes_operations* operation_get_op_list(TALLOC_CTX *ctx, 1111 const char* const* attrs, 1112 const char* const* searched_attrs, 1113 struct op_controls_flags* controls_flags) 1114 { 1115 int idx = 0; 1116 int i; 1117 struct op_attributes_operations *list = talloc_zero_array(ctx, 1118 struct op_attributes_operations, 1119 ARRAY_SIZE(operational_remove) + 1); 1120 1121 if (list == NULL) { 1122 return NULL; 1123 } 1124 1125 for (i=0; i<ARRAY_SIZE(operational_remove); i++) { 1126 switch (operational_remove[i].op) { 1127 case OPERATIONAL_REMOVE_UNASKED: 1128 if (ldb_attr_in_list(attrs, operational_remove[i].attr)) { 1129 continue; 1130 } 1131 if (ldb_attr_in_list(searched_attrs, operational_remove[i].attr)) { 1132 continue; 1133 } 1134 list[idx].attr = operational_remove[i].attr; 1135 list[idx].op = OPERATIONAL_REMOVE_UNASKED; 1136 idx++; 1137 break; 1138 1139 case OPERATIONAL_REMOVE_ALWAYS: 1140 list[idx].attr = operational_remove[i].attr; 1141 list[idx].op = OPERATIONAL_REMOVE_ALWAYS; 1142 idx++; 1143 break; 1144 1145 case OPERATIONAL_REMOVE_UNLESS_CONTROL: 1146 if (!check_keep_control_for_attribute(controls_flags, operational_remove[i].attr)) { 1147 list[idx].attr = operational_remove[i].attr; 1148 list[idx].op = OPERATIONAL_REMOVE_UNLESS_CONTROL; 1149 idx++; 1150 } 1151 break; 1152 1153 case OPERATIONAL_SD_FLAGS: 1154 if (ldb_attr_in_list(attrs, operational_remove[i].attr)) { 1155 continue; 1156 } 1157 if (controls_flags->sd) { 1158 if (attrs == NULL) { 1159 continue; 1160 } 1161 if (attrs[0] == NULL) { 1162 continue; 1163 } 1164 if (ldb_attr_in_list(attrs, "*")) { 1165 continue; 1166 } 1167 } 1168 list[idx].attr = operational_remove[i].attr; 1169 list[idx].op = OPERATIONAL_SD_FLAGS; 1170 idx++; 1171 break; 1172 } 1173 } 1174 1175 return list; 801 1176 } 802 1177 … … 845 1220 (ldb_request_get_control(req, LDB_CONTROL_BYPASS_OPERATIONAL_OID) != NULL); 846 1221 1222 ac->attrs_to_replace = NULL; 1223 ac->attrs_to_replace_size = 0; 847 1224 /* in the list of attributes we are looking for, rename any 848 1225 attributes to the alias for any hidden attributes that can … … 853 1230 } 854 1231 for (i=0;i<ARRAY_SIZE(search_sub);i++) { 855 if (ldb_attr_cmp(ac->attrs[a], search_sub[i].attr) == 0 && 856 search_sub[i].replace) { 857 858 if (search_sub[i].extra_attr) { 859 const char **search_attrs2; 860 /* Only adds to the end of the list */ 1232 1233 if (ldb_attr_cmp(ac->attrs[a], search_sub[i].attr) != 0 ) { 1234 continue; 1235 } 1236 1237 ac->attrs_to_replace = talloc_realloc(ac, 1238 ac->attrs_to_replace, 1239 struct op_attributes_replace, 1240 ac->attrs_to_replace_size + 1); 1241 1242 ac->attrs_to_replace[ac->attrs_to_replace_size] = search_sub[i]; 1243 ac->attrs_to_replace_size++; 1244 if (!search_sub[i].replace) { 1245 continue; 1246 } 1247 1248 if (search_sub[i].extra_attrs && search_sub[i].extra_attrs[0]) { 1249 unsigned int j; 1250 const char **search_attrs2; 1251 /* Only adds to the end of the list */ 1252 for (j = 0; search_sub[i].extra_attrs[j]; j++) { 861 1253 search_attrs2 = ldb_attr_list_copy_add(req, search_attrs 862 1254 ? search_attrs 863 1255 : ac->attrs, 864 search_sub[i].extra_attr );1256 search_sub[i].extra_attrs[j]); 865 1257 if (search_attrs2 == NULL) { 866 1258 return ldb_operr(ldb); … … 870 1262 search_attrs = search_attrs2; 871 1263 } 872 873 if (!search_attrs) { 874 search_attrs = ldb_attr_list_copy(req, ac->attrs);875 if (search_attrs == NULL) {876 return ldb_operr(ldb);877 }1264 } 1265 1266 if (!search_attrs) { 1267 search_attrs = ldb_attr_list_copy(req, ac->attrs); 1268 if (search_attrs == NULL) { 1269 return ldb_operr(ldb); 878 1270 } 879 /* Despite the ldb_attr_list_copy_add, this is safe as that fn only adds to the end */ 880 search_attrs[a] = search_sub[i].replace; 881 } 882 } 883 } 884 1271 } 1272 /* Despite the ldb_attr_list_copy_add, this is safe as that fn only adds to the end */ 1273 search_attrs[a] = search_sub[i].replace; 1274 } 1275 } 1276 ac->list_operations = operation_get_op_list(ac, ac->attrs, 1277 search_attrs == NULL?req->op.search.attrs:search_attrs, 1278 ac->controls_flags); 1279 ac->list_operations_size = 0; 1280 i = 0; 1281 1282 while (ac->list_operations && ac->list_operations[i].attr != NULL) { 1283 i++; 1284 } 1285 ac->list_operations_size = i; 885 1286 ret = ldb_build_search_req_ex(&down_req, ldb, ac, 886 1287 req->op.search.base, -
vendor/current/source4/dsdb/samdb/ldb_modules/partition.c
r740 r988 135 135 struct ldb_request *nreq; 136 136 int ret; 137 struct partition_private_data *data;138 137 struct ldb_control *partition_ctrl; 139 138 140 139 ac = talloc_get_type(req->context, struct partition_context); 141 data = talloc_get_type(ldb_module_get_private(ac->module), struct partition_private_data);142 140 143 141 if (!ares) { … … 399 397 } 400 398 399 400 /** 401 * send an operation to the top partition, then copy the resulting 402 * object to all other partitions 403 */ 404 static int partition_copy_all(struct ldb_module *module, 405 struct partition_context *ac, 406 struct ldb_request *req, 407 struct ldb_dn *dn) 408 { 409 unsigned int i; 410 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module), 411 struct partition_private_data); 412 int ret, search_ret; 413 struct ldb_result *res; 414 415 /* do the request on the top level sam.ldb synchronously */ 416 ret = ldb_next_request(module, req); 417 if (ret != LDB_SUCCESS) { 418 return ret; 419 } 420 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 421 if (ret != LDB_SUCCESS) { 422 return ret; 423 } 424 425 /* now fetch the resulting object, and then copy it to all the 426 * other partitions. We need this approach to cope with the 427 * partitions getting out of sync. If for example the 428 * @ATTRIBUTES object exists on one partition but not the 429 * others then just doing each of the partitions in turn will 430 * lead to an error 431 */ 432 search_ret = dsdb_module_search_dn(module, ac, &res, dn, NULL, DSDB_FLAG_NEXT_MODULE, req); 433 if (search_ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { 434 return search_ret; 435 } 436 437 /* now delete the object in the other partitions. Once that is 438 done we will re-add the object, if search_ret was not 439 LDB_ERR_NO_SUCH_OBJECT 440 */ 441 for (i=0; data->partitions && data->partitions[i]; i++) { 442 int pret; 443 pret = dsdb_module_del(data->partitions[i]->module, dn, DSDB_FLAG_NEXT_MODULE, req); 444 if (pret != LDB_SUCCESS && pret != LDB_ERR_NO_SUCH_OBJECT) { 445 /* we should only get success or no 446 such object from the other partitions */ 447 return pret; 448 } 449 } 450 451 452 if (search_ret != LDB_ERR_NO_SUCH_OBJECT) { 453 /* now re-add in the other partitions */ 454 for (i=0; data->partitions && data->partitions[i]; i++) { 455 int pret; 456 pret = dsdb_module_add(data->partitions[i]->module, res->msgs[0], DSDB_FLAG_NEXT_MODULE, req); 457 if (pret != LDB_SUCCESS) { 458 return pret; 459 } 460 } 461 } 462 463 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); 464 } 465 401 466 /** 402 467 * Figure out which backend a request needs to be aimed at. Some … … 428 493 } 429 494 430 return partition_ send_all(module, ac, req);495 return partition_copy_all(module, ac, req, dn); 431 496 } 432 497 } … … 477 542 struct ldb_control *search_control = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID); 478 543 struct ldb_control *domain_scope_control = ldb_request_get_control(req, LDB_CONTROL_DOMAIN_SCOPE_OID); 544 struct ldb_control *no_gc_control = ldb_request_get_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG); 479 545 480 546 struct ldb_search_options_control *search_options = NULL; … … 484 550 bool domain_scope = false, phantom_root = false; 485 551 486 /* see if we are still up-to-date */487 ret = partition_reload_if_required(module, data, req);488 if (ret != LDB_SUCCESS) {489 return ret;490 }491 492 552 p = find_partition(data, NULL, req); 493 553 if (p != NULL) { … … 518 578 } 519 579 580 /* Special DNs without specified partition should go further */ 581 if (ldb_dn_is_special(req->op.search.base)) { 582 return ldb_next_request(module, req); 583 } 584 520 585 /* Locate the options */ 521 586 domain_scope = (search_options … … 543 608 /* Search from the base DN */ 544 609 if (ldb_dn_is_null(req->op.search.base)) { 610 if (!phantom_root) { 611 return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, "empty base DN"); 612 } 545 613 return partition_send_all(module, ac, req); 546 614 } … … 548 616 for (i=0; data->partitions[i]; i++) { 549 617 bool match = false, stop = false; 618 619 if (data->partitions[i]->partial_replica && no_gc_control != NULL) { 620 if (ldb_dn_compare_base(data->partitions[i]->ctrl->dn, 621 req->op.search.base) == 0) { 622 /* base DN is in a partial replica 623 with the NO_GLOBAL_CATALOG 624 control. This partition is invisible */ 625 /* DEBUG(0,("DENYING NON-GC OP: %s\n", ldb_module_call_chain(req, req))); */ 626 continue; 627 } 628 } 550 629 551 630 if (phantom_root) { … … 615 694 /* Initialise the referrals list */ 616 695 if (ac->referrals == NULL) { 617 ac->referrals = (const char **) str_list_make_empty(ac); 696 char **l = str_list_make_empty(ac); 697 ac->referrals = discard_const_p(const char *, l); 618 698 if (ac->referrals == NULL) { 619 699 return ldb_oom(ldb); … … 726 806 static int partition_start_trans(struct ldb_module *module) 727 807 { 728 unsignedint i;808 int i; 729 809 int ret; 730 810 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module), … … 733 813 /* Figure out which partition it is under */ 734 814 /* Skip the lot if 'data' isn't here yet (initialization) */ 735 if ( (module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {815 if (ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING) { 736 816 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_start_trans() -> (metadata partition)"); 737 817 } … … 743 823 ret = partition_reload_if_required(module, data, NULL); 744 824 if (ret != LDB_SUCCESS) { 825 ldb_next_del_trans(module); 826 return ret; 827 } 828 829 ret = partition_metadata_start_trans(module); 830 if (ret != LDB_SUCCESS) { 831 ldb_next_del_trans(module); 745 832 return ret; 746 833 } … … 758 845 } 759 846 ldb_next_del_trans(module); 847 partition_metadata_del_trans(module); 760 848 return ret; 761 849 } … … 773 861 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module), 774 862 struct partition_private_data); 863 int ret; 775 864 776 865 for (i=0; data && data->partitions && data->partitions[i]; i++) { 777 int ret;778 779 866 if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) { 780 867 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_prepare_commit() -> %s", … … 793 880 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_prepare_commit() -> (metadata partition)"); 794 881 } 795 return ldb_next_prepare_commit(module); 882 883 ret = ldb_next_prepare_commit(module); 884 if (ret != LDB_SUCCESS) { 885 return ret; 886 } 887 888 /* metadata prepare commit must come last, as other partitions could modify 889 * the database inside the prepare commit method of a module */ 890 return partition_metadata_prepare_commit(module); 796 891 } 797 892 … … 812 907 } else { 813 908 data->in_transaction--; 909 } 910 911 ret2 = partition_metadata_end_trans(module); 912 if (ret2 != LDB_SUCCESS) { 913 ret = ret2; 814 914 } 815 915 … … 845 945 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module), 846 946 struct partition_private_data); 947 ret = partition_metadata_del_trans(module); 948 if (ret != LDB_SUCCESS) { 949 final_ret = ret; 950 } 951 847 952 for (i=0; data && data->partitions && data->partitions[i]; i++) { 848 953 if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) { … … 876 981 877 982 int partition_primary_sequence_number(struct ldb_module *module, TALLOC_CTX *mem_ctx, 878 enum ldb_sequence_type type, uint64_t *seq_number) 983 uint64_t *seq_number, 984 struct ldb_request *parent) 879 985 { 880 986 int ret; 881 987 struct ldb_result *res; 882 988 struct ldb_seqnum_request *tseq; 883 struct ldb_request *treq;884 989 struct ldb_seqnum_result *seqr; 885 res = talloc_zero(mem_ctx, struct ldb_result); 886 if (res == NULL) { 990 991 tseq = talloc_zero(mem_ctx, struct ldb_seqnum_request); 992 if (tseq == NULL) { 887 993 return ldb_oom(ldb_module_get_ctx(module)); 888 994 } 889 tseq = talloc_zero(res, struct ldb_seqnum_request); 890 if (tseq == NULL) { 995 tseq->type = LDB_SEQ_HIGHEST_SEQ; 996 997 ret = dsdb_module_extended(module, tseq, &res, 998 LDB_EXTENDED_SEQUENCE_NUMBER, 999 tseq, 1000 DSDB_FLAG_NEXT_MODULE, 1001 parent); 1002 if (ret != LDB_SUCCESS) { 1003 talloc_free(tseq); 1004 return ret; 1005 } 1006 1007 seqr = talloc_get_type_abort(res->extended->data, 1008 struct ldb_seqnum_result); 1009 if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) { 891 1010 talloc_free(res); 892 return ldb_oom(ldb_module_get_ctx(module)); 893 } 894 tseq->type = type; 895 896 ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res, 897 LDB_EXTENDED_SEQUENCE_NUMBER, 898 tseq, 899 NULL, 900 res, 901 ldb_extended_default_callback, 902 NULL); 903 LDB_REQ_SET_LOCATION(treq); 904 if (ret != LDB_SUCCESS) { 905 talloc_free(res); 906 return ret; 907 } 908 909 ret = ldb_next_request(module, treq); 910 if (ret != LDB_SUCCESS) { 911 talloc_free(res); 912 return ret; 913 } 914 ret = ldb_wait(treq->handle, LDB_WAIT_ALL); 915 if (ret != LDB_SUCCESS) { 916 talloc_free(res); 917 return ret; 918 } 919 920 seqr = talloc_get_type(res->extended->data, 921 struct ldb_seqnum_result); 922 if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) { 923 ret = LDB_ERR_OPERATIONS_ERROR; 924 ldb_set_errstring(ldb_module_get_ctx(module), "Primary backend in partitions module returned a timestamp based seq number (must return a normal number)"); 925 talloc_free(res); 926 return ret; 927 } else { 928 *seq_number = seqr->seq_num; 929 } 930 talloc_free(res); 1011 return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR, 1012 "Primary backend in partition module returned a timestamp based seq"); 1013 } 1014 1015 *seq_number = seqr->seq_num; 1016 talloc_free(tseq); 931 1017 return LDB_SUCCESS; 932 1018 } 933 1019 934 /* FIXME: This function is still semi-async */ 935 static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req) 1020 1021 /* 1022 * Older version of sequence number as sum of sequence numbers for each partition 1023 */ 1024 int partition_sequence_number_from_partitions(struct ldb_module *module, 1025 uint64_t *seqr) 936 1026 { 937 1027 int ret; 938 1028 unsigned int i; 939 1029 uint64_t seq_number = 0; 940 uint64_t timestamp_sequence = 0;941 uint64_t timestamp = 0;942 1030 struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module), 943 1031 struct partition_private_data); 944 struct ldb_seqnum_request *seq; 945 struct ldb_seqnum_result *seqr; 946 struct ldb_request *treq; 947 struct ldb_seqnum_request *tseq; 948 struct ldb_seqnum_result *tseqr; 949 struct ldb_extended *ext; 950 struct ldb_result *res; 951 struct dsdb_partition *p; 952 953 p = find_partition(data, NULL, req); 954 if (p != NULL) { 955 /* the caller specified what partition they want the 956 * sequence number operation on - just pass it on 957 */ 958 return ldb_next_request(p->module, req); 959 } 960 961 seq = talloc_get_type(req->op.extended.data, struct ldb_seqnum_request); 962 963 switch (seq->type) { 964 case LDB_SEQ_NEXT: 965 case LDB_SEQ_HIGHEST_SEQ: 966 967 ret = partition_primary_sequence_number(module, req, seq->type, &seq_number); 968 if (ret != LDB_SUCCESS) { 969 return ret; 970 } 971 972 /* Skip the lot if 'data' isn't here yet (initialisation) */ 973 for (i=0; data && data->partitions && data->partitions[i]; i++) { 974 975 res = talloc_zero(req, struct ldb_result); 976 if (res == NULL) { 977 return ldb_oom(ldb_module_get_ctx(module)); 978 } 979 tseq = talloc_zero(res, struct ldb_seqnum_request); 980 if (tseq == NULL) { 981 talloc_free(res); 982 return ldb_oom(ldb_module_get_ctx(module)); 983 } 984 tseq->type = seq->type; 985 986 ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res, 987 LDB_EXTENDED_SEQUENCE_NUMBER, 988 tseq, 989 NULL, 990 res, 991 ldb_extended_default_callback, 992 req); 993 LDB_REQ_SET_LOCATION(treq); 994 if (ret != LDB_SUCCESS) { 995 talloc_free(res); 996 return ret; 997 } 998 999 ret = ldb_request_add_control(treq, 1000 DSDB_CONTROL_CURRENT_PARTITION_OID, 1001 false, data->partitions[i]->ctrl); 1002 if (ret != LDB_SUCCESS) { 1003 talloc_free(res); 1004 return ret; 1005 } 1006 1007 ret = partition_request(data->partitions[i]->module, treq); 1008 if (ret != LDB_SUCCESS) { 1009 talloc_free(res); 1010 return ret; 1011 } 1012 ret = ldb_wait(treq->handle, LDB_WAIT_ALL); 1013 if (ret != LDB_SUCCESS) { 1014 talloc_free(res); 1015 return ret; 1016 } 1017 tseqr = talloc_get_type(res->extended->data, 1018 struct ldb_seqnum_result); 1019 if (tseqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) { 1020 timestamp_sequence = MAX(timestamp_sequence, 1021 tseqr->seq_num); 1022 } else { 1023 seq_number += tseqr->seq_num; 1024 } 1025 talloc_free(res); 1026 } 1027 /* fall through */ 1028 case LDB_SEQ_HIGHEST_TIMESTAMP: 1029 1030 res = talloc_zero(req, struct ldb_result); 1032 1033 ret = partition_primary_sequence_number(module, data, &seq_number, NULL); 1034 if (ret != LDB_SUCCESS) { 1035 return ret; 1036 } 1037 1038 /* Skip the lot if 'data' isn't here yet (initialisation) */ 1039 for (i=0; data && data->partitions && data->partitions[i]; i++) { 1040 struct ldb_seqnum_request *tseq; 1041 struct ldb_seqnum_result *tseqr; 1042 struct ldb_request *treq; 1043 struct ldb_result *res = talloc_zero(data, struct ldb_result); 1031 1044 if (res == NULL) { 1032 1045 return ldb_oom(ldb_module_get_ctx(module)); 1033 1046 } 1034 1035 1047 tseq = talloc_zero(res, struct ldb_seqnum_request); 1036 1048 if (tseq == NULL) { … … 1038 1050 return ldb_oom(ldb_module_get_ctx(module)); 1039 1051 } 1040 tseq->type = LDB_SEQ_HIGHEST_ TIMESTAMP;1041 1052 tseq->type = LDB_SEQ_HIGHEST_SEQ; 1053 1042 1054 ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res, 1043 1055 LDB_EXTENDED_SEQUENCE_NUMBER, … … 1046 1058 res, 1047 1059 ldb_extended_default_callback, 1048 req);1060 NULL); 1049 1061 LDB_REQ_SET_LOCATION(treq); 1050 1062 if (ret != LDB_SUCCESS) { … … 1052 1064 return ret; 1053 1065 } 1054 1055 ret = ldb_next_request(module, treq);1066 1067 ret = partition_request(data->partitions[i]->module, treq); 1056 1068 if (ret != LDB_SUCCESS) { 1057 1069 talloc_free(res); … … 1063 1075 return ret; 1064 1076 } 1065 1066 1077 tseqr = talloc_get_type(res->extended->data, 1067 struct ldb_seqnum_result); 1068 timestamp = tseqr->seq_num; 1069 1078 struct ldb_seqnum_result); 1079 seq_number += tseqr->seq_num; 1070 1080 talloc_free(res); 1071 1072 /* Skip the lot if 'data' isn't here yet (initialisation) */ 1073 for (i=0; data && data->partitions && data->partitions[i]; i++) { 1074 1075 res = talloc_zero(req, struct ldb_result); 1076 if (res == NULL) { 1077 return ldb_oom(ldb_module_get_ctx(module)); 1078 } 1079 1080 tseq = talloc_zero(res, struct ldb_seqnum_request); 1081 if (tseq == NULL) { 1082 talloc_free(res); 1083 return ldb_oom(ldb_module_get_ctx(module)); 1084 } 1085 tseq->type = LDB_SEQ_HIGHEST_TIMESTAMP; 1086 1087 ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res, 1088 LDB_EXTENDED_SEQUENCE_NUMBER, 1089 tseq, 1090 NULL, 1091 res, 1092 ldb_extended_default_callback, 1093 req); 1094 LDB_REQ_SET_LOCATION(treq); 1095 if (ret != LDB_SUCCESS) { 1096 talloc_free(res); 1097 return ret; 1098 } 1099 1100 ret = ldb_request_add_control(treq, 1101 DSDB_CONTROL_CURRENT_PARTITION_OID, 1102 false, data->partitions[i]->ctrl); 1103 if (ret != LDB_SUCCESS) { 1104 talloc_free(res); 1105 return ret; 1106 } 1107 1108 ret = partition_request(data->partitions[i]->module, treq); 1109 if (ret != LDB_SUCCESS) { 1110 talloc_free(res); 1111 return ret; 1112 } 1113 ret = ldb_wait(treq->handle, LDB_WAIT_ALL); 1114 if (ret != LDB_SUCCESS) { 1115 talloc_free(res); 1116 return ret; 1117 } 1118 1119 tseqr = talloc_get_type(res->extended->data, 1120 struct ldb_seqnum_result); 1121 timestamp = MAX(timestamp, tseqr->seq_num); 1122 1123 talloc_free(res); 1124 } 1125 1081 } 1082 1083 *seqr = seq_number; 1084 return LDB_SUCCESS; 1085 } 1086 1087 1088 /* 1089 * Newer version of sequence number using metadata tdb 1090 */ 1091 static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req) 1092 { 1093 struct ldb_extended *ext; 1094 struct ldb_seqnum_request *seq; 1095 struct ldb_seqnum_result *seqr; 1096 uint64_t seq_number; 1097 int ret; 1098 1099 seq = talloc_get_type_abort(req->op.extended.data, struct ldb_seqnum_request); 1100 switch (seq->type) { 1101 case LDB_SEQ_NEXT: 1102 ret = partition_metadata_sequence_number_increment(module, &seq_number); 1103 if (ret != LDB_SUCCESS) { 1104 return ret; 1105 } 1126 1106 break; 1107 1108 case LDB_SEQ_HIGHEST_SEQ: 1109 ret = partition_metadata_sequence_number(module, &seq_number); 1110 if (ret != LDB_SUCCESS) { 1111 return ret; 1112 } 1113 break; 1114 1115 case LDB_SEQ_HIGHEST_TIMESTAMP: 1116 return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR, 1117 "LDB_SEQ_HIGHEST_TIMESTAMP not supported"); 1127 1118 } 1128 1119 1129 1120 ext = talloc_zero(req, struct ldb_extended); 1130 1121 if (!ext) { 1131 return ldb_ oom(ldb_module_get_ctx(module));1122 return ldb_module_oom(module); 1132 1123 } 1133 1124 seqr = talloc_zero(ext, struct ldb_seqnum_result); 1134 1125 if (seqr == NULL) { 1135 1126 talloc_free(ext); 1136 return ldb_ oom(ldb_module_get_ctx(module));1127 return ldb_module_oom(module); 1137 1128 } 1138 1129 ext->oid = LDB_EXTENDED_SEQUENCE_NUMBER; 1139 1130 ext->data = seqr; 1140 1131 1141 switch (seq->type) { 1142 case LDB_SEQ_NEXT: 1143 case LDB_SEQ_HIGHEST_SEQ: 1144 1145 /* Has someone above set a timebase sequence? */ 1146 if (timestamp_sequence) { 1147 seqr->seq_num = (((unsigned long long)timestamp << 24) | (seq_number & 0xFFFFFF)); 1148 } else { 1149 seqr->seq_num = seq_number; 1150 } 1151 1152 if (timestamp_sequence > seqr->seq_num) { 1153 seqr->seq_num = timestamp_sequence; 1154 seqr->flags |= LDB_SEQ_TIMESTAMP_SEQUENCE; 1155 } 1156 1157 seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE; 1158 break; 1159 case LDB_SEQ_HIGHEST_TIMESTAMP: 1160 seqr->seq_num = timestamp; 1161 break; 1162 } 1163 1164 if (seq->type == LDB_SEQ_NEXT) { 1165 seqr->seq_num++; 1166 } 1132 seqr->seq_num = seq_number; 1133 seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE; 1167 1134 1168 1135 /* send request done */ … … 1183 1150 } 1184 1151 1185 /* see if we are still up-to-date */ 1186 ret = partition_reload_if_required(module, data, req); 1187 if (ret != LDB_SUCCESS) { 1188 return ret; 1152 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) == 0) { 1153 /* Update the metadata.tdb to increment the schema version if needed*/ 1154 DEBUG(10, ("Incrementing the sequence_number after schema_update_now\n")); 1155 ret = partition_metadata_inc_schema_sequence(module); 1156 return ldb_module_done(req, NULL, NULL, ret); 1189 1157 } 1190 1158 -
vendor/current/source4/dsdb/samdb/ldb_modules/partition.h
r740 r988 22 22 #include <ldb_errors.h> 23 23 #include <ldb_module.h> 24 #include "lib/tdb_wrap/tdb_wrap.h" 24 25 #include "dsdb/samdb/samdb.h" 25 26 #include "dsdb/samdb/ldb_modules/util.h" … … 32 33 const char *backend_url; 33 34 DATA_BLOB orig_record; 35 bool partial_replica; /* a GC partition */ 34 36 }; 35 37 … … 39 41 }; 40 42 43 struct partition_metadata { 44 struct tdb_wrap *db; 45 int in_transaction; 46 }; 47 41 48 struct partition_private_data { 42 49 struct dsdb_partition **partitions; 43 50 struct ldb_dn **replicate; 51 struct partition_metadata *metadata; 44 52 45 53 struct partition_module **modules; -
vendor/current/source4/dsdb/samdb/ldb_modules/partition_init.c
r740 r988 139 139 struct ldb_result *res; 140 140 struct ldb_context *ldb = ldb_module_get_ctx(module); 141 const char *attrs[] = { "partition", "replicateEntries", "modules", "ldapBackend", NULL }; 141 const char *attrs[] = { "partition", "replicateEntries", "modules", "ldapBackend", 142 "partialReplica", NULL }; 142 143 /* perform search for @PARTITION, looking for module, replicateEntries and ldapBackend */ 143 144 ret = dsdb_module_search_dn(module, mem_ctx, &res, … … 209 210 int ret; 210 211 211 (*partition) = talloc (mem_ctx, struct dsdb_partition);212 (*partition) = talloc_zero(mem_ctx, struct dsdb_partition); 212 213 if (!*partition) { 213 214 return ldb_oom(ldb); … … 384 385 struct ldb_message *msg; 385 386 struct ldb_message_element *partition_attributes; 387 struct ldb_message_element *partial_replicas; 386 388 TALLOC_CTX *mem_ctx; 387 389 … … 396 398 } 397 399 398 ret = partition_primary_sequence_number(module, mem_ctx, LDB_SEQ_HIGHEST_SEQ, &seq);400 ret = partition_primary_sequence_number(module, mem_ctx, &seq, parent); 399 401 if (ret != LDB_SUCCESS) { 400 402 talloc_free(mem_ctx); … … 415 417 416 418 partition_attributes = ldb_msg_find_element(msg, "partition"); 419 partial_replicas = ldb_msg_find_element(msg, "partialReplica"); 417 420 418 421 for (i=0; partition_attributes && i < partition_attributes->num_values; i++) { … … 514 517 partition->ctrl->dn = talloc_steal(partition->ctrl, dn_res->msgs[0]->dn); 515 518 talloc_free(dn_res); 519 if (data->ldapBackend) { 520 ret = dsdb_fix_dn_rdncase(ldb, partition->ctrl->dn); 521 if (ret) { 522 talloc_free(mem_ctx); 523 return ret; 524 } 525 } 516 526 } else if (ret != LDB_ERR_NO_SUCH_OBJECT) { 517 527 ldb_asprintf_errstring(ldb, … … 522 532 talloc_free(mem_ctx); 523 533 return ret; 534 } 535 536 /* see if it is a partial replica */ 537 for (j=0; partial_replicas && j<partial_replicas->num_values; j++) { 538 struct ldb_dn *pa_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, &partial_replicas->values[j]); 539 if (pa_dn != NULL && ldb_dn_compare(pa_dn, partition->ctrl->dn) == 0) { 540 partition->partial_replica = true; 541 } 542 talloc_free(pa_dn); 524 543 } 525 544 … … 696 715 } 697 716 717 /* see if we are still up-to-date */ 718 ret = partition_reload_if_required(module, data, req); 719 if (ret != LDB_SUCCESS) { 720 return ret; 721 } 722 698 723 for (i=0; data->partitions && data->partitions[i]; i++) { 699 724 if (ldb_dn_compare(data->partitions[i]->ctrl->dn, dn) == 0) { … … 759 784 return ret; 760 785 } 786 787 if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) { 788 /* this new partition is a partial replica */ 789 ret = ldb_msg_add_empty(mod_msg, "partialReplica", LDB_FLAG_MOD_ADD, NULL); 790 if (ret != LDB_SUCCESS) { 791 return ret; 792 } 793 ret = ldb_msg_add_fmt(mod_msg, "partialReplica", "%s", ldb_dn_get_linearized(dn)); 794 if (ret != LDB_SUCCESS) { 795 return ret; 796 } 797 } 761 798 762 799 /* Perform modify on @PARTITION record */ … … 852 889 } 853 890 891 /* This loads metadata tdb. If it's missing, creates it */ 892 ret = partition_metadata_init(module); 893 if (ret != LDB_SUCCESS) { 894 return ret; 895 } 896 854 897 return ldb_next_init(module); 855 898 } -
vendor/current/source4/dsdb/samdb/ldb_modules/password_hash.c
r746 r988 44 44 #include "../lib/crypto/crypto.h" 45 45 #include "param/param.h" 46 #include "lib/krb5_wrap/krb5_samba.h" 46 47 47 48 /* If we have decided there is a reason to work on this request, then … … 96 97 bool hash_values; 97 98 bool userPassword; 99 bool pwd_last_set_bypass; 98 100 }; 99 101 … … 301 303 } 302 304 305 if (scpp == NULL) { 306 return ldb_error(ldb, 307 LDB_ERR_CONSTRAINT_VIOLATION, 308 "Primary:Packages missing"); 309 } 310 311 if (scpk == NULL) { 312 /* 313 * If Primary:Kerberos is missing w2k8r2 reboots 314 * when a password is changed. 315 */ 316 return ldb_error(ldb, 317 LDB_ERR_CONSTRAINT_VIOLATION, 318 "Primary:Kerberos missing"); 319 } 320 303 321 if (scpp) { 304 322 struct package_PackagesBlob *p; … … 629 647 struct ldb_context *ldb; 630 648 krb5_error_code krb5_ret; 631 Principal *salt_principal;632 krb5_ saltsalt;649 krb5_principal salt_principal; 650 krb5_data salt; 633 651 krb5_keyblock key; 634 652 krb5_data cleartext_data; 635 653 636 654 ldb = ldb_module_get_ctx(io->ac->module); 637 cleartext_data.data = io->n.cleartext_utf8->data;655 cleartext_data.data = (char *)io->n.cleartext_utf8->data; 638 656 cleartext_data.length = io->n.cleartext_utf8->length; 639 657 640 658 /* Many, many thanks to lukeh@padl.com for this 641 659 * algorithm, described in his Nov 10 2004 mail to 642 * samba-technical@ samba.org */660 * samba-technical@lists.samba.org */ 643 661 644 662 /* … … 664 682 } 665 683 666 krb5_ret = krb5_make_principal(io->smb_krb5_context->krb5_context,684 krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context, 667 685 &salt_principal, 668 686 io->ac->status->domain_data.realm, … … 682 700 } 683 701 684 krb5_ret = krb5_make_principal(io->smb_krb5_context->krb5_context,702 krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context, 685 703 &salt_principal, 686 704 io->ac->status->domain_data.realm, 687 705 user_principal_name, NULL); 688 706 } else { 689 krb5_ret = krb5_make_principal(io->smb_krb5_context->krb5_context,707 krb5_ret = smb_krb5_make_principal(io->smb_krb5_context->krb5_context, 690 708 &salt_principal, 691 709 io->ac->status->domain_data.realm, … … 704 722 * create salt from salt_principal 705 723 */ 706 krb5_ret = krb5_get_pw_salt(io->smb_krb5_context->krb5_context,724 krb5_ret = smb_krb5_get_pw_salt(io->smb_krb5_context->krb5_context, 707 725 salt_principal, &salt); 708 726 krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal); … … 717 735 /* create a talloc copy */ 718 736 io->g.salt = talloc_strndup(io->ac, 719 (char *)salt. saltvalue.data,720 salt. saltvalue.length);721 k rb5_free_salt(io->smb_krb5_context->krb5_context,salt);737 (char *)salt.data, 738 salt.length); 739 kerberos_free_data_contents(io->smb_krb5_context->krb5_context, &salt); 722 740 if (!io->g.salt) { 723 741 return ldb_oom(ldb); 724 742 } 725 salt.saltvalue.data = discard_const(io->g.salt); 726 salt.saltvalue.length = strlen(io->g.salt); 743 /* now use the talloced copy of the salt */ 744 salt.data = discard_const(io->g.salt); 745 salt.length = strlen(io->g.salt); 727 746 728 747 /* … … 730 749 * the salt and the cleartext password 731 750 */ 732 krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context, 733 ENCTYPE_AES256_CTS_HMAC_SHA1_96, 734 cleartext_data, 735 salt, 736 &key); 751 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context, 752 NULL, 753 &salt, 754 &cleartext_data, 755 ENCTYPE_AES256_CTS_HMAC_SHA1_96, 756 &key); 737 757 if (krb5_ret) { 738 758 ldb_asprintf_errstring(ldb, … … 744 764 } 745 765 io->g.aes_256 = data_blob_talloc(io->ac, 746 key.keyvalue.data,747 key.keyvalue.length);766 KRB5_KEY_DATA(&key), 767 KRB5_KEY_LENGTH(&key)); 748 768 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); 749 769 if (!io->g.aes_256.data) { … … 755 775 * the salt and the cleartext password 756 776 */ 757 krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context, 758 ENCTYPE_AES128_CTS_HMAC_SHA1_96, 759 cleartext_data, 760 salt, 761 &key); 777 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context, 778 NULL, 779 &salt, 780 &cleartext_data, 781 ENCTYPE_AES128_CTS_HMAC_SHA1_96, 782 &key); 762 783 if (krb5_ret) { 763 784 ldb_asprintf_errstring(ldb, … … 769 790 } 770 791 io->g.aes_128 = data_blob_talloc(io->ac, 771 key.keyvalue.data,772 key.keyvalue.length);792 KRB5_KEY_DATA(&key), 793 KRB5_KEY_LENGTH(&key)); 773 794 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); 774 795 if (!io->g.aes_128.data) { … … 780 801 * the salt and the cleartext password 781 802 */ 782 krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context, 783 ENCTYPE_DES_CBC_MD5, 784 cleartext_data, 785 salt, 786 &key); 803 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context, 804 NULL, 805 &salt, 806 &cleartext_data, 807 ENCTYPE_DES_CBC_MD5, 808 &key); 787 809 if (krb5_ret) { 788 810 ldb_asprintf_errstring(ldb, … … 794 816 } 795 817 io->g.des_md5 = data_blob_talloc(io->ac, 796 key.keyvalue.data,797 key.keyvalue.length);818 KRB5_KEY_DATA(&key), 819 KRB5_KEY_LENGTH(&key)); 798 820 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); 799 821 if (!io->g.des_md5.data) { … … 805 827 * the salt and the cleartext password 806 828 */ 807 krb5_ret = krb5_string_to_key_data_salt(io->smb_krb5_context->krb5_context, 808 ENCTYPE_DES_CBC_CRC, 809 cleartext_data, 810 salt, 811 &key); 829 krb5_ret = smb_krb5_create_key_from_string(io->smb_krb5_context->krb5_context, 830 NULL, 831 &salt, 832 &cleartext_data, 833 ENCTYPE_DES_CBC_CRC, 834 &key); 812 835 if (krb5_ret) { 813 836 ldb_asprintf_errstring(ldb, … … 819 842 } 820 843 io->g.des_crc = data_blob_talloc(io->ac, 821 key.keyvalue.data,822 key.keyvalue.length);844 KRB5_KEY_DATA(&key), 845 KRB5_KEY_LENGTH(&key)); 823 846 krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); 824 847 if (!io->g.des_crc.data) { … … 1664 1687 static int setup_last_set_field(struct setup_password_fields_io *io) 1665 1688 { 1689 const struct ldb_message *msg = NULL; 1690 1691 switch (io->ac->req->operation) { 1692 case LDB_ADD: 1693 msg = io->ac->req->op.add.message; 1694 break; 1695 case LDB_MODIFY: 1696 msg = io->ac->req->op.mod.message; 1697 break; 1698 default: 1699 return LDB_ERR_OPERATIONS_ERROR; 1700 break; 1701 } 1702 1703 if (io->ac->pwd_last_set_bypass) { 1704 struct ldb_message_element *el; 1705 1706 if (msg == NULL) { 1707 return LDB_ERR_CONSTRAINT_VIOLATION; 1708 } 1709 1710 el = ldb_msg_find_element(msg, "pwdLastSet"); 1711 if (el == NULL) { 1712 return LDB_ERR_CONSTRAINT_VIOLATION; 1713 } 1714 1715 io->g.last_set = samdb_result_nttime(msg, "pwdLastSet", 0); 1716 return LDB_SUCCESS; 1717 } 1718 1666 1719 /* set it as now */ 1667 1720 unix_to_nt_time(&io->g.last_set, time(NULL)); … … 1690 1743 g->cleartext_utf8->length, 1691 1744 (void *)&cleartext_utf16_blob->data, 1692 &cleartext_utf16_blob->length, 1693 false)) { 1745 &cleartext_utf16_blob->length)) { 1694 1746 if (g->cleartext_utf8->length != 0) { 1695 1747 talloc_free(cleartext_utf16_blob); … … 1718 1770 g->cleartext_utf16->length, 1719 1771 (void *)&cleartext_utf8_blob->data, 1720 &cleartext_utf8_blob->length, 1721 false)) { 1772 &cleartext_utf8_blob->length)) { 1722 1773 if (g->cleartext_utf16->length != 0) { 1723 1774 /* We must bail out here, the input wasn't even … … 1828 1879 } 1829 1880 1881 static int make_error_and_update_badPwdCount(struct setup_password_fields_io *io) 1882 { 1883 struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module); 1884 struct ldb_message *mod_msg = NULL; 1885 NTSTATUS status; 1886 int ret; 1887 1888 status = dsdb_update_bad_pwd_count(io->ac, ldb, 1889 io->ac->search_res->message, 1890 io->ac->dom_res->message, 1891 &mod_msg); 1892 if (!NT_STATUS_IS_OK(status)) { 1893 goto done; 1894 } 1895 1896 if (mod_msg == NULL) { 1897 goto done; 1898 } 1899 1900 /* 1901 * OK, horrible semantics ahead. 1902 * 1903 * - We need to abort any existing transaction 1904 * - create a transaction arround the badPwdCount update 1905 * - re-open the transaction so the upper layer 1906 * doesn't know what happened. 1907 * 1908 * This is needed because returning an error to the upper 1909 * layer will cancel the transaction and undo the badPwdCount 1910 * update. 1911 */ 1912 1913 /* 1914 * Checking errors here is a bit pointless. 1915 * What can we do if we can't end the transaction? 1916 */ 1917 ret = ldb_next_del_trans(io->ac->module); 1918 if (ret != LDB_SUCCESS) { 1919 ldb_debug(ldb, LDB_DEBUG_FATAL, 1920 "Failed to abort transaction prior to update of badPwdCount of %s: %s", 1921 ldb_dn_get_linearized(io->ac->search_res->message->dn), 1922 ldb_errstring(ldb)); 1923 /* 1924 * just return the original error 1925 */ 1926 goto done; 1927 } 1928 1929 /* Likewise, what should we do if we can't open a new transaction? */ 1930 ret = ldb_next_start_trans(io->ac->module); 1931 if (ret != LDB_SUCCESS) { 1932 ldb_debug(ldb, LDB_DEBUG_ERROR, 1933 "Failed to open transaction to update badPwdCount of %s: %s", 1934 ldb_dn_get_linearized(io->ac->search_res->message->dn), 1935 ldb_errstring(ldb)); 1936 /* 1937 * just return the original error 1938 */ 1939 goto done; 1940 } 1941 1942 ret = dsdb_module_modify(io->ac->module, mod_msg, 1943 DSDB_FLAG_NEXT_MODULE, 1944 io->ac->req); 1945 if (ret != LDB_SUCCESS) { 1946 ldb_debug(ldb, LDB_DEBUG_ERROR, 1947 "Failed to update badPwdCount of %s: %s", 1948 ldb_dn_get_linearized(io->ac->search_res->message->dn), 1949 ldb_errstring(ldb)); 1950 /* 1951 * We can only ignore this... 1952 */ 1953 } 1954 1955 ret = ldb_next_end_trans(io->ac->module); 1956 if (ret != LDB_SUCCESS) { 1957 ldb_debug(ldb, LDB_DEBUG_ERROR, 1958 "Failed to close transaction to update badPwdCount of %s: %s", 1959 ldb_dn_get_linearized(io->ac->search_res->message->dn), 1960 ldb_errstring(ldb)); 1961 /* 1962 * We can only ignore this... 1963 */ 1964 } 1965 1966 ret = ldb_next_start_trans(io->ac->module); 1967 if (ret != LDB_SUCCESS) { 1968 ldb_debug(ldb, LDB_DEBUG_ERROR, 1969 "Failed to open transaction after update of badPwdCount of %s: %s", 1970 ldb_dn_get_linearized(io->ac->search_res->message->dn), 1971 ldb_errstring(ldb)); 1972 /* 1973 * We can only ignore this... 1974 */ 1975 } 1976 1977 done: 1978 ret = LDB_ERR_CONSTRAINT_VIOLATION; 1979 ldb_asprintf_errstring(ldb, 1980 "%08X: %s - check_password_restrictions: " 1981 "The old password specified doesn't match!", 1982 W_ERROR_V(WERR_INVALID_PASSWORD), 1983 ldb_strerror(ret)); 1984 return ret; 1985 } 1986 1830 1987 static int check_password_restrictions(struct setup_password_fields_io *io) 1831 1988 { 1832 1989 struct ldb_context *ldb; 1833 1990 int ret; 1834 enum samr_ValidationStatus stat;1835 1991 1836 1992 ldb = ldb_module_get_ctx(io->ac->module); … … 1852 2008 has no problems at all */ 1853 2009 if (io->og.nt_hash) { 1854 if (!io->o.nt_hash) { 1855 ret = LDB_ERR_CONSTRAINT_VIOLATION; 1856 ldb_asprintf_errstring(ldb, 1857 "%08X: %s - check_password_restrictions: " 1858 "There's no old nt_hash, which is needed " 1859 "in order to change your password!", 1860 W_ERROR_V(WERR_INVALID_PASSWORD), 1861 ldb_strerror(ret)); 1862 return ret; 1863 } 1864 1865 if (memcmp(io->og.nt_hash->hash, io->o.nt_hash->hash, 16) != 0) { 1866 ret = LDB_ERR_CONSTRAINT_VIOLATION; 1867 ldb_asprintf_errstring(ldb, 1868 "%08X: %s - check_password_restrictions: " 1869 "The old password specified doesn't match!", 1870 W_ERROR_V(WERR_INVALID_PASSWORD), 1871 ldb_strerror(ret)); 1872 return ret; 2010 if (!io->o.nt_hash || memcmp(io->og.nt_hash->hash, io->o.nt_hash->hash, 16) != 0) { 2011 return make_error_and_update_badPwdCount(io); 1873 2012 } 1874 2013 … … 1881 2020 * (as the SAMR operations request it). */ 1882 2021 if (io->og.lm_hash) { 1883 if (!io->o.lm_hash && !nt_hash_checked) { 1884 ret = LDB_ERR_CONSTRAINT_VIOLATION; 1885 ldb_asprintf_errstring(ldb, 1886 "%08X: %s - check_password_restrictions: " 1887 "There's no old lm_hash, which is needed " 1888 "in order to change your password!", 1889 W_ERROR_V(WERR_INVALID_PASSWORD), 1890 ldb_strerror(ret)); 1891 return ret; 1892 } 1893 1894 if (io->o.lm_hash && 1895 memcmp(io->og.lm_hash->hash, io->o.lm_hash->hash, 16) != 0) { 1896 ret = LDB_ERR_CONSTRAINT_VIOLATION; 1897 ldb_asprintf_errstring(ldb, 1898 "%08X: %s - check_password_restrictions: " 1899 "The old password specified doesn't match!", 1900 W_ERROR_V(WERR_INVALID_PASSWORD), 1901 ldb_strerror(ret)); 1902 return ret; 2022 if ((!io->o.lm_hash && !nt_hash_checked) 2023 || (io->o.lm_hash && memcmp(io->og.lm_hash->hash, io->o.lm_hash->hash, 16) != 0)) { 2024 return make_error_and_update_badPwdCount(io); 1903 2025 } 1904 2026 } … … 1908 2030 /* FIXME: Is this right? */ 1909 2031 return LDB_SUCCESS; 2032 } 2033 2034 /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */ 2035 if ((io->u.pwdLastSet - io->ac->status->domain_data.minPwdAge > io->g.last_set) && 2036 !io->ac->pwd_reset) 2037 { 2038 ret = LDB_ERR_CONSTRAINT_VIOLATION; 2039 ldb_asprintf_errstring(ldb, 2040 "%08X: %s - check_password_restrictions: " 2041 "password is too young to change!", 2042 W_ERROR_V(WERR_PASSWORD_RESTRICTION), 2043 ldb_strerror(ret)); 2044 return ret; 1910 2045 } 1911 2046 … … 1916 2051 */ 1917 2052 if (io->n.cleartext_utf8 != NULL) { 1918 stat = samdb_check_password(io->n.cleartext_utf8, 1919 io->ac->status->domain_data.pwdProperties, 1920 io->ac->status->domain_data.minPwdLength); 1921 switch (stat) { 2053 enum samr_ValidationStatus vstat; 2054 vstat = samdb_check_password(io->n.cleartext_utf8, 2055 io->ac->status->domain_data.pwdProperties, 2056 io->ac->status->domain_data.minPwdLength); 2057 switch (vstat) { 1922 2058 case SAMR_VALIDATION_STATUS_SUCCESS: 1923 2059 /* perfect -> proceed! */ … … 1984 2120 /* checks the LM hash password history */ 1985 2121 for (i = 0; i < io->o.lm_history_len; i++) { 1986 ret = memcmp(io->n. nt_hash, io->o.lm_history[i].hash, 16);2122 ret = memcmp(io->n.lm_hash, io->o.lm_history[i].hash, 16); 1987 2123 if (ret == 0) { 1988 2124 ret = LDB_ERR_CONSTRAINT_VIOLATION; … … 2015 2151 "%08X: %s - check_password_restrictions: " 2016 2152 "password can't be changed on this account!", 2017 W_ERROR_V(WERR_PASSWORD_RESTRICTION),2018 ldb_strerror(ret));2019 return ret;2020 }2021 2022 /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */2023 if (io->u.pwdLastSet - io->ac->status->domain_data.minPwdAge > io->g.last_set) {2024 ret = LDB_ERR_CONSTRAINT_VIOLATION;2025 ldb_asprintf_errstring(ldb,2026 "%08X: %s - check_password_restrictions: "2027 "password is too young to change!",2028 2153 W_ERROR_V(WERR_PASSWORD_RESTRICTION), 2029 2154 ldb_strerror(ret)); … … 2103 2228 const struct ldb_val *quoted_utf16, *old_quoted_utf16, *lm_hash, *old_lm_hash; 2104 2229 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 2105 struct loadparm_context *lp_ctx = 2106 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"), 2107 struct loadparm_context); 2230 struct loadparm_context *lp_ctx = talloc_get_type( 2231 ldb_get_opaque(ldb, "loadparm"), struct loadparm_context); 2108 2232 int ret; 2109 2233 … … 2113 2237 2114 2238 if (smb_krb5_init_context(ac, 2115 ldb_get_event_context(ldb),2116 2239 (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"), 2117 2240 &io->smb_krb5_context) != 0) { … … 2138 2261 } 2139 2262 2263 if (io->u.userAccountControl & UF_INTERDOMAIN_TRUST_ACCOUNT) { 2264 struct ldb_control *permit_trust = ldb_request_get_control(ac->req, 2265 DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID); 2266 2267 if (permit_trust == NULL) { 2268 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; 2269 ldb_asprintf_errstring(ldb, 2270 "%08X: %s - setup_io: changing the interdomain trust password " 2271 "on %s not allowed via LDAP. Use LSA or NETLOGON", 2272 W_ERROR_V(WERR_ACCESS_DENIED), 2273 ldb_strerror(ret), 2274 ldb_dn_get_linearized(searched_msg->dn)); 2275 return ret; 2276 } 2277 } 2278 2140 2279 /* Only non-trust accounts have restrictions (possibly this test is the 2141 2280 * wrong way around, but we like to be restrictive if possible */ … … 2143 2282 & (UF_INTERDOMAIN_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT 2144 2283 | UF_SERVER_TRUST_ACCOUNT)); 2145 2146 if ((io->u.userAccountControl & UF_PASSWD_NOTREQD) != 0) {2147 /* see [MS-ADTS] 2.2.15 */2148 io->u.restrictions = 0;2149 }2150 2284 2151 2285 if (ac->userPassword) { … … 2160 2294 return ret; 2161 2295 } 2296 } 2297 2298 if (io->n.cleartext_utf8 != NULL) { 2299 struct ldb_val *cleartext_utf8_blob; 2300 char *p; 2301 2302 cleartext_utf8_blob = talloc(io->ac, struct ldb_val); 2303 if (!cleartext_utf8_blob) { 2304 return ldb_oom(ldb); 2305 } 2306 2307 *cleartext_utf8_blob = *io->n.cleartext_utf8; 2308 2309 /* make sure we have a null terminated string */ 2310 p = talloc_strndup(cleartext_utf8_blob, 2311 (const char *)io->n.cleartext_utf8->data, 2312 io->n.cleartext_utf8->length); 2313 if ((p == NULL) && (io->n.cleartext_utf8->length > 0)) { 2314 return ldb_oom(ldb); 2315 } 2316 cleartext_utf8_blob->data = (uint8_t *)p; 2317 2318 io->n.cleartext_utf8 = cleartext_utf8_blob; 2162 2319 } 2163 2320 … … 2198 2355 2199 2356 /* Checks and converts the actual "unicodePwd" attribute */ 2200 if (quoted_utf16 && 2357 if (!ac->hash_values && 2358 quoted_utf16 && 2201 2359 quoted_utf16->length >= 4 && 2202 2360 quoted_utf16->data[0] == '"' && … … 2254 2412 2255 2413 /* Checks and converts the previous "unicodePwd" attribute */ 2256 if (old_quoted_utf16 && 2414 if (!ac->hash_values && 2415 old_quoted_utf16 && 2257 2416 old_quoted_utf16->length >= 4 && 2258 2417 old_quoted_utf16->data[0] == '"' && … … 2485 2644 ctrl->critical = false; 2486 2645 } 2646 2647 ac->pwd_last_set_bypass = false; 2648 ctrl = ldb_request_get_control(ac->req, 2649 DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID); 2650 if (ctrl != NULL) { 2651 ac->pwd_last_set_bypass = true; 2652 2653 /* Mark the "bypass pwdLastSet" control as uncritical (done) */ 2654 ctrl->critical = false; 2655 } 2487 2656 } 2488 2657 … … 2538 2707 struct ph_context *ac; 2539 2708 struct loadparm_context *lp_ctx; 2540 int ret ;2709 int ret = LDB_SUCCESS; 2541 2710 2542 2711 ac = talloc_get_type(req->context, struct ph_context); … … 2587 2756 ac->status->domain_data.pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT; 2588 2757 2589 talloc_free(ares);2590 2591 2758 /* For a domain DN, this puts things in dotted notation */ 2592 2759 /* For builtin domains, this will give details for the host, … … 2603 2770 ac->status->reject_reason = SAM_PWD_CHANGE_NO_ERROR; 2604 2771 2772 if (ac->dom_res != NULL) { 2773 talloc_free(ares); 2774 2775 ldb_set_errstring(ldb, "Too many results"); 2776 ret = LDB_ERR_OPERATIONS_ERROR; 2777 goto done; 2778 } 2779 2780 ac->dom_res = talloc_steal(ac, ares); 2605 2781 ret = LDB_SUCCESS; 2606 2782 break; … … 2670 2846 "minPwdAge", 2671 2847 "minPwdLength", 2848 "lockoutThreshold", 2849 "lockOutObservationWindow", 2672 2850 NULL }; 2673 2851 int ret; … … 2701 2879 2702 2880 if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */ 2703 return ldb_next_request(module, req);2704 }2705 2706 /* If the caller is manipulating the local passwords directly, let them pass */2707 if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),2708 req->op.add.message->dn) == 0) {2709 2881 return ldb_next_request(module, req); 2710 2882 } … … 2903 3075 } 2904 3076 2905 /* If the caller is manipulating the local passwords directly, let them pass */2906 if (ldb_dn_compare_base(ldb_dn_new(req, ldb, LOCAL_BASE),2907 req->op.mod.message->dn) == 0) {2908 return ldb_next_request(module, req);2909 }2910 2911 3077 bypass = ldb_request_get_control(req, 2912 3078 DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID); … … 3087 3253 struct ldb_context *ldb; 3088 3254 struct ph_context *ac; 3089 int ret ;3255 int ret = LDB_SUCCESS; 3090 3256 3091 3257 ac = talloc_get_type(req->context, struct ph_context); … … 3167 3333 static const char * const attrs[] = { "objectClass", 3168 3334 "userAccountControl", 3335 "msDS-User-Account-Control-Computed", 3169 3336 "pwdLastSet", 3170 3337 "sAMAccountName", … … 3176 3343 "dBCSPwd", 3177 3344 "unicodePwd", 3345 "badPasswordTime", 3346 "badPwdCount", 3347 "lockoutTime", 3178 3348 NULL }; 3179 3349 struct ldb_request *search_req; … … 3229 3399 } 3230 3400 3231 /* Get the old password from the database */ 3232 status = samdb_result_passwords(io.ac, 3233 lp_ctx, 3234 discard_const_p(struct ldb_message, searched_msg), 3235 &io.o.lm_hash, &io.o.nt_hash); 3401 if (io.ac->pwd_reset) { 3402 /* Get the old password from the database */ 3403 status = samdb_result_passwords_no_lockout(io.ac, 3404 lp_ctx, 3405 discard_const_p(struct ldb_message, searched_msg), 3406 &io.o.lm_hash, 3407 &io.o.nt_hash); 3408 } else { 3409 /* Get the old password from the database */ 3410 status = samdb_result_passwords(io.ac, 3411 lp_ctx, 3412 discard_const_p(struct ldb_message, searched_msg), 3413 &io.o.lm_hash, &io.o.nt_hash); 3414 } 3415 3416 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) { 3417 ldb_asprintf_errstring(ldb, 3418 "%08X: check_password: " 3419 "Password change not permitted, account locked out!", 3420 W_ERROR_V(WERR_ACCOUNT_LOCKED_OUT)); 3421 return LDB_ERR_CONSTRAINT_VIOLATION; 3422 } 3423 3236 3424 if (!NT_STATUS_IS_OK(status)) { 3425 /* 3426 * This only happens if the database has gone weird, 3427 * not if we are just missing the passwords 3428 */ 3237 3429 return ldb_operr(ldb); 3238 3430 } -
vendor/current/source4/dsdb/samdb/ldb_modules/proxy.c
r740 r988 139 139 140 140 ret = ldb_connect(proxy->upstream, url, 0, NULL); 141 if (ret != 0) {141 if (ret != LDB_SUCCESS) { 142 142 ldb_debug(ldb, LDB_DEBUG_FATAL, "proxy failed to connect to %s\n", url); 143 143 goto failed; … … 340 340 341 341 newtree = proxy_convert_tree(ac, proxy, req->op.search.tree); 342 if (newtree == NULL) { 343 goto failed; 344 } 342 345 343 346 /* convert the basedn of this search */ -
vendor/current/source4/dsdb/samdb/ldb_modules/ranged_results.c
r740 r988 96 96 char *p, *new_attr; 97 97 const char *end_str; 98 unsigned int start, end , orig_num_values;98 unsigned int start, end; 99 99 struct ldb_message_element *el; 100 100 struct ldb_val *orig_values; … … 147 147 } else { 148 148 orig_values = el->values; 149 orig_num_values = el->num_values;150 149 151 150 if ((start + end < start) || (start + end < end)) { -
vendor/current/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
r740 r988 3 3 4 4 Copyright (C) Simo Sorce 2004-2008 5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 6 Copyright (C) Andrew Tridgell 2005 5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2013 6 Copyright (C) Andrew Tridgell 2005-2009 7 7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007 8 Copyright (C) Matthieu Patou <mat@samba.org> 2010 8 Copyright (C) Matthieu Patou <mat@samba.org> 2010-2011 9 9 10 10 This program is free software; you can redistribute it and/or modify … … 51 51 #include "lib/util/tsort.h" 52 52 53 /* 54 * It's 29/12/9999 at 23:59:59 UTC as specified in MS-ADTS 7.1.1.4.2 55 * Deleted Objects Container 56 */ 57 static const NTTIME DELETED_OBJECT_CONTAINER_CHANGE_TIME = 2650466015990000000ULL; 58 53 59 struct replmd_private { 54 60 TALLOC_CTX *la_ctx; … … 62 68 uint64_t mod_usn_urgent; 63 69 } *ncs; 70 struct ldb_dn *schema_dn; 64 71 }; 65 72 … … 87 94 uint64_t seq_num; 88 95 bool is_urgent; 96 97 bool isDeleted; 89 98 }; 99 100 static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar); 101 static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete); 90 102 91 103 enum urgent_situation { … … 95 107 }; 96 108 109 enum deletion_state { 110 OBJECT_NOT_DELETED=1, 111 OBJECT_DELETED=2, 112 OBJECT_RECYCLED=3, 113 OBJECT_TOMBSTONE=4, 114 OBJECT_REMOVED=5 115 }; 116 117 static void replmd_deletion_state(struct ldb_module *module, 118 const struct ldb_message *msg, 119 enum deletion_state *current_state, 120 enum deletion_state *next_state) 121 { 122 int ret; 123 bool enabled = false; 124 125 if (msg == NULL) { 126 *current_state = OBJECT_REMOVED; 127 if (next_state != NULL) { 128 *next_state = OBJECT_REMOVED; 129 } 130 return; 131 } 132 133 ret = dsdb_recyclebin_enabled(module, &enabled); 134 if (ret != LDB_SUCCESS) { 135 enabled = false; 136 } 137 138 if (ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")) { 139 if (!enabled) { 140 *current_state = OBJECT_TOMBSTONE; 141 if (next_state != NULL) { 142 *next_state = OBJECT_REMOVED; 143 } 144 return; 145 } 146 147 if (ldb_msg_check_string_attribute(msg, "isRecycled", "TRUE")) { 148 *current_state = OBJECT_RECYCLED; 149 if (next_state != NULL) { 150 *next_state = OBJECT_REMOVED; 151 } 152 return; 153 } 154 155 *current_state = OBJECT_DELETED; 156 if (next_state != NULL) { 157 *next_state = OBJECT_RECYCLED; 158 } 159 return; 160 } 161 162 *current_state = OBJECT_NOT_DELETED; 163 if (next_state == NULL) { 164 return; 165 } 166 167 if (enabled) { 168 *next_state = OBJECT_DELETED; 169 } else { 170 *next_state = OBJECT_TOMBSTONE; 171 } 172 } 97 173 98 174 static const struct { … … 147 223 148 224 149 static int replmd_replicated_apply_ next(struct replmd_replicated_request *ar);225 static int replmd_replicated_apply_isDeleted(struct replmd_replicated_request *ar); 150 226 151 227 /* … … 165 241 } 166 242 ldb_module_set_private(module, replmd_private); 243 244 replmd_private->schema_dn = ldb_get_schema_basedn(ldb); 167 245 168 246 return ldb_next_init(module); … … 255 333 256 334 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent); 257 if (ret != LDB_SUCCESS) { 335 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE && !bl->active) { 336 /* we allow LDB_ERR_NO_SUCH_ATTRIBUTE as success to 337 cope with possible corruption where the backlink has 338 already been removed */ 339 DEBUG(3,("WARNING: backlink from %s already removed from %s - %s\n", 340 ldb_dn_get_linearized(target_dn), 341 ldb_dn_get_linearized(source_dn), 342 ldb_errstring(ldb))); 343 ret = LDB_SUCCESS; 344 } else if (ret != LDB_SUCCESS) { 258 345 ldb_asprintf_errstring(ldb, "Failed to %s backlink from %s to %s - %s", 259 346 bl->active?"add":"remove", … … 387 474 388 475 if (ares->error != LDB_SUCCESS) { 389 DEBUG( 0,("%s failure. Error is: %s\n", __FUNCTION__, ldb_strerror(ares->error)));476 DEBUG(5,("%s failure. Error is: %s\n", __FUNCTION__, ldb_strerror(ares->error))); 390 477 return ldb_module_done(ac->req, controls, 391 478 ares->response, ares->error); … … 440 527 441 528 if (ac->apply_mode) { 442 talloc_free(ares); 443 ac->index_current++; 444 445 ret = replmd_replicated_apply_next(ac); 529 ret = replmd_replicated_apply_isDeleted(ac); 446 530 if (ret != LDB_SUCCESS) { 447 531 return ldb_module_done(ac->req, NULL, NULL, ret); … … 580 664 const uint32_t *rdn_attid) 581 665 { 582 if (m1->attid == m2->attid) { 666 /* 667 * This assignment seems inoccous, but it is critical for the 668 * system, as we need to do the comparisons as a unsigned 669 * quantity, not signed (enums are signed integers) 670 */ 671 uint32_t attid_1 = m1->attid; 672 uint32_t attid_2 = m2->attid; 673 674 if (attid_1 == attid_2) { 583 675 return 0; 584 676 } … … 589 681 * which means m1 is greater than m2 590 682 */ 591 if ( m1->attid== *rdn_attid) {683 if (attid_1 == *rdn_attid) { 592 684 return 1; 593 685 } … … 598 690 * which means m2 is greater than m1 599 691 */ 600 if ( m2->attid== *rdn_attid) {692 if (attid_2 == *rdn_attid) { 601 693 return -1; 602 694 } 603 695 604 return m1->attid > m2->attid ? 1 : -1; 605 } 606 607 static int replmd_replPropertyMetaDataCtr1_sort(struct replPropertyMetaDataCtr1 *ctr1, 608 const struct dsdb_schema *schema, 609 struct ldb_dn *dn) 696 /* 697 * See above regarding this being an unsigned comparison. 698 * Otherwise when the high bit is set on non-standard 699 * attributes, they would end up first, before objectClass 700 * (0). 701 */ 702 return attid_1 > attid_2 ? 1 : -1; 703 } 704 705 static int replmd_replPropertyMetaDataCtr1_verify(struct ldb_context *ldb, 706 struct replPropertyMetaDataCtr1 *ctr1, 707 const struct dsdb_attribute *rdn_sa, 708 struct ldb_dn *dn) 709 { 710 if (ctr1->count == 0) { 711 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 712 "No elements found in replPropertyMetaData for %s!\n", 713 ldb_dn_get_linearized(dn)); 714 return LDB_ERR_CONSTRAINT_VIOLATION; 715 } 716 if (ctr1->array[ctr1->count - 1].attid != rdn_sa->attributeID_id) { 717 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 718 "No rDN found in replPropertyMetaData for %s!\n", 719 ldb_dn_get_linearized(dn)); 720 return LDB_ERR_CONSTRAINT_VIOLATION; 721 } 722 723 /* the objectClass attribute is value 0x00000000, so must be first */ 724 if (ctr1->array[0].attid != DRSUAPI_ATTID_objectClass) { 725 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 726 "No objectClass found in replPropertyMetaData for %s!\n", 727 ldb_dn_get_linearized(dn)); 728 return LDB_ERR_OBJECT_CLASS_VIOLATION; 729 } 730 731 return LDB_SUCCESS; 732 } 733 734 static int replmd_replPropertyMetaDataCtr1_sort_and_verify(struct ldb_context *ldb, 735 struct replPropertyMetaDataCtr1 *ctr1, 736 const struct dsdb_schema *schema, 737 struct ldb_dn *dn) 610 738 { 611 739 const char *rdn_name; … … 614 742 rdn_name = ldb_dn_get_rdn_name(dn); 615 743 if (!rdn_name) { 616 DEBUG(0,(__location__ ": No rDN for %s?\n", ldb_dn_get_linearized(dn))); 617 return LDB_ERR_OPERATIONS_ERROR; 744 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 745 __location__ ": No rDN for %s?\n", 746 ldb_dn_get_linearized(dn)); 747 return LDB_ERR_INVALID_DN_SYNTAX; 618 748 } 619 749 620 750 rdn_sa = dsdb_attribute_by_lDAPDisplayName(schema, rdn_name); 621 751 if (rdn_sa == NULL) { 622 DEBUG(0,(__location__ ": No sa found for rDN %s for %s\n", rdn_name, ldb_dn_get_linearized(dn))); 623 return LDB_ERR_OPERATIONS_ERROR; 752 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 753 __location__ ": No sa found for rDN %s for %s\n", 754 rdn_name, ldb_dn_get_linearized(dn)); 755 return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE; 624 756 } 625 757 … … 627 759 rdn_sa->attributeID_id, rdn_name, ldb_dn_get_linearized(dn))); 628 760 629 LDB_TYPESAFE_QSORT(ctr1->array, ctr1->count, &rdn_sa->attributeID_id, replmd_replPropertyMetaData1_attid_sort);630 631 return LDB_SUCCESS;761 LDB_TYPESAFE_QSORT(ctr1->array, ctr1->count, &rdn_sa->attributeID_id, 762 replmd_replPropertyMetaData1_attid_sort); 763 return replmd_replPropertyMetaDataCtr1_verify(ldb, ctr1, rdn_sa, dn); 632 764 } 633 765 … … 737 869 static int replmd_add(struct ldb_module *module, struct ldb_request *req) 738 870 { 871 struct samldb_msds_intid_persistant *msds_intid_struct; 739 872 struct ldb_context *ldb; 740 873 struct ldb_control *control; … … 758 891 bool remove_current_guid = false; 759 892 bool is_urgent = false; 893 bool is_schema_nc = false; 760 894 struct ldb_message_element *objectclass_el; 895 struct replmd_private *replmd_private = 896 talloc_get_type_abort(ldb_module_get_private(module), struct replmd_private); 761 897 762 898 /* check if there's a show relax control (used by provision to say 'I know what I'm doing') */ … … 873 1009 } 874 1010 1011 is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0; 1012 875 1013 for (i=0; i < msg->num_elements; i++) { 876 1014 struct ldb_message_element *e = &msg->elements[i]; … … 907 1045 } 908 1046 909 m->attid = sa->attributeID_id; 910 m->version = 1; 911 m->originating_change_time = now; 1047 m->attid = dsdb_attribute_get_attid(sa, is_schema_nc); 1048 m->version = 1; 1049 if (m->attid == 0x20030) { 1050 const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn); 1051 const char* rdn; 1052 1053 if (rdn_val == NULL) { 1054 ldb_oom(ldb); 1055 talloc_free(ac); 1056 return LDB_ERR_OPERATIONS_ERROR; 1057 } 1058 1059 rdn = (const char*)rdn_val->data; 1060 if (strcmp(rdn, "Deleted Objects") == 0) { 1061 /* 1062 * Set the originating_change_time to 29/12/9999 at 23:59:59 1063 * as specified in MS-ADTS 7.1.1.4.2 Deleted Objects Container 1064 */ 1065 m->originating_change_time = DELETED_OBJECT_CONTAINER_CHANGE_TIME; 1066 } else { 1067 m->originating_change_time = now; 1068 } 1069 } else { 1070 m->originating_change_time = now; 1071 } 912 1072 m->originating_invocation_id = *our_invocation_id; 913 1073 m->originating_usn = ac->seq_num; … … 922 1082 * sort meta data array, and move the rdn attribute entry to the end 923 1083 */ 924 ret = replmd_replPropertyMetaDataCtr1_sort(&nmd.ctr.ctr1, ac->schema, msg->dn); 925 if (ret != LDB_SUCCESS) { 1084 ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &nmd.ctr.ctr1, ac->schema, msg->dn); 1085 if (ret != LDB_SUCCESS) { 1086 ldb_asprintf_errstring(ldb, "%s: error during direct ADD: %s", __func__, ldb_errstring(ldb)); 926 1087 talloc_free(ac); 927 1088 return ret; … … 977 1138 replmd_ldb_message_sort(msg, ac->schema); 978 1139 1140 /* 1141 * Assert that we do have an objectClass 1142 */ 979 1143 objectclass_el = ldb_msg_find_element(msg, "objectClass"); 1144 if (objectclass_el == NULL) { 1145 ldb_asprintf_errstring(ldb, __location__ 1146 ": objectClass missing on %s\n", 1147 ldb_dn_get_linearized(msg->dn)); 1148 talloc_free(ac); 1149 return LDB_ERR_OBJECT_CLASS_VIOLATION; 1150 } 980 1151 is_urgent = replmd_check_urgent_objectclass(objectclass_el, 981 1152 REPL_URGENT_ON_CREATE); … … 1017 1188 control->critical = 0; 1018 1189 } 1019 1190 if (ldb_dn_compare_base(replmd_private->schema_dn, req->op.add.message->dn) != 0) { 1191 1192 /* Update the usn in the SAMLDB_MSDS_INTID_OPAQUE opaque */ 1193 msds_intid_struct = (struct samldb_msds_intid_persistant *) ldb_get_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE); 1194 if (msds_intid_struct) { 1195 msds_intid_struct->usn = ac->seq_num; 1196 } 1197 } 1020 1198 /* go on with the call chain */ 1021 1199 return ldb_next_request(module, down_req); … … 1034 1212 uint64_t *seq_num, 1035 1213 const struct GUID *our_invocation_id, 1036 NTTIME now) 1214 NTTIME now, 1215 bool is_schema_nc, 1216 struct ldb_request *req) 1037 1217 { 1038 1218 uint32_t i; 1039 1219 const struct dsdb_attribute *a; 1040 1220 struct replPropertyMetaData1 *md1; 1221 bool may_skip = false; 1222 uint32_t attid; 1041 1223 1042 1224 a = dsdb_attribute_by_lDAPDisplayName(schema, el->name); 1043 1225 if (a == NULL) { 1226 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) { 1227 /* allow this to make it possible for dbcheck 1228 to remove bad attributes */ 1229 return LDB_SUCCESS; 1230 } 1231 1044 1232 DEBUG(0,(__location__ ": Unable to find attribute %s in schema\n", 1045 1233 el->name)); … … 1047 1235 } 1048 1236 1237 attid = dsdb_attribute_get_attid(a, is_schema_nc); 1238 1049 1239 if ((a->systemFlags & DS_FLAG_ATTR_NOT_REPLICATED) || (a->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED)) { 1050 1240 return LDB_SUCCESS; 1051 1241 } 1052 1242 1053 /* if the attribute's value haven't changed then return LDB_SUCCESS */ 1054 if (old_el != NULL && ldb_msg_element_compare(el, old_el) == 0) { 1055 return LDB_SUCCESS; 1243 /* 1244 * if the attribute's value haven't changed, and this isn't 1245 * just a delete of everything then return LDB_SUCCESS Unless 1246 * we have the provision control or if the attribute is 1247 * interSiteTopologyGenerator as this page explain: 1248 * http://support.microsoft.com/kb/224815 this attribute is 1249 * periodicaly written by the DC responsible for the intersite 1250 * generation in a given site 1251 * 1252 * Unchanged could be deleting or replacing an already-gone 1253 * thing with an unconstrained delete/empty replace or a 1254 * replace with the same value, but not an add with the same 1255 * value because that could be about adding a duplicate (which 1256 * is for someone else to error out on). 1257 */ 1258 if (old_el != NULL && ldb_msg_element_equal_ordered(el, old_el)) { 1259 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE) { 1260 may_skip = true; 1261 } 1262 } else if (old_el == NULL && el->num_values == 0) { 1263 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE) { 1264 may_skip = true; 1265 } else if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) { 1266 may_skip = true; 1267 } 1268 } 1269 1270 if (may_skip) { 1271 if (strcmp(el->name, "interSiteTopologyGenerator") != 0 && 1272 !ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID)) { 1273 /* 1274 * allow this to make it possible for dbcheck 1275 * to rebuild broken metadata 1276 */ 1277 return LDB_SUCCESS; 1278 } 1056 1279 } 1057 1280 1058 1281 for (i=0; i<omd->ctr.ctr1.count; i++) { 1059 if (a->attributeID_id == omd->ctr.ctr1.array[i].attid) break; 1282 /* 1283 * First check if we find it under the msDS-IntID, 1284 * then check if we find it under the OID and 1285 * prefixMap ID. 1286 * 1287 * This allows the administrator to simply re-write 1288 * the attributes and so restore replication, which is 1289 * likely what they will try to do. 1290 */ 1291 if (attid == omd->ctr.ctr1.array[i].attid) { 1292 break; 1293 } 1294 1295 if (a->attributeID_id == omd->ctr.ctr1.array[i].attid) { 1296 break; 1297 } 1060 1298 } 1061 1299 … … 1096 1334 md1 = &omd->ctr.ctr1.array[i]; 1097 1335 md1->version++; 1098 md1->attid = a->attributeID_id; 1099 md1->originating_change_time = now; 1336 md1->attid = attid; 1337 if (md1->attid == 0x20030) { 1338 const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn); 1339 const char* rdn; 1340 1341 if (rdn_val == NULL) { 1342 ldb_oom(ldb); 1343 return LDB_ERR_OPERATIONS_ERROR; 1344 } 1345 1346 rdn = (const char*)rdn_val->data; 1347 if (strcmp(rdn, "Deleted Objects") == 0) { 1348 /* 1349 * Set the originating_change_time to 29/12/9999 at 23:59:59 1350 * as specified in MS-ADTS 7.1.1.4.2 Deleted Objects Container 1351 */ 1352 md1->originating_change_time = DELETED_OBJECT_CONTAINER_CHANGE_TIME; 1353 } else { 1354 md1->originating_change_time = now; 1355 } 1356 } else { 1357 md1->originating_change_time = now; 1358 } 1100 1359 md1->originating_invocation_id = *our_invocation_id; 1101 1360 md1->originating_usn = *seq_num; … … 1127 1386 const struct dsdb_schema *schema, 1128 1387 struct ldb_request *req, 1388 const char * const *rename_attrs, 1129 1389 struct ldb_message *msg, uint64_t *seq_num, 1130 time_t t, 1131 bool *is_urgent )1390 time_t t, bool is_schema_nc, 1391 bool *is_urgent, bool *rodc) 1132 1392 { 1133 1393 const struct ldb_val *omd_value; … … 1138 1398 const struct GUID *our_invocation_id; 1139 1399 int ret; 1140 const char *attrs[] = { "replPropertyMetaData", "*", NULL }; 1141 const char *attrs2[] = { "uSNChanged", "objectClass", NULL }; 1400 const char * const *attrs = NULL; 1401 const char * const attrs1[] = { "replPropertyMetaData", "*", NULL }; 1402 const char * const attrs2[] = { "uSNChanged", "objectClass", "instanceType", NULL }; 1142 1403 struct ldb_result *res; 1143 1404 struct ldb_context *ldb; 1144 1405 struct ldb_message_element *objectclass_el; 1145 1406 enum urgent_situation situation; 1146 bool rodc, rmd_is_provided; 1407 bool rmd_is_provided; 1408 bool rmd_is_just_resorted = false; 1409 1410 if (rename_attrs) { 1411 attrs = rename_attrs; 1412 } else { 1413 attrs = attrs1; 1414 } 1147 1415 1148 1416 ldb = ldb_module_get_ctx(module); … … 1160 1428 if (ldb_request_get_control(req, DSDB_CONTROL_CHANGEREPLMETADATA_OID)) { 1161 1429 rmd_is_provided = true; 1430 if (ldb_request_get_control(req, DSDB_CONTROL_CHANGEREPLMETADATA_RESORT_OID)) { 1431 rmd_is_just_resorted = true; 1432 } 1162 1433 } else { 1163 1434 rmd_is_provided = false; … … 1168 1439 if (ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")) { 1169 1440 situation = REPL_URGENT_ON_DELETE; 1441 } else if (rename_attrs) { 1442 situation = REPL_URGENT_ON_CREATE | REPL_URGENT_ON_DELETE; 1170 1443 } else { 1171 1444 situation = REPL_URGENT_ON_UPDATE; … … 1176 1449 /* We check that it's the only attribute that is provided 1177 1450 * (it's a rare case so it's better to keep the code simplier) 1178 * We also check that the highest local_usn is bigger than1451 * We also check that the highest local_usn is bigger or the same as 1179 1452 * uSNChanged. */ 1180 1453 uint64_t db_seq; … … 1186 1459 return LDB_ERR_OPERATIONS_ERROR; 1187 1460 } 1188 if (situation == REPL_URGENT_ON_DELETE) {1461 if (situation != REPL_URGENT_ON_UPDATE) { 1189 1462 DEBUG(0,(__location__ ": changereplmetada control can't be called when deleting an object\n")); 1190 1463 return LDB_ERR_OPERATIONS_ERROR; … … 1203 1476 return LDB_ERR_OPERATIONS_ERROR; 1204 1477 } 1205 *seq_num = find_max_local_usn(omd);1206 1478 1207 1479 ret = dsdb_module_search_dn(module, msg, &res, msg->dn, attrs2, … … 1212 1484 DSDB_SEARCH_REVEAL_INTERNALS, req); 1213 1485 1214 if (ret != LDB_SUCCESS || res->count != 1) { 1215 DEBUG(0,(__location__ ": Object %s failed to find uSNChanged\n", 1216 ldb_dn_get_linearized(msg->dn))); 1217 return LDB_ERR_OPERATIONS_ERROR; 1218 } 1219 1220 objectclass_el = ldb_msg_find_element(res->msgs[0], "objectClass"); 1221 if (is_urgent && replmd_check_urgent_objectclass(objectclass_el, 1222 situation)) { 1223 *is_urgent = true; 1224 } 1225 1226 db_seq = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNChanged", 0); 1227 if (*seq_num <= db_seq) { 1228 DEBUG(0,(__location__ ": changereplmetada control provided but max(local_usn)"\ 1229 " is less or equal to uSNChanged (max = %lld uSNChanged = %lld)\n", 1230 (long long)*seq_num, (long long)db_seq)); 1231 return LDB_ERR_OPERATIONS_ERROR; 1486 if (ret != LDB_SUCCESS) { 1487 return ret; 1488 } 1489 1490 if (rmd_is_just_resorted == false) { 1491 *seq_num = find_max_local_usn(omd); 1492 1493 db_seq = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNChanged", 0); 1494 1495 /* 1496 * The test here now allows for a new 1497 * replPropertyMetaData with no change, if was 1498 * just dbcheck re-sorting the values. 1499 */ 1500 if (*seq_num <= db_seq) { 1501 DEBUG(0,(__location__ ": changereplmetada control provided but max(local_usn)" \ 1502 " is less than uSNChanged (max = %lld uSNChanged = %lld)\n", 1503 (long long)*seq_num, (long long)db_seq)); 1504 return LDB_ERR_OPERATIONS_ERROR; 1505 } 1232 1506 } 1233 1507 … … 1244 1518 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT | 1245 1519 DSDB_SEARCH_REVEAL_INTERNALS, req); 1246 if (ret != LDB_SUCCESS || res->count != 1) { 1247 DEBUG(0,(__location__ ": Object %s failed to find replPropertyMetaData\n", 1248 ldb_dn_get_linearized(msg->dn))); 1249 return LDB_ERR_OPERATIONS_ERROR; 1250 } 1251 1252 objectclass_el = ldb_msg_find_element(res->msgs[0], "objectClass"); 1253 if (is_urgent && replmd_check_urgent_objectclass(objectclass_el, 1254 situation)) { 1255 *is_urgent = true; 1520 if (ret != LDB_SUCCESS) { 1521 return ret; 1256 1522 } 1257 1523 … … 1281 1547 old_el = ldb_msg_find_element(res->msgs[0], msg->elements[i].name); 1282 1548 ret = replmd_update_rpmd_element(ldb, msg, &msg->elements[i], old_el, &omd, schema, seq_num, 1283 our_invocation_id, now); 1549 our_invocation_id, 1550 now, is_schema_nc, 1551 req); 1284 1552 if (ret != LDB_SUCCESS) { 1285 1553 return ret; 1286 1554 } 1287 1555 1288 if ( is_urgent &&!*is_urgent && (situation == REPL_URGENT_ON_UPDATE)) {1556 if (!*is_urgent && (situation == REPL_URGENT_ON_UPDATE)) { 1289 1557 *is_urgent = replmd_check_urgent_attribute(&msg->elements[i]); 1290 1558 } … … 1292 1560 } 1293 1561 } 1562 1563 /* 1564 * Assert that we have an objectClass attribute - this is major 1565 * corruption if we don't have this! 1566 */ 1567 objectclass_el = ldb_msg_find_element(res->msgs[0], "objectClass"); 1568 if (objectclass_el != NULL) { 1569 /* 1570 * Now check if this objectClass means we need to do urgent replication 1571 */ 1572 if (!*is_urgent && replmd_check_urgent_objectclass(objectclass_el, 1573 situation)) { 1574 *is_urgent = true; 1575 } 1576 } else if (!ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) { 1577 ldb_asprintf_errstring(ldb, __location__ 1578 ": objectClass missing on %s\n", 1579 ldb_dn_get_linearized(msg->dn)); 1580 return LDB_ERR_OBJECT_CLASS_VIOLATION; 1581 } 1582 1294 1583 /* 1295 1584 * replmd_update_rpmd_element has done an update if the 1296 1585 * seq_num is set 1297 1586 */ 1298 if (*seq_num != 0 ) {1587 if (*seq_num != 0 || rmd_is_just_resorted == true) { 1299 1588 struct ldb_val *md_value; 1300 1589 struct ldb_message_element *el; 1301 1590 1302 1591 /*if we are RODC and this is a DRSR update then its ok*/ 1303 if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) { 1304 ret = samdb_rodc(ldb, &rodc); 1592 if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID) 1593 && !ldb_request_get_control(req, DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA)) { 1594 unsigned instanceType; 1595 1596 ret = samdb_rodc(ldb, rodc); 1305 1597 if (ret != LDB_SUCCESS) { 1306 1598 DEBUG(4, (__location__ ": unable to tell if we are an RODC\n")); 1307 } else if ( rodc) {1308 ldb_ asprintf_errstring(ldb, "RODC modify is forbidden\n");1599 } else if (*rodc) { 1600 ldb_set_errstring(ldb, "RODC modify is forbidden!"); 1309 1601 return LDB_ERR_REFERRAL; 1602 } 1603 1604 instanceType = ldb_msg_find_attr_as_uint(res->msgs[0], "instanceType", INSTANCE_TYPE_WRITE); 1605 if (!(instanceType & INSTANCE_TYPE_WRITE)) { 1606 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, 1607 "cannot change replicated attribute on partial replica"); 1310 1608 } 1311 1609 } … … 1317 1615 } 1318 1616 1319 ret = replmd_replPropertyMetaDataCtr1_sort (&omd.ctr.ctr1, schema, msg->dn);1617 ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &omd.ctr.ctr1, schema, msg->dn); 1320 1618 if (ret != LDB_SUCCESS) { 1619 ldb_asprintf_errstring(ldb, "%s: %s", __func__, ldb_errstring(ldb)); 1321 1620 return ret; 1322 1621 } … … 1426 1725 ldb_asprintf_errstring(ldb, "Unable to find GUID for DN %s\n", 1427 1726 ldb_dn_get_linearized(dn)); 1727 if (ret == LDB_ERR_NO_SUCH_OBJECT && 1728 LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE && 1729 ldb_attr_cmp(el->name, "member") == 0) { 1730 return LDB_ERR_UNWILLING_TO_PERFORM; 1731 } 1428 1732 return ret; 1429 1733 } … … 1571 1875 static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn, 1572 1876 struct dsdb_dn *old_dsdb_dn, const struct GUID *invocation_id, 1573 uint64_t seq_num, uint64_t local_usn, NTTIME nttime,1877 uint64_t usn, uint64_t local_usn, NTTIME nttime, 1574 1878 uint32_t version, bool deleted) 1575 1879 { … … 1594 1898 tval = data_blob_string_const(tstring); 1595 1899 1596 usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long) seq_num);1900 usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)usn); 1597 1901 if (!usn_string) { 1598 1902 return LDB_ERR_OPERATIONS_ERROR; … … 1625 1929 old_addtime = &tval; 1626 1930 } 1627 if (dsdb_dn != old_dsdb_dn) { 1931 if (dsdb_dn != old_dsdb_dn || 1932 ldb_dn_get_extended_component(dn, "RMD_ADDTIME") == NULL) { 1628 1933 ret = ldb_dn_set_extended_component(dn, "RMD_ADDTIME", old_addtime); 1629 1934 if (ret != LDB_SUCCESS) return ret; … … 1742 2047 el->name, GUID_string(tmp_ctx, p->guid)); 1743 2048 talloc_free(tmp_ctx); 1744 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 2049 /* error codes for 'member' need to be 2050 special cased */ 2051 if (ldb_attr_cmp(el->name, "member") == 0) { 2052 return LDB_ERR_ENTRY_ALREADY_EXISTS; 2053 } else { 2054 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 2055 } 1745 2056 } 1746 2057 ret = replmd_update_la_val(old_el->values, p->v, dns[i].dsdb_dn, p->dsdb_dn, … … 1854 2165 ldb_asprintf_errstring(ldb, "Attribute %s doesn't exist for target GUID %s", 1855 2166 el->name, GUID_string(tmp_ctx, p->guid)); 1856 return LDB_ERR_NO_SUCH_ATTRIBUTE; 2167 if (ldb_attr_cmp(el->name, "member") == 0) { 2168 return LDB_ERR_UNWILLING_TO_PERFORM; 2169 } else { 2170 return LDB_ERR_NO_SUCH_ATTRIBUTE; 2171 } 1857 2172 } 1858 2173 rmd_flags = dsdb_dn_rmd_flags(p2->dsdb_dn->dn); … … 1860 2175 ldb_asprintf_errstring(ldb, "Attribute %s already deleted for target GUID %s", 1861 2176 el->name, GUID_string(tmp_ctx, p->guid)); 1862 return LDB_ERR_NO_SUCH_ATTRIBUTE; 2177 if (ldb_attr_cmp(el->name, "member") == 0) { 2178 return LDB_ERR_UNWILLING_TO_PERFORM; 2179 } else { 2180 return LDB_ERR_NO_SUCH_ATTRIBUTE; 2181 } 1863 2182 } 1864 2183 } … … 1998 2317 old_num_values, p->guid, NULL)) != NULL) { 1999 2318 /* update in place */ 2000 ret = replmd_update_la_val(old_el->values, old_p->v, old_p->dsdb_dn,2319 ret = replmd_update_la_val(old_el->values, old_p->v, p->dsdb_dn, 2001 2320 old_p->dsdb_dn, invocation_id, 2002 2321 seq_num, seq_num, now, 0, false); … … 2120 2439 } 2121 2440 if ((schema_attr->linkID & 1) == 1) { 2441 if (parent && ldb_request_get_control(parent, DSDB_CONTROL_DBCHECK)) { 2442 continue; 2443 } 2122 2444 /* Odd is for the target. Illegal to modify */ 2123 2445 ldb_asprintf_errstring(ldb, … … 2142 2464 return LDB_ERR_UNWILLING_TO_PERFORM; 2143 2465 } 2466 if (dsdb_check_single_valued_link(schema_attr, el) != LDB_SUCCESS) { 2467 ldb_asprintf_errstring(ldb, 2468 "Attribute %s is single valued but more than one value has been supplied", 2469 el->name); 2470 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 2471 } else { 2472 el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK; 2473 } 2474 2475 2476 2144 2477 if (ret != LDB_SUCCESS) { 2145 2478 return ret; … … 2170 2503 static int replmd_modify(struct ldb_module *module, struct ldb_request *req) 2171 2504 { 2505 struct samldb_msds_intid_persistant *msds_intid_struct; 2172 2506 struct ldb_context *ldb; 2173 2507 struct replmd_replicated_request *ac; … … 2176 2510 time_t t = time(NULL); 2177 2511 int ret; 2178 bool is_urgent = false; 2179 struct loadparm_context *lp_ctx; 2180 char *referral; 2512 bool is_urgent = false, rodc = false; 2513 bool is_schema_nc = false; 2181 2514 unsigned int functional_level; 2182 const DATA_BLOB *guid_blob; 2515 const struct ldb_message_element *guid_el = NULL; 2516 struct ldb_control *sd_propagation_control; 2517 struct replmd_private *replmd_private = 2518 talloc_get_type(ldb_module_get_private(module), struct replmd_private); 2183 2519 2184 2520 /* do not manipulate our control entries */ … … 2187 2523 } 2188 2524 2525 sd_propagation_control = ldb_request_get_control(req, 2526 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); 2527 if (sd_propagation_control != NULL) { 2528 if (req->op.mod.message->num_elements != 1) { 2529 return ldb_module_operr(module); 2530 } 2531 ret = strcmp(req->op.mod.message->elements[0].name, 2532 "nTSecurityDescriptor"); 2533 if (ret != 0) { 2534 return ldb_module_operr(module); 2535 } 2536 2537 return ldb_next_request(module, req); 2538 } 2539 2189 2540 ldb = ldb_module_get_ctx(module); 2190 2541 2191 2542 ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n"); 2192 2543 2193 guid_ blob = ldb_msg_find_ldb_val(req->op.mod.message, "objectGUID");2194 if ( guid_blob != NULL) {2544 guid_el = ldb_msg_find_element(req->op.mod.message, "objectGUID"); 2545 if (guid_el != NULL) { 2195 2546 ldb_set_errstring(ldb, 2196 2547 "replmd_modify: it's not allowed to change the objectGUID!"); … … 2204 2555 2205 2556 functional_level = dsdb_functional_level(ldb); 2206 2207 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),2208 struct loadparm_context);2209 2557 2210 2558 /* we have to copy the message as the caller might have it as a const */ … … 2219 2567 ldb_msg_remove_attr(msg, "uSNChanged"); 2220 2568 2221 ret = replmd_update_rpmd(module, ac->schema, req, msg, &ac->seq_num, t, &is_urgent); 2222 if (ret == LDB_ERR_REFERRAL) { 2569 is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0; 2570 2571 ret = replmd_update_rpmd(module, ac->schema, req, NULL, 2572 msg, &ac->seq_num, t, is_schema_nc, 2573 &is_urgent, &rodc); 2574 if (rodc && (ret == LDB_ERR_REFERRAL)) { 2575 struct loadparm_context *lp_ctx; 2576 char *referral; 2577 2578 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"), 2579 struct loadparm_context); 2580 2223 2581 referral = talloc_asprintf(req, 2224 2582 "ldap://%s/%s", … … 2227 2585 ret = ldb_module_send_referral(req, referral); 2228 2586 talloc_free(ac); 2229 return ldb_module_done(req, NULL, NULL, ret);2587 return ret; 2230 2588 } 2231 2589 … … 2288 2646 if (ret != LDB_SUCCESS) { 2289 2647 talloc_free(ac); 2648 ldb_operr(ldb); 2290 2649 return ret; 2291 2650 } … … 2294 2653 if (ret != LDB_SUCCESS) { 2295 2654 talloc_free(ac); 2655 ldb_operr(ldb); 2296 2656 return ret; 2657 } 2658 } 2659 2660 if (!ldb_dn_compare_base(replmd_private->schema_dn, msg->dn)) { 2661 /* Update the usn in the SAMLDB_MSDS_INTID_OPAQUE opaque */ 2662 msds_intid_struct = (struct samldb_msds_intid_persistant *) ldb_get_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE); 2663 if (msds_intid_struct) { 2664 msds_intid_struct->usn = ac->seq_num; 2297 2665 } 2298 2666 } … … 2351 2719 { 2352 2720 struct ldb_context *ldb; 2353 struct replmd_replicated_request *ac;2354 2721 struct ldb_request *down_req; 2355 2722 struct ldb_message *msg; 2723 const struct dsdb_attribute *rdn_attr; 2724 const char *rdn_name; 2725 const struct ldb_val *rdn_val; 2726 const char *attrs[5] = { NULL, }; 2356 2727 time_t t = time(NULL); 2357 2728 int ret; 2358 2359 ac = talloc_get_type(req->context, struct replmd_replicated_request); 2729 bool is_urgent = false, rodc = false; 2730 bool is_schema_nc; 2731 struct replmd_replicated_request *ac = 2732 talloc_get_type(req->context, struct replmd_replicated_request); 2733 struct replmd_private *replmd_private = 2734 talloc_get_type(ldb_module_get_private(ac->module), 2735 struct replmd_private); 2736 2360 2737 ldb = ldb_module_get_ctx(ac->module); 2361 2738 … … 2373 2750 } 2374 2751 2375 /* Get a sequence number from the backend */2376 ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ac->seq_num);2377 if (ret != LDB_SUCCESS) {2378 return ret;2379 }2380 2381 2752 /* TODO: 2382 2753 * - replace the old object with the newly constructed one … … 2390 2761 2391 2762 msg->dn = ac->req->op.rename.newdn; 2763 2764 is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0; 2765 2766 rdn_name = ldb_dn_get_rdn_name(msg->dn); 2767 if (rdn_name == NULL) { 2768 talloc_free(ares); 2769 return ldb_module_done(ac->req, NULL, NULL, 2770 ldb_operr(ldb)); 2771 } 2772 2773 /* normalize the rdn attribute name */ 2774 rdn_attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, rdn_name); 2775 if (rdn_attr == NULL) { 2776 talloc_free(ares); 2777 return ldb_module_done(ac->req, NULL, NULL, 2778 ldb_operr(ldb)); 2779 } 2780 rdn_name = rdn_attr->lDAPDisplayName; 2781 2782 rdn_val = ldb_dn_get_rdn_val(msg->dn); 2783 if (rdn_val == NULL) { 2784 talloc_free(ares); 2785 return ldb_module_done(ac->req, NULL, NULL, 2786 ldb_operr(ldb)); 2787 } 2788 2789 if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { 2790 talloc_free(ares); 2791 return ldb_module_done(ac->req, NULL, NULL, 2792 ldb_oom(ldb)); 2793 } 2794 if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { 2795 talloc_free(ares); 2796 return ldb_module_done(ac->req, NULL, NULL, 2797 ldb_oom(ldb)); 2798 } 2799 if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { 2800 talloc_free(ares); 2801 return ldb_module_done(ac->req, NULL, NULL, 2802 ldb_oom(ldb)); 2803 } 2804 if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { 2805 talloc_free(ares); 2806 return ldb_module_done(ac->req, NULL, NULL, 2807 ldb_oom(ldb)); 2808 } 2809 2810 /* 2811 * here we let replmd_update_rpmd() only search for 2812 * the existing "replPropertyMetaData" and rdn_name attributes. 2813 * 2814 * We do not want the existing "name" attribute as 2815 * the "name" attribute needs to get the version 2816 * updated on rename even if the rdn value hasn't changed. 2817 * 2818 * This is the diff of the meta data, for a moved user 2819 * on a w2k8r2 server: 2820 * 2821 * # record 1 2822 * -dn: CN=sdf df,CN=Users,DC=bla,DC=base 2823 * +dn: CN=sdf df,OU=TestOU,DC=bla,DC=base 2824 * replPropertyMetaData: NDR: struct replPropertyMetaDataBlob 2825 * version : 0x00000001 (1) 2826 * reserved : 0x00000000 (0) 2827 * @@ -66,11 +66,11 @@ replPropertyMetaData: NDR: struct re 2828 * local_usn : 0x00000000000037a5 (14245) 2829 * array: struct replPropertyMetaData1 2830 * attid : DRSUAPI_ATTID_name (0x90001) 2831 * - version : 0x00000001 (1) 2832 * - originating_change_time : Wed Feb 9 17:20:49 2011 CET 2833 * + version : 0x00000002 (2) 2834 * + originating_change_time : Wed Apr 6 15:21:01 2011 CEST 2835 * originating_invocation_id: 0d36ca05-5507-4e62-aca3-354bab0d39e1 2836 * - originating_usn : 0x00000000000037a5 (14245) 2837 * - local_usn : 0x00000000000037a5 (14245) 2838 * + originating_usn : 0x0000000000003834 (14388) 2839 * + local_usn : 0x0000000000003834 (14388) 2840 * array: struct replPropertyMetaData1 2841 * attid : DRSUAPI_ATTID_userAccountControl (0x90008) 2842 * version : 0x00000004 (4) 2843 */ 2844 attrs[0] = "replPropertyMetaData"; 2845 attrs[1] = "objectClass"; 2846 attrs[2] = "instanceType"; 2847 attrs[3] = rdn_name; 2848 attrs[4] = NULL; 2849 2850 ret = replmd_update_rpmd(ac->module, ac->schema, req, attrs, 2851 msg, &ac->seq_num, t, 2852 is_schema_nc, &is_urgent, &rodc); 2853 if (rodc && (ret == LDB_ERR_REFERRAL)) { 2854 struct ldb_dn *olddn = ac->req->op.rename.olddn; 2855 struct loadparm_context *lp_ctx; 2856 char *referral; 2857 2858 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"), 2859 struct loadparm_context); 2860 2861 referral = talloc_asprintf(req, 2862 "ldap://%s/%s", 2863 lpcfg_dnsdomain(lp_ctx), 2864 ldb_dn_get_linearized(olddn)); 2865 ret = ldb_module_send_referral(req, referral); 2866 talloc_free(ares); 2867 return ldb_module_done(req, NULL, NULL, ret); 2868 } 2869 2870 if (ret != LDB_SUCCESS) { 2871 talloc_free(ares); 2872 return ldb_module_done(ac->req, NULL, NULL, ret); 2873 } 2874 2875 if (ac->seq_num == 0) { 2876 talloc_free(ares); 2877 return ldb_module_done(ac->req, NULL, NULL, 2878 ldb_error(ldb, ret, 2879 "internal error seq_num == 0")); 2880 } 2881 ac->is_urgent = is_urgent; 2392 2882 2393 2883 ret = ldb_build_mod_req(&down_req, ldb, ac, … … 2418 2908 if (ret != LDB_SUCCESS) { 2419 2909 talloc_free(ac); 2910 ldb_operr(ldb); 2420 2911 return ret; 2421 2912 } … … 2424 2915 if (ret != LDB_SUCCESS) { 2425 2916 talloc_free(ac); 2917 ldb_operr(ldb); 2426 2918 return ret; 2427 2919 } … … 2432 2924 2433 2925 /* 2434 remove links from objects that point at this object when an object 2435 is deleted 2926 * remove links from objects that point at this object when an object 2927 * is deleted. We remove it from the NEXT module per MS-DRSR 5.160 2928 * RemoveObj which states that link removal due to the object being 2929 * deleted is NOT an originating update - they just go away! 2930 * 2436 2931 */ 2437 2932 static int replmd_delete_remove_link(struct ldb_module *module, … … 2514 3009 This also handles the mapping of delete to a rename operation 2515 3010 to allow deletes to be replicated. 3011 3012 It also handles the incoming deleted objects, to ensure they are 3013 fully deleted here. In that case re_delete is true, and we do not 3014 use this as a signal to change the deleted state, just reinforce it. 3015 2516 3016 */ 2517 static int replmd_delete (struct ldb_module *module, struct ldb_request *req)3017 static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete) 2518 3018 { 2519 3019 int ret = LDB_ERR_OTHER; … … 2541 3041 "whenChanged", NULL}; 2542 3042 unsigned int i, el_count = 0; 2543 enum deletion_state { OBJECT_NOT_DELETED=1, OBJECT_DELETED=2, OBJECT_RECYCLED=3,2544 OBJECT_TOMBSTONE=4, OBJECT_REMOVED=5 };2545 3043 enum deletion_state deletion_state, next_deletion_state; 2546 bool enabled;2547 3044 2548 3045 if (ldb_dn_is_special(req->op.del.dn)) { 3046 return ldb_next_request(module, req); 3047 } 3048 3049 /* 3050 * We have to allow dbcheck to remove an object that 3051 * is beyond repair, and to do so totally. This could 3052 * mean we we can get a partial object from the other 3053 * DC, causing havoc, so dbcheck suggests 3054 * re-replication first. dbcheck sets both DBCHECK 3055 * and RELAX in this situation. 3056 */ 3057 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) 3058 && ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) { 3059 /* really, really remove it */ 2549 3060 return ldb_next_request(module, req); 2550 3061 } … … 2558 3069 schema = dsdb_get_schema(ldb, tmp_ctx); 2559 3070 if (!schema) { 3071 talloc_free(tmp_ctx); 2560 3072 return LDB_ERR_OPERATIONS_ERROR; 2561 3073 } … … 2571 3083 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req); 2572 3084 if (ret != LDB_SUCCESS) { 3085 ldb_asprintf_errstring(ldb_module_get_ctx(module), 3086 "repmd_delete: Failed to %s %s, because we failed to find it: %s", 3087 re_delete ? "re-delete" : "delete", 3088 ldb_dn_get_linearized(old_dn), 3089 ldb_errstring(ldb_module_get_ctx(module))); 2573 3090 talloc_free(tmp_ctx); 2574 3091 return ret; … … 2576 3093 old_msg = res->msgs[0]; 2577 3094 2578 2579 ret = dsdb_recyclebin_enabled(module, &enabled); 2580 if (ret != LDB_SUCCESS) { 2581 talloc_free(tmp_ctx); 2582 return ret; 2583 } 2584 2585 if (ldb_msg_check_string_attribute(old_msg, "isDeleted", "TRUE")) { 2586 if (!enabled) { 2587 deletion_state = OBJECT_TOMBSTONE; 2588 next_deletion_state = OBJECT_REMOVED; 2589 } else if (ldb_msg_check_string_attribute(old_msg, "isRecycled", "TRUE")) { 2590 deletion_state = OBJECT_RECYCLED; 2591 next_deletion_state = OBJECT_REMOVED; 2592 } else { 2593 deletion_state = OBJECT_DELETED; 2594 next_deletion_state = OBJECT_RECYCLED; 2595 } 2596 } else { 2597 deletion_state = OBJECT_NOT_DELETED; 2598 if (enabled) { 2599 next_deletion_state = OBJECT_DELETED; 2600 } else { 2601 next_deletion_state = OBJECT_TOMBSTONE; 2602 } 3095 replmd_deletion_state(module, old_msg, 3096 &deletion_state, 3097 &next_deletion_state); 3098 3099 /* This supports us noticing an incoming isDeleted and acting on it */ 3100 if (re_delete) { 3101 SMB_ASSERT(deletion_state > OBJECT_NOT_DELETED); 3102 next_deletion_state = deletion_state; 2603 3103 } 2604 3104 2605 3105 if (next_deletion_state == OBJECT_REMOVED) { 2606 struct auth_session_info *session_info = 2607 (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo"); 2608 if (security_session_user_level(session_info, NULL) != SECURITY_SYSTEM) { 2609 ldb_asprintf_errstring(ldb, "Refusing to delete deleted object %s", 2610 ldb_dn_get_linearized(old_msg->dn)); 2611 return LDB_ERR_UNWILLING_TO_PERFORM; 2612 } 2613 2614 /* it is already deleted - really remove it this time */ 2615 talloc_free(tmp_ctx); 2616 return ldb_next_request(module, req); 3106 /* 3107 * We have to prevent objects being deleted, even if 3108 * the administrator really wants them gone, as 3109 * without the tombstone, we can get a partial object 3110 * from the other DC, causing havoc. 3111 * 3112 * The only other valid case is when the 180 day 3113 * timeout has expired, when relax is specified. 3114 */ 3115 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) { 3116 /* it is already deleted - really remove it this time */ 3117 talloc_free(tmp_ctx); 3118 return ldb_next_request(module, req); 3119 } 3120 3121 ldb_asprintf_errstring(ldb, "Refusing to delete tombstone object %s. " 3122 "This check is to prevent corruption of the replicated state.", 3123 ldb_dn_get_linearized(old_msg->dn)); 3124 return LDB_ERR_UNWILLING_TO_PERFORM; 2617 3125 } 2618 3126 … … 2633 3141 msg->dn = old_dn; 2634 3142 2635 if (deletion_state == OBJECT_NOT_DELETED){ 2636 /* consider the SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE flag */ 2637 disallow_move_on_delete = 2638 (ldb_msg_find_attr_as_int(old_msg, "systemFlags", 0) 2639 & SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE); 2640 2641 /* work out where we will be renaming this object to */ 2642 if (!disallow_move_on_delete) { 2643 ret = dsdb_get_deleted_objects_dn(ldb, tmp_ctx, old_dn, 2644 &new_dn); 2645 if (ret != LDB_SUCCESS) { 2646 /* this is probably an attempted delete on a partition 2647 * that doesn't allow delete operations, such as the 2648 * schema partition */ 2649 ldb_asprintf_errstring(ldb, "No Deleted Objects container for DN %s", 2650 ldb_dn_get_linearized(old_dn)); 2651 talloc_free(tmp_ctx); 2652 return LDB_ERR_UNWILLING_TO_PERFORM; 2653 } 2654 } else { 3143 /* consider the SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE flag */ 3144 disallow_move_on_delete = 3145 (ldb_msg_find_attr_as_int(old_msg, "systemFlags", 0) 3146 & SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE); 3147 3148 /* work out where we will be renaming this object to */ 3149 if (!disallow_move_on_delete) { 3150 struct ldb_dn *deleted_objects_dn; 3151 ret = dsdb_get_deleted_objects_dn(ldb, tmp_ctx, old_dn, 3152 &deleted_objects_dn); 3153 3154 /* 3155 * We should not move objects if we can't find the 3156 * deleted objects DN. Not moving (or otherwise 3157 * harming) the Deleted Objects DN itself is handled 3158 * in the caller. 3159 */ 3160 if (re_delete && (ret != LDB_SUCCESS)) { 2655 3161 new_dn = ldb_dn_get_parent(tmp_ctx, old_dn); 2656 3162 if (new_dn == NULL) { … … 2659 3165 return LDB_ERR_OPERATIONS_ERROR; 2660 3166 } 2661 } 2662 3167 } else if (ret != LDB_SUCCESS) { 3168 /* this is probably an attempted delete on a partition 3169 * that doesn't allow delete operations, such as the 3170 * schema partition */ 3171 ldb_asprintf_errstring(ldb, "No Deleted Objects container for DN %s", 3172 ldb_dn_get_linearized(old_dn)); 3173 talloc_free(tmp_ctx); 3174 return LDB_ERR_UNWILLING_TO_PERFORM; 3175 } else { 3176 new_dn = deleted_objects_dn; 3177 } 3178 } else { 3179 new_dn = ldb_dn_get_parent(tmp_ctx, old_dn); 3180 if (new_dn == NULL) { 3181 ldb_module_oom(module); 3182 talloc_free(tmp_ctx); 3183 return LDB_ERR_OPERATIONS_ERROR; 3184 } 3185 } 3186 3187 if (deletion_state == OBJECT_NOT_DELETED) { 2663 3188 /* get the objects GUID from the search we just did */ 2664 3189 guid = samdb_result_guid(old_msg, "objectGUID"); … … 2666 3191 /* Add a formatted child */ 2667 3192 retb = ldb_dn_add_child_fmt(new_dn, "%s=%s\\0ADEL:%s", 2668 2669 2670 3193 rdn_name, 3194 ldb_dn_escape_value(tmp_ctx, *rdn_value), 3195 GUID_string(tmp_ctx, &guid)); 2671 3196 if (!retb) { 2672 DEBUG(0,(__location__ ": Unable to add a formatted child to dn: %s", 2673 ldb_dn_get_linearized(new_dn))); 3197 ldb_asprintf_errstring(ldb, __location__ 3198 ": Unable to add a formatted child to dn: %s", 3199 ldb_dn_get_linearized(new_dn)); 2674 3200 talloc_free(tmp_ctx); 2675 3201 return LDB_ERR_OPERATIONS_ERROR; … … 2678 3204 ret = ldb_msg_add_string(msg, "isDeleted", "TRUE"); 2679 3205 if (ret != LDB_SUCCESS) { 2680 DEBUG(0,(__location__ ": Failed to add isDeleted string to the msg\n"));2681 ldb_module_oom(module);3206 ldb_asprintf_errstring(ldb, __location__ 3207 ": Failed to add isDeleted string to the msg"); 2682 3208 talloc_free(tmp_ctx); 2683 3209 return ret; 2684 3210 } 2685 3211 msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE; 3212 } else { 3213 /* 3214 * No matter what has happened with other renames etc, try again to 3215 * get this to be under the deleted DN. See MS-DRSR 5.160 RemoveObj 3216 */ 3217 3218 struct ldb_dn *rdn = ldb_dn_copy(tmp_ctx, old_dn); 3219 retb = ldb_dn_remove_base_components(rdn, ldb_dn_get_comp_num(rdn) - 1); 3220 if (!retb) { 3221 ldb_asprintf_errstring(ldb, __location__ 3222 ": Unable to add a prepare rdn of %s", 3223 ldb_dn_get_linearized(rdn)); 3224 talloc_free(tmp_ctx); 3225 return LDB_ERR_OPERATIONS_ERROR; 3226 } 3227 SMB_ASSERT(ldb_dn_get_comp_num(rdn) == 1); 3228 3229 retb = ldb_dn_add_child(new_dn, rdn); 3230 if (!retb) { 3231 ldb_asprintf_errstring(ldb, __location__ 3232 ": Unable to add rdn %s to base dn: %s", 3233 ldb_dn_get_linearized(rdn), 3234 ldb_dn_get_linearized(new_dn)); 3235 talloc_free(tmp_ctx); 3236 return LDB_ERR_OPERATIONS_ERROR; 3237 } 2686 3238 } 2687 3239 … … 2703 3255 */ 2704 3256 2705 /* we need the storage form of the parent GUID */ 2706 ret = dsdb_module_search_dn(module, tmp_ctx, &parent_res, 2707 ldb_dn_get_parent(tmp_ctx, old_dn), NULL, 2708 DSDB_FLAG_NEXT_MODULE | 2709 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT | 2710 DSDB_SEARCH_REVEAL_INTERNALS| 2711 DSDB_SEARCH_SHOW_RECYCLED, req); 2712 if (ret != LDB_SUCCESS) { 2713 talloc_free(tmp_ctx); 2714 return ret; 2715 } 2716 2717 if (deletion_state == OBJECT_NOT_DELETED){ 2718 ret = ldb_msg_add_steal_string(msg, "lastKnownParent", 2719 ldb_dn_get_extended_linearized(tmp_ctx, parent_res->msgs[0]->dn, 1)); 3257 if (deletion_state == OBJECT_NOT_DELETED) { 3258 struct ldb_dn *parent_dn = ldb_dn_get_parent(tmp_ctx, old_dn); 3259 char *parent_dn_str = NULL; 3260 3261 /* we need the storage form of the parent GUID */ 3262 ret = dsdb_module_search_dn(module, tmp_ctx, &parent_res, 3263 parent_dn, NULL, 3264 DSDB_FLAG_NEXT_MODULE | 3265 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT | 3266 DSDB_SEARCH_REVEAL_INTERNALS| 3267 DSDB_SEARCH_SHOW_RECYCLED, req); 2720 3268 if (ret != LDB_SUCCESS) { 2721 DEBUG(0,(__location__ ": Failed to add lastKnownParent string to the msg\n")); 2722 ldb_module_oom(module); 3269 ldb_asprintf_errstring(ldb_module_get_ctx(module), 3270 "repmd_delete: Failed to %s %s, " 3271 "because we failed to find it's parent (%s): %s", 3272 re_delete ? "re-delete" : "delete", 3273 ldb_dn_get_linearized(old_dn), 3274 ldb_dn_get_linearized(parent_dn), 3275 ldb_errstring(ldb_module_get_ctx(module))); 2723 3276 talloc_free(tmp_ctx); 2724 3277 return ret; 2725 3278 } 2726 msg->elements[el_count++].flags = LDB_FLAG_MOD_ADD; 2727 } 2728 2729 switch (next_deletion_state){ 2730 2731 case OBJECT_DELETED: 2732 2733 ret = ldb_msg_add_value(msg, "msDS-LastKnownRDN", rdn_value, NULL); 3279 3280 /* 3281 * Now we can use the DB version, 3282 * it will have the extended DN info in it 3283 */ 3284 parent_dn = parent_res->msgs[0]->dn; 3285 parent_dn_str = ldb_dn_get_extended_linearized(tmp_ctx, 3286 parent_dn, 3287 1); 3288 if (parent_dn_str == NULL) { 3289 talloc_free(tmp_ctx); 3290 return ldb_module_oom(module); 3291 } 3292 3293 ret = ldb_msg_add_steal_string(msg, "lastKnownParent", 3294 parent_dn_str); 2734 3295 if (ret != LDB_SUCCESS) { 2735 DEBUG(0,(__location__ ": Failed to add msDS-LastKnownRDN string to the msg\n")); 2736 ldb_module_oom(module); 3296 ldb_asprintf_errstring(ldb, __location__ 3297 ": Failed to add lastKnownParent " 3298 "string when deleting %s", 3299 ldb_dn_get_linearized(old_dn)); 2737 3300 talloc_free(tmp_ctx); 2738 3301 return ret; 2739 3302 } 2740 msg->elements[el_count++].flags = LDB_FLAG_MOD_ ADD;2741 2742 ret = ldb_msg_add_empty(msg, "objectCategory", LDB_FLAG_MOD_DELETE, NULL);2743 if (ret != LDB_SUCCESS) {2744 talloc_free(tmp_ctx);2745 ldb_module_oom(module);2746 return ret;2747 }2748 2749 ret = ldb_msg_add_empty(msg, "sAMAccountType", LDB_FLAG_MOD_DELETE, NULL);2750 if (ret != LDB_SUCCESS) {2751 talloc_free(tmp_ctx);2752 ldb_module_oom(module);2753 return ret;2754 2755 2756 break;3303 msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE; 3304 3305 if (next_deletion_state == OBJECT_DELETED) { 3306 ret = ldb_msg_add_value(msg, "msDS-LastKnownRDN", rdn_value, NULL); 3307 if (ret != LDB_SUCCESS) { 3308 ldb_asprintf_errstring(ldb, __location__ 3309 ": Failed to add msDS-LastKnownRDN " 3310 "string when deleting %s", 3311 ldb_dn_get_linearized(old_dn)); 3312 talloc_free(tmp_ctx); 3313 return ret; 3314 } 3315 msg->elements[el_count++].flags = LDB_FLAG_MOD_ADD; 3316 } 3317 } 3318 3319 switch (next_deletion_state) { 2757 3320 2758 3321 case OBJECT_RECYCLED: 2759 3322 case OBJECT_TOMBSTONE: 2760 3323 2761 /* we also mark it as recycled, meaning this object can't be 2762 recovered (we are stripping its attributes) */ 2763 if (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2008_R2) { 3324 /* 3325 * MS-ADTS 3.1.1.5.5.1.1 Tombstone Requirements 3326 * describes what must be removed from a tombstone 3327 * object 3328 * 3329 * MS-ADTS 3.1.1.5.5.1.3 Recycled-Object Requirements 3330 * describes what must be removed from a recycled 3331 * object 3332 * 3333 */ 3334 3335 /* 3336 * we also mark it as recycled, meaning this object can't be 3337 * recovered (we are stripping its attributes). 3338 * This is done only if we have this schema object of course ... 3339 * This behavior is identical to the one of Windows 2008R2 which 3340 * always set the isRecycled attribute, even if the recycle-bin is 3341 * not activated and what ever the forest level is. 3342 */ 3343 if (dsdb_attribute_by_lDAPDisplayName(schema, "isRecycled") != NULL) { 2764 3344 ret = ldb_msg_add_string(msg, "isRecycled", "TRUE"); 2765 3345 if (ret != LDB_SUCCESS) { … … 2769 3349 return ret; 2770 3350 } 2771 msg->elements[el_count++].flags = LDB_FLAG_MOD_ ADD;3351 msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE; 2772 3352 } 2773 3353 … … 2785 3365 continue; 2786 3366 } 2787 if (sa->linkID && sa->linkID & 1) { 3367 if (sa->linkID && (sa->linkID & 1)) { 3368 /* 3369 we have a backlink in this object 3370 that needs to be removed. We're not 3371 allowed to remove it directly 3372 however, so we instead setup a 3373 modify to delete the corresponding 3374 forward link 3375 */ 2788 3376 ret = replmd_delete_remove_link(module, schema, old_dn, el, sa, req); 2789 3377 if (ret != LDB_SUCCESS) { 3378 const char *old_dn_str 3379 = ldb_dn_get_linearized(old_dn); 3380 ldb_asprintf_errstring(ldb, 3381 __location__ 3382 ": Failed to remove backlink of " 3383 "%s when deleting %s", 3384 el->name, 3385 old_dn_str); 2790 3386 talloc_free(tmp_ctx); 2791 3387 return LDB_ERR_OPERATIONS_ERROR; 2792 3388 } 3389 /* now we continue, which means we 3390 won't remove this backlink 3391 directly 3392 */ 2793 3393 continue; 2794 3394 } 2795 if (!sa->linkID && ldb_attr_in_list(preserved_attrs, el->name)) { 2796 continue; 3395 if (!sa->linkID) { 3396 if (ldb_attr_in_list(preserved_attrs, el->name)) { 3397 continue; 3398 } 3399 if (sa->searchFlags & SEARCH_FLAG_PRESERVEONDELETE) { 3400 continue; 3401 } 2797 3402 } 2798 3403 ret = ldb_msg_add_empty(msg, el->name, LDB_FLAG_MOD_DELETE, &el); … … 2803 3408 } 2804 3409 } 3410 3411 /* Duplicate with the below - we remove the 3412 * samAccountType as an originating update, in case it 3413 * somehow came back. The objectCategory will have 3414 * gone in the above */ 3415 ret = ldb_msg_add_empty(msg, "sAMAccountType", LDB_FLAG_MOD_REPLACE, NULL); 3416 if (ret != LDB_SUCCESS) { 3417 talloc_free(tmp_ctx); 3418 ldb_module_oom(module); 3419 return ret; 3420 } 3421 3422 break; 3423 3424 case OBJECT_DELETED: 3425 /* 3426 * MS-ADTS 3.1.1.5.5.1.2 Deleted-Object Requirements 3427 * describes what must be removed from a deleted 3428 * object 3429 */ 3430 3431 ret = ldb_msg_add_empty(msg, "objectCategory", LDB_FLAG_MOD_REPLACE, NULL); 3432 if (ret != LDB_SUCCESS) { 3433 talloc_free(tmp_ctx); 3434 ldb_module_oom(module); 3435 return ret; 3436 } 3437 3438 ret = ldb_msg_add_empty(msg, "sAMAccountType", LDB_FLAG_MOD_REPLACE, NULL); 3439 if (ret != LDB_SUCCESS) { 3440 talloc_free(tmp_ctx); 3441 ldb_module_oom(module); 3442 return ret; 3443 } 3444 2805 3445 break; 2806 3446 … … 2845 3485 } 2846 3486 3487 /* 3488 * TODO: Per MS-DRSR 5.160 RemoveObj we should remove links directly, not as an originating update! 3489 * 3490 */ 3491 2847 3492 ret = dsdb_module_modify(module, msg, DSDB_FLAG_OWN_MODULE, req); 2848 3493 if (ret != LDB_SUCCESS) { … … 2853 3498 } 2854 3499 2855 if (deletion_state == OBJECT_NOT_DELETED) { 3500 /* 3501 * No matter what has happned with other renames, try again to 3502 * get this to be under the deleted DN. 3503 */ 3504 if (strcmp(ldb_dn_get_linearized(old_dn), ldb_dn_get_linearized(new_dn)) != 0) { 2856 3505 /* now rename onto the new DN */ 2857 3506 ret = dsdb_module_rename(module, old_dn, new_dn, DSDB_FLAG_NEXT_MODULE, req); … … 2871 3520 } 2872 3521 3522 static int replmd_delete(struct ldb_module *module, struct ldb_request *req) 3523 { 3524 return replmd_delete_internals(module, req, false); 3525 } 2873 3526 2874 3527 … … 2885 3538 } 2886 3539 2887 static int replmd_replicated_apply_add(struct replmd_replicated_request *ar) 2888 { 2889 struct ldb_context *ldb; 2890 struct ldb_request *change_req; 2891 enum ndr_err_code ndr_err; 2892 struct ldb_message *msg; 2893 struct replPropertyMetaDataBlob *md; 2894 struct ldb_val md_value; 2895 unsigned int i; 2896 int ret; 2897 2898 /* 2899 * TODO: check if the parent object exist 2900 */ 2901 2902 /* 2903 * TODO: handle the conflict case where an object with the 2904 * same name exist 2905 */ 2906 2907 ldb = ldb_module_get_ctx(ar->module); 2908 msg = ar->objs->objects[ar->index_current].msg; 2909 md = ar->objs->objects[ar->index_current].meta_data; 2910 2911 ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num); 2912 if (ret != LDB_SUCCESS) { 2913 return replmd_replicated_request_error(ar, ret); 2914 } 2915 2916 ret = ldb_msg_add_value(msg, "objectGUID", &ar->objs->objects[ar->index_current].guid_value, NULL); 2917 if (ret != LDB_SUCCESS) { 2918 return replmd_replicated_request_error(ar, ret); 2919 } 2920 2921 ret = ldb_msg_add_string(msg, "whenChanged", ar->objs->objects[ar->index_current].when_changed); 2922 if (ret != LDB_SUCCESS) { 2923 return replmd_replicated_request_error(ar, ret); 2924 } 2925 2926 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNCreated", ar->seq_num); 2927 if (ret != LDB_SUCCESS) { 2928 return replmd_replicated_request_error(ar, ret); 2929 } 2930 2931 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", ar->seq_num); 2932 if (ret != LDB_SUCCESS) { 2933 return replmd_replicated_request_error(ar, ret); 2934 } 2935 2936 /* remove any message elements that have zero values */ 2937 for (i=0; i<msg->num_elements; i++) { 2938 struct ldb_message_element *el = &msg->elements[i]; 2939 2940 if (el->num_values == 0) { 2941 DEBUG(4,(__location__ ": Removing attribute %s with num_values==0\n", 2942 el->name)); 2943 memmove(el, el+1, sizeof(*el)*(msg->num_elements - (i+1))); 2944 msg->num_elements--; 2945 i--; 2946 continue; 2947 } 2948 } 2949 2950 /* 2951 * the meta data array is already sorted by the caller 2952 */ 2953 for (i=0; i < md->ctr.ctr1.count; i++) { 2954 md->ctr.ctr1.array[i].local_usn = ar->seq_num; 2955 } 2956 ndr_err = ndr_push_struct_blob(&md_value, msg, md, 2957 (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob); 2958 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 2959 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); 2960 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status)); 2961 } 2962 ret = ldb_msg_add_value(msg, "replPropertyMetaData", &md_value, NULL); 2963 if (ret != LDB_SUCCESS) { 2964 return replmd_replicated_request_error(ar, ret); 2965 } 2966 2967 replmd_ldb_message_sort(msg, ar->schema); 2968 2969 if (DEBUGLVL(4)) { 2970 char *s = ldb_ldif_message_string(ldb, ar, LDB_CHANGETYPE_ADD, msg); 2971 DEBUG(4, ("DRS replication add message:\n%s\n", s)); 2972 talloc_free(s); 2973 } 2974 2975 ret = ldb_build_add_req(&change_req, 2976 ldb, 2977 ar, 2978 msg, 2979 ar->controls, 2980 ar, 2981 replmd_op_callback, 2982 ar->req); 2983 LDB_REQ_SET_LOCATION(change_req); 2984 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret); 2985 2986 /* current partition control needed by "repmd_op_callback" */ 2987 ret = ldb_request_add_control(change_req, 2988 DSDB_CONTROL_CURRENT_PARTITION_OID, 2989 false, NULL); 2990 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret); 2991 2992 return ldb_next_request(ar->module, change_req); 2993 } 3540 3541 static struct replPropertyMetaData1 * 3542 replmd_replPropertyMetaData1_find_attid(struct replPropertyMetaDataBlob *md_blob, 3543 enum drsuapi_DsAttributeId attid) 3544 { 3545 uint32_t i; 3546 struct replPropertyMetaDataCtr1 *rpmd_ctr = &md_blob->ctr.ctr1; 3547 3548 for (i = 0; i < rpmd_ctr->count; i++) { 3549 if (rpmd_ctr->array[i].attid == attid) { 3550 return &rpmd_ctr->array[i]; 3551 } 3552 } 3553 return NULL; 3554 } 3555 2994 3556 2995 3557 /* … … 3024 3586 } 3025 3587 3026 static struct replPropertyMetaData1 * 3027 replmd_replPropertyMetaData1_find_attid(struct replPropertyMetaDataBlob *md_blob, 3028 enum drsuapi_DsAttributeId attid) 3029 { 3030 uint32_t i; 3031 struct replPropertyMetaDataCtr1 *rpmd_ctr = &md_blob->ctr.ctr1; 3032 3033 for (i = 0; i < rpmd_ctr->count; i++) { 3034 if (rpmd_ctr->array[i].attid == attid) { 3035 return &rpmd_ctr->array[i]; 3036 } 3037 } 3038 return NULL; 3039 } 3040 3588 3589 /* 3590 form a conflict DN 3591 */ 3592 static struct ldb_dn *replmd_conflict_dn(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct GUID *guid) 3593 { 3594 const struct ldb_val *rdn_val; 3595 const char *rdn_name; 3596 struct ldb_dn *new_dn; 3597 3598 rdn_val = ldb_dn_get_rdn_val(dn); 3599 rdn_name = ldb_dn_get_rdn_name(dn); 3600 if (!rdn_val || !rdn_name) { 3601 return NULL; 3602 } 3603 3604 new_dn = ldb_dn_copy(mem_ctx, dn); 3605 if (!new_dn) { 3606 return NULL; 3607 } 3608 3609 if (!ldb_dn_remove_child_components(new_dn, 1)) { 3610 return NULL; 3611 } 3612 3613 if (!ldb_dn_add_child_fmt(new_dn, "%s=%s\\0ACNF:%s", 3614 rdn_name, 3615 ldb_dn_escape_value(new_dn, *rdn_val), 3616 GUID_string(new_dn, guid))) { 3617 return NULL; 3618 } 3619 3620 return new_dn; 3621 } 3622 3623 3624 /* 3625 perform a modify operation which sets the rDN and name attributes to 3626 their current values. This has the effect of changing these 3627 attributes to have been last updated by the current DC. This is 3628 needed to ensure that renames performed as part of conflict 3629 resolution are propogated to other DCs 3630 */ 3631 static int replmd_name_modify(struct replmd_replicated_request *ar, 3632 struct ldb_request *req, struct ldb_dn *dn) 3633 { 3634 struct ldb_message *msg; 3635 const char *rdn_name; 3636 const struct ldb_val *rdn_val; 3637 const struct dsdb_attribute *rdn_attr; 3638 int ret; 3639 3640 msg = ldb_msg_new(req); 3641 if (msg == NULL) { 3642 goto failed; 3643 } 3644 msg->dn = dn; 3645 3646 rdn_name = ldb_dn_get_rdn_name(dn); 3647 if (rdn_name == NULL) { 3648 goto failed; 3649 } 3650 3651 /* normalize the rdn attribute name */ 3652 rdn_attr = dsdb_attribute_by_lDAPDisplayName(ar->schema, rdn_name); 3653 if (rdn_attr == NULL) { 3654 goto failed; 3655 } 3656 rdn_name = rdn_attr->lDAPDisplayName; 3657 3658 rdn_val = ldb_dn_get_rdn_val(dn); 3659 if (rdn_val == NULL) { 3660 goto failed; 3661 } 3662 3663 if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { 3664 goto failed; 3665 } 3666 if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { 3667 goto failed; 3668 } 3669 if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { 3670 goto failed; 3671 } 3672 if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { 3673 goto failed; 3674 } 3675 3676 ret = dsdb_module_modify(ar->module, msg, DSDB_FLAG_OWN_MODULE, req); 3677 if (ret != LDB_SUCCESS) { 3678 DEBUG(0,(__location__ ": Failed to modify rDN/name of conflict DN '%s' - %s", 3679 ldb_dn_get_linearized(dn), 3680 ldb_errstring(ldb_module_get_ctx(ar->module)))); 3681 return ret; 3682 } 3683 3684 talloc_free(msg); 3685 3686 return LDB_SUCCESS; 3687 3688 failed: 3689 talloc_free(msg); 3690 DEBUG(0,(__location__ ": Failed to setup modify rDN/name of conflict DN '%s'", 3691 ldb_dn_get_linearized(dn))); 3692 return LDB_ERR_OPERATIONS_ERROR; 3693 } 3694 3695 3696 /* 3697 callback for conflict DN handling where we have renamed the incoming 3698 record. After renaming it, we need to ensure the change of name and 3699 rDN for the incoming record is seen as an originating update by this DC. 3700 3701 This also handles updating lastKnownParent for entries sent to lostAndFound 3702 */ 3703 static int replmd_op_name_modify_callback(struct ldb_request *req, struct ldb_reply *ares) 3704 { 3705 struct replmd_replicated_request *ar = 3706 talloc_get_type_abort(req->context, struct replmd_replicated_request); 3707 struct ldb_dn *conflict_dn; 3708 int ret; 3709 3710 if (ares->error != LDB_SUCCESS) { 3711 /* call the normal callback for everything except success */ 3712 return replmd_op_callback(req, ares); 3713 } 3714 3715 switch (req->operation) { 3716 case LDB_ADD: 3717 conflict_dn = req->op.add.message->dn; 3718 break; 3719 case LDB_MODIFY: 3720 conflict_dn = req->op.mod.message->dn; 3721 break; 3722 default: 3723 smb_panic("replmd_op_name_modify_callback called in unknown circumstances"); 3724 } 3725 3726 /* perform a modify of the rDN and name of the record */ 3727 ret = replmd_name_modify(ar, req, conflict_dn); 3728 if (ret != LDB_SUCCESS) { 3729 ares->error = ret; 3730 return replmd_op_callback(req, ares); 3731 } 3732 3733 if (ar->objs->objects[ar->index_current].last_known_parent) { 3734 struct ldb_message *msg = ldb_msg_new(req); 3735 if (msg == NULL) { 3736 ldb_module_oom(ar->module); 3737 return LDB_ERR_OPERATIONS_ERROR; 3738 } 3739 3740 msg->dn = req->op.add.message->dn; 3741 3742 ret = ldb_msg_add_steal_string(msg, "lastKnownParent", 3743 ldb_dn_get_extended_linearized(msg, ar->objs->objects[ar->index_current].last_known_parent, 1)); 3744 if (ret != LDB_SUCCESS) { 3745 DEBUG(0,(__location__ ": Failed to add lastKnownParent string to the msg\n")); 3746 ldb_module_oom(ar->module); 3747 return ret; 3748 } 3749 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE; 3750 3751 ret = dsdb_module_modify(ar->module, msg, DSDB_FLAG_OWN_MODULE, req); 3752 if (ret != LDB_SUCCESS) { 3753 DEBUG(0,(__location__ ": Failed to modify lastKnownParent of lostAndFound DN '%s' - %s", 3754 ldb_dn_get_linearized(msg->dn), 3755 ldb_errstring(ldb_module_get_ctx(ar->module)))); 3756 return ret; 3757 } 3758 TALLOC_FREE(msg); 3759 } 3760 3761 return replmd_op_callback(req, ares); 3762 } 3763 3764 /* 3765 callback for replmd_replicated_apply_add() and replmd_replicated_handle_rename() 3766 This copes with the creation of conflict records in the case where 3767 the DN exists, but with a different objectGUID 3768 */ 3769 static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct ldb_reply *ares, int (*callback)(struct ldb_request *req, struct ldb_reply *ares)) 3770 { 3771 struct ldb_dn *conflict_dn; 3772 struct replmd_replicated_request *ar = 3773 talloc_get_type_abort(req->context, struct replmd_replicated_request); 3774 struct ldb_result *res; 3775 const char *attrs[] = { "replPropertyMetaData", "objectGUID", NULL }; 3776 int ret; 3777 const struct ldb_val *omd_value; 3778 struct replPropertyMetaDataBlob omd, *rmd; 3779 enum ndr_err_code ndr_err; 3780 bool rename_incoming_record, rodc; 3781 struct replPropertyMetaData1 *rmd_name, *omd_name; 3782 struct ldb_message *msg; 3783 3784 req->callback = callback; 3785 3786 if (ares->error != LDB_ERR_ENTRY_ALREADY_EXISTS) { 3787 /* call the normal callback for everything except 3788 conflicts */ 3789 return ldb_module_done(req, ares->controls, ares->response, ares->error); 3790 } 3791 3792 ret = samdb_rodc(ldb_module_get_ctx(ar->module), &rodc); 3793 if (ret != LDB_SUCCESS) { 3794 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to determine if we are an RODC when attempting to form conflict DN: %s", ldb_errstring(ldb_module_get_ctx(ar->module))); 3795 return ldb_module_done(req, ares->controls, ares->response, LDB_ERR_OPERATIONS_ERROR); 3796 } 3797 /* 3798 * we have a conflict, and need to decide if we will keep the 3799 * new record or the old record 3800 */ 3801 3802 msg = ar->objs->objects[ar->index_current].msg; 3803 3804 switch (req->operation) { 3805 case LDB_ADD: 3806 conflict_dn = msg->dn; 3807 break; 3808 case LDB_RENAME: 3809 conflict_dn = req->op.rename.newdn; 3810 break; 3811 default: 3812 return ldb_module_done(req, ares->controls, ares->response, ldb_module_operr(ar->module)); 3813 } 3814 3815 if (rodc) { 3816 /* 3817 * We are on an RODC, or were a GC for this 3818 * partition, so we have to fail this until 3819 * someone who owns the partition sorts it 3820 * out 3821 */ 3822 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), 3823 "Conflict adding object '%s' from incoming replication as we are read only for the partition. \n" 3824 " - We must fail the operation until a master for this partition resolves the conflict", 3825 ldb_dn_get_linearized(conflict_dn)); 3826 goto failed; 3827 } 3828 3829 /* 3830 * first we need the replPropertyMetaData attribute from the 3831 * old record 3832 */ 3833 ret = dsdb_module_search_dn(ar->module, req, &res, conflict_dn, 3834 attrs, 3835 DSDB_FLAG_NEXT_MODULE | 3836 DSDB_SEARCH_SHOW_DELETED | 3837 DSDB_SEARCH_SHOW_RECYCLED, req); 3838 if (ret != LDB_SUCCESS) { 3839 DEBUG(0,(__location__ ": Unable to find object for conflicting record '%s'\n", 3840 ldb_dn_get_linearized(conflict_dn))); 3841 goto failed; 3842 } 3843 3844 omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData"); 3845 if (omd_value == NULL) { 3846 DEBUG(0,(__location__ ": Unable to find replPropertyMetaData for conflicting record '%s'\n", 3847 ldb_dn_get_linearized(conflict_dn))); 3848 goto failed; 3849 } 3850 3851 ndr_err = ndr_pull_struct_blob(omd_value, res->msgs[0], &omd, 3852 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob); 3853 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 3854 DEBUG(0,(__location__ ": Failed to parse old replPropertyMetaData for %s\n", 3855 ldb_dn_get_linearized(conflict_dn))); 3856 goto failed; 3857 } 3858 3859 rmd = ar->objs->objects[ar->index_current].meta_data; 3860 3861 /* we decide which is newer based on the RPMD on the name 3862 attribute. See [MS-DRSR] ResolveNameConflict */ 3863 rmd_name = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name); 3864 omd_name = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTID_name); 3865 if (!rmd_name || !omd_name) { 3866 DEBUG(0,(__location__ ": Failed to find name attribute in replPropertyMetaData for %s\n", 3867 ldb_dn_get_linearized(conflict_dn))); 3868 goto failed; 3869 } 3870 3871 rename_incoming_record = !(ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING) && 3872 !replmd_replPropertyMetaData1_is_newer(omd_name, rmd_name); 3873 3874 if (rename_incoming_record) { 3875 struct GUID guid; 3876 struct ldb_dn *new_dn; 3877 3878 /* 3879 * We want to run the original callback here, which 3880 * will return LDB_ERR_ENTRY_ALREADY_EXISTS to the 3881 * caller, which will in turn know to rename the 3882 * incoming record. The error string is set in case 3883 * this isn't handled properly at some point in the 3884 * future. 3885 */ 3886 if (req->operation == LDB_RENAME) { 3887 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), 3888 "Unable to handle incoming renames where this would " 3889 "create a conflict. Incoming record is %s (caller to handle)\n", 3890 ldb_dn_get_extended_linearized(req, conflict_dn, 1)); 3891 3892 goto failed; 3893 } 3894 3895 guid = samdb_result_guid(msg, "objectGUID"); 3896 if (GUID_all_zero(&guid)) { 3897 DEBUG(0,(__location__ ": Failed to find objectGUID for conflicting incoming record %s\n", 3898 ldb_dn_get_linearized(conflict_dn))); 3899 goto failed; 3900 } 3901 new_dn = replmd_conflict_dn(req, conflict_dn, &guid); 3902 if (new_dn == NULL) { 3903 DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n", 3904 ldb_dn_get_linearized(conflict_dn))); 3905 goto failed; 3906 } 3907 3908 DEBUG(2,(__location__ ": Resolving conflict record via incoming rename '%s' -> '%s'\n", 3909 ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn))); 3910 3911 /* re-submit the request, but with a different 3912 callback, so we don't loop forever. */ 3913 msg->dn = new_dn; 3914 req->callback = replmd_op_name_modify_callback; 3915 3916 return ldb_next_request(ar->module, req); 3917 } else { 3918 /* we are renaming the existing record */ 3919 struct GUID guid; 3920 struct ldb_dn *new_dn; 3921 3922 guid = samdb_result_guid(res->msgs[0], "objectGUID"); 3923 if (GUID_all_zero(&guid)) { 3924 DEBUG(0,(__location__ ": Failed to find objectGUID for existing conflict record %s\n", 3925 ldb_dn_get_linearized(conflict_dn))); 3926 goto failed; 3927 } 3928 3929 new_dn = replmd_conflict_dn(req, conflict_dn, &guid); 3930 if (new_dn == NULL) { 3931 DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n", 3932 ldb_dn_get_linearized(conflict_dn))); 3933 goto failed; 3934 } 3935 3936 DEBUG(2,(__location__ ": Resolving conflict record via existing rename '%s' -> '%s'\n", 3937 ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn))); 3938 3939 ret = dsdb_module_rename(ar->module, conflict_dn, new_dn, 3940 DSDB_FLAG_OWN_MODULE, req); 3941 if (ret != LDB_SUCCESS) { 3942 DEBUG(0,(__location__ ": Failed to rename conflict dn '%s' to '%s' - %s\n", 3943 ldb_dn_get_linearized(conflict_dn), 3944 ldb_dn_get_linearized(new_dn), 3945 ldb_errstring(ldb_module_get_ctx(ar->module)))); 3946 goto failed; 3947 } 3948 3949 /* 3950 * now we need to ensure that the rename is seen as an 3951 * originating update. We do that with a modify. 3952 */ 3953 ret = replmd_name_modify(ar, req, new_dn); 3954 if (ret != LDB_SUCCESS) { 3955 goto failed; 3956 } 3957 3958 return ldb_next_request(ar->module, req); 3959 } 3960 3961 failed: 3962 /* on failure do the original callback. This means replication 3963 * will stop with an error, but there is not much else we can 3964 * do 3965 */ 3966 return ldb_module_done(req, ares->controls, ares->response, ares->error); 3967 } 3968 3969 /* 3970 callback for replmd_replicated_apply_add() 3971 This copes with the creation of conflict records in the case where 3972 the DN exists, but with a different objectGUID 3973 */ 3974 static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *ares) 3975 { 3976 struct replmd_replicated_request *ar = 3977 talloc_get_type_abort(req->context, struct replmd_replicated_request); 3978 3979 if (ar->objs->objects[ar->index_current].last_known_parent) { 3980 /* This is like a conflict DN, where we put the object in LostAndFound 3981 see MS-DRSR 4.1.10.6.10 FindBestParentObject */ 3982 return replmd_op_possible_conflict_callback(req, ares, replmd_op_name_modify_callback); 3983 } 3984 3985 return replmd_op_possible_conflict_callback(req, ares, replmd_op_callback); 3986 } 3987 3988 /* 3989 callback for replmd_replicated_handle_rename() 3990 This copes with the creation of conflict records in the case where 3991 the DN exists, but with a different objectGUID 3992 */ 3993 static int replmd_op_rename_callback(struct ldb_request *req, struct ldb_reply *ares) 3994 { 3995 return replmd_op_possible_conflict_callback(req, ares, ldb_modify_default_callback); 3996 } 3997 3998 /* 3999 this is called when a new object comes in over DRS 4000 */ 4001 static int replmd_replicated_apply_add(struct replmd_replicated_request *ar) 4002 { 4003 struct ldb_context *ldb; 4004 struct ldb_request *change_req; 4005 enum ndr_err_code ndr_err; 4006 struct ldb_message *msg; 4007 struct replPropertyMetaDataBlob *md; 4008 struct ldb_val md_value; 4009 unsigned int i; 4010 int ret; 4011 bool remote_isDeleted = false; 4012 const struct dsdb_attribute *rdn_sa; 4013 const char *rdn_name; 4014 4015 ldb = ldb_module_get_ctx(ar->module); 4016 msg = ar->objs->objects[ar->index_current].msg; 4017 md = ar->objs->objects[ar->index_current].meta_data; 4018 4019 ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num); 4020 if (ret != LDB_SUCCESS) { 4021 return replmd_replicated_request_error(ar, ret); 4022 } 4023 4024 ret = ldb_msg_add_value(msg, "objectGUID", &ar->objs->objects[ar->index_current].guid_value, NULL); 4025 if (ret != LDB_SUCCESS) { 4026 return replmd_replicated_request_error(ar, ret); 4027 } 4028 4029 ret = ldb_msg_add_string(msg, "whenChanged", ar->objs->objects[ar->index_current].when_changed); 4030 if (ret != LDB_SUCCESS) { 4031 return replmd_replicated_request_error(ar, ret); 4032 } 4033 4034 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNCreated", ar->seq_num); 4035 if (ret != LDB_SUCCESS) { 4036 return replmd_replicated_request_error(ar, ret); 4037 } 4038 4039 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", ar->seq_num); 4040 if (ret != LDB_SUCCESS) { 4041 return replmd_replicated_request_error(ar, ret); 4042 } 4043 4044 /* remove any message elements that have zero values */ 4045 for (i=0; i<msg->num_elements; i++) { 4046 struct ldb_message_element *el = &msg->elements[i]; 4047 4048 if (el->num_values == 0) { 4049 if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) { 4050 ldb_asprintf_errstring(ldb, __location__ 4051 ": empty objectClass sent on %s, aborting replication\n", 4052 ldb_dn_get_linearized(msg->dn)); 4053 return replmd_replicated_request_error(ar, LDB_ERR_OBJECT_CLASS_VIOLATION); 4054 } 4055 4056 DEBUG(4,(__location__ ": Removing attribute %s with num_values==0\n", 4057 el->name)); 4058 memmove(el, el+1, sizeof(*el)*(msg->num_elements - (i+1))); 4059 msg->num_elements--; 4060 i--; 4061 continue; 4062 } 4063 } 4064 4065 if (DEBUGLVL(4)) { 4066 char *s = ldb_ldif_message_string(ldb, ar, LDB_CHANGETYPE_ADD, msg); 4067 DEBUG(4, ("DRS replication add message:\n%s\n", s)); 4068 talloc_free(s); 4069 } 4070 4071 remote_isDeleted = ldb_msg_find_attr_as_bool(msg, 4072 "isDeleted", false); 4073 4074 /* 4075 * the meta data array is already sorted by the caller 4076 */ 4077 4078 rdn_name = ldb_dn_get_rdn_name(msg->dn); 4079 if (rdn_name == NULL) { 4080 ldb_asprintf_errstring(ldb, __location__ ": No rDN for %s?\n", ldb_dn_get_linearized(msg->dn)); 4081 return replmd_replicated_request_error(ar, LDB_ERR_INVALID_DN_SYNTAX); 4082 } 4083 4084 rdn_sa = dsdb_attribute_by_lDAPDisplayName(ar->schema, rdn_name); 4085 if (rdn_sa == NULL) { 4086 ldb_asprintf_errstring(ldb, ": No schema attribute found for rDN %s for %s\n", 4087 rdn_name, ldb_dn_get_linearized(msg->dn)); 4088 return replmd_replicated_request_error(ar, LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE); 4089 } 4090 4091 ret = replmd_replPropertyMetaDataCtr1_verify(ldb, &md->ctr.ctr1, rdn_sa, msg->dn); 4092 if (ret != LDB_SUCCESS) { 4093 ldb_asprintf_errstring(ldb, "%s: error during DRS repl ADD: %s", __func__, ldb_errstring(ldb)); 4094 return replmd_replicated_request_error(ar, ret); 4095 } 4096 4097 for (i=0; i < md->ctr.ctr1.count; i++) { 4098 md->ctr.ctr1.array[i].local_usn = ar->seq_num; 4099 } 4100 ndr_err = ndr_push_struct_blob(&md_value, msg, md, 4101 (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob); 4102 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 4103 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); 4104 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status)); 4105 } 4106 ret = ldb_msg_add_value(msg, "replPropertyMetaData", &md_value, NULL); 4107 if (ret != LDB_SUCCESS) { 4108 return replmd_replicated_request_error(ar, ret); 4109 } 4110 4111 replmd_ldb_message_sort(msg, ar->schema); 4112 4113 if (!remote_isDeleted) { 4114 ret = dsdb_module_schedule_sd_propagation(ar->module, 4115 ar->objs->partition_dn, 4116 msg->dn, true); 4117 if (ret != LDB_SUCCESS) { 4118 return replmd_replicated_request_error(ar, ret); 4119 } 4120 } 4121 4122 ar->isDeleted = remote_isDeleted; 4123 4124 ret = ldb_build_add_req(&change_req, 4125 ldb, 4126 ar, 4127 msg, 4128 ar->controls, 4129 ar, 4130 replmd_op_add_callback, 4131 ar->req); 4132 LDB_REQ_SET_LOCATION(change_req); 4133 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret); 4134 4135 /* current partition control needed by "repmd_op_callback" */ 4136 ret = ldb_request_add_control(change_req, 4137 DSDB_CONTROL_CURRENT_PARTITION_OID, 4138 false, NULL); 4139 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret); 4140 4141 if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) { 4142 /* this tells the partition module to make it a 4143 partial replica if creating an NC */ 4144 ret = ldb_request_add_control(change_req, 4145 DSDB_CONTROL_PARTIAL_REPLICA, 4146 false, NULL); 4147 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret); 4148 } 4149 4150 return ldb_next_request(ar->module, change_req); 4151 } 4152 4153 static int replmd_replicated_apply_search_for_parent_callback(struct ldb_request *req, 4154 struct ldb_reply *ares) 4155 { 4156 struct replmd_replicated_request *ar = talloc_get_type(req->context, 4157 struct replmd_replicated_request); 4158 int ret; 4159 4160 if (!ares) { 4161 return ldb_module_done(ar->req, NULL, NULL, 4162 LDB_ERR_OPERATIONS_ERROR); 4163 } 4164 if (ares->error != LDB_SUCCESS && 4165 ares->error != LDB_ERR_NO_SUCH_OBJECT) { 4166 /* 4167 * TODO: deal with the above error that the parent object doesn't exist 4168 */ 4169 4170 return ldb_module_done(ar->req, ares->controls, 4171 ares->response, ares->error); 4172 } 4173 4174 switch (ares->type) { 4175 case LDB_REPLY_ENTRY: 4176 { 4177 struct ldb_message *parent_msg = ares->message; 4178 struct ldb_message *msg = ar->objs->objects[ar->index_current].msg; 4179 struct ldb_dn *parent_dn; 4180 int comp_num; 4181 4182 if (!ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE") 4183 && ldb_msg_check_string_attribute(parent_msg, "isDeleted", "TRUE")) { 4184 /* Per MS-DRSR 4.1.10.6.10 4185 * FindBestParentObject we need to move this 4186 * new object under a deleted object to 4187 * lost-and-found */ 4188 struct ldb_dn *nc_root; 4189 4190 ret = dsdb_find_nc_root(ldb_module_get_ctx(ar->module), msg, msg->dn, &nc_root); 4191 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 4192 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), 4193 "No suitable NC root found for %s. " 4194 "We need to move this object because parent object %s " 4195 "is deleted, but this object is not.", 4196 ldb_dn_get_linearized(msg->dn), 4197 ldb_dn_get_linearized(parent_msg->dn)); 4198 return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); 4199 } else if (ret != LDB_SUCCESS) { 4200 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), 4201 "Unable to find NC root for %s: %s. " 4202 "We need to move this object because parent object %s " 4203 "is deleted, but this object is not.", 4204 ldb_dn_get_linearized(msg->dn), 4205 ldb_errstring(ldb_module_get_ctx(ar->module)), 4206 ldb_dn_get_linearized(parent_msg->dn)); 4207 return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); 4208 } 4209 4210 ret = dsdb_wellknown_dn(ldb_module_get_ctx(ar->module), msg, 4211 nc_root, 4212 DS_GUID_LOSTANDFOUND_CONTAINER, 4213 &parent_dn); 4214 if (ret != LDB_SUCCESS) { 4215 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), 4216 "Unable to find LostAndFound Container for %s " 4217 "in partition %s: %s. " 4218 "We need to move this object because parent object %s " 4219 "is deleted, but this object is not.", 4220 ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(nc_root), 4221 ldb_errstring(ldb_module_get_ctx(ar->module)), 4222 ldb_dn_get_linearized(parent_msg->dn)); 4223 return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); 4224 } 4225 ar->objs->objects[ar->index_current].last_known_parent 4226 = talloc_steal(ar->objs->objects[ar->index_current].msg, parent_msg->dn); 4227 } else { 4228 parent_dn = parent_msg->dn; 4229 } 4230 4231 comp_num = ldb_dn_get_comp_num(msg->dn); 4232 if (comp_num > 1) { 4233 if (!ldb_dn_remove_base_components(msg->dn, comp_num - 1)) { 4234 talloc_free(ares); 4235 return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module)); 4236 } 4237 } 4238 if (!ldb_dn_add_base(msg->dn, parent_dn)) { 4239 talloc_free(ares); 4240 return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module)); 4241 } 4242 break; 4243 } 4244 case LDB_REPLY_REFERRAL: 4245 /* we ignore referrals */ 4246 break; 4247 4248 case LDB_REPLY_DONE: 4249 if (ar->search_msg != NULL) { 4250 ret = replmd_replicated_apply_merge(ar); 4251 } else { 4252 ret = replmd_replicated_apply_add(ar); 4253 } 4254 if (ret != LDB_SUCCESS) { 4255 return ldb_module_done(ar->req, NULL, NULL, ret); 4256 } 4257 } 4258 4259 talloc_free(ares); 4260 return LDB_SUCCESS; 4261 } 4262 4263 /* 4264 * Look for the parent object, so we put the new object in the right 4265 * place This is akin to NameObject in MS-DRSR - this routine and the 4266 * callbacks find the right parent name, and correct name for this 4267 * object 4268 */ 4269 4270 static int replmd_replicated_apply_search_for_parent(struct replmd_replicated_request *ar) 4271 { 4272 struct ldb_context *ldb; 4273 int ret; 4274 char *tmp_str; 4275 char *filter; 4276 struct ldb_request *search_req; 4277 static const char *attrs[] = {"isDeleted", NULL}; 4278 4279 ldb = ldb_module_get_ctx(ar->module); 4280 4281 if (!ar->objs->objects[ar->index_current].parent_guid_value.data) { 4282 if (ar->search_msg != NULL) { 4283 return replmd_replicated_apply_merge(ar); 4284 } else { 4285 return replmd_replicated_apply_add(ar); 4286 } 4287 } 4288 4289 tmp_str = ldb_binary_encode(ar, ar->objs->objects[ar->index_current].parent_guid_value); 4290 if (!tmp_str) return replmd_replicated_request_werror(ar, WERR_NOMEM); 4291 4292 filter = talloc_asprintf(ar, "(objectGUID=%s)", tmp_str); 4293 if (!filter) return replmd_replicated_request_werror(ar, WERR_NOMEM); 4294 talloc_free(tmp_str); 4295 4296 ret = ldb_build_search_req(&search_req, 4297 ldb, 4298 ar, 4299 ar->objs->partition_dn, 4300 LDB_SCOPE_SUBTREE, 4301 filter, 4302 attrs, 4303 NULL, 4304 ar, 4305 replmd_replicated_apply_search_for_parent_callback, 4306 ar->req); 4307 LDB_REQ_SET_LOCATION(search_req); 4308 4309 ret = dsdb_request_add_controls(search_req, 4310 DSDB_SEARCH_SHOW_RECYCLED| 4311 DSDB_SEARCH_SHOW_DELETED| 4312 DSDB_SEARCH_SHOW_EXTENDED_DN); 4313 if (ret != LDB_SUCCESS) { 4314 return ret; 4315 } 4316 4317 return ldb_next_request(ar->module, search_req); 4318 } 3041 4319 3042 4320 /* … … 3045 4323 static int replmd_replicated_handle_rename(struct replmd_replicated_request *ar, 3046 4324 struct ldb_message *msg, 3047 struct replPropertyMetaDataBlob *rmd,3048 struct replPropertyMetaDataBlob *omd,3049 4325 struct ldb_request *parent) 3050 4326 { 3051 struct replPropertyMetaData1 *md_remote; 3052 struct replPropertyMetaData1 *md_local; 3053 3054 if (ldb_dn_compare(msg->dn, ar->search_msg->dn) == 0) { 3055 /* no rename */ 3056 return LDB_SUCCESS; 3057 } 3058 3059 /* now we need to check for double renames. We could have a 3060 * local rename pending which our replication partner hasn't 3061 * received yet. We choose which one wins by looking at the 3062 * attribute stamps on the two objects, the newer one wins 3063 */ 3064 md_remote = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name); 3065 md_local = replmd_replPropertyMetaData1_find_attid(omd, DRSUAPI_ATTID_name); 3066 /* if there is no name attribute then we have to assume the 3067 object we've received is in fact newer */ 3068 if (!md_remote || !md_local || 3069 replmd_replPropertyMetaData1_is_newer(md_local, md_remote)) { 3070 DEBUG(4,("replmd_replicated_request rename %s => %s\n", 3071 ldb_dn_get_linearized(ar->search_msg->dn), 3072 ldb_dn_get_linearized(msg->dn))); 3073 /* pass rename to the next module 3074 * so it doesn't appear as an originating update */ 3075 return dsdb_module_rename(ar->module, 3076 ar->search_msg->dn, msg->dn, 3077 DSDB_FLAG_NEXT_MODULE | DSDB_MODIFY_RELAX, parent); 3078 } 3079 3080 /* we're going to keep our old object */ 3081 DEBUG(4,(__location__ ": Keeping object %s and rejecting older rename to %s\n", 4327 struct ldb_request *req; 4328 int ret; 4329 TALLOC_CTX *tmp_ctx = talloc_new(msg); 4330 struct ldb_result *res; 4331 4332 DEBUG(4,("replmd_replicated_request rename %s => %s\n", 3082 4333 ldb_dn_get_linearized(ar->search_msg->dn), 3083 4334 ldb_dn_get_linearized(msg->dn))); 3084 return LDB_SUCCESS; 4335 4336 4337 res = talloc_zero(tmp_ctx, struct ldb_result); 4338 if (!res) { 4339 talloc_free(tmp_ctx); 4340 return ldb_oom(ldb_module_get_ctx(ar->module)); 4341 } 4342 4343 /* pass rename to the next module 4344 * so it doesn't appear as an originating update */ 4345 ret = ldb_build_rename_req(&req, ldb_module_get_ctx(ar->module), tmp_ctx, 4346 ar->search_msg->dn, msg->dn, 4347 NULL, 4348 ar, 4349 replmd_op_rename_callback, 4350 parent); 4351 LDB_REQ_SET_LOCATION(req); 4352 if (ret != LDB_SUCCESS) { 4353 talloc_free(tmp_ctx); 4354 return ret; 4355 } 4356 4357 ret = dsdb_request_add_controls(req, DSDB_MODIFY_RELAX); 4358 if (ret != LDB_SUCCESS) { 4359 talloc_free(tmp_ctx); 4360 return ret; 4361 } 4362 4363 ret = ldb_next_request(ar->module, req); 4364 4365 if (ret == LDB_SUCCESS) { 4366 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 4367 } 4368 4369 talloc_free(tmp_ctx); 4370 return ret; 3085 4371 } 3086 4372 … … 3101 4387 unsigned int removed_attrs = 0; 3102 4388 int ret; 4389 int (*callback)(struct ldb_request *req, struct ldb_reply *ares) = replmd_op_callback; 4390 bool isDeleted = false; 4391 bool local_isDeleted = false; 4392 bool remote_isDeleted = false; 4393 bool take_remote_isDeleted = false; 4394 bool sd_updated = false; 4395 bool renamed = false; 3103 4396 3104 4397 ldb = ldb_module_get_ctx(ar->module); 3105 4398 msg = ar->objs->objects[ar->index_current].msg; 4399 3106 4400 rmd = ar->objs->objects[ar->index_current].meta_data; 3107 4401 ZERO_STRUCT(omd); … … 3123 4417 } 3124 4418 3125 /* handle renames that come in over DRS */ 3126 ret = replmd_replicated_handle_rename(ar, msg, rmd, &omd, ar->req); 3127 if (ret != LDB_SUCCESS) { 4419 local_isDeleted = ldb_msg_find_attr_as_bool(ar->search_msg, 4420 "isDeleted", false); 4421 remote_isDeleted = ldb_msg_find_attr_as_bool(msg, 4422 "isDeleted", false); 4423 4424 if (strcmp(ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(ar->search_msg->dn)) == 0) { 4425 ret = LDB_SUCCESS; 4426 } else { 4427 /* 4428 * handle renames, even just by case that come in over 4429 * DRS. Changes in the parent DN don't hit us here, 4430 * because the search for a parent will clean up those 4431 * components. 4432 * 4433 * We also have already filtered out the case where 4434 * the peer has an older name to what we have (see 4435 * replmd_replicated_apply_search_callback()) 4436 */ 4437 renamed = true; 4438 ret = replmd_replicated_handle_rename(ar, msg, ar->req); 4439 } 4440 4441 /* 4442 * This particular error code means that we already tried the 4443 * conflict algrorithm, and the existing record name was newer, so we 4444 * need to rename the incoming record 4445 */ 4446 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { 4447 struct GUID guid; 4448 NTSTATUS status; 4449 struct ldb_dn *new_dn; 4450 status = GUID_from_ndr_blob(&ar->objs->objects[ar->index_current].guid_value, &guid); 4451 /* This really, really can't fail */ 4452 SMB_ASSERT(NT_STATUS_IS_OK(status)); 4453 4454 new_dn = replmd_conflict_dn(msg, msg->dn, &guid); 4455 if (new_dn == NULL) { 4456 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), 4457 "Failed to form conflict DN for %s\n", 4458 ldb_dn_get_linearized(msg->dn)); 4459 4460 return replmd_replicated_request_werror(ar, WERR_NOMEM); 4461 } 4462 4463 ret = dsdb_module_rename(ar->module, ar->search_msg->dn, new_dn, 4464 DSDB_FLAG_NEXT_MODULE, ar->req); 4465 if (ret != LDB_SUCCESS) { 4466 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), 4467 "Failed to rename incoming conflicting dn '%s' (was '%s') to '%s' - %s\n", 4468 ldb_dn_get_linearized(msg->dn), 4469 ldb_dn_get_linearized(ar->search_msg->dn), 4470 ldb_dn_get_linearized(new_dn), 4471 ldb_errstring(ldb_module_get_ctx(ar->module))); 4472 return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR); 4473 } 4474 4475 /* Set the callback to one that will fix up the name to be a conflict DN */ 4476 callback = replmd_op_name_modify_callback; 4477 msg->dn = new_dn; 4478 renamed = true; 4479 } else if (ret != LDB_SUCCESS) { 3128 4480 ldb_debug(ldb, LDB_DEBUG_FATAL, 3129 4481 "replmd_replicated_request rename %s => %s failed - %s\n", … … 3148 4500 } 3149 4501 4502 ar->seq_num = 0; 3150 4503 /* now merge in the new meta data */ 3151 4504 for (i=0; i < rmd->ctr.ctr1.count; i++) { … … 3159 4512 } 3160 4513 3161 cmp = replmd_replPropertyMetaData1_is_newer(&nmd.ctr.ctr1.array[j], 3162 &rmd->ctr.ctr1.array[i]); 4514 if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING) { 4515 /* 4516 * if we compare equal then do an 4517 * update. This is used when a client 4518 * asks for a FULL_SYNC, and can be 4519 * used to recover a corrupt 4520 * replica. 4521 * 4522 * This call is a bit tricky, what we 4523 * are doing it turning the 'is_newer' 4524 * call into a 'not is older' by 4525 * swapping i and j, and negating the 4526 * outcome. 4527 */ 4528 cmp = !replmd_replPropertyMetaData1_is_newer(&rmd->ctr.ctr1.array[i], 4529 &nmd.ctr.ctr1.array[j]); 4530 } else { 4531 cmp = replmd_replPropertyMetaData1_is_newer(&nmd.ctr.ctr1.array[j], 4532 &rmd->ctr.ctr1.array[i]); 4533 } 3163 4534 if (cmp) { 3164 4535 /* replace the entry */ 3165 4536 nmd.ctr.ctr1.array[j] = rmd->ctr.ctr1.array[i]; 4537 if (ar->seq_num == 0) { 4538 ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num); 4539 if (ret != LDB_SUCCESS) { 4540 return replmd_replicated_request_error(ar, ret); 4541 } 4542 } 4543 nmd.ctr.ctr1.array[j].local_usn = ar->seq_num; 4544 switch (nmd.ctr.ctr1.array[j].attid) { 4545 case DRSUAPI_ATTID_ntSecurityDescriptor: 4546 sd_updated = true; 4547 break; 4548 case DRSUAPI_ATTID_isDeleted: 4549 take_remote_isDeleted = true; 4550 break; 4551 default: 4552 break; 4553 } 3166 4554 found = true; 3167 4555 break; … … 3186 4574 3187 4575 nmd.ctr.ctr1.array[ni] = rmd->ctr.ctr1.array[i]; 4576 if (ar->seq_num == 0) { 4577 ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num); 4578 if (ret != LDB_SUCCESS) { 4579 return replmd_replicated_request_error(ar, ret); 4580 } 4581 } 4582 nmd.ctr.ctr1.array[ni].local_usn = ar->seq_num; 4583 switch (nmd.ctr.ctr1.array[ni].attid) { 4584 case DRSUAPI_ATTID_ntSecurityDescriptor: 4585 sd_updated = true; 4586 break; 4587 case DRSUAPI_ATTID_isDeleted: 4588 take_remote_isDeleted = true; 4589 break; 4590 default: 4591 break; 4592 } 3188 4593 ni++; 3189 4594 } … … 3201 4606 * sort the new meta data array 3202 4607 */ 3203 ret = replmd_replPropertyMetaDataCtr1_sort(&nmd.ctr.ctr1, ar->schema, msg->dn); 3204 if (ret != LDB_SUCCESS) { 4608 ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &nmd.ctr.ctr1, ar->schema, msg->dn); 4609 if (ret != LDB_SUCCESS) { 4610 ldb_asprintf_errstring(ldb, "%s: error during DRS repl merge: %s", __func__, ldb_errstring(ldb)); 3205 4611 return ret; 3206 4612 } 4613 4614 /* 4615 * Work out if this object is deleted, so we can prune any extra attributes. See MS-DRSR 4.1.10.6.9 4616 * UpdateObject. 4617 * 4618 * This also controls SD propagation below 4619 */ 4620 if (take_remote_isDeleted) { 4621 isDeleted = remote_isDeleted; 4622 } else { 4623 isDeleted = local_isDeleted; 4624 } 4625 4626 ar->isDeleted = isDeleted; 3207 4627 3208 4628 /* … … 3213 4633 ar->index_current); 3214 4634 3215 ar->index_current++; 3216 return replmd_replicated_apply_next(ar); 4635 return replmd_replicated_apply_isDeleted(ar); 3217 4636 } 3218 4637 … … 3220 4639 ar->index_current, msg->num_elements); 3221 4640 3222 ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num); 3223 if (ret != LDB_SUCCESS) { 3224 return replmd_replicated_request_error(ar, ret); 3225 } 3226 3227 for (i=0; i<ni; i++) { 3228 nmd.ctr.ctr1.array[i].local_usn = ar->seq_num; 4641 if (renamed) { 4642 sd_updated = true; 4643 } 4644 4645 if (sd_updated && !isDeleted) { 4646 ret = dsdb_module_schedule_sd_propagation(ar->module, 4647 ar->objs->partition_dn, 4648 msg->dn, true); 4649 if (ret != LDB_SUCCESS) { 4650 return ldb_operr(ldb); 4651 } 3229 4652 } 3230 4653 … … 3259 4682 for (i=0; i < msg->num_elements; i++) { 3260 4683 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; 4684 if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) { 4685 if (msg->elements[i].num_values == 0) { 4686 ldb_asprintf_errstring(ldb, __location__ 4687 ": objectClass removed on %s, aborting replication\n", 4688 ldb_dn_get_linearized(msg->dn)); 4689 return replmd_replicated_request_error(ar, LDB_ERR_OBJECT_CLASS_VIOLATION); 4690 } 4691 } 3261 4692 } 3262 4693 … … 3273 4704 ar->controls, 3274 4705 ar, 3275 replmd_op_callback,4706 callback, 3276 4707 ar->req); 3277 4708 LDB_REQ_SET_LOCATION(change_req); … … 3314 4745 3315 4746 case LDB_REPLY_DONE: 3316 if (ar->search_msg != NULL) { 4747 { 4748 struct replPropertyMetaData1 *md_remote; 4749 struct replPropertyMetaData1 *md_local; 4750 4751 struct replPropertyMetaDataBlob omd; 4752 const struct ldb_val *omd_value; 4753 struct replPropertyMetaDataBlob *rmd; 4754 struct ldb_message *msg; 4755 4756 ar->objs->objects[ar->index_current].last_known_parent = NULL; 4757 4758 /* 4759 * This is the ADD case, find the appropriate parent, 4760 * as this object doesn't exist locally: 4761 */ 4762 if (ar->search_msg == NULL) { 4763 ret = replmd_replicated_apply_search_for_parent(ar); 4764 if (ret != LDB_SUCCESS) { 4765 return ldb_module_done(ar->req, NULL, NULL, ret); 4766 } 4767 talloc_free(ares); 4768 return LDB_SUCCESS; 4769 } 4770 4771 /* 4772 * Otherwise, in the MERGE case, work out if we are 4773 * attempting a rename, and if so find the parent the 4774 * newly renamed object wants to belong under (which 4775 * may not be the parent in it's attached string DN 4776 */ 4777 rmd = ar->objs->objects[ar->index_current].meta_data; 4778 ZERO_STRUCT(omd); 4779 omd.version = 1; 4780 4781 /* find existing meta data */ 4782 omd_value = ldb_msg_find_ldb_val(ar->search_msg, "replPropertyMetaData"); 4783 if (omd_value) { 4784 enum ndr_err_code ndr_err; 4785 ndr_err = ndr_pull_struct_blob(omd_value, ar, &omd, 4786 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob); 4787 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 4788 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); 4789 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status)); 4790 } 4791 4792 if (omd.version != 1) { 4793 return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR); 4794 } 4795 } 4796 4797 /* 4798 * now we need to check for double renames. We could have a 4799 * local rename pending which our replication partner hasn't 4800 * received yet. We choose which one wins by looking at the 4801 * attribute stamps on the two objects, the newer one wins 4802 */ 4803 md_remote = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name); 4804 md_local = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTID_name); 4805 /* if there is no name attribute then we have to assume the 4806 object we've received is in fact newer */ 4807 if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING || 4808 !md_remote || !md_local || 4809 replmd_replPropertyMetaData1_is_newer(md_local, md_remote)) { 4810 ret = replmd_replicated_apply_search_for_parent(ar); 4811 } else { 4812 msg = ar->objs->objects[ar->index_current].msg; 4813 4814 /* Otherwise, just merge on the existing object, force no rename */ 4815 DEBUG(4,(__location__ ": Keeping object %s and rejecting older rename to %s\n", 4816 ldb_dn_get_linearized(ar->search_msg->dn), 4817 ldb_dn_get_linearized(msg->dn))); 4818 4819 /* 4820 * This assignment ensures that the strcmp() 4821 * in replmd_replicated_apply_merge() avoids 4822 * the rename call 4823 */ 4824 msg->dn = ar->search_msg->dn; 3317 4825 ret = replmd_replicated_apply_merge(ar); 3318 } else {3319 ret = replmd_replicated_apply_add(ar);3320 4826 } 3321 4827 if (ret != LDB_SUCCESS) { 3322 4828 return ldb_module_done(ar->req, NULL, NULL, ret); 3323 4829 } 4830 } 3324 4831 } 3325 4832 … … 3337 4844 char *filter; 3338 4845 struct ldb_request *search_req; 3339 struct ldb_search_options_control *options;3340 4846 3341 4847 if (ar->index_current >= ar->objs->num_objects) { … … 3346 4852 ldb = ldb_module_get_ctx(ar->module); 3347 4853 ar->search_msg = NULL; 4854 ar->isDeleted = false; 3348 4855 3349 4856 tmp_str = ldb_binary_encode(ar, ar->objs->objects[ar->index_current].guid_value); … … 3367 4874 LDB_REQ_SET_LOCATION(search_req); 3368 4875 3369 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,3370 true, NULL); 4876 ret = dsdb_request_add_controls(search_req, DSDB_SEARCH_SEARCH_ALL_PARTITIONS|DSDB_SEARCH_SHOW_RECYCLED); 4877 3371 4878 if (ret != LDB_SUCCESS) { 3372 4879 return ret; 3373 4880 } 3374 4881 3375 /* we need to cope with cross-partition links, so search for3376 the GUID over all partitions */3377 options = talloc(search_req, struct ldb_search_options_control);3378 if (options == NULL) {3379 DEBUG(0, (__location__ ": out of memory\n"));3380 return LDB_ERR_OPERATIONS_ERROR;3381 }3382 options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;3383 3384 ret = ldb_request_add_control(search_req,3385 LDB_CONTROL_SEARCH_OPTIONS_OID,3386 true, options);3387 if (ret != LDB_SUCCESS) {3388 return ret;3389 }3390 3391 4882 return ldb_next_request(ar->module, search_req); 4883 } 4884 4885 /* 4886 * This is essentially a wrapper for replmd_replicated_apply_next() 4887 * 4888 * This is needed to ensure that both codepaths call this handler. 4889 */ 4890 static int replmd_replicated_apply_isDeleted(struct replmd_replicated_request *ar) 4891 { 4892 struct ldb_dn *deleted_objects_dn; 4893 struct ldb_message *msg = ar->objs->objects[ar->index_current].msg; 4894 int ret = dsdb_get_deleted_objects_dn(ldb_module_get_ctx(ar->module), msg, msg->dn, 4895 &deleted_objects_dn); 4896 if (ar->isDeleted && (ret != LDB_SUCCESS || ldb_dn_compare(msg->dn, deleted_objects_dn) != 0)) { 4897 /* 4898 * Do a delete here again, so that if there is 4899 * anything local that conflicts with this 4900 * object being deleted, it is removed. This 4901 * includes links. See MS-DRSR 4.1.10.6.9 4902 * UpdateObject. 4903 * 4904 * If the object is already deleted, and there 4905 * is no more work required, it doesn't do 4906 * anything. 4907 */ 4908 4909 /* This has been updated to point to the DN we eventually did the modify on */ 4910 4911 struct ldb_request *del_req; 4912 struct ldb_result *res; 4913 4914 TALLOC_CTX *tmp_ctx = talloc_new(ar); 4915 if (!tmp_ctx) { 4916 ret = ldb_oom(ldb_module_get_ctx(ar->module)); 4917 return ret; 4918 } 4919 4920 res = talloc_zero(tmp_ctx, struct ldb_result); 4921 if (!res) { 4922 ret = ldb_oom(ldb_module_get_ctx(ar->module)); 4923 talloc_free(tmp_ctx); 4924 return ret; 4925 } 4926 4927 /* Build a delete request, which hopefully will artually turn into nothing */ 4928 ret = ldb_build_del_req(&del_req, ldb_module_get_ctx(ar->module), tmp_ctx, 4929 msg->dn, 4930 NULL, 4931 res, 4932 ldb_modify_default_callback, 4933 ar->req); 4934 LDB_REQ_SET_LOCATION(del_req); 4935 if (ret != LDB_SUCCESS) { 4936 talloc_free(tmp_ctx); 4937 return ret; 4938 } 4939 4940 /* 4941 * This is the guts of the call, call back 4942 * into our delete code, but setting the 4943 * re_delete flag so we delete anything that 4944 * shouldn't be there on a deleted or recycled 4945 * object 4946 */ 4947 ret = replmd_delete_internals(ar->module, del_req, true); 4948 if (ret == LDB_SUCCESS) { 4949 ret = ldb_wait(del_req->handle, LDB_WAIT_ALL); 4950 } 4951 4952 talloc_free(tmp_ctx); 4953 if (ret != LDB_SUCCESS) { 4954 return ret; 4955 } 4956 } 4957 4958 ar->index_current++; 4959 return replmd_replicated_apply_next(ar); 3392 4960 } 3393 4961 … … 3410 4978 3411 4979 if (ares->type != LDB_REPLY_DONE) { 3412 ldb_ set_errstring(ldb, "Invalid reply type\n!");4980 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type); 3413 4981 return ldb_module_done(ar->req, NULL, NULL, 3414 4982 LDB_ERR_OPERATIONS_ERROR); … … 3454 5022 unix_to_nt_time(&now, t); 3455 5023 5024 if (ar->search_msg == NULL) { 5025 /* this happens for a REPL_OBJ call where we are 5026 creating the target object by replicating it. The 5027 subdomain join code does this for the partition DN 5028 */ 5029 DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as no target DN\n")); 5030 return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS); 5031 } 5032 3456 5033 instanceType = ldb_msg_find_attr_as_uint(ar->search_msg, "instanceType", 0); 3457 5034 if (! (instanceType & INSTANCE_TYPE_IS_NC_HEAD)) { … … 3484 5061 * plus optional values from our old vector and the one from the source_dsa 3485 5062 */ 3486 nuv.ctr.ctr2.count = 1 +ouv.ctr.ctr2.count;5063 nuv.ctr.ctr2.count = ouv.ctr.ctr2.count; 3487 5064 if (ruv) nuv.ctr.ctr2.count += ruv->count; 3488 5065 nuv.ctr.ctr2.cursors = talloc_array(ar, … … 3499 5076 /* get our invocation_id if we have one already attached to the ldb */ 3500 5077 our_invocation_id = samdb_ntds_invocation_id(ldb); 5078 if (our_invocation_id == NULL) { 5079 DEBUG(0, ("repl_meta_data: Could not find our own server's invocationID!\n")); 5080 return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR); 5081 } 3501 5082 3502 5083 /* merge in the source_dsa vector is available */ … … 3518 5099 found = true; 3519 5100 3520 /*3521 * we update only the highest_usn and not the latest_sync_success time,3522 * because the last success stands for direct replication3523 */3524 5101 if (ruv->cursors[i].highest_usn > nuv.ctr.ctr2.cursors[j].highest_usn) { 3525 nuv.ctr.ctr2.cursors[j] .highest_usn = ruv->cursors[i].highest_usn;5102 nuv.ctr.ctr2.cursors[j] = ruv->cursors[i]; 3526 5103 } 3527 5104 break; … … 3532 5109 /* if it's not there yet, add it */ 3533 5110 nuv.ctr.ctr2.cursors[ni] = ruv->cursors[i]; 3534 ni++;3535 }3536 3537 /*3538 * merge in the current highwatermark for the source_dsa3539 */3540 found = false;3541 for (j=0; j < ni; j++) {3542 if (!GUID_equal(&ar->objs->source_dsa->source_dsa_invocation_id,3543 &nuv.ctr.ctr2.cursors[j].source_dsa_invocation_id)) {3544 continue;3545 }3546 3547 found = true;3548 3549 /*3550 * here we update the highest_usn and last_sync_success time3551 * because we're directly replicating from the source_dsa3552 *3553 * and use the tmp_highest_usn because this is what we have just applied3554 * to our ldb3555 */3556 nuv.ctr.ctr2.cursors[j].highest_usn = ar->objs->source_dsa->highwatermark.tmp_highest_usn;3557 nuv.ctr.ctr2.cursors[j].last_sync_success = now;3558 break;3559 }3560 if (!found) {3561 /*3562 * here we update the highest_usn and last_sync_success time3563 * because we're directly replicating from the source_dsa3564 *3565 * and use the tmp_highest_usn because this is what we have just applied3566 * to our ldb3567 */3568 nuv.ctr.ctr2.cursors[ni].source_dsa_invocation_id= ar->objs->source_dsa->source_dsa_invocation_id;3569 nuv.ctr.ctr2.cursors[ni].highest_usn = ar->objs->source_dsa->highwatermark.tmp_highest_usn;3570 nuv.ctr.ctr2.cursors[ni].last_sync_success = now;3571 5111 ni++; 3572 5112 } … … 3607 5147 nrf.version = 1; 3608 5148 nrf.ctr.ctr1 = *ar->objs->source_dsa; 3609 nrf.ctr.ctr1.highwatermark.highest_usn = nrf.ctr.ctr1.highwatermark.tmp_highest_usn; 5149 nrf.ctr.ctr1.last_attempt = now; 5150 nrf.ctr.ctr1.last_success = now; 5151 nrf.ctr.ctr1.result_last_attempt = WERR_OK; 3610 5152 3611 5153 /* … … 3685 5227 nrf_el->flags = LDB_FLAG_MOD_REPLACE; 3686 5228 3687 if ( DEBUGLVL(4)) {5229 if (CHECK_DEBUGLVL(4)) { 3688 5230 char *s = ldb_ldif_message_string(ldb, ar, LDB_CHANGETYPE_MODIFY, msg); 3689 5231 DEBUG(4, ("DRS replication uptodate modify message:\n%s\n", s)); … … 3733 5275 3734 5276 case LDB_REPLY_DONE: 3735 if (ar->search_msg == NULL) { 3736 ret = replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR); 3737 } else { 3738 ret = replmd_replicated_uptodate_modify(ar); 3739 } 5277 ret = replmd_replicated_uptodate_modify(ar); 3740 5278 if (ret != LDB_SUCCESS) { 3741 5279 return ldb_module_done(ar->req, NULL, NULL, ret); … … 3792 5330 struct replmd_private *replmd_private = 3793 5331 talloc_get_type(ldb_module_get_private(module), struct replmd_private); 5332 struct dsdb_control_replicated_update *rep_update; 3794 5333 3795 5334 ldb = ldb_module_get_ctx(module); … … 3832 5371 } 3833 5372 3834 /* This allows layers further down to know if a change came in over replication */ 3835 ret = ldb_request_add_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID, false, NULL); 5373 /* This allows layers further down to know if a change came in 5374 over replication and what the replication flags were */ 5375 rep_update = talloc_zero(ar, struct dsdb_control_replicated_update); 5376 if (rep_update == NULL) { 5377 return ldb_module_oom(module); 5378 } 5379 rep_update->dsdb_repl_flags = objs->dsdb_repl_flags; 5380 5381 ret = ldb_request_add_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID, false, rep_update); 3836 5382 if (ret != LDB_SUCCESS) { 3837 5383 return ret; … … 3893 5439 struct ldb_context *ldb = ldb_module_get_ctx(module); 3894 5440 struct ldb_message *msg; 5441 struct ldb_message *target_msg = NULL; 3895 5442 TALLOC_CTX *tmp_ctx = talloc_new(la_entry); 3896 5443 const struct dsdb_schema *schema = dsdb_get_schema(ldb, tmp_ctx); … … 3903 5450 time_t t = time(NULL); 3904 5451 struct ldb_result *res; 3905 const char *attrs[2]; 5452 struct ldb_result *target_res; 5453 const char *attrs[4]; 5454 const char *attrs2[] = { "isDeleted", "isRecycled", NULL }; 3906 5455 struct parsed_dn *pdn_list, *pdn; 3907 5456 struct GUID guid = GUID_zero(); … … 3909 5458 bool active = (la->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)?true:false; 3910 5459 const struct GUID *our_invocation_id; 5460 5461 enum deletion_state deletion_state = OBJECT_NOT_DELETED; 5462 enum deletion_state target_deletion_state = OBJECT_NOT_DELETED; 3911 5463 3912 5464 /* … … 3954 5506 3955 5507 attrs[0] = attr->lDAPDisplayName; 3956 attrs[1] = NULL; 5508 attrs[1] = "isDeleted"; 5509 attrs[2] = "isRecycled"; 5510 attrs[3] = NULL; 3957 5511 3958 5512 /* get the existing message from the db for the object with … … 3979 5533 msg = res->msgs[0]; 3980 5534 3981 if (msg->num_elements == 0) { 5535 /* 5536 * Check for deleted objects per MS-DRSR 4.1.10.6.13 5537 * ProcessLinkValue, because link updates are not applied to 5538 * recycled and tombstone objects. We don't have to delete 5539 * any existing link, that should have happened when the 5540 * object deletion was replicated or initiated. 5541 */ 5542 5543 replmd_deletion_state(module, msg, &deletion_state, NULL); 5544 5545 if (deletion_state >= OBJECT_RECYCLED) { 5546 talloc_free(tmp_ctx); 5547 return LDB_SUCCESS; 5548 } 5549 5550 old_el = ldb_msg_find_element(msg, attr->lDAPDisplayName); 5551 if (old_el == NULL) { 3982 5552 ret = ldb_msg_add_empty(msg, attr->lDAPDisplayName, LDB_FLAG_MOD_REPLACE, &old_el); 3983 5553 if (ret != LDB_SUCCESS) { … … 3987 5557 } 3988 5558 } else { 3989 old_el = &msg->elements[0];3990 5559 old_el->flags = LDB_FLAG_MOD_REPLACE; 3991 5560 } … … 4016 5585 ldb_asprintf_errstring(ldb, "Failed to parsed linked attribute blob for %s on %s - %s\n", 4017 5586 old_el->name, ldb_dn_get_linearized(msg->dn), win_errstr(status)); 5587 talloc_free(tmp_ctx); 4018 5588 return LDB_ERR_OPERATIONS_ERROR; 4019 5589 } 4020 5590 4021 5591 ntstatus = dsdb_get_extended_dn_guid(dsdb_dn->dn, &guid, "GUID"); 4022 if (!NT_STATUS_IS_OK(ntstatus) && active) { 5592 if (!NT_STATUS_IS_OK(ntstatus) && !active) { 5593 /* 5594 * This strange behaviour (allowing a NULL/missing 5595 * GUID) originally comes from: 5596 * 5597 * commit e3054ce0fe0f8f62d2f5b2a77893e7a1479128bd 5598 * Author: Andrew Tridgell <tridge@samba.org> 5599 * Date: Mon Dec 21 21:21:55 2009 +1100 5600 * 5601 * s4-drs: cope better with NULL GUIDS from DRS 5602 * 5603 * It is valid to get a NULL GUID over DRS for a deleted forward link. We 5604 * need to match by DN if possible when seeing if we should update an 5605 * existing link. 5606 * 5607 * Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org> 5608 */ 5609 5610 ret = dsdb_module_search_dn(module, tmp_ctx, &target_res, 5611 dsdb_dn->dn, attrs2, 5612 DSDB_FLAG_NEXT_MODULE | 5613 DSDB_SEARCH_SHOW_RECYCLED | 5614 DSDB_SEARCH_SEARCH_ALL_PARTITIONS | 5615 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, 5616 parent); 5617 } else if (!NT_STATUS_IS_OK(ntstatus)) { 4023 5618 ldb_asprintf_errstring(ldb, "Failed to find GUID in linked attribute blob for %s on %s from %s", 4024 5619 old_el->name, 4025 5620 ldb_dn_get_linearized(dsdb_dn->dn), 4026 5621 ldb_dn_get_linearized(msg->dn)); 5622 talloc_free(tmp_ctx); 4027 5623 return LDB_ERR_OPERATIONS_ERROR; 4028 } 4029 4030 /* re-resolve the DN by GUID, as the DRS server may give us an 4031 old DN value */ 4032 ret = dsdb_module_dn_by_guid(module, dsdb_dn, &guid, &dsdb_dn->dn, parent); 4033 if (ret != LDB_SUCCESS) { 4034 DEBUG(2,(__location__ ": WARNING: Failed to re-resolve GUID %s - using %s", 5624 } else { 5625 ret = dsdb_module_search(module, tmp_ctx, &target_res, 5626 NULL, LDB_SCOPE_SUBTREE, 5627 attrs2, 5628 DSDB_FLAG_NEXT_MODULE | 5629 DSDB_SEARCH_SHOW_RECYCLED | 5630 DSDB_SEARCH_SEARCH_ALL_PARTITIONS | 5631 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, 5632 parent, 5633 "objectGUID=%s", 5634 GUID_string(tmp_ctx, &guid)); 5635 } 5636 5637 if (ret != LDB_SUCCESS) { 5638 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to re-resolve GUID %s: %s\n", 5639 GUID_string(tmp_ctx, &guid), 5640 ldb_errstring(ldb_module_get_ctx(module))); 5641 talloc_free(tmp_ctx); 5642 return ret; 5643 } 5644 5645 if (target_res->count == 0) { 5646 DEBUG(2,(__location__ ": WARNING: Failed to re-resolve GUID %s - using %s\n", 4035 5647 GUID_string(tmp_ctx, &guid), 4036 5648 ldb_dn_get_linearized(dsdb_dn->dn))); 5649 } else if (target_res->count != 1) { 5650 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n", 5651 GUID_string(tmp_ctx, &guid)); 5652 talloc_free(tmp_ctx); 5653 return LDB_ERR_OPERATIONS_ERROR; 5654 } else { 5655 target_msg = target_res->msgs[0]; 5656 dsdb_dn->dn = talloc_steal(dsdb_dn, target_msg->dn); 5657 } 5658 5659 /* 5660 * Check for deleted objects per MS-DRSR 4.1.10.6.13 5661 * ProcessLinkValue, because link updates are not applied to 5662 * recycled and tombstone objects. We don't have to delete 5663 * any existing link, that should have happened when the 5664 * object deletion was replicated or initiated. 5665 */ 5666 replmd_deletion_state(module, target_msg, 5667 &target_deletion_state, NULL); 5668 5669 if (target_deletion_state >= OBJECT_RECYCLED) { 5670 talloc_free(tmp_ctx); 5671 return LDB_SUCCESS; 4037 5672 } 4038 5673 … … 4139 5774 /* we only change whenChanged and uSNChanged if the seq_num 4140 5775 has changed */ 4141 if (add_time_element(msg, "whenChanged", t) != LDB_SUCCESS) { 5776 ret = add_time_element(msg, "whenChanged", t); 5777 if (ret != LDB_SUCCESS) { 4142 5778 talloc_free(tmp_ctx); 4143 return ldb_operr(ldb); 4144 } 4145 4146 if (add_uint64_element(ldb, msg, "uSNChanged", 4147 seq_num) != LDB_SUCCESS) { 5779 ldb_operr(ldb); 5780 return ret; 5781 } 5782 5783 ret = add_uint64_element(ldb, msg, "uSNChanged", seq_num); 5784 if (ret != LDB_SUCCESS) { 4148 5785 talloc_free(tmp_ctx); 4149 return ldb_operr(ldb); 5786 ldb_operr(ldb); 5787 return ret; 4150 5788 } 4151 5789 -
vendor/current/source4/dsdb/samdb/ldb_modules/resolve_oids.c
r740 r988 413 413 static int resolve_oids_callback(struct ldb_request *req, struct ldb_reply *ares) 414 414 { 415 struct ldb_context *ldb;416 415 struct resolve_oids_context *ac; 417 416 418 417 ac = talloc_get_type_abort(req->context, struct resolve_oids_context); 419 ldb = ldb_module_get_ctx(ac->module);420 418 421 419 if (!ares) { -
vendor/current/source4/dsdb/samdb/ldb_modules/ridalloc.c
r740 r988 35 35 #include "param/param.h" 36 36 #include "librpc/gen_ndr/ndr_misc.h" 37 #include "dsdb/samdb/ldb_modules/ridalloc.h" 37 38 38 39 /* … … 64 65 completely run out of RIDs 65 66 */ 66 static voidridalloc_poke_rid_manager(struct ldb_module *module)67 static int ridalloc_poke_rid_manager(struct ldb_module *module) 67 68 { 68 struct messaging_context *msg; 69 struct server_id *server; 69 struct imessaging_context *msg; 70 unsigned num_servers; 71 struct server_id *servers; 70 72 struct ldb_context *ldb = ldb_module_get_ctx(module); 71 73 struct loadparm_context *lp_ctx = 72 74 (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"); 73 75 TALLOC_CTX *tmp_ctx = talloc_new(module); 74 75 msg = messaging_client_init(tmp_ctx, lpcfg_messaging_path(tmp_ctx, lp_ctx), 76 NTSTATUS status; 77 78 msg = imessaging_client_init(tmp_ctx, lp_ctx, 76 79 ldb_get_event_context(ldb)); 77 80 if (!msg) { 81 ldb_asprintf_errstring(ldb_module_get_ctx(module), 82 "Failed to send MSG_DREPL_ALLOCATE_RID, " 83 "unable init client messaging context"); 78 84 DEBUG(3,(__location__ ": Failed to create messaging context\n")); 79 85 talloc_free(tmp_ctx); 80 return; 81 } 82 83 server = irpc_servers_byname(msg, msg, "dreplsrv"); 84 if (!server) { 86 return LDB_ERR_UNWILLING_TO_PERFORM; 87 } 88 89 status = irpc_servers_byname(msg, msg, "dreplsrv", 90 &num_servers, &servers); 91 if (!NT_STATUS_IS_OK(status)) { 92 ldb_asprintf_errstring(ldb_module_get_ctx(module), 93 "Failed to send MSG_DREPL_ALLOCATE_RID, " 94 "unable to locate dreplsrv"); 85 95 /* this means the drepl service is not running */ 86 96 talloc_free(tmp_ctx); 87 return; 88 } 89 90 messaging_send(msg, server[0], MSG_DREPL_ALLOCATE_RID, NULL); 91 92 /* we don't care if the message got through */ 97 return LDB_ERR_UNWILLING_TO_PERFORM; 98 } 99 100 status = imessaging_send(msg, servers[0], MSG_DREPL_ALLOCATE_RID, NULL); 101 102 /* Only error out if an error happened, not on STATUS_MORE_ENTRIES, ie a delayed message */ 103 if (NT_STATUS_IS_ERR(status)) { 104 struct server_id_buf idbuf; 105 ldb_asprintf_errstring(ldb_module_get_ctx(module), 106 "Failed to send MSG_DREPL_ALLOCATE_RID to dreplsrv at %s: %s", 107 server_id_str_buf(*servers, &idbuf), 108 nt_errstr(status)); 109 talloc_free(tmp_ctx); 110 return LDB_ERR_UNWILLING_TO_PERFORM; 111 } 112 93 113 talloc_free(tmp_ctx); 114 return LDB_SUCCESS; 94 115 } 95 116 … … 263 284 .used_pool = 0, 264 285 }; 286 const char *no_attrs[] = { NULL }; 287 struct ldb_result *res; 265 288 266 289 /* … … 339 362 msg->dn = machine_dn; 340 363 341 ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn)); 364 /* we need the extended DN of the RID Set object for 365 * rIDSetReferences */ 366 ret = dsdb_module_search_dn(module, msg, &res, rid_set_dn, no_attrs, 367 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, parent); 368 if (ret != LDB_SUCCESS) { 369 ldb_asprintf_errstring(ldb, "Failed to find extended DN of RID Set %s - %s", 370 ldb_dn_get_linearized(msg->dn), 371 ldb_errstring(ldb)); 372 talloc_free(tmp_ctx); 373 return ret; 374 } 375 rid_set_dn = res->msgs[0]->dn; 376 377 378 ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_extended_linearized(msg, rid_set_dn, 1)); 342 379 if (ret != LDB_SUCCESS) { 343 380 talloc_free(tmp_ctx); … … 372 409 int ret; 373 410 struct ldb_context *ldb = ldb_module_get_ctx(module); 411 struct GUID fsmo_role_guid; 412 const struct GUID *our_ntds_guid; 413 NTSTATUS status; 374 414 375 415 /* work out who is the RID Manager */ … … 391 431 } 392 432 393 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) { 394 ridalloc_poke_rid_manager(module); 395 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh"); 433 status = dsdb_get_extended_dn_guid(fsmo_role_dn, &fsmo_role_guid, "GUID"); 434 if (!NT_STATUS_IS_OK(status)) { 435 talloc_free(tmp_ctx); 436 return ldb_operr(ldb_module_get_ctx(module)); 437 } 438 439 our_ntds_guid = samdb_ntds_objectGUID(ldb_module_get_ctx(module)); 440 if (!our_ntds_guid) { 441 talloc_free(tmp_ctx); 442 return ldb_operr(ldb_module_get_ctx(module)); 443 } 444 445 if (!GUID_equal(&fsmo_role_guid, our_ntds_guid)) { 446 ret = ridalloc_poke_rid_manager(module); 447 if (ret != LDB_SUCCESS) { 448 ldb_asprintf_errstring(ldb, 449 "Request for remote creation of " 450 "RID Set for this DC failed: %s", 451 ldb_errstring(ldb)); 452 } else { 453 ldb_asprintf_errstring(ldb, 454 "Remote RID Set creation needed"); 455 } 396 456 talloc_free(tmp_ctx); 397 457 return LDB_ERR_UNWILLING_TO_PERFORM; … … 413 473 int ret; 414 474 struct ldb_context *ldb = ldb_module_get_ctx(module); 475 bool is_us; 415 476 416 477 /* work out who is the RID Manager */ … … 432 493 } 433 494 434 if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) { 435 ridalloc_poke_rid_manager(module); 436 ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh"); 495 ret = samdb_dn_is_our_ntdsa(ldb, fsmo_role_dn, &is_us); 496 if (ret != LDB_SUCCESS) { 497 ldb_asprintf_errstring(ldb, "Failed to confirm if our ntdsDsa is %s: %s", 498 ldb_dn_get_linearized(fsmo_role_dn), ldb_errstring(ldb)); 499 talloc_free(tmp_ctx); 500 return ret; 501 } 502 503 if (!is_us) { 504 ret = ridalloc_poke_rid_manager(module); 505 if (ret != LDB_SUCCESS) { 506 ldb_asprintf_errstring(ldb, "Request for remote refresh of RID Set allocation failed: %s", 507 ldb_errstring(ldb)); 508 } else { 509 ldb_asprintf_errstring(ldb, "Remote RID Set refresh needed"); 510 } 437 511 talloc_free(tmp_ctx); 438 512 return LDB_ERR_UNWILLING_TO_PERFORM; … … 528 602 */ 529 603 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent); 530 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {531 ridalloc_poke_rid_manager(module);532 talloc_free(tmp_ctx);533 return ret;534 }535 604 if (ret != LDB_SUCCESS) { 605 ldb_asprintf_errstring(ldb, "NO RID values available: %s", 606 ldb_errstring(ldb)); 536 607 talloc_free(tmp_ctx); 537 608 return ret; … … 566 637 * if we are half-exhausted then try to get a new pool. 567 638 */ 568 if (nridset.next_rid > (prev_pool_hi + prev_pool_lo)/2) { 639 if (nridset.next_rid > (prev_pool_hi + prev_pool_lo)/2 && 640 nridset.alloc_pool == nridset.prev_pool) { 569 641 /* 570 642 * if we are the RID Manager, … … 575 647 ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent); 576 648 if (ret == LDB_ERR_UNWILLING_TO_PERFORM) { 577 ridalloc_poke_rid_manager(module);649 ldb_reset_err_string(ldb); 578 650 ret = LDB_SUCCESS; 579 651 } -
vendor/current/source4/dsdb/samdb/ldb_modules/rootdse.c
r740 r988 6 6 Copyright (C) Andrew Tridgell 2005 7 7 Copyright (C) Simo Sorce 2005-2008 8 Copyright (C) Matthieu Patou <mat@matws.net> 2011 8 9 9 10 This program is free software; you can redistribute it and/or modify … … 34 35 #include "lib/messaging/irpc.h" 35 36 #include "librpc/gen_ndr/ndr_irpc_c.h" 36 37 struct private_data { 37 #include "lib/tsocket/tsocket.h" 38 #include "cldap_server/cldap_server.h" 39 #include "lib/events/events.h" 40 41 struct rootdse_private_data { 38 42 unsigned int num_controls; 39 43 char **controls; … … 41 45 struct ldb_dn **partitions; 42 46 bool block_anonymous; 47 struct tevent_context *saved_ev; 48 struct tevent_context *private_ev; 49 }; 50 51 struct rootdse_context { 52 struct ldb_module *module; 53 struct ldb_request *req; 54 struct ldb_val netlogon; 43 55 }; 44 56 … … 77 89 struct ldb_context *ldb; 78 90 int edn_type = 0; 91 unsigned int i; 92 struct ldb_message_element *el; 79 93 80 94 ldb = ldb_module_get_ctx(module); … … 85 99 } 86 100 87 v = discard_const_p(struct ldb_val, ldb_msg_find_ldb_val(msg, attrname)); 88 if (v == NULL) { 101 el = ldb_msg_find_element(msg, attrname); 102 if (!el || el->num_values == 0) { 103 return LDB_SUCCESS; 104 } 105 106 for (i = 0; i < el->num_values; i++) { 107 v = &el->values[i]; 108 if (v == NULL) { 109 talloc_free(tmp_ctx); 110 return LDB_SUCCESS; 111 } 112 113 dn_string = talloc_strndup(tmp_ctx, (const char *)v->data, v->length); 114 if (dn_string == NULL) { 115 talloc_free(tmp_ctx); 116 return ldb_operr(ldb); 117 } 118 119 res = talloc_zero(tmp_ctx, struct ldb_result); 120 if (res == NULL) { 121 talloc_free(tmp_ctx); 122 return ldb_operr(ldb); 123 } 124 125 dn = ldb_dn_new(tmp_ctx, ldb, dn_string); 126 if (dn == NULL) { 127 talloc_free(tmp_ctx); 128 return ldb_operr(ldb); 129 } 130 131 ret = ldb_build_search_req(&req2, ldb, tmp_ctx, 132 dn, 133 LDB_SCOPE_BASE, 134 NULL, 135 no_attrs, 136 NULL, 137 res, ldb_search_default_callback, 138 req); 139 LDB_REQ_SET_LOCATION(req2); 140 if (ret != LDB_SUCCESS) { 141 talloc_free(tmp_ctx); 142 return ret; 143 } 144 145 ret = dsdb_request_add_controls(req2, DSDB_FLAG_AS_SYSTEM | 146 DSDB_SEARCH_SHOW_EXTENDED_DN); 147 if (ret != LDB_SUCCESS) { 148 talloc_free(tmp_ctx); 149 return ldb_error(ldb, ret, "Failed to add control"); 150 } 151 152 ret = ldb_next_request(module, req2); 153 if (ret == LDB_SUCCESS) { 154 ret = ldb_wait(req2->handle, LDB_WAIT_ALL); 155 } 156 157 if (ret != LDB_SUCCESS) { 158 talloc_free(tmp_ctx); 159 return ret; 160 } 161 162 if (!res || res->count != 1) { 163 talloc_free(tmp_ctx); 164 return ldb_operr(ldb); 165 } 166 167 dn2 = res->msgs[0]->dn; 168 169 v->data = (uint8_t *)ldb_dn_get_extended_linearized(msg->elements, dn2, edn_type); 170 if (v->data == NULL) { 171 talloc_free(tmp_ctx); 172 return ldb_operr(ldb); 173 } 174 v->length = strlen((char *)v->data); 175 } 176 177 talloc_free(tmp_ctx); 178 179 return LDB_SUCCESS; 180 } 181 182 /* 183 see if we are master for a FSMO role 184 */ 185 static int dsdb_module_we_are_master(struct ldb_module *module, struct ldb_dn *dn, bool *master, 186 struct ldb_request *parent) 187 { 188 const char *attrs[] = { "fSMORoleOwner", NULL }; 189 TALLOC_CTX *tmp_ctx = talloc_new(parent); 190 struct ldb_result *res; 191 int ret; 192 struct ldb_dn *owner_dn; 193 194 ret = dsdb_module_search_dn(module, tmp_ctx, &res, 195 dn, attrs, 196 DSDB_FLAG_NEXT_MODULE | 197 DSDB_FLAG_AS_SYSTEM | 198 DSDB_SEARCH_SHOW_EXTENDED_DN, 199 parent); 200 if (ret != LDB_SUCCESS) { 201 talloc_free(tmp_ctx); 202 return ret; 203 } 204 205 owner_dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module), 206 tmp_ctx, res->msgs[0], "fSMORoleOwner"); 207 if (!owner_dn) { 208 *master = false; 89 209 talloc_free(tmp_ctx); 90 210 return LDB_SUCCESS; 91 211 } 92 212 93 dn_string = talloc_strndup(tmp_ctx, (const char *)v->data, v->length); 94 if (dn_string == NULL) { 213 ret = samdb_dn_is_our_ntdsa(ldb_module_get_ctx(module), dn, master); 214 if (ret != LDB_SUCCESS) { 215 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to confirm if our ntdsDsa is %s: %s", 216 ldb_dn_get_linearized(owner_dn), ldb_errstring(ldb_module_get_ctx(module))); 95 217 talloc_free(tmp_ctx); 96 return ldb_operr(ldb); 97 } 98 99 res = talloc_zero(tmp_ctx, struct ldb_result); 100 if (res == NULL) { 101 talloc_free(tmp_ctx); 102 return ldb_operr(ldb); 103 } 104 105 dn = ldb_dn_new(tmp_ctx, ldb, dn_string); 106 if (dn == NULL) { 107 talloc_free(tmp_ctx); 108 return ldb_operr(ldb); 109 } 110 111 ret = ldb_build_search_req(&req2, ldb, tmp_ctx, 112 dn, 113 LDB_SCOPE_BASE, 114 NULL, 115 no_attrs, 116 NULL, 117 res, ldb_search_default_callback, 118 req); 119 LDB_REQ_SET_LOCATION(req2); 120 if (ret != LDB_SUCCESS) { 121 talloc_free(tmp_ctx); 122 return ret; 123 } 124 125 126 ret = ldb_request_add_control(req2, 127 LDB_CONTROL_EXTENDED_DN_OID, 128 edn_control->critical, edn); 129 if (ret != LDB_SUCCESS) { 130 talloc_free(tmp_ctx); 131 return ret; 132 } 133 134 ret = ldb_next_request(module, req2); 135 if (ret == LDB_SUCCESS) { 136 ret = ldb_wait(req2->handle, LDB_WAIT_ALL); 137 } 138 if (ret != LDB_SUCCESS) { 139 talloc_free(tmp_ctx); 140 return ret; 141 } 142 143 if (!res || res->count != 1) { 144 talloc_free(tmp_ctx); 145 return ldb_operr(ldb); 146 } 147 148 dn2 = res->msgs[0]->dn; 149 150 v->data = (uint8_t *)ldb_dn_get_extended_linearized(msg->elements, dn2, edn_type); 151 if (v->data == NULL) { 152 talloc_free(tmp_ctx); 153 return ldb_operr(ldb); 154 } 155 v->length = strlen((char *)v->data); 156 157 218 return ret; 219 } 220 158 221 talloc_free(tmp_ctx); 159 160 222 return LDB_SUCCESS; 161 223 } 162 163 224 164 225 /* 165 226 add dynamically generated attributes to rootDSE result 166 227 */ 167 static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *msg, 168 const char * const *attrs, struct ldb_request *req) 228 static int rootdse_add_dynamic(struct rootdse_context *ac, struct ldb_message *msg) 169 229 { 170 230 struct ldb_context *ldb; 171 struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data); 231 struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(ac->module), struct rootdse_private_data); 232 const char * const *attrs = ac->req->op.search.attrs; 172 233 char **server_sasl; 173 234 const struct dsdb_schema *schema; … … 177 238 "configurationNamingContext", 178 239 "defaultNamingContext", 179 "dsServiceName",180 240 "rootDomainNamingContext", 181 241 "schemaNamingContext", 182 242 "serverName", 243 "validFSMOs", 244 "namingContexts", 183 245 NULL 184 246 }; 185 186 ldb = ldb_module_get_ctx(module); 247 const char *guid_attrs[] = { 248 "dsServiceName", 249 NULL 250 }; 251 unsigned int i; 252 253 ldb = ldb_module_get_ctx(ac->module); 187 254 schema = dsdb_get_schema(ldb, NULL); 188 255 … … 205 272 int ret; 206 273 const char *dns_attrs[] = { "dNSHostName", NULL }; 207 ret = dsdb_module_search_dn(module, msg, &res, samdb_server_dn(ldb, msg), 208 dns_attrs, DSDB_FLAG_NEXT_MODULE, req); 274 ret = dsdb_module_search_dn(ac->module, msg, &res, samdb_server_dn(ldb, msg), 275 dns_attrs, 276 DSDB_FLAG_NEXT_MODULE | 277 DSDB_FLAG_AS_SYSTEM, 278 ac->req); 209 279 if (ret == LDB_SUCCESS) { 210 280 const char *hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL); 211 281 if (hostname != NULL) { 212 if (ldb_msg_add_string(msg, "d NSHostName", hostname)) {282 if (ldb_msg_add_string(msg, "dnsHostName", hostname)) { 213 283 goto failed; 214 284 } … … 223 293 char *ldap_service_name, *hostname; 224 294 225 hostname = talloc_strdup(msg, lpcfg_netbios_name(lp_ctx));295 hostname = strlower_talloc(msg, lpcfg_netbios_name(lp_ctx)); 226 296 if (hostname == NULL) { 227 297 goto failed; 228 298 } 229 strlower_m(hostname);230 299 231 300 ldap_service_name = talloc_asprintf(msg, "%s:%s$@%s", … … 250 319 251 320 if (priv && do_attribute(attrs, "supportedControl")) { 252 unsigned int i;253 321 for (i = 0; i < priv->num_controls; i++) { 254 322 char *control = talloc_strdup(msg, priv->controls[i]); … … 264 332 265 333 if (priv && do_attribute(attrs, "namingContexts")) { 266 unsigned int i;267 334 for (i = 0; i < priv->num_partitions; i++) { 268 335 struct ldb_dn *dn = priv->partitions[i]; … … 277 344 char *); 278 345 if (server_sasl && do_attribute(attrs, "supportedSASLMechanisms")) { 279 unsigned int i;280 346 for (i = 0; server_sasl && server_sasl[i]; i++) { 281 347 char *sasl_name = talloc_strdup(msg, server_sasl[i]); … … 338 404 339 405 if (do_attribute_explicit(attrs, "validFSMOs")) { 340 const struct dsdb_naming_fsmo *naming_fsmo; 341 const struct dsdb_pdc_fsmo *pdc_fsmo; 342 const char *dn_str; 343 344 if (schema && schema->fsmo.we_are_master) { 345 dn_str = ldb_dn_get_linearized(ldb_get_schema_basedn(ldb)); 346 if (dn_str && dn_str[0]) { 347 if (ldb_msg_add_fmt(msg, "validFSMOs", "%s", dn_str) != LDB_SUCCESS) { 348 goto failed; 349 } 406 struct ldb_dn *dns[3]; 407 408 dns[0] = ldb_get_schema_basedn(ldb); 409 dns[1] = samdb_partitions_dn(ldb, msg); 410 dns[2] = ldb_get_default_basedn(ldb); 411 412 for (i=0; i<3; i++) { 413 bool master; 414 int ret = dsdb_module_we_are_master(ac->module, dns[i], &master, ac->req); 415 if (ret != LDB_SUCCESS) { 416 goto failed; 350 417 } 351 } 352 353 naming_fsmo = talloc_get_type(ldb_get_opaque(ldb, "dsdb_naming_fsmo"), 354 struct dsdb_naming_fsmo); 355 if (naming_fsmo && naming_fsmo->we_are_master) { 356 dn_str = ldb_dn_get_linearized(samdb_partitions_dn(ldb, msg)); 357 if (dn_str && dn_str[0]) { 358 if (ldb_msg_add_fmt(msg, "validFSMOs", "%s", dn_str) != LDB_SUCCESS) { 359 goto failed; 360 } 361 } 362 } 363 364 pdc_fsmo = talloc_get_type(ldb_get_opaque(ldb, "dsdb_pdc_fsmo"), 365 struct dsdb_pdc_fsmo); 366 if (pdc_fsmo && pdc_fsmo->we_are_master) { 367 dn_str = ldb_dn_get_linearized(ldb_get_default_basedn(ldb)); 368 if (dn_str && dn_str[0]) { 369 if (ldb_msg_add_fmt(msg, "validFSMOs", "%s", dn_str) != LDB_SUCCESS) { 370 goto failed; 371 } 418 if (master && ldb_msg_add_fmt(msg, "validFSMOs", "%s", 419 ldb_dn_get_linearized(dns[i])) != LDB_SUCCESS) { 420 goto failed; 372 421 } 373 422 } … … 418 467 419 468 if (do_attribute_explicit(attrs, "tokenGroups")) { 420 unsigned int i;421 469 /* Obtain the user's session_info */ 422 470 struct auth_session_info *session_info … … 434 482 } 435 483 484 if (ac->netlogon.length > 0) { 485 if (ldb_msg_add_steal_value(msg, "netlogon", &ac->netlogon) != LDB_SUCCESS) { 486 goto failed; 487 } 488 } 489 436 490 /* TODO: lots more dynamic attributes should be added here */ 437 491 438 edn_control = ldb_request_get_control(req, LDB_CONTROL_EXTENDED_DN_OID); 492 edn_control = ldb_request_get_control(ac->req, LDB_CONTROL_EXTENDED_DN_OID); 493 494 /* convert any GUID attributes to be in the right form */ 495 for (i=0; guid_attrs[i]; i++) { 496 struct ldb_result *res; 497 struct ldb_message_element *el; 498 struct ldb_dn *attr_dn; 499 const char *no_attrs[] = { NULL }; 500 int ret; 501 502 if (!do_attribute(attrs, guid_attrs[i])) continue; 503 504 attr_dn = ldb_msg_find_attr_as_dn(ldb, ac->req, msg, guid_attrs[i]); 505 if (attr_dn == NULL) { 506 continue; 507 } 508 509 ret = dsdb_module_search_dn(ac->module, ac->req, &res, 510 attr_dn, no_attrs, 511 DSDB_FLAG_NEXT_MODULE | 512 DSDB_FLAG_AS_SYSTEM | 513 DSDB_SEARCH_SHOW_EXTENDED_DN, 514 ac->req); 515 if (ret != LDB_SUCCESS) { 516 return ldb_operr(ldb); 517 } 518 519 el = ldb_msg_find_element(msg, guid_attrs[i]); 520 if (el == NULL) { 521 return ldb_operr(ldb); 522 } 523 524 talloc_steal(el->values, res->msgs[0]->dn); 525 if (edn_control) { 526 struct ldb_extended_dn_control *edn; 527 int edn_type = 0; 528 edn = talloc_get_type(edn_control->data, struct ldb_extended_dn_control); 529 if (edn != NULL) { 530 edn_type = edn->type; 531 } 532 el->values[0].data = (uint8_t *)ldb_dn_get_extended_linearized(el->values, 533 res->msgs[0]->dn, 534 edn_type); 535 } else { 536 el->values[0].data = (uint8_t *)talloc_strdup(el->values, 537 ldb_dn_get_linearized(res->msgs[0]->dn)); 538 } 539 if (el->values[0].data == NULL) { 540 return ldb_oom(ldb); 541 } 542 el->values[0].length = strlen((const char *)el->values[0].data); 543 } 439 544 440 545 /* if the client sent us the EXTENDED_DN control then we need … … 442 547 this */ 443 548 if (edn_control) { 444 unsigned int i;445 549 int ret; 446 550 for (i=0; dn_attrs[i]; i++) { 447 551 if (!do_attribute(attrs, dn_attrs[i])) continue; 448 ret = expand_dn_in_message( module, msg, dn_attrs[i],449 edn_control, req);552 ret = expand_dn_in_message(ac->module, msg, dn_attrs[i], 553 edn_control, ac->req); 450 554 if (ret != LDB_SUCCESS) { 451 555 DEBUG(0,(__location__ ": Failed to expand DN in rootDSE for %s\n", … … 466 570 */ 467 571 468 struct rootdse_context {469 struct ldb_module *module;470 struct ldb_request *req;471 };472 473 572 static struct rootdse_context *rootdse_init_context(struct ldb_module *module, 474 573 struct ldb_request *req) … … 509 608 switch (ares->type) { 510 609 case LDB_REPLY_ENTRY: 511 /*512 * if the client explicit asks for the 'netlogon' attribute513 * the reply_entry needs to be skipped514 */515 if (ac->req->op.search.attrs &&516 ldb_attr_in_list(ac->req->op.search.attrs, "netlogon")) {517 talloc_free(ares);518 return LDB_SUCCESS;519 }520 521 610 /* for each record returned post-process to add any dynamic 522 611 attributes that have been asked for */ 523 ret = rootdse_add_dynamic(ac->module, ares->message, 524 ac->req->op.search.attrs, ac->req); 612 ret = rootdse_add_dynamic(ac, ares->message); 525 613 if (ret != LDB_SUCCESS) { 526 614 talloc_free(ares); … … 568 656 { 569 657 unsigned int i, j; 570 struct private_data *priv = talloc_get_type(ldb_module_get_private(module), structprivate_data);658 struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data); 571 659 bool is_untrusted; 572 660 … … 614 702 } 615 703 616 if (is_registered) { 704 /* If the control is DIRSYNC control then we keep the critical 705 * flag as the dirsync module will need to act upon it 706 */ 707 if (is_registered && strcmp(req->controls[i]->oid, 708 LDB_CONTROL_DIRSYNC_OID)!= 0) { 617 709 req->controls[i]->critical = 0; 618 710 } … … 627 719 { 628 720 struct auth_session_info *session_info; 629 struct private_data *priv = talloc_get_type(ldb_module_get_private(module), structprivate_data);721 struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data); 630 722 bool is_untrusted = ldb_req_is_untrusted(req); 631 723 bool is_anonymous = true; … … 652 744 } 653 745 746 static int rootdse_handle_netlogon(struct rootdse_context *ac) 747 { 748 struct ldb_context *ldb; 749 struct ldb_parse_tree *tree; 750 struct loadparm_context *lp_ctx; 751 struct tsocket_address *src_addr; 752 TALLOC_CTX *tmp_ctx = talloc_new(ac->req); 753 const char *domain, *host, *user, *domain_guid; 754 char *src_addr_s = NULL; 755 struct dom_sid *domain_sid; 756 int acct_control = -1; 757 int version = -1; 758 NTSTATUS status; 759 struct netlogon_samlogon_response netlogon; 760 int ret = LDB_ERR_OPERATIONS_ERROR; 761 762 ldb = ldb_module_get_ctx(ac->module); 763 tree = ac->req->op.search.tree; 764 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"), 765 struct loadparm_context); 766 src_addr = talloc_get_type(ldb_get_opaque(ldb, "remoteAddress"), 767 struct tsocket_address); 768 if (src_addr) { 769 src_addr_s = tsocket_address_inet_addr_string(src_addr, 770 tmp_ctx); 771 } 772 773 status = parse_netlogon_request(tree, lp_ctx, tmp_ctx, 774 &domain, &host, &user, &domain_guid, 775 &domain_sid, &acct_control, &version); 776 if (!NT_STATUS_IS_OK(status)) { 777 goto failed; 778 } 779 780 status = fill_netlogon_samlogon_response(ldb, tmp_ctx, 781 domain, NULL, domain_sid, 782 domain_guid, 783 user, acct_control, 784 src_addr_s, 785 version, lp_ctx, 786 &netlogon, false); 787 if (!NT_STATUS_IS_OK(status)) { 788 goto failed; 789 } 790 791 status = push_netlogon_samlogon_response(&ac->netlogon, ac, &netlogon); 792 if (!NT_STATUS_IS_OK(status)) { 793 goto failed; 794 } 795 796 ret = LDB_SUCCESS; 797 failed: 798 talloc_free(tmp_ctx); 799 return ret; 800 } 801 654 802 static int rootdse_search(struct ldb_module *module, struct ldb_request *req) 655 803 { … … 680 828 if (ac == NULL) { 681 829 return ldb_operr(ldb); 830 } 831 832 if (do_attribute_explicit(req->op.search.attrs, "netlogon")) { 833 ret = rootdse_handle_netlogon(ac); 834 /* We have to return an empty result, so don't forward `ret' */ 835 if (ret != LDB_SUCCESS) { 836 return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS); 837 } 682 838 } 683 839 … … 701 857 static int rootdse_register_control(struct ldb_module *module, struct ldb_request *req) 702 858 { 703 struct private_data *priv = talloc_get_type(ldb_module_get_private(module), structprivate_data);859 struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data); 704 860 char **list; 705 861 … … 722 878 static int rootdse_register_partition(struct ldb_module *module, struct ldb_request *req) 723 879 { 724 struct private_data *priv = talloc_get_type(ldb_module_get_private(module), structprivate_data);880 struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data); 725 881 struct ldb_dn **list; 726 882 … … 762 918 struct ldb_context *ldb; 763 919 struct ldb_result *res; 764 struct private_data *data;920 struct rootdse_private_data *data; 765 921 const char *attrs[] = { "msDS-Behavior-Version", NULL }; 766 922 const char *ds_attrs[] = { "dsServiceName", NULL }; … … 769 925 ldb = ldb_module_get_ctx(module); 770 926 771 data = talloc_zero(module, struct private_data);927 data = talloc_zero(module, struct rootdse_private_data); 772 928 if (data == NULL) { 773 929 return ldb_oom(ldb); … … 804 960 ret = dsdb_module_search(module, mem_ctx, &res, 805 961 ldb_get_default_basedn(ldb), 806 LDB_SCOPE_BASE, attrs, DSDB_FLAG_NEXT_MODULE, NULL, NULL); 962 LDB_SCOPE_BASE, attrs, 963 DSDB_FLAG_NEXT_MODULE | 964 DSDB_FLAG_AS_SYSTEM, 965 NULL, NULL); 807 966 if (ret == LDB_SUCCESS && res->count == 1) { 808 967 int domain_behaviour_version … … 826 985 ret = dsdb_module_search(module, mem_ctx, &res, 827 986 samdb_partitions_dn(ldb, mem_ctx), 828 LDB_SCOPE_BASE, attrs, DSDB_FLAG_NEXT_MODULE, NULL, NULL); 987 LDB_SCOPE_BASE, attrs, 988 DSDB_FLAG_NEXT_MODULE | 989 DSDB_FLAG_AS_SYSTEM, 990 NULL, NULL); 829 991 if (ret == LDB_SUCCESS && res->count == 1) { 830 992 int forest_behaviour_version … … 850 1012 ret = dsdb_module_search(module, mem_ctx, &res, 851 1013 ldb_dn_new(mem_ctx, ldb, "@ROOTDSE"), 852 LDB_SCOPE_BASE, ds_attrs, DSDB_FLAG_NEXT_MODULE, NULL, NULL); 1014 LDB_SCOPE_BASE, ds_attrs, 1015 DSDB_FLAG_NEXT_MODULE | 1016 DSDB_FLAG_AS_SYSTEM, 1017 NULL, NULL); 853 1018 if (ret == LDB_SUCCESS && res->count == 1) { 854 1019 struct ldb_dn *ds_dn … … 857 1022 if (ds_dn) { 858 1023 ret = dsdb_module_search(module, mem_ctx, &res, ds_dn, 859 LDB_SCOPE_BASE, attrs, DSDB_FLAG_NEXT_MODULE, NULL, NULL); 1024 LDB_SCOPE_BASE, attrs, 1025 DSDB_FLAG_NEXT_MODULE | 1026 DSDB_FLAG_AS_SYSTEM, 1027 NULL, NULL); 860 1028 if (ret == LDB_SUCCESS && res->count == 1) { 861 1029 int domain_controller_behaviour_version … … 950 1118 NULL, 951 1119 DSDB_FLAG_NEXT_MODULE | 1120 DSDB_FLAG_AS_SYSTEM | 952 1121 DSDB_SEARCH_SEARCH_ALL_PARTITIONS, 953 1122 parent, … … 997 1166 998 1167 tmp_ctx = talloc_new(mem_ctx); 999 ntds_settings_dn = samdb_ntds_settings_dn(ldb );1168 ntds_settings_dn = samdb_ntds_settings_dn(ldb, tmp_ctx); 1000 1169 if (!ntds_settings_dn) { 1001 DEBUG(0, (__location__ ": Failed to find NTDS settings DN\n"));1002 ret = LDB_ERR_OPERATIONS_ERROR;1003 1170 talloc_free(tmp_ctx); 1004 return ret;1171 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "Failed to find NTDS settings DN"); 1005 1172 } 1006 1173 1007 1174 ntds_settings_dn = ldb_dn_copy(tmp_ctx, ntds_settings_dn); 1008 1175 if (!ntds_settings_dn) { 1009 DEBUG(0, (__location__ ": Failed to copy NTDS settings DN\n"));1010 ret = LDB_ERR_OPERATIONS_ERROR;1011 1176 talloc_free(tmp_ctx); 1012 return ret;1177 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "Failed to copy NTDS settings DN"); 1013 1178 } 1014 1179 1015 1180 msg = ldb_msg_new(tmp_ctx); 1181 if (msg == NULL) { 1182 talloc_free(tmp_ctx); 1183 return ldb_module_oom(module); 1184 } 1016 1185 msg->dn = ntds_settings_dn; 1017 1186 … … 1138 1307 } 1139 1308 1309 static int rootdse_schemaupgradeinprogress(struct ldb_module *module, struct ldb_request *req) 1310 { 1311 struct ldb_context *ldb = ldb_module_get_ctx(module); 1312 int ret = LDB_SUCCESS; 1313 struct ldb_dn *schema_dn; 1314 1315 schema_dn = ldb_get_schema_basedn(ldb); 1316 if (!schema_dn) { 1317 ldb_reset_err_string(ldb); 1318 ldb_debug(ldb, LDB_DEBUG_WARNING, 1319 "rootdse_modify: no schema dn present: (skip ldb_extended call)\n"); 1320 return ldb_next_request(module, req); 1321 } 1322 1323 /* FIXME we have to do something in order to relax constraints for DRS 1324 * setting schemaUpgradeInProgress cause the fschemaUpgradeInProgress 1325 * in all LDAP connection (2K3/2K3R2) or in the current connection (2K8 and +) 1326 * to be set to true. 1327 */ 1328 1329 /* from 5.113 LDAPConnections in DRSR.pdf 1330 * fschemaUpgradeInProgress: A Boolean that specifies certain constraint 1331 * validations are skipped when adding, updating, or removing directory 1332 * objects on the opened connection. The skipped constraint validations 1333 * are documented in the applicable constraint sections in [MS-ADTS]. 1334 */ 1335 return ldb_module_done(req, NULL, NULL, ret); 1336 } 1337 1140 1338 static int rootdse_add(struct ldb_module *module, struct ldb_request *req) 1141 1339 { … … 1164 1362 } 1165 1363 1364 static int rootdse_start_trans(struct ldb_module *module) 1365 { 1366 int ret; 1367 struct ldb_context *ldb = ldb_module_get_ctx(module); 1368 struct rootdse_private_data *data = talloc_get_type_abort(ldb_module_get_private(module), 1369 struct rootdse_private_data); 1370 ret = ldb_next_start_trans(module); 1371 if (ret == LDB_SUCCESS) { 1372 if (data->private_ev != NULL) { 1373 return ldb_operr(ldb); 1374 } 1375 data->private_ev = s4_event_context_init(data); 1376 if (data->private_ev == NULL) { 1377 return ldb_operr(ldb); 1378 } 1379 data->saved_ev = ldb_get_event_context(ldb); 1380 ldb_set_event_context(ldb, data->private_ev); 1381 } 1382 return ret; 1383 } 1384 1385 static int rootdse_end_trans(struct ldb_module *module) 1386 { 1387 int ret; 1388 struct ldb_context *ldb = ldb_module_get_ctx(module); 1389 struct rootdse_private_data *data = talloc_get_type_abort(ldb_module_get_private(module), 1390 struct rootdse_private_data); 1391 ret = ldb_next_end_trans(module); 1392 if (data->saved_ev == NULL) { 1393 return ldb_operr(ldb); 1394 } 1395 1396 if (data->private_ev != ldb_get_event_context(ldb)) { 1397 return ldb_operr(ldb); 1398 } 1399 ldb_set_event_context(ldb, data->saved_ev); 1400 data->saved_ev = NULL; 1401 TALLOC_FREE(data->private_ev); 1402 return ret; 1403 } 1404 1405 static int rootdse_del_trans(struct ldb_module *module) 1406 { 1407 int ret; 1408 struct ldb_context *ldb = ldb_module_get_ctx(module); 1409 struct rootdse_private_data *data = talloc_get_type_abort(ldb_module_get_private(module), 1410 struct rootdse_private_data); 1411 ret = ldb_next_del_trans(module); 1412 if (data->saved_ev == NULL) { 1413 return ldb_operr(ldb); 1414 } 1415 1416 if (data->private_ev != ldb_get_event_context(ldb)) { 1417 return ldb_operr(ldb); 1418 } 1419 ldb_set_event_context(ldb, data->saved_ev); 1420 data->saved_ev = NULL; 1421 TALLOC_FREE(data->private_ev); 1422 return ret; 1423 } 1424 1425 struct fsmo_transfer_state { 1426 struct ldb_context *ldb; 1427 struct ldb_request *req; 1428 struct ldb_module *module; 1429 }; 1430 1431 /* 1432 called when a FSMO transfer operation has completed 1433 */ 1434 static void rootdse_fsmo_transfer_callback(struct tevent_req *treq) 1435 { 1436 struct fsmo_transfer_state *fsmo = tevent_req_callback_data(treq, struct fsmo_transfer_state); 1437 NTSTATUS status; 1438 WERROR werr; 1439 int ret; 1440 struct ldb_request *req = fsmo->req; 1441 struct ldb_context *ldb = fsmo->ldb; 1442 struct ldb_module *module = fsmo->module; 1443 1444 status = dcerpc_drepl_takeFSMORole_recv(treq, fsmo, &werr); 1445 talloc_free(fsmo); 1446 if (!NT_STATUS_IS_OK(status)) { 1447 ldb_asprintf_errstring(ldb, "Failed FSMO transfer: %s", nt_errstr(status)); 1448 /* 1449 * Now that it is failed, start the transaction up 1450 * again so the wrappers can close it without additional error 1451 */ 1452 rootdse_start_trans(module); 1453 ldb_module_done(req, NULL, NULL, LDB_ERR_UNAVAILABLE); 1454 return; 1455 } 1456 if (!W_ERROR_IS_OK(werr)) { 1457 ldb_asprintf_errstring(ldb, "Failed FSMO transfer: %s", win_errstr(werr)); 1458 /* 1459 * Now that it is failed, start the transaction up 1460 * again so the wrappers can close it without additional error 1461 */ 1462 rootdse_start_trans(module); 1463 ldb_module_done(req, NULL, NULL, LDB_ERR_UNAVAILABLE); 1464 return; 1465 } 1466 1467 /* 1468 * Now that it is done, start the transaction up again so the 1469 * wrappers can close it without error 1470 */ 1471 ret = rootdse_start_trans(module); 1472 ldb_module_done(req, NULL, NULL, ret); 1473 } 1474 1166 1475 static int rootdse_become_master(struct ldb_module *module, 1167 1476 struct ldb_request *req, 1168 1477 enum drepl_role_master role) 1169 1478 { 1170 struct drepl_takeFSMORole r; 1171 struct messaging_context *msg; 1479 struct imessaging_context *msg; 1172 1480 struct ldb_context *ldb = ldb_module_get_ctx(module); 1173 1481 TALLOC_CTX *tmp_ctx = talloc_new(req); 1174 1482 struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm"); 1175 NTSTATUS status_call;1176 WERROR status_fn;1177 1483 bool am_rodc; 1178 1484 struct dcerpc_binding_handle *irpc_handle; 1179 1485 int ret; 1486 struct auth_session_info *session_info; 1487 enum security_user_level level; 1488 struct fsmo_transfer_state *fsmo; 1489 struct tevent_req *treq; 1490 1491 session_info = (struct auth_session_info *)ldb_get_opaque(ldb_module_get_ctx(module), "sessionInfo"); 1492 level = security_session_user_level(session_info, NULL); 1493 if (level < SECURITY_ADMINISTRATOR) { 1494 return ldb_error(ldb, LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS, "Denied rootDSE modify for non-administrator"); 1495 } 1180 1496 1181 1497 ret = samdb_rodc(ldb, &am_rodc); … … 1189 1505 } 1190 1506 1191 msg = messaging_client_init(tmp_ctx, lpcfg_messaging_path(tmp_ctx, lp_ctx), 1507 /* 1508 * We always delete the transaction, not commit it, because 1509 * this gives the least supprise to this supprising action (as 1510 * we will never record anything done to this point 1511 */ 1512 rootdse_del_trans(module); 1513 1514 msg = imessaging_client_init(tmp_ctx, lp_ctx, 1192 1515 ldb_get_event_context(ldb)); 1193 1516 if (!msg) { 1194 ldb_asprintf_errstring(ldb, "Failed to generate client messaging context in %s", lpcfg_ messaging_path(tmp_ctx, lp_ctx));1517 ldb_asprintf_errstring(ldb, "Failed to generate client messaging context in %s", lpcfg_imessaging_path(tmp_ctx, lp_ctx)); 1195 1518 return LDB_ERR_OPERATIONS_ERROR; 1196 1519 } … … 1201 1524 return ldb_oom(ldb); 1202 1525 } 1203 r.in.role = role; 1204 1205 status_call = dcerpc_drepl_takeFSMORole_r(irpc_handle, tmp_ctx, &r); 1206 if (!NT_STATUS_IS_OK(status_call)) { 1207 return LDB_ERR_OPERATIONS_ERROR; 1208 } 1209 status_fn = r.out.result; 1210 if (!W_ERROR_IS_OK(status_fn)) { 1211 return LDB_ERR_OPERATIONS_ERROR; 1212 } 1213 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); 1526 fsmo = talloc_zero(req, struct fsmo_transfer_state); 1527 if (fsmo == NULL) { 1528 return ldb_oom(ldb); 1529 } 1530 fsmo->ldb = ldb; 1531 fsmo->req = req; 1532 fsmo->module = module; 1533 1534 /* 1535 * we send the call asynchronously, as the ldap client is 1536 * expecting to get an error back if the role transfer fails 1537 * 1538 * We need more than the default 10 seconds IRPC allows, so 1539 * set a longer timeout (default ldb timeout is 300 seconds). 1540 * We send an async reply when we are done. 1541 * 1542 * We are the first module, so don't bother working out how 1543 * long we have spent so far. 1544 */ 1545 dcerpc_binding_handle_set_timeout(irpc_handle, req->timeout); 1546 1547 treq = dcerpc_drepl_takeFSMORole_send(req, ldb_get_event_context(ldb), irpc_handle, role); 1548 if (treq == NULL) { 1549 return ldb_oom(ldb); 1550 } 1551 1552 tevent_req_set_callback(treq, rootdse_fsmo_transfer_callback, fsmo); 1553 return LDB_SUCCESS; 1214 1554 } 1215 1555 … … 1261 1601 return rootdse_enableoptionalfeature(module, req); 1262 1602 } 1603 if (ldb_msg_find_element(req->op.mod.message, "schemaUpgradeInProgress")) { 1604 return rootdse_schemaupgradeinprogress(module, req); 1605 } 1263 1606 1264 1607 ldb_set_errstring(ldb, "rootdse_modify: unknown attribute to change!"); … … 1336 1679 1337 1680 static const struct ldb_module_ops ldb_rootdse_module_ops = { 1338 .name = "rootdse", 1339 .init_context = rootdse_init, 1340 .search = rootdse_search, 1341 .request = rootdse_request, 1342 .add = rootdse_add, 1343 .modify = rootdse_modify, 1344 .rename = rootdse_rename, 1345 .extended = rootdse_extended, 1346 .del = rootdse_delete 1681 .name = "rootdse", 1682 .init_context = rootdse_init, 1683 .search = rootdse_search, 1684 .request = rootdse_request, 1685 .add = rootdse_add, 1686 .modify = rootdse_modify, 1687 .rename = rootdse_rename, 1688 .extended = rootdse_extended, 1689 .del = rootdse_delete, 1690 .start_transaction = rootdse_start_trans, 1691 .end_transaction = rootdse_end_trans, 1692 .del_transaction = rootdse_del_trans 1347 1693 }; 1348 1694 -
vendor/current/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
r740 r988 38 38 #include "dsdb/samdb/samdb.h" 39 39 #include "librpc/ndr/libndr.h" 40 #include "auth/credentials/credentials.h" 41 #include "param/secrets.h" 42 #include "lib/ldb-samba/ldb_wrap.h" 40 43 41 44 static int read_at_rootdse_record(struct ldb_context *ldb, struct ldb_module *module, TALLOC_CTX *mem_ctx, … … 103 106 104 107 if (backend_mod) { 105 backend_full_list = (const char **)str_list_make_single(tmp_ctx, backend_mod); 108 char **b = str_list_make_single(tmp_ctx, backend_mod); 109 backend_full_list = discard_const_p(const char *, b); 106 110 } else { 107 backend_full_list = (const char **)str_list_make_empty(tmp_ctx); 111 char **b = str_list_make_empty(tmp_ctx); 112 backend_full_list = discard_const_p(const char *, b); 108 113 } 109 114 if (!backend_full_list) { … … 130 135 } 131 136 132 137 /* 138 * Force overwrite of the credentials with those 139 * specified in secrets.ldb, to connect across the 140 * ldapi socket to an LDAP backend 141 */ 142 143 static int set_ldap_credentials(struct ldb_context *ldb, bool use_external) 144 { 145 const char *secrets_ldb_path, *sam_ldb_path; 146 char *private_dir, *p, *error_string; 147 struct ldb_context *secrets_ldb; 148 struct cli_credentials *cred; 149 struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm"); 150 TALLOC_CTX *tmp_ctx = talloc_new(ldb); 151 152 if (!tmp_ctx) { 153 return ldb_oom(ldb); 154 } 155 156 cred = cli_credentials_init(ldb); 157 if (!cred) { 158 talloc_free(tmp_ctx); 159 return ldb_oom(ldb); 160 } 161 cli_credentials_set_anonymous(cred); 162 if (use_external) { 163 cli_credentials_set_forced_sasl_mech(cred, "EXTERNAL"); 164 } else { 165 cli_credentials_set_forced_sasl_mech(cred, "DIGEST-MD5"); 166 167 /* 168 * We don't want to use krb5 to talk to our samdb - recursion 169 * here would be bad, and this account isn't in the KDC 170 * anyway 171 */ 172 cli_credentials_set_kerberos_state(cred, CRED_DONT_USE_KERBEROS); 173 174 /* 175 * Work out where *our* secrets.ldb is. It must be in 176 * the same directory as sam.ldb 177 */ 178 sam_ldb_path = (const char *)ldb_get_opaque(ldb, "ldb_url"); 179 if (!sam_ldb_path) { 180 talloc_free(tmp_ctx); 181 return ldb_operr(ldb); 182 } 183 if (strncmp("tdb://", sam_ldb_path, 6) == 0) { 184 sam_ldb_path += 6; 185 } 186 private_dir = talloc_strdup(tmp_ctx, sam_ldb_path); 187 p = strrchr(private_dir, '/'); 188 if (p) { 189 *p = '\0'; 190 } else { 191 private_dir = talloc_strdup(tmp_ctx, "."); 192 } 193 194 secrets_ldb_path = talloc_asprintf(private_dir, "tdb://%s/secrets.ldb", 195 private_dir); 196 197 if (!secrets_ldb_path) { 198 talloc_free(tmp_ctx); 199 return ldb_oom(ldb); 200 } 201 202 /* 203 * Now that we have found the location, connect to 204 * secrets.ldb so we can read the SamDB Credentials 205 * record 206 */ 207 secrets_ldb = ldb_wrap_connect(tmp_ctx, NULL, lp_ctx, secrets_ldb_path, 208 NULL, NULL, 0); 209 210 if (!NT_STATUS_IS_OK(cli_credentials_set_secrets(cred, NULL, secrets_ldb, NULL, 211 SECRETS_LDAP_FILTER, &error_string))) { 212 ldb_asprintf_errstring(ldb, "Failed to read LDAP backend password from %s", secrets_ldb_path); 213 talloc_free(tmp_ctx); 214 return LDB_ERR_STRONG_AUTH_REQUIRED; 215 } 216 } 217 218 /* 219 * Finally overwrite any supplied credentials with 220 * these ones, as only secrets.ldb contains the magic 221 * credentials to talk on the ldapi socket 222 */ 223 if (ldb_set_opaque(ldb, "credentials", cred)) { 224 talloc_free(tmp_ctx); 225 return ldb_operr(ldb); 226 } 227 talloc_free(tmp_ctx); 228 return LDB_SUCCESS; 229 } 133 230 134 231 static int samba_dsdb_init(struct ldb_module *module) … … 138 235 TALLOC_CTX *tmp_ctx = talloc_new(module); 139 236 struct ldb_result *res; 140 struct ldb_message *rootdse_msg , *partition_msg;141 struct ldb_dn *samba_dsdb_dn ;237 struct ldb_message *rootdse_msg = NULL, *partition_msg; 238 struct ldb_dn *samba_dsdb_dn, *partition_dn; 142 239 struct ldb_module *backend_module, *module_chain; 143 240 const char **final_module_list, **reverse_module_list; … … 151 248 - objectclass must be before password_hash and samldb since these LDB 152 249 modules require the expanded "objectClass" list 250 - objectclass must be before descriptor and acl, as both assume that 251 objectClass values are sorted 153 252 - objectclass_attrs must be behind operational in order to see all 154 253 attributes (the operational module protects and therefore … … 161 260 based on the parameters loaded from the database. 162 261 */ 163 static const char *modules_list [] = {"resolve_oids",262 static const char *modules_list1[] = {"resolve_oids", 164 263 "rootdse", 264 "schema_load", 165 265 "lazy_commit", 266 "dirsync", 166 267 "paged_results", 167 268 "ranged_results", … … 170 271 "asq", 171 272 "extended_dn_store", 172 "extended_dn_in", 173 "objectclass", 273 NULL }; 274 /* extended_dn_in or extended_dn_in_openldap goes here */ 275 static const char *modules_list1a[] = {"objectclass", 174 276 "descriptor", 175 277 "acl", … … 178 280 "password_hash", 179 281 "operational", 180 "schema_load",181 282 "instancetype", 182 283 "objectclass_attrs", … … 200 301 const char *extended_dn_module_fds = "extended_dn_out_fds"; 201 302 const char *extended_dn_module_openldap = "extended_dn_out_openldap"; 202 203 static const char *modules_list2[] = {"show_deleted", 303 const char *extended_dn_in_module = "extended_dn_in"; 304 305 static const char *modules_list2[] = {"dns_notify", 306 "show_deleted", 204 307 "new_partition", 205 308 "partition", … … 210 313 "nsuniqueid", "paged_searches", "simple_dn", NULL }; 211 314 static const char *openldap_backend_modules[] = { 212 "entryuuid", "paged_searches", "simple_dn", NULL }; 213 214 static const char *samba_dsdb_attrs[] = { "backendType", "serverRole", NULL }; 215 const char *backendType, *serverRole; 315 "entryuuid", "simple_dn", NULL }; 316 317 static const char *samba_dsdb_attrs[] = { "backendType", NULL }; 318 static const char *partition_attrs[] = { "ldapBackend", NULL }; 319 const char *backendType, *backendUrl; 320 bool use_sasl_external = false; 216 321 217 322 if (!tmp_ctx) { … … 227 332 samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB"); 228 333 if (!samba_dsdb_dn) { 334 talloc_free(tmp_ctx); 335 return ldb_oom(ldb); 336 } 337 338 partition_dn = ldb_dn_new(tmp_ctx, ldb, DSDB_PARTITION_DN); 339 if (!partition_dn) { 229 340 talloc_free(tmp_ctx); 230 341 return ldb_oom(ldb); … … 243 354 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 244 355 backendType = "ldb"; 245 serverRole = "domain controller";246 356 } else if (ret == LDB_SUCCESS) { 247 357 backendType = ldb_msg_find_attr_as_string(res->msgs[0], "backendType", "ldb"); 248 serverRole = ldb_msg_find_attr_as_string(res->msgs[0], "serverRole", "domain controller");249 358 } else { 250 359 talloc_free(tmp_ctx); … … 257 366 link_modules = tdb_modules_list; 258 367 } else { 368 struct cli_credentials *cred; 369 bool is_ldapi = false; 370 371 ret = dsdb_module_search_dn(module, tmp_ctx, &res, partition_dn, 372 partition_attrs, DSDB_FLAG_NEXT_MODULE, NULL); 373 if (ret == LDB_SUCCESS) { 374 backendUrl = ldb_msg_find_attr_as_string(res->msgs[0], "ldapBackend", "ldapi://"); 375 if (!strncasecmp(backendUrl, "ldapi://", sizeof("ldapi://")-1)) { 376 is_ldapi = true; 377 } 378 } else if (ret != LDB_ERR_NO_SUCH_OBJECT) { 379 talloc_free(tmp_ctx); 380 return ret; 381 } 259 382 if (strcasecmp(backendType, "fedora-ds") == 0) { 260 383 link_modules = fedora_ds_modules; … … 265 388 backend_modules = openldap_backend_modules; 266 389 extended_dn_module = extended_dn_module_openldap; 390 extended_dn_in_module = "extended_dn_in_openldap"; 391 if (is_ldapi) { 392 use_sasl_external = true; 393 } 267 394 } else { 268 395 return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "invalid backend type"); … … 271 398 if (ret != LDB_SUCCESS) { 272 399 ldb_set_errstring(ldb, "Failed to set readOnlySchema opaque"); 400 } 401 402 cred = ldb_get_opaque(ldb, "credentials"); 403 if (!cred || !cli_credentials_authentication_requested(cred)) { 404 ret = set_ldap_credentials(ldb, use_sasl_external); 405 if (ret != LDB_SUCCESS) { 406 return ret; 407 } 273 408 } 274 409 } … … 282 417 } while (0) 283 418 284 final_module_list = str_list_copy_const(tmp_ctx, modules_list); 419 final_module_list = str_list_copy_const(tmp_ctx, modules_list1); 420 CHECK_MODULE_LIST; 421 422 final_module_list = str_list_add_const(final_module_list, extended_dn_in_module); 423 CHECK_MODULE_LIST; 424 425 final_module_list = str_list_append_const(final_module_list, modules_list1a); 285 426 CHECK_MODULE_LIST; 286 427 … … 300 441 partition_msg = ldb_msg_new(tmp_ctx); 301 442 partition_msg->dn = ldb_dn_new(partition_msg, ldb, "@" DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME); 302 303 ret = prepare_modules_line(ldb, tmp_ctx,304 rootdse_msg,305 partition_msg, "defaultNamingContext",306 "pdc_fsmo", backend_modules);307 CHECK_LDB_RET(ret);308 309 ret = prepare_modules_line(ldb, tmp_ctx,310 rootdse_msg,311 partition_msg, "configurationNamingContext",312 "naming_fsmo", backend_modules);313 CHECK_LDB_RET(ret);314 443 315 444 ret = prepare_modules_line(ldb, tmp_ctx, -
vendor/current/source4/dsdb/samdb/ldb_modules/samba_secrets.c
r740 r988 53 53 */ 54 54 static const char *modules_list[] = {"update_keytab", 55 "secrets_tdb_sync", 55 56 "objectguid", 56 57 "rdn_name", -
vendor/current/source4/dsdb/samdb/ldb_modules/samldb.c
r740 r988 2 2 SAM ldb module 3 3 4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2014 5 5 Copyright (C) Simo Sorce 2004-2008 6 Copyright (C) Matthias Dieter Wallnöfer 2009-2010 6 Copyright (C) Matthias Dieter Wallnöfer 2009-2011 7 Copyright (C) Matthieu Patou 2012 7 8 8 9 This program is free software; you can redistribute it and/or modify … … 33 34 #include "libcli/ldap/ldap_ndr.h" 34 35 #include "ldb_module.h" 36 #include "auth/auth.h" 35 37 #include "dsdb/samdb/samdb.h" 36 38 #include "dsdb/samdb/ldb_modules/util.h" … … 41 43 #include "param/param.h" 42 44 #include "libds/common/flag_mapping.h" 45 #include "system/network.h" 43 46 44 47 struct samldb_ctx; 48 enum samldb_add_type { 49 SAMLDB_TYPE_USER, 50 SAMLDB_TYPE_GROUP, 51 SAMLDB_TYPE_CLASS, 52 SAMLDB_TYPE_ATTRIBUTE 53 }; 45 54 46 55 typedef int (*samldb_step_fn_t)(struct samldb_ctx *); … … 56 65 57 66 /* used for add operations */ 58 const char *type;67 enum samldb_add_type type; 59 68 60 69 /* the resulting message */ … … 170 179 int ret; 171 180 struct ldb_result *res; 172 const char * noattrs[] = { NULL };181 const char * const noattrs[] = { NULL }; 173 182 174 183 if (ldb_msg_find_element(ac->msg, "sAMAccountName") == NULL) { … … 188 197 189 198 ret = dsdb_module_search(ac->module, ac, &res, 190 NULL, LDB_SCOPE_SUBTREE, noattrs,199 ldb_get_default_basedn(ldb), LDB_SCOPE_SUBTREE, noattrs, 191 200 DSDB_FLAG_NEXT_MODULE, 192 201 ac->req, … … 258 267 TALLOC_CTX *tmp_ctx = talloc_new(ac); 259 268 struct ldb_result *res; 260 const char * no_attrs[] = { NULL };269 const char * const no_attrs[] = { NULL }; 261 270 int ret; 262 271 263 ret = dsdb_module_search(ac->module, tmp_ctx, &res, NULL, 272 ret = dsdb_module_search(ac->module, tmp_ctx, &res, 273 ldb_get_default_basedn(ldb_module_get_ctx(ac->module)), 264 274 LDB_SCOPE_SUBTREE, no_attrs, 265 275 DSDB_FLAG_NEXT_MODULE, … … 336 346 newpass, strlen(newpass), 337 347 (void *)&newpass_utf16.data, 338 &newpass_utf16.length , false)) {348 &newpass_utf16.length)) { 339 349 ldb_asprintf_errstring(ldb, 340 350 "samldb_rodc_add: " … … 354 364 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 355 365 struct ldb_result *res; 356 const char * no_attrs[] = { NULL };366 const char * const no_attrs[] = { NULL }; 357 367 int ret; 358 368 … … 380 390 } 381 391 392 if (ret == LDB_SUCCESS) { 393 /* ensure the defaultObjectCategory has a full GUID */ 394 struct ldb_message *m; 395 m = ldb_msg_new(ac->msg); 396 if (m == NULL) { 397 return ldb_oom(ldb); 398 } 399 m->dn = ac->msg->dn; 400 if (ldb_msg_add_string(m, "defaultObjectCategory", 401 ldb_dn_get_extended_linearized(m, res->msgs[0]->dn, 1)) != 402 LDB_SUCCESS) { 403 return ldb_oom(ldb); 404 } 405 m->elements[0].flags = LDB_FLAG_MOD_REPLACE; 406 407 ret = dsdb_module_modify(ac->module, m, 408 DSDB_FLAG_NEXT_MODULE, 409 ac->req); 410 if (ret != LDB_SUCCESS) { 411 return ret; 412 } 413 } 414 415 382 416 ac->res_dn = ac->dn; 383 417 … … 398 432 struct ldb_result *ldb_res; 399 433 struct ldb_dn *schema_dn; 434 struct samldb_msds_intid_persistant *msds_intid_struct; 435 struct dsdb_schema *schema; 400 436 401 437 ldb = ldb_module_get_ctx(ac->module); … … 429 465 return LDB_SUCCESS; 430 466 } 431 432 /* Generate new value for msDs-IntId 433 * Value should be in 0x80000000..0xBFFFFFFF range */ 434 msds_intid = generate_random() % 0X3FFFFFFF; 435 msds_intid += 0x80000000; 467 schema = dsdb_get_schema(ldb, NULL); 468 if (!schema) { 469 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 470 "samldb_schema_info_update: no dsdb_schema loaded"); 471 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb))); 472 return ldb_operr(ldb); 473 } 474 475 msds_intid_struct = (struct samldb_msds_intid_persistant*) ldb_get_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE); 476 if (!msds_intid_struct) { 477 msds_intid_struct = talloc(ldb, struct samldb_msds_intid_persistant); 478 /* Generate new value for msDs-IntId 479 * Value should be in 0x80000000..0xBFFFFFFF range */ 480 msds_intid = generate_random() % 0X3FFFFFFF; 481 msds_intid += 0x80000000; 482 msds_intid_struct->msds_intid = msds_intid; 483 msds_intid_struct->usn = schema->loaded_usn; 484 DEBUG(2, ("No samldb_msds_intid_persistant struct, allocating a new one\n")); 485 } else { 486 msds_intid = msds_intid_struct->msds_intid; 487 } 436 488 437 489 /* probe id values until unique one is found */ 438 490 do { 491 uint64_t current_usn; 439 492 msds_intid++; 440 493 if (msds_intid > 0xBFFFFFFF) { 441 494 msds_intid = 0x80000001; 442 495 } 443 444 ret = dsdb_module_search(ac->module, ac, 445 &ldb_res, 446 schema_dn, LDB_SCOPE_ONELEVEL, NULL, 447 DSDB_FLAG_NEXT_MODULE, 448 ac->req, 449 "(msDS-IntId=%d)", msds_intid); 496 /* 497 * Alternative strategy to a costly (even indexed search) to the 498 * database. 499 * We search in the schema if we have already this intid (using dsdb_attribute_by_attributeID_id because 500 * in the range 0x80000000 0xBFFFFFFFF, attributeID is a DSDB_ATTID_TYPE_INTID). 501 * If so generate another random value. 502 * If not check if the highest USN in the database for the schema partition is the 503 * one that we know. 504 * If so it means that's only this ldb context that is touching the schema in the database. 505 * If not it means that's someone else has modified the database while we are doing our changes too 506 * (this case should be very bery rare) in order to be sure do the search in the database. 507 */ 508 if (dsdb_attribute_by_attributeID_id(schema, msds_intid)) { 509 msds_intid = generate_random() % 0X3FFFFFFF; 510 msds_intid += 0x80000000; 511 continue; 512 } 513 514 ret = dsdb_module_load_partition_usn(ac->module, schema_dn, 515 ¤t_usn, NULL, NULL); 450 516 if (ret != LDB_SUCCESS) { 451 517 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 452 __location__": Searching for msDS-IntId=%d failed - %s\n", 453 msds_intid, 518 __location__": Searching for schema USN failed: %s\n", 454 519 ldb_errstring(ldb)); 455 520 return ldb_operr(ldb); 456 521 } 457 id_exists = (ldb_res->count > 0); 458 459 talloc_free(ldb_res); 522 523 /* current_usn can be lesser than msds_intid_struct-> if there is 524 * uncommited changes. 525 */ 526 if (current_usn > msds_intid_struct->usn) { 527 /* oups something has changed, someone/something 528 * else is modifying or has modified the schema 529 * we'd better check this intid is the database directly 530 */ 531 532 DEBUG(2, ("Schema has changed, searching the database for the unicity of %d\n", 533 msds_intid)); 534 535 ret = dsdb_module_search(ac->module, ac, 536 &ldb_res, 537 schema_dn, LDB_SCOPE_ONELEVEL, NULL, 538 DSDB_FLAG_NEXT_MODULE, 539 ac->req, 540 "(msDS-IntId=%d)", msds_intid); 541 if (ret != LDB_SUCCESS) { 542 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 543 __location__": Searching for msDS-IntId=%d failed - %s\n", 544 msds_intid, 545 ldb_errstring(ldb)); 546 return ldb_operr(ldb); 547 } 548 id_exists = (ldb_res->count > 0); 549 talloc_free(ldb_res); 550 } else { 551 id_exists = 0; 552 } 553 460 554 } while(id_exists); 555 msds_intid_struct->msds_intid = msds_intid; 556 ldb_set_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE, msds_intid_struct); 461 557 462 558 return samdb_msg_add_int(ldb, ac->msg, ac->msg, "msDS-IntId", … … 493 589 } 494 590 if (ares->type != LDB_REPLY_DONE) { 495 ldb_set_errstring(ldb, 496 "Invalid reply type!\n"); 591 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type); 497 592 return ldb_module_done(ac->req, NULL, NULL, 498 593 LDB_ERR_OPERATIONS_ERROR); … … 558 653 559 654 /* Add information for the different account types */ 560 if (strcmp(ac->type, "user") == 0) { 655 switch(ac->type) { 656 case SAMLDB_TYPE_USER: { 561 657 struct ldb_control *rodc_control = ldb_request_get_control(ac->req, 562 658 LDB_CONTROL_RODC_DCPROMO_OID); … … 574 670 ret = samldb_add_step(ac, samldb_add_entry); 575 671 if (ret != LDB_SUCCESS) return ret; 576 577 } else if (strcmp(ac->type, "group") == 0) { 672 break; 673 } 674 675 case SAMLDB_TYPE_GROUP: { 578 676 /* check if we have a valid sAMAccountName */ 579 677 ret = samldb_add_step(ac, samldb_check_sAMAccountName); … … 582 680 ret = samldb_add_step(ac, samldb_add_entry); 583 681 if (ret != LDB_SUCCESS) return ret; 584 585 } else if (strcmp(ac->type, "classSchema") == 0) { 682 break; 683 } 684 685 case SAMLDB_TYPE_CLASS: { 586 686 const struct ldb_val *rdn_value, *def_obj_cat_val; 687 unsigned int v = ldb_msg_find_attr_as_uint(ac->msg, "objectClassCategory", -2); 688 689 /* As discussed with Microsoft through dochelp in April 2012 this is the behavior of windows*/ 690 if (!ldb_msg_find_element(ac->msg, "subClassOf")) { 691 ret = ldb_msg_add_string(ac->msg, "subClassOf", "top"); 692 if (ret != LDB_SUCCESS) return ret; 693 } 587 694 588 695 ret = samdb_find_or_add_attribute(ldb, ac->msg, … … 590 697 if (ret != LDB_SUCCESS) return ret; 591 698 592 /* do not allow to mark an attributeSchema as RODC filtered if it699 /* do not allow one to mark an attributeSchema as RODC filtered if it 593 700 * is system-critical */ 594 701 if (check_rodc_critical_attribute(ac->msg)) { … … 662 769 if (ret != LDB_SUCCESS) return ret; 663 770 664 } else if (strcmp(ac->type, "attributeSchema") == 0) { 771 /* -2 is not a valid objectClassCategory so it means the attribute wasn't present */ 772 if (v == -2) { 773 /* Windows 2003 does this*/ 774 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "objectClassCategory", 0); 775 if (ret != LDB_SUCCESS) { 776 return ret; 777 } 778 } 779 break; 780 } 781 782 case SAMLDB_TYPE_ATTRIBUTE: { 665 783 const struct ldb_val *rdn_value; 784 struct ldb_message_element *el; 666 785 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn); 667 786 if (rdn_value == NULL) { … … 679 798 } 680 799 681 /* do not allow to mark an attributeSchema as RODC filtered if it800 /* do not allow one to mark an attributeSchema as RODC filtered if it 682 801 * is system-critical */ 683 802 if (check_rodc_critical_attribute(ac->msg)) { … … 703 822 } 704 823 824 el = ldb_msg_find_element(ac->msg, "attributeSyntax"); 825 if (el) { 826 /* 827 * No need to scream if there isn't as we have code later on 828 * that will take care of it. 829 */ 830 const struct dsdb_syntax *syntax = find_syntax_map_by_ad_oid((const char *)el->values[0].data); 831 if (!syntax) { 832 DEBUG(9, ("Can't find dsdb_syntax object for attributeSyntax %s\n", 833 (const char *)el->values[0].data)); 834 } else { 835 unsigned int v = ldb_msg_find_attr_as_uint(ac->msg, "oMSyntax", 0); 836 const struct ldb_val *val = ldb_msg_find_ldb_val(ac->msg, "oMObjectClass"); 837 838 if (v == 0) { 839 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "oMSyntax", syntax->oMSyntax); 840 if (ret != LDB_SUCCESS) { 841 return ret; 842 } 843 } 844 if (!val) { 845 struct ldb_val val2 = ldb_val_dup(ldb, &syntax->oMObjectClass); 846 if (val2.length > 0) { 847 ret = ldb_msg_add_value(ac->msg, "oMObjectClass", &val2, NULL); 848 if (ret != LDB_SUCCESS) { 849 return ret; 850 } 851 } 852 } 853 } 854 } 855 705 856 /* handle msDS-IntID attribute */ 706 857 ret = samldb_add_handle_msDS_IntId(ac); … … 709 860 ret = samldb_add_step(ac, samldb_add_entry); 710 861 if (ret != LDB_SUCCESS) return ret; 711 712 } else { 713 ldb_asprintf_errstring(ldb, 714 "Invalid entry type!"); 862 break; 863 } 864 865 default: 866 ldb_asprintf_errstring(ldb, "Invalid entry type!"); 715 867 return LDB_ERR_OPERATIONS_ERROR; 868 break; 716 869 } 717 870 … … 780 933 781 934 ret = dsdb_module_schema_info_update(ac->module, schema, 782 DSDB_FLAG_NEXT_MODULE, ac->req); 935 DSDB_FLAG_NEXT_MODULE| 936 DSDB_FLAG_AS_SYSTEM, 937 ac->req); 783 938 if (ret != LDB_SUCCESS) { 784 939 ldb_asprintf_errstring(ldb, … … 790 945 return LDB_SUCCESS; 791 946 } 947 948 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid); 949 static int samldb_check_user_account_control_rules(struct samldb_ctx *ac, 950 struct dom_sid *sid, 951 uint32_t user_account_control, 952 uint32_t user_account_control_old); 792 953 793 954 /* … … 802 963 { 803 964 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 804 struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(ldb,805 "loadparm"), struct loadparm_context);965 void *skip_allocate_sids = ldb_get_opaque(ldb, 966 "skip_allocate_sids"); 806 967 struct ldb_message_element *el, *el2; 807 enum sid_generator sid_generator;808 968 struct dom_sid *sid; 809 969 int ret; … … 831 991 832 992 /* but generate a new SID when we do have an add operations */ 833 if ((sid == NULL) && (ac->req->operation == LDB_ADD)) { 834 sid_generator = lpcfg_sid_generator(lp_ctx); 835 if (sid_generator == SID_GENERATOR_INTERNAL) { 836 ret = samldb_add_step(ac, samldb_allocate_sid); 837 if (ret != LDB_SUCCESS) return ret; 838 } 839 } 840 841 if (strcmp(ac->type, "user") == 0) { 842 bool uac_generated = false; 993 if ((sid == NULL) && (ac->req->operation == LDB_ADD) && !skip_allocate_sids) { 994 ret = samldb_add_step(ac, samldb_allocate_sid); 995 if (ret != LDB_SUCCESS) return ret; 996 } 997 998 switch(ac->type) { 999 case SAMLDB_TYPE_USER: { 1000 bool uac_generated = false, uac_add_flags = false; 843 1001 844 1002 /* Step 1.2: Default values */ 845 ret = samdb_find_or_add_attribute(ldb, ac->msg, 846 "accountExpires", "9223372036854775807"); 847 if (ret != LDB_SUCCESS) return ret; 848 ret = samdb_find_or_add_attribute(ldb, ac->msg, 849 "badPasswordTime", "0"); 850 if (ret != LDB_SUCCESS) return ret; 851 ret = samdb_find_or_add_attribute(ldb, ac->msg, 852 "badPwdCount", "0"); 853 if (ret != LDB_SUCCESS) return ret; 854 ret = samdb_find_or_add_attribute(ldb, ac->msg, 855 "codePage", "0"); 856 if (ret != LDB_SUCCESS) return ret; 857 ret = samdb_find_or_add_attribute(ldb, ac->msg, 858 "countryCode", "0"); 859 if (ret != LDB_SUCCESS) return ret; 860 ret = samdb_find_or_add_attribute(ldb, ac->msg, 861 "lastLogoff", "0"); 862 if (ret != LDB_SUCCESS) return ret; 863 ret = samdb_find_or_add_attribute(ldb, ac->msg, 864 "lastLogon", "0"); 865 if (ret != LDB_SUCCESS) return ret; 866 ret = samdb_find_or_add_attribute(ldb, ac->msg, 867 "logonCount", "0"); 868 if (ret != LDB_SUCCESS) return ret; 869 ret = samdb_find_or_add_attribute(ldb, ac->msg, 870 "pwdLastSet", "0"); 1003 ret = dsdb_user_obj_set_defaults(ldb, ac->msg); 871 1004 if (ret != LDB_SUCCESS) return ret; 872 1005 … … 882 1015 } 883 1016 uac_generated = true; 1017 uac_add_flags = true; 884 1018 } 885 1019 886 1020 el = ldb_msg_find_element(ac->msg, "userAccountControl"); 887 1021 if (el != NULL) { 888 uint32_t user_account_control, account_type; 889 1022 uint32_t user_account_control; 890 1023 /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */ 891 1024 user_account_control = ldb_msg_find_attr_as_uint(ac->msg, 892 1025 "userAccountControl", 893 1026 0); 894 895 /* Temporary duplicate accounts aren't allowed */ 896 if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) { 897 return LDB_ERR_OTHER; 898 } 899 900 account_type = ds_uf2atype(user_account_control); 901 if (account_type == 0) { 902 ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); 903 return LDB_ERR_UNWILLING_TO_PERFORM; 904 } 905 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, 906 "sAMAccountType", 907 account_type); 1027 /* 1028 * "userAccountControl" = 0 or missing one of 1029 * the types means "UF_NORMAL_ACCOUNT". See 1030 * MS-SAMR 3.1.1.8.10 point 8 1031 */ 1032 if ((user_account_control & UF_ACCOUNT_TYPE_MASK) == 0) { 1033 user_account_control = UF_NORMAL_ACCOUNT | user_account_control; 1034 uac_generated = true; 1035 } 1036 1037 /* 1038 * As per MS-SAMR 3.1.1.8.10 these flags have not to be set 1039 */ 1040 if ((user_account_control & UF_LOCKOUT) != 0) { 1041 user_account_control &= ~UF_LOCKOUT; 1042 uac_generated = true; 1043 } 1044 if ((user_account_control & UF_PASSWORD_EXPIRED) != 0) { 1045 user_account_control &= ~UF_PASSWORD_EXPIRED; 1046 uac_generated = true; 1047 } 1048 1049 ret = samldb_check_user_account_control_rules(ac, NULL, 1050 user_account_control, 0); 908 1051 if (ret != LDB_SUCCESS) { 909 1052 return ret; 910 1053 } 911 el2 = ldb_msg_find_element(ac->msg, "sAMAccountType"); 912 el2->flags = LDB_FLAG_MOD_REPLACE; 913 1054 1055 /* Workstation and (read-only) DC objects do need objectclass "computer" */ 1056 if ((samdb_find_attribute(ldb, ac->msg, 1057 "objectclass", "computer") == NULL) && 1058 (user_account_control & 1059 (UF_SERVER_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT))) { 1060 ldb_set_errstring(ldb, 1061 "samldb: Requested account type does need objectclass 'computer'!"); 1062 return LDB_ERR_OBJECT_CLASS_VIOLATION; 1063 } 1064 1065 /* add "sAMAccountType" attribute */ 1066 ret = dsdb_user_obj_set_account_type(ldb, ac->msg, user_account_control, NULL); 1067 if (ret != LDB_SUCCESS) { 1068 return ret; 1069 } 1070 1071 /* "isCriticalSystemObject" might be set */ 914 1072 if (user_account_control & 915 1073 (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) { 916 ret = samdb_msg_set_string(ldb, ac->msg, ac->msg, 917 "isCriticalSystemObject", 918 "TRUE"); 1074 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", 1075 "TRUE"); 919 1076 if (ret != LDB_SUCCESS) { 920 1077 return ret; … … 923 1080 "isCriticalSystemObject"); 924 1081 el2->flags = LDB_FLAG_MOD_REPLACE; 925 } 926 927 /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */ 928 if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) { 929 uint32_t rid = ds_uf2prim_group_rid(user_account_control); 930 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, 931 "primaryGroupID", rid); 1082 } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) { 1083 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", 1084 "FALSE"); 932 1085 if (ret != LDB_SUCCESS) { 933 1086 return ret; 934 1087 } 935 1088 el2 = ldb_msg_find_element(ac->msg, 936 " primaryGroupID");1089 "isCriticalSystemObject"); 937 1090 el2->flags = LDB_FLAG_MOD_REPLACE; 1091 } 1092 1093 /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */ 1094 if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) { 1095 uint32_t rid; 1096 1097 ret = dsdb_user_obj_set_primary_group_id(ldb, ac->msg, user_account_control, &rid); 1098 if (ret != LDB_SUCCESS) { 1099 return ret; 1100 } 1101 /* 1102 * Older AD deployments don't know about the 1103 * RODC group 1104 */ 1105 if (rid == DOMAIN_RID_READONLY_DCS) { 1106 ret = samldb_prim_group_tester(ac, rid); 1107 if (ret != LDB_SUCCESS) { 1108 return ret; 1109 } 1110 } 938 1111 } 939 1112 … … 943 1116 * Server) */ 944 1117 if (uac_generated) { 945 user_account_control |= UF_ACCOUNTDISABLE; 946 user_account_control |= UF_PASSWD_NOTREQD; 1118 if (uac_add_flags) { 1119 user_account_control |= UF_ACCOUNTDISABLE; 1120 user_account_control |= UF_PASSWD_NOTREQD; 1121 } 947 1122 948 1123 ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg, … … 953 1128 } 954 1129 } 955 } 956 957 } else if (strcmp(ac->type, "group") == 0) { 1130 1131 } 1132 break; 1133 } 1134 1135 case SAMLDB_TYPE_GROUP: { 958 1136 const char *tempstr; 959 1137 … … 997 1175 el2->flags = LDB_FLAG_MOD_REPLACE; 998 1176 } 1177 break; 1178 } 1179 1180 default: 1181 ldb_asprintf_errstring(ldb, 1182 "Invalid entry type!"); 1183 return LDB_ERR_OPERATIONS_ERROR; 1184 break; 999 1185 } 1000 1186 … … 1010 1196 */ 1011 1197 1012 static int samldb_prim_group_ set(struct samldb_ctx *ac)1198 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid) 1013 1199 { 1014 1200 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 1015 uint32_t rid;1016 1201 struct dom_sid *sid; 1017 1202 struct ldb_result *res; 1018 1203 int ret; 1019 const char *noattrs[] = { NULL }; 1020 1021 rid = ldb_msg_find_attr_as_uint(ac->msg, "primaryGroupID", (uint32_t) -1); 1022 if (rid == (uint32_t) -1) { 1023 /* we aren't affected of any primary group set */ 1024 return LDB_SUCCESS; 1025 1026 } else if (!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) { 1027 ldb_set_errstring(ldb, 1028 "The primary group isn't settable on add operations!"); 1029 return LDB_ERR_UNWILLING_TO_PERFORM; 1030 } 1204 const char * const noattrs[] = { NULL }; 1031 1205 1032 1206 sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid); … … 1035 1209 } 1036 1210 1037 ret = dsdb_module_search(ac->module, ac, &res, NULL, LDB_SCOPE_SUBTREE, 1211 ret = dsdb_module_search(ac->module, ac, &res, 1212 ldb_get_default_basedn(ldb), 1213 LDB_SCOPE_SUBTREE, 1038 1214 noattrs, DSDB_FLAG_NEXT_MODULE, 1039 1215 ac->req, … … 1055 1231 } 1056 1232 1233 static int samldb_prim_group_set(struct samldb_ctx *ac) 1234 { 1235 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 1236 uint32_t rid; 1237 1238 rid = ldb_msg_find_attr_as_uint(ac->msg, "primaryGroupID", (uint32_t) -1); 1239 if (rid == (uint32_t) -1) { 1240 /* we aren't affected of any primary group set */ 1241 return LDB_SUCCESS; 1242 1243 } else if (!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) { 1244 ldb_set_errstring(ldb, 1245 "The primary group isn't settable on add operations!"); 1246 return LDB_ERR_UNWILLING_TO_PERFORM; 1247 } 1248 1249 return samldb_prim_group_tester(ac, rid); 1250 } 1251 1057 1252 static int samldb_prim_group_change(struct samldb_ctx *ac) 1058 1253 { 1059 1254 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 1060 const char * attrs[] = { "primaryGroupID", "memberOf", NULL }; 1255 const char * const attrs[] = { 1256 "primaryGroupID", 1257 "memberOf", 1258 "userAccountControl", 1259 NULL }; 1061 1260 struct ldb_result *res, *group_res; 1062 1261 struct ldb_message_element *el; 1063 1262 struct ldb_message *msg; 1064 uint32_t prev_rid, new_rid ;1263 uint32_t prev_rid, new_rid, uac; 1065 1264 struct dom_sid *prev_sid, *new_sid; 1066 1265 struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn; 1067 1266 int ret; 1068 const char * noattrs[] = { NULL };1267 const char * const noattrs[] = { NULL }; 1069 1268 1070 1269 el = dsdb_get_single_valued_attr(ac->msg, "primaryGroupID", … … 1077 1276 /* Fetch information from the existing object */ 1078 1277 1079 ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs, 1080 DSDB_FLAG_NEXT_MODULE, ac->req, NULL); 1081 if (ret != LDB_SUCCESS) { 1082 return ret; 1083 } 1084 if (res->count != 1) { 1085 return ldb_operr(ldb); 1086 } 1278 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs, 1279 DSDB_FLAG_NEXT_MODULE, ac->req); 1280 if (ret != LDB_SUCCESS) { 1281 return ret; 1282 } 1283 1284 uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0); 1087 1285 1088 1286 /* Finds out the DN of the old primary group */ … … 1125 1323 } 1126 1324 1127 ret = dsdb_module_search(ac->module, ac, &group_res, NULL, LDB_SCOPE_SUBTREE, 1325 if ((uac & UF_SERVER_TRUST_ACCOUNT) && new_rid != DOMAIN_RID_DCS) { 1326 ldb_asprintf_errstring(ldb, 1327 "%08X: samldb: UF_SERVER_TRUST_ACCOUNT requires " 1328 "primaryGroupID=%u!", 1329 W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID), 1330 DOMAIN_RID_DCS); 1331 return LDB_ERR_UNWILLING_TO_PERFORM; 1332 } 1333 1334 if ((uac & UF_PARTIAL_SECRETS_ACCOUNT) && new_rid != DOMAIN_RID_READONLY_DCS) { 1335 ldb_asprintf_errstring(ldb, 1336 "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT requires " 1337 "primaryGroupID=%u!", 1338 W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID), 1339 DOMAIN_RID_READONLY_DCS); 1340 return LDB_ERR_UNWILLING_TO_PERFORM; 1341 } 1342 1343 ret = dsdb_module_search(ac->module, ac, &group_res, 1344 ldb_get_default_basedn(ldb), 1345 LDB_SCOPE_SUBTREE, 1128 1346 noattrs, DSDB_FLAG_NEXT_MODULE, 1129 1347 ac->req, … … 1143 1361 } 1144 1362 1145 ret = dsdb_module_search(ac->module, ac, &group_res, NULL, LDB_SCOPE_SUBTREE, 1363 ret = dsdb_module_search(ac->module, ac, &group_res, 1364 ldb_get_default_basedn(ldb), 1365 LDB_SCOPE_SUBTREE, 1146 1366 noattrs, DSDB_FLAG_NEXT_MODULE, 1147 1367 ac->req, … … 1220 1440 } 1221 1441 1442 static int samldb_check_user_account_control_invariants(struct samldb_ctx *ac, 1443 uint32_t user_account_control) 1444 { 1445 int i, ret = 0; 1446 bool need_check = false; 1447 const struct uac_to_guid { 1448 uint32_t uac; 1449 bool never; 1450 uint32_t needs; 1451 uint32_t not_with; 1452 const char *error_string; 1453 } map[] = { 1454 { 1455 .uac = UF_TEMP_DUPLICATE_ACCOUNT, 1456 .never = true, 1457 .error_string = "Updating the UF_TEMP_DUPLICATE_ACCOUNT flag is never allowed" 1458 }, 1459 { 1460 .uac = UF_PARTIAL_SECRETS_ACCOUNT, 1461 .needs = UF_WORKSTATION_TRUST_ACCOUNT, 1462 .error_string = "Setting UF_PARTIAL_SECRETS_ACCOUNT only permitted with UF_WORKSTATION_TRUST_ACCOUNT" 1463 }, 1464 { 1465 .uac = UF_TRUSTED_FOR_DELEGATION, 1466 .not_with = UF_PARTIAL_SECRETS_ACCOUNT, 1467 .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT" 1468 }, 1469 { 1470 .uac = UF_NORMAL_ACCOUNT, 1471 .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_NORMAL_ACCOUNT, 1472 .error_string = "Setting more than one account type not permitted" 1473 }, 1474 { 1475 .uac = UF_WORKSTATION_TRUST_ACCOUNT, 1476 .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_WORKSTATION_TRUST_ACCOUNT, 1477 .error_string = "Setting more than one account type not permitted" 1478 }, 1479 { 1480 .uac = UF_INTERDOMAIN_TRUST_ACCOUNT, 1481 .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_INTERDOMAIN_TRUST_ACCOUNT, 1482 .error_string = "Setting more than one account type not permitted" 1483 }, 1484 { 1485 .uac = UF_SERVER_TRUST_ACCOUNT, 1486 .not_with = UF_ACCOUNT_TYPE_MASK & ~UF_SERVER_TRUST_ACCOUNT, 1487 .error_string = "Setting more than one account type not permitted" 1488 }, 1489 { 1490 .uac = UF_TRUSTED_FOR_DELEGATION, 1491 .not_with = UF_PARTIAL_SECRETS_ACCOUNT, 1492 .error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT" 1493 } 1494 }; 1495 1496 for (i = 0; i < ARRAY_SIZE(map); i++) { 1497 if (user_account_control & map[i].uac) { 1498 need_check = true; 1499 break; 1500 } 1501 } 1502 if (need_check == false) { 1503 return LDB_SUCCESS; 1504 } 1505 1506 for (i = 0; i < ARRAY_SIZE(map); i++) { 1507 uint32_t this_uac = user_account_control & map[i].uac; 1508 if (this_uac != 0) { 1509 if (map[i].never) { 1510 ret = LDB_ERR_OTHER; 1511 break; 1512 } else if (map[i].needs != 0) { 1513 if ((map[i].needs & user_account_control) == 0) { 1514 ret = LDB_ERR_OTHER; 1515 break; 1516 } 1517 } else if (map[i].not_with != 0) { 1518 if ((map[i].not_with & user_account_control) != 0) { 1519 ret = LDB_ERR_OTHER; 1520 break; 1521 } 1522 } 1523 } 1524 } 1525 if (ret != LDB_SUCCESS) { 1526 switch (ac->req->operation) { 1527 case LDB_ADD: 1528 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), 1529 "Failed to add %s: %s", 1530 ldb_dn_get_linearized(ac->msg->dn), 1531 map[i].error_string); 1532 break; 1533 case LDB_MODIFY: 1534 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), 1535 "Failed to modify %s: %s", 1536 ldb_dn_get_linearized(ac->msg->dn), 1537 map[i].error_string); 1538 break; 1539 default: 1540 return ldb_module_operr(ac->module); 1541 } 1542 } 1543 return ret; 1544 } 1545 1546 /** 1547 * Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured 1548 * 1549 */ 1550 static int samldb_check_user_account_control_acl(struct samldb_ctx *ac, 1551 struct dom_sid *sid, 1552 uint32_t user_account_control, 1553 uint32_t user_account_control_old) 1554 { 1555 int i, ret = 0; 1556 bool need_acl_check = false; 1557 struct ldb_result *res; 1558 const char * const sd_attrs[] = {"ntSecurityDescriptor", NULL}; 1559 struct security_token *user_token; 1560 struct security_descriptor *domain_sd; 1561 struct ldb_dn *domain_dn = ldb_get_default_basedn(ldb_module_get_ctx(ac->module)); 1562 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 1563 const struct uac_to_guid { 1564 uint32_t uac; 1565 uint32_t priv_to_change_from; 1566 const char *oid; 1567 const char *guid; 1568 enum sec_privilege privilege; 1569 bool delete_is_privileged; 1570 bool admin_required; 1571 const char *error_string; 1572 } map[] = { 1573 { 1574 .uac = UF_PASSWD_NOTREQD, 1575 .guid = GUID_DRS_UPDATE_PASSWORD_NOT_REQUIRED_BIT, 1576 .error_string = "Adding the UF_PASSWD_NOTREQD bit in userAccountControl requires the Update-Password-Not-Required-Bit right that was not given on the Domain object" 1577 }, 1578 { 1579 .uac = UF_DONT_EXPIRE_PASSWD, 1580 .guid = GUID_DRS_UNEXPIRE_PASSWORD, 1581 .error_string = "Adding the UF_DONT_EXPIRE_PASSWD bit in userAccountControl requires the Unexpire-Password right that was not given on the Domain object" 1582 }, 1583 { 1584 .uac = UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED, 1585 .guid = GUID_DRS_ENABLE_PER_USER_REVERSIBLY_ENCRYPTED_PASSWORD, 1586 .error_string = "Adding the UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED bit in userAccountControl requires the Enable-Per-User-Reversibly-Encrypted-Password right that was not given on the Domain object" 1587 }, 1588 { 1589 .uac = UF_SERVER_TRUST_ACCOUNT, 1590 .guid = GUID_DRS_DS_INSTALL_REPLICA, 1591 .error_string = "Adding the UF_SERVER_TRUST_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object" 1592 }, 1593 { 1594 .uac = UF_PARTIAL_SECRETS_ACCOUNT, 1595 .guid = GUID_DRS_DS_INSTALL_REPLICA, 1596 .error_string = "Adding the UF_PARTIAL_SECRETS_ACCOUNT bit in userAccountControl requires the DS-Install-Replica right that was not given on the Domain object" 1597 }, 1598 { 1599 .uac = UF_WORKSTATION_TRUST_ACCOUNT, 1600 .priv_to_change_from = UF_NORMAL_ACCOUNT, 1601 .error_string = "Swapping UF_NORMAL_ACCOUNT to UF_WORKSTATION_TRUST_ACCOUNT requires the user to be a member of the domain admins group" 1602 }, 1603 { 1604 .uac = UF_NORMAL_ACCOUNT, 1605 .priv_to_change_from = UF_WORKSTATION_TRUST_ACCOUNT, 1606 .error_string = "Swapping UF_WORKSTATION_TRUST_ACCOUNT to UF_NORMAL_ACCOUNT requires the user to be a member of the domain admins group" 1607 }, 1608 { 1609 .uac = UF_INTERDOMAIN_TRUST_ACCOUNT, 1610 .oid = DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID, 1611 .error_string = "Updating the UF_INTERDOMAIN_TRUST_ACCOUNT bit in userAccountControl is not permitted over LDAP. This bit is restricted to the LSA CreateTrustedDomain interface", 1612 .delete_is_privileged = true 1613 }, 1614 { 1615 .uac = UF_TRUSTED_FOR_DELEGATION, 1616 .privilege = SEC_PRIV_ENABLE_DELEGATION, 1617 .delete_is_privileged = true, 1618 .error_string = "Updating the UF_TRUSTED_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege" 1619 }, 1620 { 1621 .uac = UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, 1622 .privilege = SEC_PRIV_ENABLE_DELEGATION, 1623 .delete_is_privileged = true, 1624 .error_string = "Updating the UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit in userAccountControl is not permitted without the SeEnableDelegationPrivilege" 1625 } 1626 1627 }; 1628 1629 if (dsdb_module_am_system(ac->module)) { 1630 return LDB_SUCCESS; 1631 } 1632 1633 for (i = 0; i < ARRAY_SIZE(map); i++) { 1634 if (user_account_control & map[i].uac) { 1635 need_acl_check = true; 1636 break; 1637 } 1638 } 1639 if (need_acl_check == false) { 1640 return LDB_SUCCESS; 1641 } 1642 1643 user_token = acl_user_token(ac->module); 1644 if (user_token == NULL) { 1645 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; 1646 } 1647 1648 ret = dsdb_module_search_dn(ac->module, ac, &res, 1649 domain_dn, 1650 sd_attrs, 1651 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, 1652 ac->req); 1653 if (ret != LDB_SUCCESS) { 1654 return ret; 1655 } 1656 if (res->count != 1) { 1657 return ldb_module_operr(ac->module); 1658 } 1659 1660 ret = dsdb_get_sd_from_ldb_message(ldb, 1661 ac, res->msgs[0], &domain_sd); 1662 1663 if (ret != LDB_SUCCESS) { 1664 return ret; 1665 } 1666 1667 for (i = 0; i < ARRAY_SIZE(map); i++) { 1668 uint32_t this_uac_new = user_account_control & map[i].uac; 1669 uint32_t this_uac_old = user_account_control_old & map[i].uac; 1670 if (this_uac_new != this_uac_old) { 1671 if (this_uac_old != 0) { 1672 if (map[i].delete_is_privileged == false) { 1673 continue; 1674 } 1675 } 1676 if (map[i].oid) { 1677 struct ldb_control *control = ldb_request_get_control(ac->req, map[i].oid); 1678 if (control == NULL) { 1679 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; 1680 } 1681 } else if (map[i].privilege != SEC_PRIV_INVALID) { 1682 bool have_priv = security_token_has_privilege(user_token, 1683 map[i].privilege); 1684 if (have_priv == false) { 1685 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; 1686 } 1687 } else if (map[i].priv_to_change_from & user_account_control_old) { 1688 bool is_admin = security_token_has_builtin_administrators(user_token); 1689 if (is_admin == false) { 1690 ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; 1691 } 1692 } else if (map[i].guid) { 1693 ret = acl_check_extended_right(ac, domain_sd, 1694 user_token, 1695 map[i].guid, 1696 SEC_ADS_CONTROL_ACCESS, 1697 sid); 1698 } else { 1699 ret = LDB_SUCCESS; 1700 } 1701 if (ret != LDB_SUCCESS) { 1702 break; 1703 } 1704 } 1705 } 1706 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { 1707 switch (ac->req->operation) { 1708 case LDB_ADD: 1709 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), 1710 "Failed to add %s: %s", 1711 ldb_dn_get_linearized(ac->msg->dn), 1712 map[i].error_string); 1713 break; 1714 case LDB_MODIFY: 1715 ldb_asprintf_errstring(ldb_module_get_ctx(ac->module), 1716 "Failed to modify %s: %s", 1717 ldb_dn_get_linearized(ac->msg->dn), 1718 map[i].error_string); 1719 break; 1720 default: 1721 return ldb_module_operr(ac->module); 1722 } 1723 if (map[i].guid) { 1724 dsdb_acl_debug(domain_sd, acl_user_token(ac->module), 1725 domain_dn, 1726 true, 1727 10); 1728 } 1729 } 1730 return ret; 1731 } 1732 1733 static int samldb_check_user_account_control_rules(struct samldb_ctx *ac, 1734 struct dom_sid *sid, 1735 uint32_t user_account_control, 1736 uint32_t user_account_control_old) 1737 { 1738 int ret; 1739 ret = samldb_check_user_account_control_invariants(ac, user_account_control); 1740 if (ret != LDB_SUCCESS) { 1741 return ret; 1742 } 1743 ret = samldb_check_user_account_control_acl(ac, sid, user_account_control, user_account_control_old); 1744 if (ret != LDB_SUCCESS) { 1745 return ret; 1746 } 1747 return ret; 1748 } 1749 1750 1751 /** 1752 * This function is called on LDB modify operations. It performs some additions/ 1753 * replaces on the current LDB message when "userAccountControl" changes. 1754 */ 1222 1755 static int samldb_user_account_control_change(struct samldb_ctx *ac) 1223 1756 { 1224 1757 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 1225 uint32_t user_account_control, account_type; 1758 uint32_t old_uac; 1759 uint32_t new_uac; 1760 uint32_t raw_uac; 1761 uint32_t old_ufa; 1762 uint32_t new_ufa; 1763 uint32_t old_uac_computed; 1764 uint32_t clear_uac; 1765 uint32_t old_atype; 1766 uint32_t new_atype; 1767 uint32_t old_pgrid; 1768 uint32_t new_pgrid; 1769 NTTIME old_lockoutTime; 1226 1770 struct ldb_message_element *el; 1771 struct ldb_val *val; 1772 struct ldb_val computer_val; 1227 1773 struct ldb_message *tmp_msg; 1774 struct dom_sid *sid; 1228 1775 int ret; 1776 struct ldb_result *res; 1777 const char * const attrs[] = { 1778 "objectClass", 1779 "isCriticalSystemObject", 1780 "userAccountControl", 1781 "msDS-User-Account-Control-Computed", 1782 "lockoutTime", 1783 "objectSid", 1784 NULL 1785 }; 1786 bool is_computer = false; 1787 bool old_is_critical = false; 1788 bool new_is_critical = false; 1229 1789 1230 1790 el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl", 1231 1791 ac->req->operation); 1232 if (el == NULL) { 1233 /* we are not affected */ 1234 return LDB_SUCCESS; 1792 if (el == NULL || el->num_values == 0) { 1793 ldb_asprintf_errstring(ldb, 1794 "%08X: samldb: 'userAccountControl' can't be deleted!", 1795 W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION)); 1796 return LDB_ERR_UNWILLING_TO_PERFORM; 1235 1797 } 1236 1798 … … 1244 1806 return ret; 1245 1807 } 1246 user_account_control= ldb_msg_find_attr_as_uint(tmp_msg,1247 1248 1808 raw_uac = ldb_msg_find_attr_as_uint(tmp_msg, 1809 "userAccountControl", 1810 0); 1249 1811 talloc_free(tmp_msg); 1250 1251 /* Temporary duplicate accounts aren't allowed */ 1252 if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) { 1812 /* 1813 * UF_LOCKOUT, UF_PASSWD_CANT_CHANGE and UF_PASSWORD_EXPIRED 1814 * are only generated and not stored. We ignore them almost 1815 * completely, along with unknown bits and UF_SCRIPT. 1816 * 1817 * The only exception is ACB_AUTOLOCK, which features in 1818 * clear_acb when the bit is cleared in this modify operation. 1819 * 1820 * MS-SAMR 2.2.1.13 UF_FLAG Codes states that some bits are 1821 * ignored by clients and servers 1822 */ 1823 new_uac = raw_uac & UF_SETTABLE_BITS; 1824 1825 /* Fetch the old "userAccountControl" and "objectClass" */ 1826 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs, 1827 DSDB_FLAG_NEXT_MODULE, ac->req); 1828 if (ret != LDB_SUCCESS) { 1829 return ret; 1830 } 1831 old_uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0); 1832 if (old_uac == 0) { 1833 return ldb_operr(ldb); 1834 } 1835 old_uac_computed = ldb_msg_find_attr_as_uint(res->msgs[0], 1836 "msDS-User-Account-Control-Computed", 0); 1837 old_lockoutTime = ldb_msg_find_attr_as_int64(res->msgs[0], 1838 "lockoutTime", 0); 1839 old_is_critical = ldb_msg_find_attr_as_bool(res->msgs[0], 1840 "isCriticalSystemObject", 0); 1841 /* When we do not have objectclass "computer" we cannot switch to a (read-only) DC */ 1842 el = ldb_msg_find_element(res->msgs[0], "objectClass"); 1843 if (el == NULL) { 1844 return ldb_operr(ldb); 1845 } 1846 computer_val = data_blob_string_const("computer"); 1847 val = ldb_msg_find_val(el, &computer_val); 1848 if (val != NULL) { 1849 is_computer = true; 1850 } 1851 1852 old_ufa = old_uac & UF_ACCOUNT_TYPE_MASK; 1853 old_atype = ds_uf2atype(old_ufa); 1854 old_pgrid = ds_uf2prim_group_rid(old_uac); 1855 1856 new_ufa = new_uac & UF_ACCOUNT_TYPE_MASK; 1857 if (new_ufa == 0) { 1858 /* 1859 * "userAccountControl" = 0 or missing one of the 1860 * types means "UF_NORMAL_ACCOUNT". See MS-SAMR 1861 * 3.1.1.8.10 point 8 1862 */ 1863 new_ufa = UF_NORMAL_ACCOUNT; 1864 new_uac |= new_ufa; 1865 } 1866 sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid"); 1867 if (sid == NULL) { 1868 return ldb_module_operr(ac->module); 1869 } 1870 1871 ret = samldb_check_user_account_control_rules(ac, sid, new_uac, old_uac); 1872 if (ret != LDB_SUCCESS) { 1873 return ret; 1874 } 1875 1876 new_atype = ds_uf2atype(new_ufa); 1877 new_pgrid = ds_uf2prim_group_rid(new_uac); 1878 1879 clear_uac = (old_uac | old_uac_computed) & ~raw_uac; 1880 1881 switch (new_ufa) { 1882 case UF_NORMAL_ACCOUNT: 1883 new_is_critical = old_is_critical; 1884 break; 1885 1886 case UF_INTERDOMAIN_TRUST_ACCOUNT: 1887 new_is_critical = true; 1888 break; 1889 1890 case UF_WORKSTATION_TRUST_ACCOUNT: 1891 new_is_critical = false; 1892 if (new_uac & UF_PARTIAL_SECRETS_ACCOUNT) { 1893 if (!is_computer) { 1894 ldb_asprintf_errstring(ldb, 1895 "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT " 1896 "requires objectclass 'computer'!", 1897 W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); 1898 return LDB_ERR_UNWILLING_TO_PERFORM; 1899 } 1900 new_is_critical = true; 1901 } 1902 break; 1903 1904 case UF_SERVER_TRUST_ACCOUNT: 1905 if (!is_computer) { 1906 ldb_asprintf_errstring(ldb, 1907 "%08X: samldb: UF_SERVER_TRUST_ACCOUNT " 1908 "requires objectclass 'computer'!", 1909 W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)); 1910 return LDB_ERR_UNWILLING_TO_PERFORM; 1911 } 1912 new_is_critical = true; 1913 break; 1914 1915 default: 1916 ldb_asprintf_errstring(ldb, 1917 "%08X: samldb: invalid userAccountControl[0x%08X]", 1918 W_ERROR_V(WERR_INVALID_PARAMETER), raw_uac); 1253 1919 return LDB_ERR_OTHER; 1254 1920 } 1255 1921 1256 account_type = ds_uf2atype(user_account_control); 1257 if (account_type == 0) { 1258 ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); 1259 return LDB_ERR_UNWILLING_TO_PERFORM; 1260 } 1261 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType", 1262 account_type); 1263 if (ret != LDB_SUCCESS) { 1264 return ret; 1265 } 1266 el = ldb_msg_find_element(ac->msg, "sAMAccountType"); 1267 el->flags = LDB_FLAG_MOD_REPLACE; 1268 1269 if (user_account_control 1270 & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) { 1922 if (old_atype != new_atype) { 1923 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, 1924 "sAMAccountType", new_atype); 1925 if (ret != LDB_SUCCESS) { 1926 return ret; 1927 } 1928 el = ldb_msg_find_element(ac->msg, "sAMAccountType"); 1929 el->flags = LDB_FLAG_MOD_REPLACE; 1930 } 1931 1932 /* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */ 1933 if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) { 1934 /* "pwdLastSet" reset as password expiration has been forced */ 1935 ldb_msg_remove_attr(ac->msg, "lockoutTime"); 1936 ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime", 1937 (NTTIME)0); 1938 if (ret != LDB_SUCCESS) { 1939 return ret; 1940 } 1941 el = ldb_msg_find_element(ac->msg, "lockoutTime"); 1942 el->flags = LDB_FLAG_MOD_REPLACE; 1943 } 1944 1945 /* "isCriticalSystemObject" might be set/changed */ 1946 if (old_is_critical != new_is_critical) { 1271 1947 ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", 1272 "TRUE");1948 new_is_critical ? "TRUE": "FALSE"); 1273 1949 if (ret != LDB_SUCCESS) { 1274 1950 return ret; … … 1279 1955 } 1280 1956 1281 if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) { 1282 uint32_t rid = ds_uf2prim_group_rid(user_account_control); 1957 if (!ldb_msg_find_element(ac->msg, "primaryGroupID") && 1958 (old_pgrid != new_pgrid)) { 1959 /* Older AD deployments don't know about the RODC group */ 1960 if (new_pgrid == DOMAIN_RID_READONLY_DCS) { 1961 ret = samldb_prim_group_tester(ac, new_pgrid); 1962 if (ret != LDB_SUCCESS) { 1963 return ret; 1964 } 1965 } 1966 1283 1967 ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, 1284 "primaryGroupID", rid);1968 "primaryGroupID", new_pgrid); 1285 1969 if (ret != LDB_SUCCESS) { 1286 1970 return ret; … … 1290 1974 el->flags = LDB_FLAG_MOD_REPLACE; 1291 1975 } 1976 1977 /* Propagate eventual "userAccountControl" attribute changes */ 1978 if (old_uac != new_uac) { 1979 char *tempstr = talloc_asprintf(ac->msg, "%d", 1980 new_uac); 1981 if (tempstr == NULL) { 1982 return ldb_module_oom(ac->module); 1983 } 1984 1985 /* Overwrite "userAccountControl" correctly */ 1986 el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl", 1987 ac->req->operation); 1988 el->values[0].data = (uint8_t *) tempstr; 1989 el->values[0].length = strlen(tempstr); 1990 } else { 1991 ldb_msg_remove_attr(ac->msg, "userAccountControl"); 1992 } 1993 1994 return LDB_SUCCESS; 1995 } 1996 1997 static int samldb_lockout_time(struct samldb_ctx *ac) 1998 { 1999 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 2000 NTTIME lockoutTime; 2001 struct ldb_message_element *el; 2002 struct ldb_message *tmp_msg; 2003 int ret; 2004 2005 el = dsdb_get_single_valued_attr(ac->msg, "lockoutTime", 2006 ac->req->operation); 2007 if (el == NULL || el->num_values == 0) { 2008 ldb_asprintf_errstring(ldb, 2009 "%08X: samldb: 'lockoutTime' can't be deleted!", 2010 W_ERROR_V(WERR_DS_ILLEGAL_MOD_OPERATION)); 2011 return LDB_ERR_UNWILLING_TO_PERFORM; 2012 } 2013 2014 /* Create a temporary message for fetching the "lockoutTime" */ 2015 tmp_msg = ldb_msg_new(ac->msg); 2016 if (tmp_msg == NULL) { 2017 return ldb_module_oom(ac->module); 2018 } 2019 ret = ldb_msg_add(tmp_msg, el, 0); 2020 if (ret != LDB_SUCCESS) { 2021 return ret; 2022 } 2023 lockoutTime = ldb_msg_find_attr_as_int64(tmp_msg, 2024 "lockoutTime", 2025 0); 2026 talloc_free(tmp_msg); 2027 2028 if (lockoutTime != 0) { 2029 return LDB_SUCCESS; 2030 } 2031 2032 /* lockoutTime == 0 resets badPwdCount */ 2033 ldb_msg_remove_attr(ac->msg, "badPwdCount"); 2034 ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, 2035 "badPwdCount", 0); 2036 if (ret != LDB_SUCCESS) { 2037 return ret; 2038 } 2039 el = ldb_msg_find_element(ac->msg, "badPwdCount"); 2040 el->flags = LDB_FLAG_MOD_REPLACE; 1292 2041 1293 2042 return LDB_SUCCESS; … … 1302 2051 int ret; 1303 2052 struct ldb_result *res; 1304 const char * attrs[] = { "groupType", NULL };2053 const char * const attrs[] = { "groupType", NULL }; 1305 2054 1306 2055 el = dsdb_get_single_valued_attr(ac->msg, "groupType", … … 1324 2073 1325 2074 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs, 1326 DSDB_FLAG_NEXT_MODULE, ac->req); 2075 DSDB_FLAG_NEXT_MODULE | 2076 DSDB_SEARCH_SHOW_DELETED, ac->req); 1327 2077 if (ret != LDB_SUCCESS) { 1328 2078 return ret; … … 1393 2143 { 1394 2144 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 1395 const char * no_attrs[] = { NULL };2145 const char * const no_attrs[] = { NULL }; 1396 2146 struct ldb_result *res; 1397 2147 const char *sam_accountname, *enc_str; … … 1416 2166 return ret; 1417 2167 } 1418 sam_accountname = talloc_steal(ac, 1419 ldb_msg_find_attr_as_string(tmp_msg, "sAMAccountName", NULL)); 2168 2169 /* We must not steal the original string, it belongs to the caller! */ 2170 sam_accountname = talloc_strdup(ac, 2171 ldb_msg_find_attr_as_string(tmp_msg, "sAMAccountName", NULL)); 1420 2172 talloc_free(tmp_msg); 1421 2173 … … 1434 2186 /* Make sure that a "sAMAccountName" is only used once */ 1435 2187 1436 ret = dsdb_module_search(ac->module, ac, &res, NULL, LDB_SCOPE_SUBTREE, no_attrs, 2188 ret = dsdb_module_search(ac->module, ac, &res, 2189 ldb_get_default_basedn(ldb), 2190 LDB_SCOPE_SUBTREE, no_attrs, 1437 2191 DSDB_FLAG_NEXT_MODULE, ac->req, 1438 2192 "(sAMAccountName=%s)", enc_str); … … 1457 2211 static int samldb_member_check(struct samldb_ctx *ac) 1458 2212 { 1459 static const char * const attrs[] = { "objectSid", "member", NULL };2213 const char * const attrs[] = { "objectSid", NULL }; 1460 2214 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 1461 2215 struct ldb_message_element *el; … … 1465 2219 struct dom_sid *group_sid; 1466 2220 unsigned int i, j; 1467 int cnt;1468 2221 int ret; 1469 2222 … … 1471 2224 1472 2225 ret = dsdb_module_search(ac->module, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs, 1473 DSDB_FLAG_NEXT_MODULE , ac->req, NULL);2226 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, ac->req, NULL); 1474 2227 if (ret != LDB_SUCCESS) { 1475 2228 return ret; … … 1493 2246 el = &ac->msg->elements[i]; 1494 2247 for (j = 0; j < el->num_values; j++) { 1495 struct ldb_message_element *mo;1496 2248 struct ldb_result *group_res; 1497 2249 const char *group_attrs[] = { "primaryGroupID" , NULL }; 1498 2250 uint32_t prim_group_rid; 2251 2252 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) { 2253 /* Deletes will be handled in 2254 * repl_meta_data, and deletes not 2255 * matching a member will return 2256 * LDB_ERR_UNWILLING_TO_PERFORM 2257 * there */ 2258 continue; 2259 } 1499 2260 1500 2261 member_dn = ldb_dn_from_ldb_val(ac, ldb, … … 1502 2263 if (!ldb_dn_validate(member_dn)) { 1503 2264 return ldb_operr(ldb); 1504 }1505 1506 /* The "member" attribute can be modified with the1507 * following restrictions (beside a valid DN):1508 *1509 * - "add" operations can only be performed when the1510 * member still doesn't exist - if not then return1511 * ERR_ENTRY_ALREADY_EXISTS (not1512 * ERR_ATTRIBUTE_OR_VALUE_EXISTS!)1513 * - "delete" operations can only be performed when the1514 * member does exist - if not then return1515 * ERR_UNWILLING_TO_PERFORM (not1516 * ERR_NO_SUCH_ATTRIBUTE!)1517 * - primary group check1518 */1519 mo = samdb_find_attribute(ldb, res->msgs[0], "member",1520 ldb_dn_get_linearized(member_dn));1521 if (mo == NULL) {1522 cnt = 0;1523 } else {1524 cnt = 1;1525 }1526 1527 if ((cnt > 0) && (LDB_FLAG_MOD_TYPE(el->flags)1528 == LDB_FLAG_MOD_ADD)) {1529 return LDB_ERR_ENTRY_ALREADY_EXISTS;1530 }1531 if ((cnt == 0) && LDB_FLAG_MOD_TYPE(el->flags)1532 == LDB_FLAG_MOD_DELETE) {1533 return LDB_ERR_UNWILLING_TO_PERFORM;1534 2265 } 1535 2266 … … 1562 2293 1563 2294 if (dom_sid_equal(group_sid, sid)) { 2295 ldb_asprintf_errstring(ldb, 2296 "samldb: member %s already set via primaryGroupID %u", 2297 ldb_dn_get_linearized(member_dn), prim_group_rid); 1564 2298 return LDB_ERR_ENTRY_ALREADY_EXISTS; 1565 2299 } … … 1619 2353 struct ldb_message_element *el = NULL, *el2 = NULL; 1620 2354 struct ldb_message *msg; 1621 const char * attrs[] = { "servicePrincipalName", NULL };2355 const char * const attrs[] = { "servicePrincipalName", NULL }; 1622 2356 struct ldb_result *res; 1623 2357 const char *dns_hostname = NULL, *old_dns_hostname = NULL, 1624 2358 *sam_accountname = NULL, *old_sam_accountname = NULL; 1625 unsigned int i ;2359 unsigned int i, j; 1626 2360 int ret; 1627 2361 … … 1646 2380 return ret; 1647 2381 } 1648 dns_hostname = talloc_steal(ac, 1649 ldb_msg_find_attr_as_string(msg, "dNSHostName", NULL)); 2382 dns_hostname = talloc_strdup(ac, 2383 ldb_msg_find_attr_as_string(msg, "dNSHostName", NULL)); 2384 if (dns_hostname == NULL) { 2385 return ldb_module_oom(ac->module); 2386 } 2387 1650 2388 talloc_free(msg); 1651 2389 … … 1659 2397 /* Create a temporary message for fetching the "sAMAccountName" */ 1660 2398 if (el2 != NULL) { 1661 char *tempstr, *tempstr2 ;2399 char *tempstr, *tempstr2 = NULL; 1662 2400 const char *acct_attrs[] = { "sAMAccountName", NULL }; 1663 2401 … … 1702 2440 } 1703 2441 if ((old_dns_hostname != NULL) && (dns_hostname != NULL) && 1704 (strcasecmp (old_dns_hostname, dns_hostname) == 0)) {2442 (strcasecmp_m(old_dns_hostname, dns_hostname) == 0)) { 1705 2443 /* The "dNSHostName" didn't change */ 1706 2444 dns_hostname = NULL; … … 1712 2450 } 1713 2451 if ((old_sam_accountname != NULL) && (sam_accountname != NULL) && 1714 (strcasecmp (old_sam_accountname, sam_accountname) == 0)) {2452 (strcasecmp_m(old_sam_accountname, sam_accountname) == 0)) { 1715 2453 /* The "sAMAccountName" didn't change */ 1716 2454 sam_accountname = NULL; … … 1764 2502 1765 2503 if (res->msgs[0]->num_elements == 1) { 1766 /* Yes, we do have "servicePrincipalName"s. First we update them 2504 /* 2505 * Yes, we do have "servicePrincipalName"s. First we update them 1767 2506 * locally, that means we do always substitute the current 1768 2507 * "dNSHostName" with the new one and/or "sAMAccountName" 1769 * without "$" with the new one and then we append this to the 1770 * modification request (Windows behaviour). */ 2508 * without "$" with the new one and then we append the 2509 * modified "servicePrincipalName"s as a message element 2510 * replace to the modification request (Windows behaviour). We 2511 * need also to make sure that the values remain case- 2512 * insensitively unique. 2513 */ 2514 2515 ret = ldb_msg_add_empty(ac->msg, "servicePrincipalName", 2516 LDB_FLAG_MOD_REPLACE, &el); 2517 if (ret != LDB_SUCCESS) { 2518 return ret; 2519 } 1771 2520 1772 2521 for (i = 0; i < res->msgs[0]->elements[0].num_values; i++) { 1773 char *old_str, *new_str, *pos; 2522 char *old_str, *new_str; 2523 char *pos = NULL; 1774 2524 const char *tok; 2525 struct ldb_val *vals; 2526 bool found = false; 1775 2527 1776 2528 old_str = (char *) … … 1785 2537 while ((tok = strtok_r(NULL, "/", &pos)) != NULL) { 1786 2538 if ((dns_hostname != NULL) && 1787 (strcasecmp (tok, old_dns_hostname) == 0)) {2539 (strcasecmp_m(tok, old_dns_hostname) == 0)) { 1788 2540 tok = dns_hostname; 1789 2541 } 1790 2542 if ((sam_accountname != NULL) && 1791 (strcasecmp (tok, old_sam_accountname) == 0)) {2543 (strcasecmp_m(tok, old_sam_accountname) == 0)) { 1792 2544 tok = sam_accountname; 1793 2545 } … … 1800 2552 } 1801 2553 1802 ret = ldb_msg_add_string(ac->msg, 1803 "servicePrincipalName", 1804 new_str); 1805 if (ret != LDB_SUCCESS) { 1806 return ret; 1807 } 1808 } 1809 1810 el = ldb_msg_find_element(ac->msg, "servicePrincipalName"); 1811 el->flags = LDB_FLAG_MOD_REPLACE; 2554 /* Uniqueness check */ 2555 for (j = 0; (!found) && (j < el->num_values); j++) { 2556 if (strcasecmp_m((char *)el->values[j].data, 2557 new_str) == 0) { 2558 found = true; 2559 } 2560 } 2561 if (found) { 2562 continue; 2563 } 2564 2565 /* 2566 * append the new "servicePrincipalName" - 2567 * code derived from ldb_msg_add_value(). 2568 * 2569 * Open coded to make it clear that we must 2570 * append to the MOD_REPLACE el created above. 2571 */ 2572 vals = talloc_realloc(ac->msg, el->values, 2573 struct ldb_val, 2574 el->num_values + 1); 2575 if (vals == NULL) { 2576 return ldb_module_oom(ac->module); 2577 } 2578 el->values = vals; 2579 el->values[el->num_values] = data_blob_string_const(new_str); 2580 ++(el->num_values); 2581 } 1812 2582 } 1813 2583 1814 2584 talloc_free(res); 2585 2586 return LDB_SUCCESS; 2587 } 2588 2589 /* This checks the "fSMORoleOwner" attributes */ 2590 static int samldb_fsmo_role_owner_check(struct samldb_ctx *ac) 2591 { 2592 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 2593 const char * const no_attrs[] = { NULL }; 2594 struct ldb_message_element *el; 2595 struct ldb_message *tmp_msg; 2596 struct ldb_dn *res_dn; 2597 struct ldb_result *res; 2598 int ret; 2599 2600 el = dsdb_get_single_valued_attr(ac->msg, "fSMORoleOwner", 2601 ac->req->operation); 2602 if (el == NULL) { 2603 /* we are not affected */ 2604 return LDB_SUCCESS; 2605 } 2606 2607 /* Create a temporary message for fetching the "fSMORoleOwner" */ 2608 tmp_msg = ldb_msg_new(ac->msg); 2609 if (tmp_msg == NULL) { 2610 return ldb_module_oom(ac->module); 2611 } 2612 ret = ldb_msg_add(tmp_msg, el, 0); 2613 if (ret != LDB_SUCCESS) { 2614 return ret; 2615 } 2616 res_dn = ldb_msg_find_attr_as_dn(ldb, ac, tmp_msg, "fSMORoleOwner"); 2617 talloc_free(tmp_msg); 2618 2619 if (res_dn == NULL) { 2620 ldb_set_errstring(ldb, 2621 "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!"); 2622 if (ac->req->operation == LDB_ADD) { 2623 return LDB_ERR_CONSTRAINT_VIOLATION; 2624 } else { 2625 return LDB_ERR_UNWILLING_TO_PERFORM; 2626 } 2627 } 2628 2629 /* Fetched DN has to reference a "nTDSDSA" entry */ 2630 ret = dsdb_module_search(ac->module, ac, &res, res_dn, LDB_SCOPE_BASE, 2631 no_attrs, 2632 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, 2633 ac->req, "(objectClass=nTDSDSA)"); 2634 if (ret != LDB_SUCCESS) { 2635 return ret; 2636 } 2637 if (res->count != 1) { 2638 ldb_set_errstring(ldb, 2639 "samldb: 'fSMORoleOwner' attributes have to reference 'nTDSDSA' entries!"); 2640 return LDB_ERR_UNWILLING_TO_PERFORM; 2641 } 2642 2643 talloc_free(res); 2644 2645 return LDB_SUCCESS; 2646 } 2647 2648 /* 2649 * Return zero if the number of zero bits in the address (looking from low to 2650 * high) is equal to or greater than the length minus the mask. Otherwise it 2651 * returns -1. 2652 */ 2653 static int check_cidr_zero_bits(uint8_t *address, unsigned int len, 2654 unsigned int mask) 2655 { 2656 /* <address> is an integer in big-endian form, <len> bits long. All 2657 bits between <mask> and <len> must be zero. */ 2658 int i; 2659 unsigned int byte_len; 2660 unsigned int byte_mask; 2661 unsigned int bit_mask; 2662 if (len == 32) { 2663 DBG_INFO("Looking at address %02x%02x%02x%02x, mask %u\n", 2664 address[0], address[1], address[2], address[3], 2665 mask); 2666 } else if (len == 128){ 2667 DBG_INFO("Looking at address " 2668 "%02x%02x-%02x%02x-%02x%02x-%02x%02x-" 2669 "%02x%02x-%02x%02x-%02x%02x-%02x%02x, mask %u\n", 2670 address[0], address[1], address[2], address[3], 2671 address[4], address[5], address[6], address[7], 2672 address[8], address[9], address[10], address[11], 2673 address[12], address[13], address[14], address[15], 2674 mask); 2675 } 2676 2677 if (mask > len){ 2678 DBG_INFO("mask %u is too big (> %u)\n", mask, len); 2679 return -1; 2680 } 2681 if (mask == len){ 2682 /* single address subnet. 2683 * In IPv4 all 255s is invalid by the bitmask != address rule 2684 * in MS-ADTS. IPv6 does not suffer. 2685 */ 2686 if (len == 32){ 2687 if (address[0] == 255 && 2688 address[1] == 255 && 2689 address[2] == 255 && 2690 address[3] == 255){ 2691 return -1; 2692 } 2693 } 2694 return 0; 2695 } 2696 2697 byte_len = len / 8; 2698 byte_mask = mask / 8; 2699 2700 for (i = byte_len - 1; i > byte_mask; i--){ 2701 DBG_DEBUG("checking byte %d %02x\n", i, address[i]); 2702 if (address[i] != 0){ 2703 return -1; 2704 } 2705 } 2706 bit_mask = (1 << (8 - (mask & 7))) - 1; 2707 DBG_DEBUG("checking bitmask %02x & %02x overlap %02x\n", bit_mask, address[byte_mask], 2708 bit_mask & address[byte_mask]); 2709 if (address[byte_mask] & bit_mask){ 2710 return -1; 2711 } 2712 2713 /* According to MS-ADTS, the mask can't exactly equal the bitmask for 2714 * IPv4 (but this is fine for v6). That is 255.255.80.0/17 is bad, 2715 * because the bitmask implied by "/17" is 255.255.80.0. 2716 * 2717 * The bit_mask used in the previous check is the complement of what 2718 * we want here. 2719 */ 2720 if (len == 32 && address[byte_mask] == (uint8_t)~bit_mask){ 2721 bool ok = false; 2722 for (i = 0; i < byte_mask; i++){ 2723 if (address[i] != 255){ 2724 ok = true; 2725 break; 2726 } 2727 } 2728 if (ok == false){ 2729 return -1; 2730 } 2731 } 2732 return 0; 2733 } 2734 2735 2736 2737 static int check_address_roundtrip(const char *address, int family, 2738 const uint8_t *address_bytes, 2739 char *buffer, int buffer_len) 2740 { 2741 /* 2742 * Check that the address is in the canonical RFC5952 format for IPv6, 2743 * and lacks extra leading zeros for each dotted decimal for IPv4. 2744 * Handily this is what inet_ntop() gives you. 2745 */ 2746 const char *address_redux = inet_ntop(family, address_bytes, 2747 buffer, buffer_len); 2748 if (address_redux == NULL){ 2749 DBG_INFO("Address round trip %s failed unexpectedly" 2750 " with errno %d\n", address, errno); 2751 return -1; 2752 } 2753 if (strcasecmp(address, address_redux) != 0){ 2754 DBG_INFO("Address %s round trips to %s; fail!\n", 2755 address, address_redux); 2756 /* If the address family is IPv6, and the address is in a 2757 certain range 2758 2759 */ 2760 if (strchr(address_redux, '.') != NULL){ 2761 DEBUG(0, ("The IPv6 address '%s' has the misfortune of " 2762 "lying in a range that was once used for " 2763 "IPv4 embedding (that is, it might also be " 2764 "represented as '%s').\n", address, 2765 address_redux)); 2766 } 2767 return -1; 2768 } 2769 return 0; 2770 } 2771 2772 2773 2774 /* 2775 * MS-ADTS v20150630 6.1.1.2.2.2.1 Subnet Object, refers to RFC1166 and 2776 * RFC2373. It specifies something seemingly indistinguishable from an RFC4632 2777 * CIDR address range without saying so explicitly. Here we follow the CIDR 2778 * spec. 2779 * 2780 * Return 0 on success, -1 on error. 2781 */ 2782 static int verify_cidr(const char *cidr) 2783 { 2784 char *address = NULL, *slash = NULL, *endptr = NULL; 2785 bool has_colon, has_dot; 2786 int res, ret; 2787 unsigned long mask; 2788 uint8_t *address_bytes = NULL; 2789 char *address_redux = NULL; 2790 unsigned int address_len; 2791 TALLOC_CTX *frame = NULL; 2792 2793 DBG_DEBUG("CIDR is %s\n", cidr); 2794 frame = talloc_stackframe(); 2795 address = talloc_strdup(frame, cidr); 2796 if (address == NULL){ 2797 goto error; 2798 } 2799 2800 /* there must be a '/' */ 2801 slash = strchr(address, '/'); 2802 if (slash == NULL){ 2803 goto error; 2804 } 2805 /* terminate the address for strchr, inet_pton */ 2806 *slash = '\0'; 2807 2808 mask = strtoul(slash + 1, &endptr, 10); 2809 if (mask == 0){ 2810 DBG_INFO("Windows does not like the zero mask, " 2811 "so nor do we: %s\n", cidr); 2812 goto error; 2813 } 2814 2815 if (*endptr != '\0' || endptr == slash + 1){ 2816 DBG_INFO("CIDR mask is not a proper integer: %s\n", cidr); 2817 goto error; 2818 } 2819 2820 address_bytes = talloc_size(frame, sizeof(struct in6_addr)); 2821 if (address_bytes == NULL){ 2822 goto error; 2823 } 2824 2825 address_redux = talloc_size(frame, INET6_ADDRSTRLEN); 2826 if (address_redux == NULL){ 2827 goto error; 2828 } 2829 2830 DBG_INFO("found address %s, mask %lu\n", address, mask); 2831 has_colon = (strchr(address, ':') == NULL) ? false : true; 2832 has_dot = (strchr(address, '.') == NULL) ? false : true; 2833 if (has_dot && has_colon){ 2834 /* This seems to be an IPv4 address embedded in IPv6, which is 2835 icky. We don't support it. */ 2836 DBG_INFO("Refusing to consider cidr '%s' with dots and colons\n", 2837 cidr); 2838 goto error; 2839 } else if (has_colon){ /* looks like IPv6 */ 2840 res = inet_pton(AF_INET6, address, address_bytes); 2841 if (res != 1) { 2842 DBG_INFO("Address in %s fails to parse as IPv6\n", cidr); 2843 goto error; 2844 } 2845 address_len = 128; 2846 if (check_address_roundtrip(address, AF_INET6, address_bytes, 2847 address_redux, INET6_ADDRSTRLEN)){ 2848 goto error; 2849 } 2850 } else if (has_dot) { 2851 /* looks like IPv4 */ 2852 if (strcmp(address, "0.0.0.0") == 0){ 2853 DBG_INFO("Windows does not like the zero IPv4 address, " 2854 "so nor do we.\n"); 2855 goto error; 2856 } 2857 res = inet_pton(AF_INET, address, address_bytes); 2858 if (res != 1) { 2859 DBG_INFO("Address in %s fails to parse as IPv4\n", cidr); 2860 goto error; 2861 } 2862 address_len = 32; 2863 2864 if (check_address_roundtrip(address, AF_INET, address_bytes, 2865 address_redux, INET_ADDRSTRLEN)){ 2866 goto error; 2867 } 2868 } else { 2869 /* This doesn't look like an IP address at all. */ 2870 goto error; 2871 } 2872 2873 ret = check_cidr_zero_bits(address_bytes, address_len, mask); 2874 talloc_free(frame); 2875 return ret; 2876 error: 2877 talloc_free(frame); 2878 return -1; 2879 } 2880 2881 2882 static int samldb_verify_subnet(struct samldb_ctx *ac) 2883 { 2884 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 2885 const char *cidr = NULL; 2886 const struct ldb_val *rdn_value = NULL; 2887 2888 rdn_value = ldb_dn_get_rdn_val(ac->msg->dn); 2889 if (rdn_value == NULL) { 2890 ldb_set_errstring(ldb, "samldb: ldb_dn_get_rdn_val " 2891 "failed"); 2892 return LDB_ERR_UNWILLING_TO_PERFORM; 2893 } 2894 2895 cidr = ldb_dn_escape_value(ac, *rdn_value); 2896 DBG_INFO("looking at cidr '%s'\n", cidr); 2897 if (cidr == NULL) { 2898 ldb_set_errstring(ldb, 2899 "samldb: adding an empty subnet cidr seems wrong"); 2900 return LDB_ERR_UNWILLING_TO_PERFORM; 2901 } 2902 2903 if (verify_cidr(cidr)){ 2904 ldb_set_errstring(ldb, 2905 "samldb: subnet value is invalid"); 2906 return LDB_ERR_INVALID_DN_SYNTAX; 2907 } 1815 2908 1816 2909 return LDB_SUCCESS; … … 1823 2916 struct ldb_context *ldb; 1824 2917 struct samldb_ctx *ac; 2918 struct ldb_message_element *el; 1825 2919 int ret; 1826 2920 … … 1831 2925 if (ldb_dn_is_special(req->op.add.message->dn)) { 1832 2926 return ldb_next_request(module, req); 2927 } 2928 2929 el = ldb_msg_find_element(req->op.add.message, "userParameters"); 2930 if (el != NULL && ldb_req_is_untrusted(req)) { 2931 const char *reason = "samldb_add: " 2932 "setting userParameters is not supported over LDAP, " 2933 "see https://bugzilla.samba.org/show_bug.cgi?id=8077"; 2934 ldb_debug(ldb, LDB_DEBUG_WARNING, "%s", reason); 2935 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, reason); 1833 2936 } 1834 2937 … … 1847 2950 } 1848 2951 2952 el = ldb_msg_find_element(ac->msg, "fSMORoleOwner"); 2953 if (el != NULL) { 2954 ret = samldb_fsmo_role_owner_check(ac); 2955 if (ret != LDB_SUCCESS) { 2956 return ret; 2957 } 2958 } 2959 1849 2960 if (samdb_find_attribute(ldb, ac->msg, 1850 2961 "objectclass", "user") != NULL) { 1851 ac->type = "user";2962 ac->type = SAMLDB_TYPE_USER; 1852 2963 1853 2964 ret = samldb_prim_group_trigger(ac); … … 1866 2977 if (samdb_find_attribute(ldb, ac->msg, 1867 2978 "objectclass", "group") != NULL) { 1868 ac->type = "group";2979 ac->type = SAMLDB_TYPE_GROUP; 1869 2980 1870 2981 ret = samldb_objectclass_trigger(ac); … … 1891 3002 } 1892 3003 1893 ac->type = "classSchema";3004 ac->type = SAMLDB_TYPE_CLASS; 1894 3005 return samldb_fill_object(ac); 1895 3006 } … … 1903 3014 } 1904 3015 1905 ac->type = "attributeSchema";3016 ac->type = SAMLDB_TYPE_ATTRIBUTE; 1906 3017 return samldb_fill_object(ac); 3018 } 3019 3020 if (samdb_find_attribute(ldb, ac->msg, 3021 "objectclass", "subnet") != NULL) { 3022 ret = samldb_verify_subnet(ac); 3023 if (ret != LDB_SUCCESS) { 3024 talloc_free(ac); 3025 return ret; 3026 } 3027 /* We are just checking the value is valid, and there are no 3028 values to fill in. */ 1907 3029 } 1908 3030 … … 1919 3041 struct samldb_ctx *ac; 1920 3042 struct ldb_message_element *el, *el2; 3043 struct ldb_control *is_undelete; 1921 3044 bool modified = false; 1922 3045 int ret; … … 1929 3052 ldb = ldb_module_get_ctx(module); 1930 3053 3054 /* 3055 * we are going to need some special handling if in Undelete call. 3056 * Since tombstone_reanimate module will restore certain attributes, 3057 * we need to relax checks for: sAMAccountType, primaryGroupID 3058 */ 3059 is_undelete = ldb_request_get_control(req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID); 3060 1931 3061 /* make sure that "objectSid" is not specified */ 1932 3062 el = ldb_msg_find_element(req->op.mod.message, "objectSid"); 1933 3063 if (el != NULL) { 1934 ldb_set_errstring(ldb, 1935 "samldb: objectSid must not be specified!"); 1936 return LDB_ERR_UNWILLING_TO_PERFORM; 1937 } 1938 /* make sure that "sAMAccountType" is not specified */ 1939 el = ldb_msg_find_element(req->op.mod.message, "sAMAccountType"); 1940 if (el != NULL) { 1941 ldb_set_errstring(ldb, 1942 "samldb: sAMAccountType must not be specified!"); 1943 return LDB_ERR_UNWILLING_TO_PERFORM; 3064 if (ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID) == NULL) { 3065 ldb_set_errstring(ldb, 3066 "samldb: objectSid must not be specified!"); 3067 return LDB_ERR_UNWILLING_TO_PERFORM; 3068 } 3069 } 3070 if (is_undelete == NULL) { 3071 /* make sure that "sAMAccountType" is not specified */ 3072 el = ldb_msg_find_element(req->op.mod.message, "sAMAccountType"); 3073 if (el != NULL) { 3074 ldb_set_errstring(ldb, 3075 "samldb: sAMAccountType must not be specified!"); 3076 return LDB_ERR_UNWILLING_TO_PERFORM; 3077 } 1944 3078 } 1945 3079 /* make sure that "isCriticalSystemObject" is not specified */ … … 1962 3096 } 1963 3097 3098 el = ldb_msg_find_element(req->op.mod.message, "userParameters"); 3099 if (el != NULL && ldb_req_is_untrusted(req)) { 3100 const char *reason = "samldb: " 3101 "setting userParameters is not supported over LDAP, " 3102 "see https://bugzilla.samba.org/show_bug.cgi?id=8077"; 3103 ldb_debug(ldb, LDB_DEBUG_WARNING, "%s", reason); 3104 return ldb_error(ldb, LDB_ERR_CONSTRAINT_VIOLATION, reason); 3105 } 3106 1964 3107 ac = samldb_ctx_init(module, req); 1965 3108 if (ac == NULL) { … … 1976 3119 } 1977 3120 1978 el = ldb_msg_find_element(ac->msg, "primaryGroupID"); 1979 if (el != NULL) { 1980 ret = samldb_prim_group_change(ac); 1981 if (ret != LDB_SUCCESS) { 1982 return ret; 3121 if (is_undelete == NULL) { 3122 el = ldb_msg_find_element(ac->msg, "primaryGroupID"); 3123 if (el != NULL) { 3124 ret = samldb_prim_group_trigger(ac); 3125 if (ret != LDB_SUCCESS) { 3126 return ret; 3127 } 1983 3128 } 1984 3129 } … … 1993 3138 } 1994 3139 3140 el = ldb_msg_find_element(ac->msg, "lockoutTime"); 3141 if (el != NULL) { 3142 modified = true; 3143 ret = samldb_lockout_time(ac); 3144 if (ret != LDB_SUCCESS) { 3145 return ret; 3146 } 3147 } 3148 1995 3149 el = ldb_msg_find_element(ac->msg, "groupType"); 1996 3150 if (el != NULL) { … … 2031 3185 modified = true; 2032 3186 ret = samldb_service_principal_names_change(ac); 3187 if (ret != LDB_SUCCESS) { 3188 return ret; 3189 } 3190 } 3191 3192 el = ldb_msg_find_element(ac->msg, "fSMORoleOwner"); 3193 if (el != NULL) { 3194 ret = samldb_fsmo_role_owner_check(ac); 2033 3195 if (ret != LDB_SUCCESS) { 2034 3196 return ret; … … 2069 3231 int ret; 2070 3232 struct ldb_result *res; 2071 const char * attrs[] = { "objectSid", NULL };2072 const char * noattrs[] = { NULL };3233 const char * const attrs[] = { "objectSid", "isDeleted", NULL }; 3234 const char * const noattrs[] = { NULL }; 2073 3235 2074 3236 ldb = ldb_module_get_ctx(ac->module); 2075 3237 2076 3238 /* Finds out the SID/RID of the SAM object */ 2077 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->req->op.del.dn, attrs, DSDB_FLAG_NEXT_MODULE, ac->req); 2078 if (ret != LDB_SUCCESS) { 2079 return ret; 3239 ret = dsdb_module_search_dn(ac->module, ac, &res, ac->req->op.del.dn, 3240 attrs, 3241 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DELETED, 3242 ac->req); 3243 if (ret != LDB_SUCCESS) { 3244 return ret; 3245 } 3246 3247 if (ldb_msg_check_string_attribute(res->msgs[0], "isDeleted", "TRUE")) { 3248 return LDB_SUCCESS; 2080 3249 } 2081 3250 … … 2093 3262 return LDB_SUCCESS; 2094 3263 } 3264 /* do not allow deletion of well-known sids */ 3265 if (rid < DSDB_SAMDB_MINIMUM_ALLOWED_RID && 3266 (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) == NULL)) { 3267 return LDB_ERR_OTHER; 3268 } 2095 3269 2096 3270 /* Deny delete requests from groups which are primary ones */ 2097 ret = dsdb_module_search(ac->module, ac, &res, NULL, LDB_SCOPE_SUBTREE, noattrs, 3271 ret = dsdb_module_search(ac->module, ac, &res, 3272 ldb_get_default_basedn(ldb), 3273 LDB_SCOPE_SUBTREE, noattrs, 2098 3274 DSDB_FLAG_NEXT_MODULE, 2099 3275 ac->req, … … 2132 3308 2133 3309 return ldb_next_request(module, req); 3310 } 3311 3312 /* rename */ 3313 3314 static int check_rename_constraints(struct ldb_message *msg, 3315 struct samldb_ctx *ac, 3316 struct ldb_dn *olddn, struct ldb_dn *newdn) 3317 { 3318 struct ldb_context *ldb = ldb_module_get_ctx(ac->module); 3319 struct ldb_dn *dn1, *dn2, *nc_root; 3320 int32_t systemFlags; 3321 bool move_op = false; 3322 bool rename_op = false; 3323 int ret; 3324 3325 /* Skip the checks if old and new DN are the same, or if we have the 3326 * relax control specified or if the returned objects is already 3327 * deleted and needs only to be moved for consistency. */ 3328 3329 if (ldb_dn_compare(olddn, newdn) == 0) { 3330 return LDB_SUCCESS; 3331 } 3332 if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) != NULL) { 3333 return LDB_SUCCESS; 3334 } 3335 3336 if (ldb_msg_find_attr_as_bool(msg, "isDeleted", false)) { 3337 /* 3338 * check originating request if we are supposed 3339 * to "see" this record in first place. 3340 */ 3341 if (ldb_request_get_control(ac->req, LDB_CONTROL_SHOW_DELETED_OID) == NULL) { 3342 return LDB_ERR_NO_SUCH_OBJECT; 3343 } 3344 return LDB_ERR_UNWILLING_TO_PERFORM; 3345 } 3346 3347 /* Objects under CN=System */ 3348 3349 dn1 = ldb_dn_copy(ac, ldb_get_default_basedn(ldb)); 3350 if (dn1 == NULL) return ldb_oom(ldb); 3351 3352 if ( ! ldb_dn_add_child_fmt(dn1, "CN=System")) { 3353 talloc_free(dn1); 3354 return LDB_ERR_OPERATIONS_ERROR; 3355 } 3356 3357 if ((ldb_dn_compare_base(dn1, olddn) == 0) && 3358 (ldb_dn_compare_base(dn1, newdn) != 0)) { 3359 talloc_free(dn1); 3360 ldb_asprintf_errstring(ldb, 3361 "subtree_rename: Cannot move/rename %s. Objects under CN=System have to stay under it!", 3362 ldb_dn_get_linearized(olddn)); 3363 return LDB_ERR_OTHER; 3364 } 3365 3366 talloc_free(dn1); 3367 3368 /* LSA objects */ 3369 3370 if ((samdb_find_attribute(ldb, msg, "objectClass", "secret") != NULL) || 3371 (samdb_find_attribute(ldb, msg, "objectClass", "trustedDomain") != NULL)) { 3372 ldb_asprintf_errstring(ldb, 3373 "subtree_rename: Cannot move/rename %s. It's an LSA-specific object!", 3374 ldb_dn_get_linearized(olddn)); 3375 return LDB_ERR_UNWILLING_TO_PERFORM; 3376 } 3377 3378 /* subnet objects */ 3379 if (samdb_find_attribute(ldb, msg, "objectclass", "subnet") != NULL) { 3380 ret = samldb_verify_subnet(ac); 3381 if (ret != LDB_SUCCESS) { 3382 talloc_free(ac); 3383 return ret; 3384 } 3385 } 3386 3387 /* systemFlags */ 3388 3389 dn1 = ldb_dn_get_parent(ac, olddn); 3390 if (dn1 == NULL) return ldb_oom(ldb); 3391 dn2 = ldb_dn_get_parent(ac, newdn); 3392 if (dn2 == NULL) return ldb_oom(ldb); 3393 3394 if (ldb_dn_compare(dn1, dn2) == 0) { 3395 rename_op = true; 3396 } else { 3397 move_op = true; 3398 } 3399 3400 talloc_free(dn1); 3401 talloc_free(dn2); 3402 3403 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0); 3404 3405 /* Fetch name context */ 3406 3407 ret = dsdb_find_nc_root(ldb, ac, olddn, &nc_root); 3408 if (ret != LDB_SUCCESS) { 3409 return ret; 3410 } 3411 3412 if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) { 3413 if (move_op) { 3414 ldb_asprintf_errstring(ldb, 3415 "subtree_rename: Cannot move %s within schema partition", 3416 ldb_dn_get_linearized(olddn)); 3417 return LDB_ERR_UNWILLING_TO_PERFORM; 3418 } 3419 if (rename_op && 3420 (systemFlags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) != 0) { 3421 ldb_asprintf_errstring(ldb, 3422 "subtree_rename: Cannot rename %s within schema partition", 3423 ldb_dn_get_linearized(olddn)); 3424 return LDB_ERR_UNWILLING_TO_PERFORM; 3425 } 3426 } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) { 3427 if (move_op && 3428 (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_MOVE) == 0) { 3429 /* Here we have to do more: control the 3430 * "ALLOW_LIMITED_MOVE" flag. This means that the 3431 * grand-grand-parents of two objects have to be equal 3432 * in order to perform the move (this is used for 3433 * moving "server" objects in the "sites" container). */ 3434 bool limited_move = 3435 systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE; 3436 3437 if (limited_move) { 3438 dn1 = ldb_dn_copy(ac, olddn); 3439 if (dn1 == NULL) return ldb_oom(ldb); 3440 dn2 = ldb_dn_copy(ac, newdn); 3441 if (dn2 == NULL) return ldb_oom(ldb); 3442 3443 limited_move &= ldb_dn_remove_child_components(dn1, 3); 3444 limited_move &= ldb_dn_remove_child_components(dn2, 3); 3445 limited_move &= ldb_dn_compare(dn1, dn2) == 0; 3446 3447 talloc_free(dn1); 3448 talloc_free(dn2); 3449 } 3450 3451 if (!limited_move 3452 && ldb_request_get_control(ac->req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID) == NULL) { 3453 ldb_asprintf_errstring(ldb, 3454 "subtree_rename: Cannot move %s to %s in config partition", 3455 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); 3456 return LDB_ERR_UNWILLING_TO_PERFORM; 3457 } 3458 } 3459 if (rename_op && 3460 (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_RENAME) == 0) { 3461 ldb_asprintf_errstring(ldb, 3462 "subtree_rename: Cannot rename %s to %s within config partition", 3463 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); 3464 return LDB_ERR_UNWILLING_TO_PERFORM; 3465 } 3466 } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) { 3467 if (move_op && 3468 (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE) != 0) { 3469 ldb_asprintf_errstring(ldb, 3470 "subtree_rename: Cannot move %s to %s - DISALLOW_MOVE set", 3471 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); 3472 return LDB_ERR_UNWILLING_TO_PERFORM; 3473 } 3474 if (rename_op && 3475 (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME) != 0) { 3476 ldb_asprintf_errstring(ldb, 3477 "subtree_rename: Cannot rename %s to %s - DISALLOW_RENAME set", 3478 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn)); 3479 return LDB_ERR_UNWILLING_TO_PERFORM; 3480 } 3481 } 3482 3483 talloc_free(nc_root); 3484 3485 return LDB_SUCCESS; 3486 } 3487 3488 3489 static int samldb_rename_search_base_callback(struct ldb_request *req, 3490 struct ldb_reply *ares) 3491 { 3492 struct samldb_ctx *ac; 3493 int ret; 3494 3495 ac = talloc_get_type(req->context, struct samldb_ctx); 3496 3497 if (!ares) { 3498 return ldb_module_done(ac->req, NULL, NULL, 3499 LDB_ERR_OPERATIONS_ERROR); 3500 } 3501 if (ares->error != LDB_SUCCESS) { 3502 return ldb_module_done(ac->req, ares->controls, 3503 ares->response, ares->error); 3504 } 3505 3506 switch (ares->type) { 3507 case LDB_REPLY_ENTRY: 3508 /* 3509 * This is the root entry of the originating move 3510 * respectively rename request. It has been already 3511 * stored in the list using "subtree_rename_search()". 3512 * Only this one is subject to constraint checking. 3513 */ 3514 ret = check_rename_constraints(ares->message, ac, 3515 ac->req->op.rename.olddn, 3516 ac->req->op.rename.newdn); 3517 if (ret != LDB_SUCCESS) { 3518 return ldb_module_done(ac->req, NULL, NULL, 3519 ret); 3520 } 3521 break; 3522 3523 case LDB_REPLY_REFERRAL: 3524 /* ignore */ 3525 break; 3526 3527 case LDB_REPLY_DONE: 3528 3529 /* 3530 * Great, no problem with the rename, so go ahead as 3531 * if we never were here 3532 */ 3533 ret = ldb_next_request(ac->module, ac->req); 3534 talloc_free(ares); 3535 return ret; 3536 } 3537 3538 talloc_free(ares); 3539 return LDB_SUCCESS; 3540 } 3541 3542 3543 /* rename */ 3544 static int samldb_rename(struct ldb_module *module, struct ldb_request *req) 3545 { 3546 struct ldb_context *ldb; 3547 static const char * const attrs[] = { "objectClass", "systemFlags", 3548 "isDeleted", NULL }; 3549 struct ldb_request *search_req; 3550 struct samldb_ctx *ac; 3551 int ret; 3552 3553 if (ldb_dn_is_special(req->op.rename.olddn)) { /* do not manipulate our control entries */ 3554 return ldb_next_request(module, req); 3555 } 3556 3557 ldb = ldb_module_get_ctx(module); 3558 3559 ac = samldb_ctx_init(module, req); 3560 if (!ac) { 3561 return ldb_oom(ldb); 3562 } 3563 3564 ret = ldb_build_search_req(&search_req, ldb, ac, 3565 req->op.rename.olddn, 3566 LDB_SCOPE_BASE, 3567 "(objectClass=*)", 3568 attrs, 3569 NULL, 3570 ac, 3571 samldb_rename_search_base_callback, 3572 req); 3573 LDB_REQ_SET_LOCATION(search_req); 3574 if (ret != LDB_SUCCESS) { 3575 return ret; 3576 } 3577 3578 ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID, 3579 true, NULL); 3580 if (ret != LDB_SUCCESS) { 3581 return ret; 3582 } 3583 3584 return ldb_next_request(ac->module, search_req); 2134 3585 } 2135 3586 … … 2173 3624 .modify = samldb_modify, 2174 3625 .del = samldb_delete, 3626 .rename = samldb_rename, 2175 3627 .extended = samldb_extended 2176 3628 }; -
vendor/current/source4/dsdb/samdb/ldb_modules/schema_data.c
r740 r988 140 140 const char *oid_attr = NULL; 141 141 const char *oid = NULL; 142 struct ldb_dn *parent_dn = NULL; 143 int cmp; 142 144 WERROR status; 143 bool rodc; 144 int ret; 145 bool rodc = false; 146 int ret; 147 struct schema_data_private_data *mc; 148 mc = talloc_get_type(ldb_module_get_private(module), struct schema_data_private_data); 145 149 146 150 ldb = ldb_module_get_ctx(module); … … 169 173 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 170 174 "schema_data_add: we are not master: reject request\n"); 175 return LDB_ERR_UNWILLING_TO_PERFORM; 176 } 177 178 if (!schema->fsmo.update_allowed && !rodc) { 179 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 180 "schema_data_add: updates are not allowed: reject request\n"); 181 return LDB_ERR_UNWILLING_TO_PERFORM; 182 } 183 184 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) { 185 /* 186 * the provision code needs to create 187 * the schema root object. 188 */ 189 cmp = ldb_dn_compare(req->op.add.message->dn, mc->schema_dn); 190 if (cmp == 0) { 191 return ldb_next_request(module, req); 192 } 193 } 194 195 parent_dn = ldb_dn_get_parent(req, req->op.add.message->dn); 196 if (!parent_dn) { 197 return ldb_oom(ldb); 198 } 199 200 cmp = ldb_dn_compare(parent_dn, mc->schema_dn); 201 if (cmp != 0) { 202 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 203 "schema_data_add: no direct child :%s\n", 204 ldb_dn_get_linearized(req->op.add.message->dn)); 171 205 return LDB_ERR_UNWILLING_TO_PERFORM; 172 206 } … … 212 246 } 213 247 248 static int schema_data_modify(struct ldb_module *module, struct ldb_request *req) 249 { 250 struct ldb_context *ldb; 251 struct dsdb_schema *schema; 252 int cmp; 253 bool rodc = false; 254 int ret; 255 struct ldb_control *sd_propagation_control; 256 struct schema_data_private_data *mc; 257 mc = talloc_get_type(ldb_module_get_private(module), struct schema_data_private_data); 258 259 ldb = ldb_module_get_ctx(module); 260 261 /* special objects should always go through */ 262 if (ldb_dn_is_special(req->op.mod.message->dn)) { 263 return ldb_next_request(module, req); 264 } 265 266 /* replicated update should always go through */ 267 if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) { 268 return ldb_next_request(module, req); 269 } 270 271 /* dbcheck should be able to fix things */ 272 if (ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) { 273 return ldb_next_request(module, req); 274 } 275 276 sd_propagation_control = ldb_request_get_control(req, 277 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID); 278 if (sd_propagation_control != NULL) { 279 if (req->op.mod.message->num_elements != 1) { 280 return ldb_module_operr(module); 281 } 282 ret = strcmp(req->op.mod.message->elements[0].name, 283 "nTSecurityDescriptor"); 284 if (ret != 0) { 285 return ldb_module_operr(module); 286 } 287 288 return ldb_next_request(module, req); 289 } 290 291 schema = dsdb_get_schema(ldb, req); 292 if (!schema) { 293 return ldb_next_request(module, req); 294 } 295 296 cmp = ldb_dn_compare(req->op.mod.message->dn, mc->schema_dn); 297 if (cmp == 0) { 298 static const char * const constrained_attrs[] = { 299 "schemaInfo", 300 "prefixMap", 301 "msDs-Schema-Extensions", 302 "msDS-IntId", 303 NULL 304 }; 305 size_t i; 306 struct ldb_message_element *el; 307 308 if (ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID)) { 309 return ldb_next_request(module, req); 310 } 311 312 for (i=0; constrained_attrs[i]; i++) { 313 el = ldb_msg_find_element(req->op.mod.message, 314 constrained_attrs[i]); 315 if (el == NULL) { 316 continue; 317 } 318 319 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 320 "schema_data_modify: reject update " 321 "of attribute[%s]\n", 322 constrained_attrs[i]); 323 return LDB_ERR_CONSTRAINT_VIOLATION; 324 } 325 326 return ldb_next_request(module, req); 327 } 328 329 ret = samdb_rodc(ldb, &rodc); 330 if (ret != LDB_SUCCESS) { 331 DEBUG(4, (__location__ ": unable to tell if we are an RODC \n")); 332 } 333 334 if (!schema->fsmo.we_are_master && !rodc) { 335 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 336 "schema_data_modify: we are not master: reject request\n"); 337 return LDB_ERR_UNWILLING_TO_PERFORM; 338 } 339 340 if (!schema->fsmo.update_allowed && !rodc) { 341 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 342 "schema_data_modify: updates are not allowed: reject request\n"); 343 return LDB_ERR_UNWILLING_TO_PERFORM; 344 } 345 346 return ldb_next_request(module, req); 347 } 348 349 static int schema_data_del(struct ldb_module *module, struct ldb_request *req) 350 { 351 struct ldb_context *ldb; 352 struct dsdb_schema *schema; 353 bool rodc = false; 354 int ret; 355 356 ldb = ldb_module_get_ctx(module); 357 358 /* special objects should always go through */ 359 if (ldb_dn_is_special(req->op.del.dn)) { 360 return ldb_next_request(module, req); 361 } 362 363 /* replicated update should always go through */ 364 if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) { 365 return ldb_next_request(module, req); 366 } 367 368 /* dbcheck should be able to fix things */ 369 if (ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) { 370 return ldb_next_request(module, req); 371 } 372 373 schema = dsdb_get_schema(ldb, req); 374 if (!schema) { 375 return ldb_next_request(module, req); 376 } 377 378 ret = samdb_rodc(ldb, &rodc); 379 if (ret != LDB_SUCCESS) { 380 DEBUG(4, (__location__ ": unable to tell if we are an RODC \n")); 381 } 382 383 if (!schema->fsmo.we_are_master && !rodc) { 384 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 385 "schema_data_modify: we are not master: reject request\n"); 386 return LDB_ERR_UNWILLING_TO_PERFORM; 387 } 388 389 /* 390 * normaly the DACL will prevent delete 391 * with LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS 392 * above us. 393 */ 394 ldb_debug_set(ldb, LDB_DEBUG_ERROR, 395 "schema_data_del: delete is not allowed in the schema\n"); 396 return LDB_ERR_UNWILLING_TO_PERFORM; 397 } 398 214 399 static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg, 215 400 const struct dsdb_schema *schema) … … 219 404 220 405 for (sclass = schema->classes; sclass; sclass = sclass->next) { 221 ret = ldb_msg_add_string(msg, "objectClasses", schema_class_to_description(msg, sclass)); 406 char *v = schema_class_to_description(msg, sclass); 407 if (v == NULL) { 408 return ldb_oom(ldb); 409 } 410 ret = ldb_msg_add_steal_string(msg, "objectClasses", v); 222 411 if (ret != LDB_SUCCESS) { 223 412 return ret; … … 231 420 const struct dsdb_attribute *attribute; 232 421 int ret; 233 422 234 423 for (attribute = schema->attributes; attribute; attribute = attribute->next) { 235 ret = ldb_msg_add_string(msg, "attributeTypes", schema_attribute_to_description(msg, attribute)); 424 char *v = schema_attribute_to_description(msg, attribute); 425 if (v == NULL) { 426 return ldb_oom(ldb); 427 } 428 ret = ldb_msg_add_steal_string(msg, "attributeTypes", v); 236 429 if (ret != LDB_SUCCESS) { 237 430 return ret; … … 275 468 } 276 469 277 ret = ldb_msg_add_st ring(msg, "extendedAttributeInfo", val);470 ret = ldb_msg_add_steal_string(msg, "extendedAttributeInfo", val); 278 471 if (ret != LDB_SUCCESS) { 279 472 return ret; … … 297 490 } 298 491 299 ret = ldb_msg_add_st ring(msg, "extendedClassInfo", val);492 ret = ldb_msg_add_steal_string(msg, "extendedClassInfo", val); 300 493 if (ret != LDB_SUCCESS) { 301 494 return ret; … … 335 528 336 529 for (i=0;possibleInferiors[i];i++) { 337 ret = ldb_msg_add_string(msg, "possibleInferiors", possibleInferiors[i]); 530 char *v = talloc_strdup(msg, possibleInferiors[i]); 531 if (v == NULL) { 532 return ldb_oom(ldb); 533 } 534 ret = ldb_msg_add_steal_string(msg, "possibleInferiors", v); 338 535 if (ret != LDB_SUCCESS) { 339 536 return ret; … … 481 678 .init_context = schema_data_init, 482 679 .add = schema_data_add, 680 .modify = schema_data_modify, 681 .del = schema_data_del, 483 682 .search = schema_data_search 484 683 }; -
vendor/current/source4/dsdb/samdb/ldb_modules/schema_load.c
r740 r988 30 30 #include "librpc/gen_ndr/ndr_drsblobs.h" 31 31 #include "param/param.h" 32 #include <tdb.h> 33 #include "lib/tdb_wrap/tdb_wrap.h" 32 34 #include "dsdb/samdb/ldb_modules/util.h" 33 35 36 #include "system/filesys.h" 34 37 struct schema_load_private_data { 35 38 bool in_transaction; 39 struct tdb_wrap *metadata; 36 40 }; 37 41 38 static int dsdb_schema_from_db(struct ldb_module *module, struct ldb_dn *schema_dn, uint64_t current_usn, 42 static int dsdb_schema_from_db(struct ldb_module *module, 43 TALLOC_CTX *mem_ctx, 44 uint64_t current_usn, 45 uint64_t schema_seq_num, 39 46 struct dsdb_schema **schema); 40 47 41 struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct dsdb_schema *schema, bool is_global_schema) 42 { 43 uint64_t current_usn; 48 /* 49 * Open sam.ldb.d/metadata.tdb. 50 */ 51 static int schema_metadata_open(struct ldb_module *module) 52 { 53 struct schema_load_private_data *data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data); 54 struct ldb_context *ldb = ldb_module_get_ctx(module); 55 TALLOC_CTX *tmp_ctx; 56 struct loadparm_context *lp_ctx; 57 const char *sam_name; 58 char *filename; 59 int open_flags; 60 struct stat statbuf; 61 62 if (!data) { 63 return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR, 64 "schema_load: metadata not initialized"); 65 } 66 data->metadata = NULL; 67 68 tmp_ctx = talloc_new(NULL); 69 if (tmp_ctx == NULL) { 70 return ldb_module_oom(module); 71 } 72 73 sam_name = (const char *)ldb_get_opaque(ldb, "ldb_url"); 74 if (!sam_name) { 75 talloc_free(tmp_ctx); 76 return ldb_operr(ldb); 77 } 78 if (strncmp("tdb://", sam_name, 6) == 0) { 79 sam_name += 6; 80 } 81 filename = talloc_asprintf(tmp_ctx, "%s.d/metadata.tdb", sam_name); 82 if (!filename) { 83 talloc_free(tmp_ctx); 84 return ldb_oom(ldb); 85 } 86 87 open_flags = O_RDWR; 88 if (stat(filename, &statbuf) != 0) { 89 talloc_free(tmp_ctx); 90 return LDB_ERR_OPERATIONS_ERROR; 91 } 92 93 lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"), 94 struct loadparm_context); 95 96 data->metadata = tdb_wrap_open(data, filename, 10, 97 lpcfg_tdb_flags(lp_ctx, TDB_DEFAULT), 98 open_flags, 0660); 99 if (data->metadata == NULL) { 100 talloc_free(tmp_ctx); 101 return LDB_ERR_OPERATIONS_ERROR; 102 } 103 104 talloc_free(tmp_ctx); 105 return LDB_SUCCESS; 106 } 107 108 static int schema_metadata_get_uint64(struct ldb_module *module, 109 const char *key, uint64_t *value, 110 uint64_t default_value) 111 { 112 struct schema_load_private_data *data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data); 113 struct tdb_context *tdb; 114 TDB_DATA tdb_key, tdb_data; 115 char *value_str; 116 TALLOC_CTX *tmp_ctx; 117 118 if (!data || !data->metadata) { 119 *value = default_value; 120 return LDB_SUCCESS; 121 } 122 123 tmp_ctx = talloc_new(NULL); 124 if (tmp_ctx == NULL) { 125 return ldb_module_oom(module); 126 } 127 128 tdb = data->metadata->tdb; 129 130 tdb_key.dptr = (uint8_t *)discard_const_p(char, key); 131 tdb_key.dsize = strlen(key); 132 133 tdb_data = tdb_fetch(tdb, tdb_key); 134 if (!tdb_data.dptr) { 135 if (tdb_error(tdb) == TDB_ERR_NOEXIST) { 136 *value = default_value; 137 talloc_free(tmp_ctx); 138 return LDB_SUCCESS; 139 } else { 140 talloc_free(tmp_ctx); 141 return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR, 142 tdb_errorstr(tdb)); 143 } 144 } 145 146 value_str = talloc_strndup(tmp_ctx, (char *)tdb_data.dptr, tdb_data.dsize); 147 if (value_str == NULL) { 148 SAFE_FREE(tdb_data.dptr); 149 talloc_free(tmp_ctx); 150 return ldb_module_oom(module); 151 } 152 153 *value = strtoull(value_str, NULL, 10); 154 155 SAFE_FREE(tdb_data.dptr); 156 talloc_free(tmp_ctx); 157 158 return LDB_SUCCESS; 159 } 160 161 static struct dsdb_schema *dsdb_schema_refresh(struct ldb_module *module, struct tevent_context *ev, 162 struct dsdb_schema *schema, bool is_global_schema) 163 { 164 TALLOC_CTX *mem_ctx; 165 uint64_t current_usn, schema_seq_num = 0; 44 166 int ret; 45 struct ldb_result *res;46 struct ldb_request *treq;47 struct ldb_seqnum_request *tseq;48 struct ldb_seqnum_result *tseqr;49 struct dsdb_control_current_partition *ctrl;50 167 struct ldb_context *ldb = ldb_module_get_ctx(module); 51 168 struct dsdb_schema *new_schema; 169 struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb); 170 time_t ts, lastts; 52 171 53 172 struct schema_load_private_data *private_data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data); … … 62 181 } 63 182 64 res = talloc_zero(schema, struct ldb_result); 65 if (res == NULL) { 183 SMB_ASSERT(ev == ldb_get_event_context(ldb)); 184 185 mem_ctx = talloc_new(module); 186 if (mem_ctx == NULL) { 66 187 return NULL; 67 188 } 68 tseq = talloc_zero(res, struct ldb_seqnum_request); 69 if (tseq == NULL) { 70 talloc_free(res); 71 return NULL; 72 } 73 tseq->type = LDB_SEQ_HIGHEST_SEQ; 74 75 ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res, 76 LDB_EXTENDED_SEQUENCE_NUMBER, 77 tseq, 78 NULL, 79 res, 80 ldb_extended_default_callback, 81 NULL); 82 LDB_REQ_SET_LOCATION(treq); 189 190 /* 191 * We update right now the last refresh timestamp so that if 192 * the schema partition hasn't change we don't keep on retrying. 193 * Otherwise if the timestamp was update only when the schema has 194 * actually changed (and therefor completely reloaded) we would 195 * continue to hit the database to get the highest USN. 196 */ 197 198 ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &schema_seq_num, 0); 199 200 if (schema != NULL) { 201 lastts = schema->last_refresh; 202 ts = time(NULL); 203 if (lastts > (ts - schema->refresh_interval)) { 204 DEBUG(11, ("Less than %d seconds since last reload, " 205 "returning cached version ts = %d\n", 206 (int)schema->refresh_interval, 207 (int)lastts)); 208 TALLOC_FREE(mem_ctx); 209 return schema; 210 } 211 212 if (ret == LDB_SUCCESS) { 213 schema->metadata_usn = schema_seq_num; 214 } else { 215 /* From an old provision it can happen that the tdb didn't exists yet */ 216 DEBUG(0, ("Error while searching for the schema usn in the metadata ignoring: %d:%s:%s\n", 217 ret, ldb_strerror(ret), ldb_errstring(ldb))); 218 schema->metadata_usn = 0; 219 } 220 schema->last_refresh = ts; 221 222 } 223 224 ret = dsdb_module_load_partition_usn(module, schema_dn, ¤t_usn, NULL, NULL); 225 if (ret != LDB_SUCCESS || (schema && (current_usn == schema->loaded_usn))) { 226 TALLOC_FREE(mem_ctx); 227 return schema; 228 } 229 230 ret = dsdb_schema_from_db(module, mem_ctx, current_usn, schema_seq_num, &new_schema); 83 231 if (ret != LDB_SUCCESS) { 84 talloc_free(res); 85 return NULL; 86 } 87 88 ctrl = talloc(treq, struct dsdb_control_current_partition); 89 if (!ctrl) { 90 talloc_free(res); 91 return NULL; 92 } 93 ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION; 94 ctrl->dn = schema->base_dn; 95 96 ret = ldb_request_add_control(treq, 97 DSDB_CONTROL_CURRENT_PARTITION_OID, 98 false, ctrl); 232 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 233 "dsdb_schema_from_db() failed: %d:%s: %s", 234 ret, ldb_strerror(ret), ldb_errstring(ldb)); 235 TALLOC_FREE(mem_ctx); 236 return schema; 237 } 238 239 ret = dsdb_set_schema(ldb, new_schema); 99 240 if (ret != LDB_SUCCESS) { 100 talloc_free(res); 101 return NULL; 102 } 103 104 ret = ldb_next_request(module, treq); 105 if (ret != LDB_SUCCESS) { 106 talloc_free(res); 107 return NULL; 108 } 109 ret = ldb_wait(treq->handle, LDB_WAIT_ALL); 110 if (ret != LDB_SUCCESS) { 111 talloc_free(res); 112 return NULL; 113 } 114 tseqr = talloc_get_type(res->extended->data, 115 struct ldb_seqnum_result); 116 if (tseqr->seq_num == schema->reload_seq_number) { 117 talloc_free(res); 241 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 242 "dsdb_set_schema() failed: %d:%s: %s", 243 ret, ldb_strerror(ret), ldb_errstring(ldb)); 244 TALLOC_FREE(mem_ctx); 118 245 return schema; 119 246 } 120 121 schema->reload_seq_number = tseqr->seq_num;122 talloc_free(res);123 124 ret = dsdb_module_load_partition_usn(module, schema->base_dn, ¤t_usn, NULL, NULL);125 if (ret != LDB_SUCCESS || current_usn == schema->loaded_usn) {126 return schema;127 }128 129 ret = dsdb_schema_from_db(module, schema->base_dn, current_usn, &new_schema);130 if (ret != LDB_SUCCESS) {131 return schema;132 }133 134 247 if (is_global_schema) { 135 248 dsdb_make_schema_global(ldb, new_schema); 136 249 } 250 TALLOC_FREE(mem_ctx); 137 251 return new_schema; 138 252 } … … 143 257 */ 144 258 145 static int dsdb_schema_from_db(struct ldb_module *module, struct ldb_dn *schema_dn, uint64_t current_usn, 259 static int dsdb_schema_from_db(struct ldb_module *module, 260 TALLOC_CTX *mem_ctx, 261 uint64_t current_usn, 262 uint64_t schema_seq_num, 146 263 struct dsdb_schema **schema) 147 264 { … … 150 267 char *error_string; 151 268 int ret; 269 struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb); 152 270 struct ldb_result *schema_res; 153 struct ldb_result *a_res; 154 struct ldb_result *c_res; 271 struct ldb_result *res; 155 272 static const char *schema_attrs[] = { 156 273 "prefixMap", … … 191 308 * load the attribute definitions 192 309 */ 193 ret = dsdb_module_search(module, tmp_ctx, &a_res, 194 schema_dn, LDB_SCOPE_ONELEVEL, NULL, 195 DSDB_FLAG_NEXT_MODULE, 196 NULL, 197 "(objectClass=attributeSchema)"); 198 if (ret != LDB_SUCCESS) { 199 ldb_asprintf_errstring(ldb, 200 "dsdb_schema: failed to search attributeSchema objects: %s", 201 ldb_errstring(ldb)); 202 goto failed; 203 } 204 205 /* 206 * load the objectClass definitions 207 */ 208 ret = dsdb_module_search(module, tmp_ctx, &c_res, 310 ret = dsdb_module_search(module, tmp_ctx, &res, 209 311 schema_dn, LDB_SCOPE_ONELEVEL, NULL, 210 312 DSDB_FLAG_NEXT_MODULE | 211 313 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, 212 314 NULL, 213 "( objectClass=classSchema)");315 "(|(objectClass=attributeSchema)(objectClass=classSchema))"); 214 316 if (ret != LDB_SUCCESS) { 215 317 ldb_asprintf_errstring(ldb, 216 "dsdb_schema: failed to search classSchema objects: %s",318 "dsdb_schema: failed to search attributeSchema and classSchema objects: %s", 217 319 ldb_errstring(ldb)); 218 320 goto failed; … … 220 322 221 323 ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb, 222 schema_res, a_res, c_res, schema, &error_string);324 schema_res, res, schema, &error_string); 223 325 if (ret != LDB_SUCCESS) { 224 326 ldb_asprintf_errstring(ldb, … … 228 330 } 229 331 230 (*schema)->refresh_in_progress = true; 231 232 /* If we have the readOnlySchema opaque, then don't check for 233 * runtime schema updates, as they are not permitted (we would 234 * have to update the backend server schema too */ 235 if (!ldb_get_opaque(ldb, "readOnlySchema")) { 236 (*schema)->refresh_fn = dsdb_schema_refresh; 237 (*schema)->loaded_from_module = module; 238 (*schema)->loaded_usn = current_usn; 239 } 240 241 /* "dsdb_set_schema()" steals schema into the ldb_context */ 242 ret = dsdb_set_schema(ldb, (*schema)); 243 244 (*schema)->refresh_in_progress = false; 245 246 if (ret != LDB_SUCCESS) { 247 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 248 "schema_load_init: dsdb_set_schema() failed: %d:%s: %s", 249 ret, ldb_strerror(ret), ldb_errstring(ldb)); 250 goto failed; 251 } 252 253 /* Ensure this module won't go away before the callback */ 254 if (talloc_reference(*schema, ldb) == NULL) { 255 ldb_oom(ldb); 256 ret = LDB_ERR_OPERATIONS_ERROR; 257 } 332 (*schema)->loaded_usn = current_usn; 333 (*schema)->metadata_usn = schema_seq_num; 334 (*schema)->last_refresh = time(NULL); 335 336 talloc_steal(mem_ctx, *schema); 258 337 259 338 failed: … … 270 349 { 271 350 struct schema_load_private_data *private_data; 351 struct ldb_context *ldb = ldb_module_get_ctx(module); 272 352 struct dsdb_schema *schema; 273 struct ldb_context *ldb = ldb_module_get_ctx(module);353 void *readOnlySchema; 274 354 int ret; 275 uint64_t current_usn;276 struct ldb_dn *schema_dn;277 355 278 356 private_data = talloc_zero(module, struct schema_load_private_data); … … 288 366 } 289 367 290 if (dsdb_get_schema(ldb, NULL)) { 368 schema = dsdb_get_schema(ldb, NULL); 369 370 /* We might already have a schema */ 371 if (schema != NULL) { 372 /* Hook up the refresh function */ 373 if (dsdb_uses_global_schema(ldb)) { 374 ret = dsdb_set_schema_refresh_function(ldb, dsdb_schema_refresh, module); 375 376 if (ret != LDB_SUCCESS) { 377 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 378 "schema_load_init: dsdb_set_schema_refresh_fns() failed: %d:%s: %s", 379 ret, ldb_strerror(ret), ldb_errstring(ldb)); 380 return ret; 381 } 382 } 383 291 384 return LDB_SUCCESS; 292 385 } 293 386 294 schema_dn = ldb_get_schema_basedn(ldb); 295 if (!schema_dn) { 296 ldb_reset_err_string(ldb); 297 ldb_debug(ldb, LDB_DEBUG_WARNING, 298 "schema_load_init: no schema dn present: (skip schema loading)\n"); 299 return LDB_SUCCESS; 300 } 301 302 ret = dsdb_module_load_partition_usn(module, schema_dn, ¤t_usn, NULL, NULL); 303 if (ret != LDB_SUCCESS) { 304 /* Ignore the error and just reload the DB more often */ 305 current_usn = 0; 306 } 307 308 return dsdb_schema_from_db(module, schema_dn, current_usn, &schema); 309 } 310 311 static int schema_load_start_transaction(struct ldb_module *module) 312 { 387 readOnlySchema = ldb_get_opaque(ldb, "readOnlySchema"); 388 389 /* If we have the readOnlySchema opaque, then don't check for 390 * runtime schema updates, as they are not permitted (we would 391 * have to update the backend server schema too */ 392 if (readOnlySchema != NULL) { 393 struct dsdb_schema *new_schema; 394 ret = dsdb_schema_from_db(module, private_data, 0, 0, &new_schema); 395 if (ret != LDB_SUCCESS) { 396 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 397 "schema_load_init: dsdb_schema_from_db() failed: %d:%s: %s", 398 ret, ldb_strerror(ret), ldb_errstring(ldb)); 399 return ret; 400 } 401 402 /* "dsdb_set_schema()" steals schema into the ldb_context */ 403 ret = dsdb_set_schema(ldb, new_schema); 404 if (ret != LDB_SUCCESS) { 405 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 406 "schema_load_init: dsdb_set_schema() failed: %d:%s: %s", 407 ret, ldb_strerror(ret), ldb_errstring(ldb)); 408 return ret; 409 } 410 411 } else { 412 ret = dsdb_set_schema_refresh_function(ldb, dsdb_schema_refresh, module); 413 414 if (ret != LDB_SUCCESS) { 415 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 416 "schema_load_init: dsdb_set_schema_refresh_fns() failed: %d:%s: %s", 417 ret, ldb_strerror(ret), ldb_errstring(ldb)); 418 return ret; 419 } 420 } 421 422 schema = dsdb_get_schema(ldb, NULL); 423 424 /* We do this, invoking the refresh handler, so we know that it works */ 425 if (schema == NULL) { 426 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 427 "schema_load_init: dsdb_get_schema failed"); 428 return LDB_ERR_OPERATIONS_ERROR; 429 } 430 431 return ret; 432 } 433 434 static int schema_search(struct ldb_module *module, struct ldb_request *req) 435 { 436 struct dsdb_schema *schema; 437 struct ldb_context *ldb = ldb_module_get_ctx(module); 438 uint64_t value; 439 int ret; 313 440 struct schema_load_private_data *private_data = 314 441 talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data); 315 442 316 private_data->in_transaction = true; 317 318 return ldb_next_start_trans(module); 319 } 320 321 static int schema_load_end_transaction(struct ldb_module *module) 443 schema = dsdb_get_schema(ldb, NULL); 444 if (schema && private_data && !private_data->in_transaction) { 445 ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &value, 0); 446 if (ret == LDB_SUCCESS && schema->metadata_usn < value) { 447 /* The usn of the schema was changed in the metadata, 448 * this indicate that another process has modified the schema and 449 * that a reload is needed. 450 */ 451 schema->last_refresh = 0; 452 schema = dsdb_get_schema(ldb, NULL); 453 } 454 } 455 456 return ldb_next_request(module, req); 457 } 458 459 static int schema_load_start_transaction(struct ldb_module *module) 322 460 { 323 461 struct schema_load_private_data *private_data = 324 462 talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data); 325 326 private_data->in_transaction = false; 327 328 return ldb_next_end_trans(module); 329 } 330 331 static int schema_load_del_transaction(struct ldb_module *module) 463 struct dsdb_schema *schema; 464 struct ldb_context *ldb = ldb_module_get_ctx(module); 465 uint64_t value; 466 int ret; 467 468 schema = dsdb_get_schema(ldb, NULL); 469 if (!private_data->metadata) { 470 schema_metadata_open(module); 471 } 472 ret = schema_metadata_get_uint64(module, DSDB_METADATA_SCHEMA_SEQ_NUM, &value, 0); 473 if (ret == LDB_SUCCESS && schema->metadata_usn < value) { 474 /* The usn of the schema was changed in the metadata, 475 * this indicate that another process has modified the schema and 476 * that a reload is needed. 477 */ 478 schema->last_refresh = 0; 479 schema = dsdb_get_schema(ldb, NULL); 480 } 481 private_data->in_transaction = true; 482 483 return ldb_next_start_trans(module); 484 } 485 486 static int schema_load_end_transaction(struct ldb_module *module) 332 487 { 333 488 struct schema_load_private_data *private_data = … … 336 491 private_data->in_transaction = false; 337 492 493 return ldb_next_end_trans(module); 494 } 495 496 static int schema_load_del_transaction(struct ldb_module *module) 497 { 498 struct schema_load_private_data *private_data = 499 talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data); 500 501 private_data->in_transaction = false; 502 338 503 return ldb_next_del_trans(module); 339 504 } … … 341 506 static int schema_load_extended(struct ldb_module *module, struct ldb_request *req) 342 507 { 343 struct ldb_context *ldb;344 345 ldb = ldb_module_get_ctx(module);508 time_t *lastts; 509 struct ldb_context *ldb = ldb_module_get_ctx(module); 510 struct dsdb_schema *schema; 346 511 347 512 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) { 348 513 return ldb_next_request(module, req); 349 514 } 350 351 /* This is a no-op. We reload as soon as we can */ 352 return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); 515 lastts = (time_t *)ldb_get_opaque(ldb, DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME); 516 if (!lastts) { 517 lastts = talloc(ldb, time_t); 518 } 519 schema = dsdb_get_schema(ldb, NULL); 520 /* Force a refresh */ 521 schema->last_refresh = 0; 522 *lastts = 0; 523 ldb_set_opaque(ldb, DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME, lastts); 524 525 /* Pass to next module, the partition one should finish the chain */ 526 return ldb_next_request(module, req); 353 527 } 354 528 … … 358 532 .init_context = schema_load_init, 359 533 .extended = schema_load_extended, 534 .search = schema_search, 360 535 .start_transaction = schema_load_start_transaction, 361 536 .end_transaction = schema_load_end_transaction, -
vendor/current/source4/dsdb/samdb/ldb_modules/schema_util.c
r740 r988 144 144 { 145 145 int ldb_err; 146 struct ldb_message *msg ;146 struct ldb_message *msg = NULL; 147 147 TALLOC_CTX *temp_ctx; 148 148 … … 241 241 temp_ctx = talloc_new(ldb_module); 242 242 if (temp_ctx == NULL) { 243 return ldb_module_oom( temp_ctx);243 return ldb_module_oom(ldb_module); 244 244 } 245 245 -
vendor/current/source4/dsdb/samdb/ldb_modules/show_deleted.c
r740 r988 37 37 #include "dsdb/samdb/ldb_modules/util.h" 38 38 39 struct show_deleted_state { 40 bool need_refresh; 41 bool recycle_bin_enabled; 42 }; 43 39 44 static int show_deleted_search(struct ldb_module *module, struct ldb_request *req) 40 45 { … … 43 48 struct ldb_request *down_req; 44 49 struct ldb_parse_tree *new_tree = req->op.search.tree; 50 struct show_deleted_state *state; 45 51 int ret; 52 const char *attr_filter = NULL; 46 53 47 54 ldb = ldb_module_get_ctx(module); 55 56 state = talloc_get_type(ldb_module_get_private(module), struct show_deleted_state); 57 58 /* note that state may be NULL during initialisation */ 59 if (state != NULL && state->need_refresh) { 60 state->need_refresh = false; 61 ret = dsdb_recyclebin_enabled(module, &state->recycle_bin_enabled); 62 if (ret != LDB_SUCCESS) { 63 return ret; 64 } 65 } 66 67 /* This is the logic from MS-ADTS 3.1.1.3.4.1.14 that 68 determines if objects are visible 69 70 Extended control name Deleted-objects Tombstones Recycled-objects 71 LDAP_SERVER_SHOW_DELETED_OID Visible Visible Not Visible 72 LDAP_SERVER_SHOW_RECYCLED_OID Visible Visible Visible 73 74 Note that if the recycle bin is disabled, then the 75 isRecycled attribute is ignored, and objects are either 76 "normal" or "tombstone". 77 78 When the recycle bin is enabled, then objects are in one of 79 3 states, "normal", "deleted" or "recycled" 80 */ 48 81 49 82 /* check if there's a show deleted control */ … … 52 85 show_rec = ldb_request_get_control(req, LDB_CONTROL_SHOW_RECYCLED_OID); 53 86 54 if ((show_del == NULL) && (show_rec == NULL)) { 55 /* Here we have to suppress all deleted objects: 56 * MS-ADTS 3.1.1.3.4.1 57 * 58 * Filter: (&(!(isDeleted=TRUE))(...)) 87 88 if (state == NULL || !state->recycle_bin_enabled) { 89 /* when recycle bin is not enabled, then all we look 90 at is the isDeleted attribute. We hide objects with this 91 attribute set to TRUE when the client has not specified either 92 SHOW_DELETED or SHOW_RECYCLED 93 */ 94 if (show_del != NULL || show_rec != NULL) { 95 attr_filter = NULL; 96 } else { 97 attr_filter = "isDeleted"; 98 } 99 } else { 100 /* the recycle bin is enabled 59 101 */ 60 /* FIXME: we could use a constant tree here once we are sure 61 * that no ldb modules modify trees in-site */ 102 if (show_rec != NULL) { 103 attr_filter = NULL; 104 } else if (show_del != NULL) { 105 /* we want deleted but not recycled objects */ 106 attr_filter = "isRecycled"; 107 } else { 108 /* we don't want deleted or recycled objects, 109 * which we get by filtering on isDeleted */ 110 attr_filter = "isDeleted"; 111 } 112 } 113 114 115 if (attr_filter != NULL) { 62 116 new_tree = talloc(req, struct ldb_parse_tree); 63 117 if (!new_tree) { … … 79 133 } 80 134 new_tree->u.list.elements[0]->u.isnot.child->operation = LDB_OP_EQUALITY; 81 new_tree->u.list.elements[0]->u.isnot.child->u.equality.attr = "isDeleted";135 new_tree->u.list.elements[0]->u.isnot.child->u.equality.attr = attr_filter; 82 136 new_tree->u.list.elements[0]->u.isnot.child->u.equality.value = data_blob_string_const("TRUE"); 83 84 new_tree->u.list.elements[1] = req->op.search.tree;85 } else if ((show_del != NULL) && (show_rec == NULL)) {86 /* Here we need to suppress all recycled objects:87 * MS-ADTS 3.1.1.3.4.188 *89 * Filter: (&(!(isRecycled=TRUE))(...))90 */91 /* FIXME: we could use a constant tree here once we are sure92 * that no ldb modules modify trees in-site */93 new_tree = talloc(req, struct ldb_parse_tree);94 if (!new_tree) {95 return ldb_oom(ldb);96 }97 new_tree->operation = LDB_OP_AND;98 new_tree->u.list.num_elements = 2;99 new_tree->u.list.elements = talloc_array(new_tree, struct ldb_parse_tree *, 2);100 if (!new_tree->u.list.elements) {101 return ldb_oom(ldb);102 }103 104 new_tree->u.list.elements[0] = talloc(new_tree->u.list.elements, struct ldb_parse_tree);105 new_tree->u.list.elements[0]->operation = LDB_OP_NOT;106 new_tree->u.list.elements[0]->u.isnot.child =107 talloc(new_tree->u.list.elements, struct ldb_parse_tree);108 if (!new_tree->u.list.elements[0]->u.isnot.child) {109 return ldb_oom(ldb);110 }111 new_tree->u.list.elements[0]->u.isnot.child->operation = LDB_OP_EQUALITY;112 new_tree->u.list.elements[0]->u.isnot.child->u.equality.attr = "isRecycled";113 new_tree->u.list.elements[0]->u.isnot.child->u.equality.value = data_blob_string_const("TRUE");114 115 137 new_tree->u.list.elements[1] = req->op.search.tree; 116 138 } … … 145 167 struct ldb_context *ldb; 146 168 int ret; 169 struct show_deleted_state *state; 170 171 state = talloc_zero(module, struct show_deleted_state); 172 if (state == NULL) { 173 return ldb_module_oom(module); 174 } 175 state->need_refresh = true; 147 176 148 177 ldb = ldb_module_get_ctx(module); … … 162 191 } 163 192 164 return ldb_next_init(module); 193 ret = ldb_next_init(module); 194 195 ldb_module_set_private(module, state); 196 197 return ret; 165 198 } 166 199 -
vendor/current/source4/dsdb/samdb/ldb_modules/simple_dn.c
r740 r988 45 45 new_base = ldb_dn_copy(req, req->op.search.base); 46 46 if (!new_base) { 47 ldb_module_oom(module);47 return ldb_module_oom(module); 48 48 } 49 49 -
vendor/current/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c
r740 r988 34 34 #include "librpc/ndr/libndr.h" 35 35 #include "dsdb/samdb/samdb.h" 36 #include "dsdb/common/util.h" 36 37 #include <ldb_handlers.h> 37 38 … … 176 177 unsigned long long usn = strtoull((const char *)val->data, NULL, 10); 177 178 time_t t = (usn >> 24); 178 out = data_blob_string_const(talloc_asprintf(ctx, "%s#%06x#00#000000", ldb_timestring(ctx, t), (unsigned int)(usn & 0xFFFFFF))); 179 struct tm *tm = gmtime(&t); 180 /* CSN timestamp is YYYYMMDDhhmmss.ssssssZ */ 181 out = data_blob_string_const(talloc_asprintf(ctx, 182 "%04u%02u%02u%02u%02u%02u.000000Z#%06x#000#000000", 183 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, 184 tm->tm_hour, tm->tm_min, tm->tm_sec, 185 (unsigned int)(usn & 0xFFFFFF))); 179 186 return out; 180 187 } … … 362 369 { 363 370 .local_name = "distinguishedName", 364 .type = LDB_MAP_REN AME,371 .type = LDB_MAP_RENDROP, 365 372 .u = { 366 373 .rename = { … … 476 483 "usnChanged", 477 484 "memberOf", 485 "name", 486 "distinguishedName", 478 487 NULL 479 488 }; … … 822 831 int ret; 823 832 struct map_private *map_private; 824 struct entryuuid_private *entryuuid_private;825 833 unsigned long long seq_num = 0; 826 834 struct ldb_request *search_req; … … 842 850 843 851 map_private = talloc_get_type(ldb_module_get_private(module), struct map_private); 844 845 entryuuid_private = talloc_get_type(map_private->caller_private, struct entryuuid_private); 852 if (!map_private) { 853 ldb_debug_set(ldb, LDB_DEBUG_FATAL, 854 "private data is not of type struct map_private"); 855 return LDB_ERR_PROTOCOL_ERROR; 856 } 846 857 847 858 /* All this to get the DN of the parition, so we can search the right thing */ … … 903 914 break; 904 915 case LDB_SEQ_HIGHEST_TIMESTAMP: 905 { 906 seqr->seq_num = (seq_num >> 24); 907 break; 908 } 909 } 916 return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR, "LDB_SEQ_HIGHEST_TIMESTAMP not supported"); 917 } 918 910 919 seqr->flags = 0; 911 seqr->flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;912 920 seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE; 913 921 -
vendor/current/source4/dsdb/samdb/ldb_modules/subtree_delete.c
r740 r988 39 39 40 40 41 static int subtree_delete_sort(struct ldb_message **m1, 42 struct ldb_message **m2, 43 void *private_data) 44 { 45 struct ldb_dn *dn1 = (*m1)->dn; 46 struct ldb_dn *dn2 = (*m2)->dn; 47 48 /* 49 * This sorts in tree order, children first 50 */ 51 return ldb_dn_compare(dn1, dn2); 52 } 53 41 54 static int subtree_delete(struct ldb_module *module, struct ldb_request *req) 42 55 { … … 62 75 return ret; 63 76 } 64 if (res->count > 0) { 65 if (ldb_request_get_control(req, LDB_CONTROL_TREE_DELETE_OID) == NULL) { 66 /* Do not add any DN outputs to this error string! 67 * Some MMC consoles (eg release 2000) have a strange 68 * bug and prevent subtree deletes afterwards. */ 69 ldb_asprintf_errstring(ldb_module_get_ctx(module), 70 "subtree_delete: Unable to " 71 "delete a non-leaf node " 72 "(it has %u children)!", 73 res->count); 74 talloc_free(res); 75 return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF; 76 } 77 if (res->count == 0) { 78 talloc_free(res); 79 return ldb_next_request(module, req); 80 } 77 81 78 /* we need to start from the top since other LDB modules could 79 * enforce constraints (eg "objectclass" and "samldb" do so). */ 80 flags = DSDB_FLAG_TOP_MODULE | DSDB_TREE_DELETE; 81 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) { 82 flags |= DSDB_MODIFY_RELAX; 83 } 82 if (ldb_request_get_control(req, LDB_CONTROL_TREE_DELETE_OID) == NULL) { 83 /* Do not add any DN outputs to this error string! 84 * Some MMC consoles (eg release 2000) have a strange 85 * bug and prevent subtree deletes afterwards. */ 86 ldb_asprintf_errstring(ldb_module_get_ctx(module), 87 "subtree_delete: Unable to " 88 "delete a non-leaf node " 89 "(it has %u children)!", 90 res->count); 91 talloc_free(res); 92 return LDB_ERR_NOT_ALLOWED_ON_NON_LEAF; 93 } 84 94 85 for (i = 0; i < res->count; i++) { 86 ret = dsdb_module_del(module, res->msgs[i]->dn, flags, req); 87 if (ret != LDB_SUCCESS) { 88 return ret; 89 } 95 /* 96 * First we sort the results from the leaf to the root 97 */ 98 LDB_TYPESAFE_QSORT(res->msgs, res->count, NULL, 99 subtree_delete_sort); 100 101 /* 102 * we need to start from the top since other LDB modules could 103 * enforce constraints (eg "objectclass" and "samldb" do so). 104 * 105 * We pass DSDB_FLAG_AS_SYSTEM as the acl module above us 106 * has already checked for SEC_ADS_DELETE_TREE. 107 */ 108 flags = DSDB_FLAG_TOP_MODULE | 109 DSDB_FLAG_AS_SYSTEM | 110 DSDB_FLAG_TRUSTED | 111 DSDB_TREE_DELETE; 112 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID) != NULL) { 113 flags |= DSDB_MODIFY_RELAX; 114 } 115 116 for (i = 0; i < res->count; i++) { 117 ret = dsdb_module_del(module, res->msgs[i]->dn, flags, req); 118 if (ret != LDB_SUCCESS) { 119 return ret; 90 120 } 91 121 } 122 92 123 talloc_free(res); 93 124 -
vendor/current/source4/dsdb/samdb/ldb_modules/subtree_rename.c
r740 r988 4 4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007 5 5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007 6 Copyright (C) Matthias Dieter Wallnöfer <mdw@samba.org> 2010-2011 6 7 7 8 This program is free software; you can redistribute it and/or modify … … 34 35 #include "libds/common/flags.h" 35 36 #include "dsdb/samdb/samdb.h" 36 37 struct subren_msg_store { 38 struct subren_msg_store *next; 39 struct ldb_dn *olddn; 40 struct ldb_dn *newdn; 41 }; 37 #include "dsdb/samdb/ldb_modules/util.h" 42 38 43 39 struct subtree_rename_context { 44 40 struct ldb_module *module; 45 41 struct ldb_request *req; 46 47 struct subren_msg_store *list;48 struct subren_msg_store *current;49 42 }; 50 43 … … 52 45 struct ldb_request *req) 53 46 { 54 struct ldb_context *ldb; 55 struct subtree_rename_context *ac; 56 57 ldb = ldb_module_get_ctx(module); 47 struct subtree_rename_context *ac; 48 58 49 59 50 ac = talloc_zero(req, struct subtree_rename_context); … … 68 59 } 69 60 70 static int subtree_rename_next_request(struct subtree_rename_context *ac);71 72 61 static int subtree_rename_callback(struct ldb_request *req, 73 62 struct ldb_reply *ares) … … 75 64 struct ldb_context *ldb; 76 65 struct subtree_rename_context *ac; 77 int ret;78 66 79 67 ac = talloc_get_type(req->context, struct subtree_rename_context); … … 95 83 96 84 if (ares->type != LDB_REPLY_DONE) { 97 ldb_ set_errstring(ldb, "Invalid reply type!\n");85 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type); 98 86 return ldb_module_done(ac->req, NULL, NULL, 99 87 LDB_ERR_OPERATIONS_ERROR); 100 88 } 101 89 102 if (ac->current == NULL) {103 /* this was the last one */104 return ldb_module_done(ac->req, ares->controls,105 ares->response, LDB_SUCCESS);106 }107 108 ret = subtree_rename_next_request(ac);109 if (ret != LDB_SUCCESS) {110 return ldb_module_done(ac->req, NULL, NULL, ret);111 }112 113 90 talloc_free(ares); 114 return LDB_SUCCESS; 115 } 116 117 static int subtree_rename_next_request(struct subtree_rename_context *ac) 118 { 119 struct ldb_context *ldb; 120 struct ldb_request *req; 91 return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS); 92 } 93 94 static int subtree_rename_search_onelevel_callback(struct ldb_request *req, 95 struct ldb_reply *ares) 96 { 97 struct subtree_rename_context *ac; 98 struct ldb_request *rename_req; 121 99 int ret; 122 100 123 ldb = ldb_module_get_ctx(ac->module);124 125 if (ac->current == NULL) {126 return ldb_operr(ldb);127 }128 129 ret = ldb_build_rename_req(&req, ldb, ac->current,130 ac->current->olddn,131 ac->current->newdn,132 ac->req->controls,133 ac, subtree_rename_callback,134 ac->req);135 LDB_REQ_SET_LOCATION(req);136 if (ret != LDB_SUCCESS) {137 return ret;138 }139 140 ac->current = ac->current->next;141 142 return ldb_next_request(ac->module, req);143 }144 145 static int check_constraints(struct ldb_message *msg,146 struct subtree_rename_context *ac,147 struct ldb_dn *olddn, struct ldb_dn *newdn)148 {149 struct ldb_context *ldb = ldb_module_get_ctx(ac->module);150 struct ldb_dn *dn1, *dn2, *nc_root;151 int32_t systemFlags;152 bool move_op = false;153 bool rename_op = false;154 int ret;155 156 /* Skip the checks if old and new DN are the same, or if we have the157 * relax control specified or if the returned objects is already158 * deleted and needs only to be moved for consistency. */159 160 if (ldb_dn_compare(olddn, newdn) == 0) {161 return LDB_SUCCESS;162 }163 if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) != NULL) {164 return LDB_SUCCESS;165 }166 if (ldb_msg_find_attr_as_bool(msg, "isDeleted", false)) {167 return LDB_SUCCESS;168 }169 170 /* Objects under CN=System */171 172 dn1 = ldb_dn_copy(ac, ldb_get_default_basedn(ldb));173 if (dn1 == NULL) return ldb_oom(ldb);174 175 if ( ! ldb_dn_add_child_fmt(dn1, "CN=System")) {176 talloc_free(dn1);177 return LDB_ERR_OPERATIONS_ERROR;178 }179 180 if ((ldb_dn_compare_base(dn1, olddn) == 0) &&181 (ldb_dn_compare_base(dn1, newdn) != 0)) {182 talloc_free(dn1);183 ldb_asprintf_errstring(ldb,184 "subtree_rename: Cannot move/rename %s. Objects under CN=System have to stay under it!",185 ldb_dn_get_linearized(olddn));186 return LDB_ERR_OTHER;187 }188 189 talloc_free(dn1);190 191 /* LSA objects */192 193 if ((samdb_find_attribute(ldb, msg, "objectClass", "secret") != NULL) ||194 (samdb_find_attribute(ldb, msg, "objectClass", "trustedDomain") != NULL)) {195 ldb_asprintf_errstring(ldb,196 "subtree_rename: Cannot move/rename %s. It's an LSA-specific object!",197 ldb_dn_get_linearized(olddn));198 return LDB_ERR_UNWILLING_TO_PERFORM;199 }200 201 /* systemFlags */202 203 dn1 = ldb_dn_get_parent(ac, olddn);204 if (dn1 == NULL) return ldb_oom(ldb);205 dn2 = ldb_dn_get_parent(ac, newdn);206 if (dn2 == NULL) return ldb_oom(ldb);207 208 if (ldb_dn_compare(dn1, dn2) == 0) {209 rename_op = true;210 } else {211 move_op = true;212 }213 214 talloc_free(dn1);215 talloc_free(dn2);216 217 systemFlags = ldb_msg_find_attr_as_int(msg, "systemFlags", 0);218 219 /* Fetch name context */220 221 ret = dsdb_find_nc_root(ldb, ac, olddn, &nc_root);222 if (ret != LDB_SUCCESS) {223 return ret;224 }225 226 if (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0) {227 if (move_op) {228 ldb_asprintf_errstring(ldb,229 "subtree_rename: Cannot move %s within schema partition",230 ldb_dn_get_linearized(olddn));231 return LDB_ERR_UNWILLING_TO_PERFORM;232 }233 if (rename_op &&234 (systemFlags & SYSTEM_FLAG_SCHEMA_BASE_OBJECT) != 0) {235 ldb_asprintf_errstring(ldb,236 "subtree_rename: Cannot rename %s within schema partition",237 ldb_dn_get_linearized(olddn));238 return LDB_ERR_UNWILLING_TO_PERFORM;239 }240 } else if (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) {241 if (move_op &&242 (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_MOVE) == 0) {243 /* Here we have to do more: control the244 * "ALLOW_LIMITED_MOVE" flag. This means that the245 * grand-grand-parents of two objects have to be equal246 * in order to perform the move (this is used for247 * moving "server" objects in the "sites" container). */248 bool limited_move =249 systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE;250 251 if (limited_move) {252 dn1 = ldb_dn_copy(ac, olddn);253 if (dn1 == NULL) return ldb_oom(ldb);254 dn2 = ldb_dn_copy(ac, newdn);255 if (dn2 == NULL) return ldb_oom(ldb);256 257 limited_move &= ldb_dn_remove_child_components(dn1, 3);258 limited_move &= ldb_dn_remove_child_components(dn2, 3);259 limited_move &= ldb_dn_compare(dn1, dn2) == 0;260 261 talloc_free(dn1);262 talloc_free(dn2);263 }264 265 if (!limited_move) {266 ldb_asprintf_errstring(ldb,267 "subtree_rename: Cannot move %s to %s in config partition",268 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));269 return LDB_ERR_UNWILLING_TO_PERFORM;270 }271 }272 if (rename_op &&273 (systemFlags & SYSTEM_FLAG_CONFIG_ALLOW_RENAME) == 0) {274 ldb_asprintf_errstring(ldb,275 "subtree_rename: Cannot rename %s to %s within config partition",276 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));277 return LDB_ERR_UNWILLING_TO_PERFORM;278 }279 } else if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) {280 if (move_op &&281 (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE) != 0) {282 ldb_asprintf_errstring(ldb,283 "subtree_rename: Cannot move %s to %s - DISALLOW_MOVE set",284 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));285 return LDB_ERR_UNWILLING_TO_PERFORM;286 }287 if (rename_op &&288 (systemFlags & SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME) != 0) {289 ldb_asprintf_errstring(ldb,290 "subtree_rename: Cannot rename %s to %s - DISALLOW_RENAME set",291 ldb_dn_get_linearized(olddn), ldb_dn_get_linearized(newdn));292 return LDB_ERR_UNWILLING_TO_PERFORM;293 }294 }295 296 talloc_free(nc_root);297 298 return LDB_SUCCESS;299 }300 301 static int subtree_rename_search_callback(struct ldb_request *req,302 struct ldb_reply *ares)303 {304 struct subren_msg_store *store;305 struct subtree_rename_context *ac;306 int ret;307 308 101 ac = talloc_get_type(req->context, struct subtree_rename_context); 309 102 310 if (!ares || !ac->current) {103 if (!ares) { 311 104 return ldb_module_done(ac->req, NULL, NULL, 312 105 LDB_ERR_OPERATIONS_ERROR); … … 319 112 switch (ares->type) { 320 113 case LDB_REPLY_ENTRY: 321 if (ldb_dn_compare(ares->message->dn, ac->list->olddn) == 0) { 322 /* this was already stored by the 323 * subtree_rename_search() */ 324 325 ret = check_constraints(ares->message, ac, 326 ac->list->olddn, 327 ac->list->newdn); 328 if (ret != LDB_SUCCESS) { 329 return ldb_module_done(ac->req, NULL, NULL, 330 ret); 331 } 332 333 talloc_free(ares); 334 return LDB_SUCCESS; 335 } 336 337 store = talloc_zero(ac, struct subren_msg_store); 338 if (store == NULL) { 114 { 115 struct ldb_dn *old_dn = ares->message->dn; 116 struct ldb_dn *new_dn = ldb_dn_copy(ares, old_dn); 117 if (!new_dn) { 118 return ldb_module_oom(ac->module); 119 } 120 121 if ( ! ldb_dn_remove_base_components(new_dn, 122 ldb_dn_get_comp_num(ac->req->op.rename.olddn))) { 339 123 return ldb_module_done(ac->req, NULL, NULL, 340 124 LDB_ERR_OPERATIONS_ERROR); 341 125 } 342 ac->current->next = store; 343 ac->current = store; 344 345 /* the first list element contains the base for the rename */ 346 store->olddn = talloc_steal(store, ares->message->dn); 347 store->newdn = ldb_dn_copy(store, store->olddn); 348 349 if ( ! ldb_dn_remove_base_components(store->newdn, 350 ldb_dn_get_comp_num(ac->list->olddn))) { 126 127 if ( ! ldb_dn_add_base(new_dn, ac->req->op.rename.newdn)) { 351 128 return ldb_module_done(ac->req, NULL, NULL, 352 129 LDB_ERR_OPERATIONS_ERROR); 353 130 } 354 355 if ( ! ldb_dn_add_base(store->newdn, ac->list->newdn)) { 356 return ldb_module_done(ac->req, NULL, NULL, 357 LDB_ERR_OPERATIONS_ERROR); 358 } 359 360 ret = check_constraints(ares->message, ac, 361 store->olddn, store->newdn); 131 ret = dsdb_module_rename(ac->module, old_dn, new_dn, DSDB_FLAG_OWN_MODULE, req); 362 132 if (ret != LDB_SUCCESS) { 363 return ldb_module_done(ac->req, NULL, NULL, ret); 364 } 365 366 break; 367 133 return ret; 134 } 135 136 talloc_free(ares); 137 138 return LDB_SUCCESS; 139 } 368 140 case LDB_REPLY_REFERRAL: 369 141 /* ignore */ … … 372 144 case LDB_REPLY_DONE: 373 145 374 /* rewind ac->current */ 375 ac->current = ac->list; 376 377 /* All dns set up, start with the first one */ 378 ret = subtree_rename_next_request(ac); 379 146 ret = ldb_build_rename_req(&rename_req, ldb_module_get_ctx(ac->module), ac, 147 ac->req->op.rename.olddn, 148 ac->req->op.rename.newdn, 149 ac->req->controls, 150 ac, subtree_rename_callback, 151 ac->req); 152 LDB_REQ_SET_LOCATION(req); 380 153 if (ret != LDB_SUCCESS) { 381 return ldb_module_done(ac->req, NULL, NULL, ret); 382 } 383 break; 384 } 385 386 talloc_free(ares); 154 return ret; 155 } 156 157 talloc_free(ares); 158 return ldb_next_request(ac->module, rename_req); 159 } 160 387 161 return LDB_SUCCESS; 388 162 } … … 392 166 { 393 167 struct ldb_context *ldb; 394 static const char * const attrs[] = { "objectClass", "systemFlags", 395 "isDeleted", NULL }; 168 static const char * const no_attrs[] = {NULL}; 396 169 struct ldb_request *search_req; 397 170 struct subtree_rename_context *ac; … … 418 191 } 419 192 420 /* add this entry as the first to do */ 421 ac->current = talloc_zero(ac, struct subren_msg_store); 422 if (ac->current == NULL) { 423 return ldb_oom(ldb); 424 } 425 ac->current->olddn = req->op.rename.olddn; 426 ac->current->newdn = req->op.rename.newdn; 427 ac->list = ac->current; 428 429 ret = ldb_build_search_req(&search_req, ldb, ac, 430 req->op.rename.olddn, 431 LDB_SCOPE_SUBTREE, 193 ret = ldb_build_search_req(&search_req, ldb_module_get_ctx(ac->module), ac, 194 ac->req->op.rename.olddn, 195 LDB_SCOPE_ONELEVEL, 432 196 "(objectClass=*)", 433 attrs,197 no_attrs, 434 198 NULL, 435 ac, 436 subtree_rename_search_ callback,199 ac, 200 subtree_rename_search_onelevel_callback, 437 201 req); 438 202 LDB_REQ_SET_LOCATION(search_req); … … 447 211 } 448 212 449 return ldb_next_request( module, search_req);213 return ldb_next_request(ac->module, search_req); 450 214 } 451 215 -
vendor/current/source4/dsdb/samdb/ldb_modules/update_keytab.c
r740 r988 35 35 #include "system/kerberos.h" 36 36 #include "auth/kerberos/kerberos.h" 37 #include "util.h" 37 #include "auth/kerberos/kerberos_srv_keytab.h" 38 #include "dsdb/samdb/ldb_modules/util.h" 39 #include "param/secrets.h" 38 40 39 41 struct dn_list { … … 90 92 int ret; 91 93 92 filter = talloc_asprintf(data, "(&(dn=%s)(&(objectClass=kerberosSecret)(privateKeytab=*)))",93 ldb_dn_get_linearized(dn));94 filter = talloc_asprintf(data, 95 "(&(objectClass=kerberosSecret)(privateKeytab=*))"); 94 96 if (!filter) { 95 97 return ldb_oom(ldb); … … 108 110 /* if it's not a kerberosSecret then we don't have anything to update */ 109 111 talloc_free(res); 110 talloc_free(filter);111 112 return LDB_SUCCESS; 112 113 } … … 115 116 if (!item) { 116 117 talloc_free(res); 117 talloc_free(filter);118 118 return ldb_oom(ldb); 119 119 } … … 123 123 talloc_free(res); 124 124 125 DLIST_ADD_END(data->changed_dns, item , struct dn_list *);125 DLIST_ADD_END(data->changed_dns, item); 126 126 return LDB_SUCCESS; 127 127 } … … 378 378 struct dn_list *p; 379 379 struct smb_krb5_context *smb_krb5_context; 380 int krb5_ret = smb_krb5_init_context(data, ldb_get_event_context(ldb), ldb_get_opaque(ldb, "loadparm"), 380 int krb5_ret = smb_krb5_init_context(data, 381 ldb_get_opaque(ldb, "loadparm"), 381 382 &smb_krb5_context); 383 TALLOC_CTX *tmp_ctx = NULL; 384 382 385 if (krb5_ret != 0) { 383 talloc_free(data->changed_dns);384 data->changed_dns = NULL;385 386 ldb_asprintf_errstring(ldb, "Failed to setup krb5_context: %s", error_message(krb5_ret)); 386 return LDB_ERR_OPERATIONS_ERROR; 387 } 388 389 ldb = ldb_module_get_ctx(module); 387 goto fail; 388 } 389 390 tmp_ctx = talloc_new(data); 391 if (!tmp_ctx) { 392 ldb_oom(ldb); 393 goto fail; 394 } 390 395 391 396 for (p=data->changed_dns; p; p = p->next) { 392 397 const char *error_string; 393 krb5_ret = smb_krb5_update_keytab(data, smb_krb5_context, ldb, p->msg, p->do_delete, &error_string); 398 const char *realm; 399 char *upper_realm; 400 struct ldb_message_element *spn_el = ldb_msg_find_element(p->msg, "servicePrincipalName"); 401 const char **SPNs = NULL; 402 int num_SPNs = 0; 403 int i; 404 405 realm = ldb_msg_find_attr_as_string(p->msg, "realm", NULL); 406 407 if (spn_el) { 408 upper_realm = strupper_talloc(tmp_ctx, realm); 409 if (!upper_realm) { 410 ldb_oom(ldb); 411 goto fail; 412 } 413 414 num_SPNs = spn_el->num_values; 415 SPNs = talloc_array(tmp_ctx, const char *, num_SPNs); 416 if (!SPNs) { 417 ldb_oom(ldb); 418 goto fail; 419 } 420 for (i = 0; i < num_SPNs; i++) { 421 SPNs[i] = talloc_asprintf(SPNs, "%*.*s@%s", 422 (int)spn_el->values[i].length, 423 (int)spn_el->values[i].length, 424 (const char *)spn_el->values[i].data, 425 upper_realm); 426 if (!SPNs[i]) { 427 ldb_oom(ldb); 428 goto fail; 429 } 430 } 431 } 432 433 krb5_ret = smb_krb5_update_keytab(tmp_ctx, smb_krb5_context->krb5_context, 434 keytab_name_from_msg(tmp_ctx, ldb, p->msg), 435 ldb_msg_find_attr_as_string(p->msg, "samAccountName", NULL), 436 realm, SPNs, num_SPNs, 437 ldb_msg_find_attr_as_string(p->msg, "saltPrincipal", NULL), 438 ldb_msg_find_attr_as_string(p->msg, "secret", NULL), 439 ldb_msg_find_attr_as_string(p->msg, "priorSecret", NULL), 440 ldb_msg_find_attr_as_int(p->msg, "msDS-KeyVersionNumber", 0), 441 (uint32_t)ldb_msg_find_attr_as_int(p->msg, "msDS-SupportedEncryptionTypes", ENC_ALL_TYPES), 442 p->do_delete, NULL, &error_string); 394 443 if (krb5_ret != 0) { 395 talloc_free(data->changed_dns);396 data->changed_dns = NULL;397 444 ldb_asprintf_errstring(ldb, "Failed to update keytab from entry %s in %s: %s", 398 445 ldb_dn_get_linearized(p->msg->dn), 399 446 (const char *)ldb_get_opaque(ldb, "ldb_url"), 400 447 error_string); 401 return LDB_ERR_OPERATIONS_ERROR;448 goto fail; 402 449 } 403 450 } … … 405 452 talloc_free(data->changed_dns); 406 453 data->changed_dns = NULL; 454 talloc_free(tmp_ctx); 407 455 408 456 return ldb_next_prepare_commit(module); 457 458 fail: 459 talloc_free(data->changed_dns); 460 data->changed_dns = NULL; 461 talloc_free(tmp_ctx); 462 return LDB_ERR_OPERATIONS_ERROR; 409 463 } 410 464 -
vendor/current/source4/dsdb/samdb/ldb_modules/util.c
r740 r988 5 5 Copyright (C) Andrew Tridgell 2009 6 6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009 7 Copyright (C) Matthieu Patou <mat@matws.net> 2011 7 8 8 9 This program is free software; you can redistribute it and/or modify … … 26 27 #include "dsdb/samdb/ldb_modules/util.h" 27 28 #include "dsdb/samdb/samdb.h" 28 #include " util.h"29 #include "dsdb/common/util.h" 29 30 #include "libcli/security/security.h" 30 31 … … 110 111 } 111 112 112 /* 113 search for attrs in the modules below 114 */ 115 int dsdb_module_search(struct ldb_module *module, 113 int dsdb_module_search_tree(struct ldb_module *module, 116 114 TALLOC_CTX *mem_ctx, 117 115 struct ldb_result **_res, 118 struct ldb_dn *basedn, enum ldb_scope scope, 116 struct ldb_dn *basedn, 117 enum ldb_scope scope, 118 struct ldb_parse_tree *tree, 119 119 const char * const *attrs, 120 int dsdb_flags, 121 struct ldb_request *parent, 122 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10) 120 int dsdb_flags, 121 struct ldb_request *parent) 123 122 { 124 123 int ret; … … 126 125 TALLOC_CTX *tmp_ctx; 127 126 struct ldb_result *res; 128 va_list ap;129 char *expression;130 127 131 128 tmp_ctx = talloc_new(mem_ctx); 132 129 133 if (format) { 134 va_start(ap, format); 135 expression = talloc_vasprintf(tmp_ctx, format, ap); 136 va_end(ap); 137 138 if (!expression) { 139 talloc_free(tmp_ctx); 140 return ldb_oom(ldb_module_get_ctx(module)); 141 } 142 } else { 143 expression = NULL; 144 } 130 /* cross-partitions searches with a basedn break multi-domain support */ 131 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0); 145 132 146 133 res = talloc_zero(tmp_ctx, struct ldb_result); … … 150 137 } 151 138 152 ret = ldb_build_search_req (&req, ldb_module_get_ctx(module), tmp_ctx,139 ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx, 153 140 basedn, 154 141 scope, 155 expression,142 tree, 156 143 attrs, 157 144 NULL, … … 188 175 } 189 176 177 if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) { 178 if (res->count == 0) { 179 talloc_free(tmp_ctx); 180 ldb_reset_err_string(ldb_module_get_ctx(module)); 181 return LDB_ERR_NO_SUCH_OBJECT; 182 } 183 if (res->count != 1) { 184 talloc_free(tmp_ctx); 185 ldb_reset_err_string(ldb_module_get_ctx(module)); 186 return LDB_ERR_CONSTRAINT_VIOLATION; 187 } 188 } 189 190 190 talloc_free(req); 191 191 if (ret == LDB_SUCCESS) { 192 192 *_res = talloc_steal(mem_ctx, res); 193 193 } 194 talloc_free(tmp_ctx); 195 return ret; 196 } 197 198 /* 199 search for attrs in the modules below 200 */ 201 int dsdb_module_search(struct ldb_module *module, 202 TALLOC_CTX *mem_ctx, 203 struct ldb_result **_res, 204 struct ldb_dn *basedn, enum ldb_scope scope, 205 const char * const *attrs, 206 int dsdb_flags, 207 struct ldb_request *parent, 208 const char *format, ...) _PRINTF_ATTRIBUTE(9, 10) 209 { 210 int ret; 211 TALLOC_CTX *tmp_ctx; 212 va_list ap; 213 char *expression; 214 struct ldb_parse_tree *tree; 215 216 /* cross-partitions searches with a basedn break multi-domain support */ 217 SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0); 218 219 tmp_ctx = talloc_new(mem_ctx); 220 221 if (format) { 222 va_start(ap, format); 223 expression = talloc_vasprintf(tmp_ctx, format, ap); 224 va_end(ap); 225 226 if (!expression) { 227 talloc_free(tmp_ctx); 228 return ldb_oom(ldb_module_get_ctx(module)); 229 } 230 } else { 231 expression = NULL; 232 } 233 234 tree = ldb_parse_tree(tmp_ctx, expression); 235 if (tree == NULL) { 236 talloc_free(tmp_ctx); 237 ldb_set_errstring(ldb_module_get_ctx(module), 238 "Unable to parse search expression"); 239 return LDB_ERR_OPERATIONS_ERROR; 240 } 241 242 ret = dsdb_module_search_tree(module, 243 mem_ctx, 244 _res, 245 basedn, 246 scope, 247 tree, 248 attrs, 249 dsdb_flags, 250 parent); 251 194 252 talloc_free(tmp_ctx); 195 253 return ret; … … 270 328 return LDB_SUCCESS; 271 329 } 330 331 332 /* 333 a ldb_extended request operating on modules below the 334 current module 335 336 Note that this does not automatically start a transaction. If you 337 need a transaction the caller needs to start it as needed. 338 */ 339 int dsdb_module_extended(struct ldb_module *module, 340 TALLOC_CTX *mem_ctx, 341 struct ldb_result **_res, 342 const char* oid, void* data, 343 uint32_t dsdb_flags, 344 struct ldb_request *parent) 345 { 346 struct ldb_request *req; 347 int ret; 348 struct ldb_context *ldb = ldb_module_get_ctx(module); 349 TALLOC_CTX *tmp_ctx = talloc_new(module); 350 struct ldb_result *res; 351 352 if (_res != NULL) { 353 (*_res) = NULL; 354 } 355 356 res = talloc_zero(tmp_ctx, struct ldb_result); 357 if (!res) { 358 talloc_free(tmp_ctx); 359 return ldb_oom(ldb_module_get_ctx(module)); 360 } 361 362 ret = ldb_build_extended_req(&req, ldb, 363 tmp_ctx, 364 oid, 365 data, 366 NULL, 367 res, ldb_extended_default_callback, 368 parent); 369 370 LDB_REQ_SET_LOCATION(req); 371 if (ret != LDB_SUCCESS) { 372 talloc_free(tmp_ctx); 373 return ret; 374 } 375 376 ret = dsdb_request_add_controls(req, dsdb_flags); 377 if (ret != LDB_SUCCESS) { 378 talloc_free(tmp_ctx); 379 return ret; 380 } 381 382 if (dsdb_flags & DSDB_FLAG_TRUSTED) { 383 ldb_req_mark_trusted(req); 384 } 385 386 /* Run the new request */ 387 if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) { 388 ret = ldb_next_request(module, req); 389 } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) { 390 ret = ldb_request(ldb_module_get_ctx(module), req); 391 } else { 392 const struct ldb_module_ops *ops = ldb_module_get_ops(module); 393 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE); 394 ret = ops->extended(module, req); 395 } 396 if (ret == LDB_SUCCESS) { 397 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 398 } 399 400 if (_res != NULL && ret == LDB_SUCCESS) { 401 (*_res) = talloc_steal(mem_ctx, res); 402 } 403 404 talloc_free(tmp_ctx); 405 return ret; 406 } 407 272 408 273 409 /* … … 547 683 } 548 684 549 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope, 550 struct GUID op_feature_guid, bool *feature_enabled) 685 /* 686 check if an optional feature is enabled on our own NTDS DN 687 688 Note that features can be marked as enabled in more than one 689 place. For example, the recyclebin feature is marked as enabled both 690 on the CN=Partitions,CN=Configurration object and on the NTDS DN of 691 each DC in the forest. It seems likely that it is the job of the KCC 692 to propogate between the two 693 */ 694 int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled) 551 695 { 552 696 TALLOC_CTX *tmp_ctx; … … 559 703 unsigned int i; 560 704 struct ldb_message_element *el; 705 struct ldb_dn *feature_dn; 706 707 tmp_ctx = talloc_new(ldb); 708 709 feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx); 710 if (feature_dn == NULL) { 711 talloc_free(tmp_ctx); 712 return ldb_operr(ldb_module_get_ctx(module)); 713 } 561 714 562 715 *feature_enabled = false; 563 716 564 tmp_ctx = talloc_new(ldb); 565 566 ret = ldb_search(ldb, tmp_ctx, &res, 567 scope, LDB_SCOPE_BASE, attrs, 568 NULL); 717 ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL); 569 718 if (ret != LDB_SUCCESS) { 570 719 ldb_asprintf_errstring(ldb, 571 "Could no find the scope object - dn: %s\n",572 ldb_dn_get_linearized( scope));720 "Could not find the feature object - dn: %s\n", 721 ldb_dn_get_linearized(feature_dn)); 573 722 talloc_free(tmp_ctx); 574 723 return LDB_ERR_OPERATIONS_ERROR; 575 724 } 576 725 if (res->msgs[0]->num_elements > 0) { 726 const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL}; 577 727 578 728 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature"); 579 580 attrs[0] = "msDS-OptionalFeatureGUID";581 729 582 730 for (i=0; i<el->num_values; i++) { 583 731 search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]); 584 732 585 ret = ldb_search(ldb, tmp_ctx, &res, 586 search_dn, LDB_SCOPE_BASE, attrs, 587 NULL); 733 ret = dsdb_module_search_dn(module, tmp_ctx, &res, 734 search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL); 588 735 if (ret != LDB_SUCCESS) { 589 736 ldb_asprintf_errstring(ldb, … … 596 743 search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID"); 597 744 598 if (GUID_ compare(&search_guid, &op_feature_guid) == 0){745 if (GUID_equal(&search_guid, &op_feature_guid)) { 599 746 *feature_enabled = true; 600 747 break; … … 651 798 652 799 ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs, 653 DSDB_FLAG_NEXT_MODULE , parent);800 DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent); 654 801 if (ret != LDB_SUCCESS) { 655 802 return ret; … … 902 1049 { 903 1050 struct ldb_context *ldb = ldb_module_get_ctx(module); 904 struct ldb_dn *partitions_dn;905 1051 struct GUID recyclebin_guid; 906 1052 int ret; 907 1053 908 partitions_dn = samdb_partitions_dn(ldb, module);909 910 1054 GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid); 911 1055 912 ret = dsdb_check_optional_feature(module, partitions_dn,recyclebin_guid, enabled);1056 ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled); 913 1057 if (ret != LDB_SUCCESS) { 914 1058 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n"); 915 talloc_free(partitions_dn);916 1059 return LDB_ERR_UNWILLING_TO_PERFORM; 917 1060 } 918 1061 919 talloc_free(partitions_dn);920 1062 return LDB_SUCCESS; 921 1063 } … … 1051 1193 1052 1194 msg = ldb_msg_new(module); 1195 if (msg == NULL) { 1196 return ldb_module_oom(module); 1197 } 1053 1198 msg->dn = dn; 1054 1199 … … 1093 1238 1094 1239 msg = ldb_msg_new(module); 1240 if (msg == NULL) { 1241 return ldb_module_oom(module); 1242 } 1095 1243 msg->dn = dn; 1096 1244 … … 1235 1383 return el; 1236 1384 } 1385 1386 /* 1387 * This function determines the (last) structural or 88 object class of a passed 1388 * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value. 1389 * Without schema this does not work and hence NULL is returned. 1390 */ 1391 const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema, 1392 const struct ldb_message_element *element) 1393 { 1394 const struct dsdb_class *last_class; 1395 1396 if (schema == NULL) { 1397 return NULL; 1398 } 1399 1400 if (element->num_values == 0) { 1401 return NULL; 1402 } 1403 1404 last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, 1405 &element->values[element->num_values-1]); 1406 if (last_class == NULL) { 1407 return NULL; 1408 } 1409 if (last_class->objectClassCategory > 1) { 1410 return NULL; 1411 } 1412 1413 return last_class; 1414 } 1415 1416 const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema, 1417 const struct ldb_message *msg) 1418 { 1419 struct ldb_message_element *oc_el; 1420 1421 oc_el = ldb_msg_find_element(msg, "objectClass"); 1422 if (!oc_el) { 1423 return NULL; 1424 } 1425 1426 return dsdb_get_last_structural_class(schema, oc_el); 1427 } 1428 1429 /* Fix the DN so that the relative attribute names are in upper case so that the DN: 1430 cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes 1431 CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com 1432 */ 1433 int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn) 1434 { 1435 int i, ret; 1436 char *upper_rdn_attr; 1437 1438 for (i=0; i < ldb_dn_get_comp_num(dn); i++) { 1439 /* We need the attribute name in upper case */ 1440 upper_rdn_attr = strupper_talloc(dn, 1441 ldb_dn_get_component_name(dn, i)); 1442 if (!upper_rdn_attr) { 1443 return ldb_oom(ldb); 1444 } 1445 ret = ldb_dn_set_component(dn, i, upper_rdn_attr, 1446 *ldb_dn_get_component_val(dn, i)); 1447 talloc_free(upper_rdn_attr); 1448 if (ret != LDB_SUCCESS) { 1449 return ret; 1450 } 1451 } 1452 return LDB_SUCCESS; 1453 } 1454 1455 /** 1456 * Make most specific objectCategory for the objectClass of passed object 1457 * NOTE: In this implementation we count that it is called on already 1458 * verified objectClass attribute value. See objectclass.c thorough 1459 * implementation for all the magic that involves 1460 * 1461 * @param ldb ldb context 1462 * @param schema cached schema for ldb. We may get it, but it is very time consuming. 1463 * Hence leave the responsibility to the caller. 1464 * @param obj AD object to determint objectCategory for 1465 * @param mem_ctx Memory context - usually it is obj actually 1466 * @param pobjectcategory location to store found objectCategory 1467 * 1468 * @return LDB_SUCCESS or error including out of memory error 1469 */ 1470 int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema, 1471 struct ldb_message *obj, 1472 TALLOC_CTX *mem_ctx, const char **pobjectcategory) 1473 { 1474 const struct dsdb_class *objectclass; 1475 struct ldb_message_element *objectclass_element; 1476 struct dsdb_extended_dn_store_format *dn_format; 1477 1478 objectclass_element = ldb_msg_find_element(obj, "objectClass"); 1479 if (!objectclass_element) { 1480 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!", 1481 ldb_dn_get_linearized(obj->dn)); 1482 return LDB_ERR_OBJECT_CLASS_VIOLATION; 1483 } 1484 if (objectclass_element->num_values == 0) { 1485 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!", 1486 ldb_dn_get_linearized(obj->dn)); 1487 return LDB_ERR_CONSTRAINT_VIOLATION; 1488 } 1489 1490 /* 1491 * Get the new top-most structural object class and check for 1492 * unrelated structural classes 1493 */ 1494 objectclass = dsdb_get_last_structural_class(schema, 1495 objectclass_element); 1496 if (objectclass == NULL) { 1497 ldb_asprintf_errstring(ldb, 1498 "Failed to find a structural class for %s", 1499 ldb_dn_get_linearized(obj->dn)); 1500 return LDB_ERR_UNWILLING_TO_PERFORM; 1501 } 1502 1503 dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME), 1504 struct dsdb_extended_dn_store_format); 1505 if (dn_format && dn_format->store_extended_dn_in_ldb == false) { 1506 /* Strip off extended components */ 1507 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, 1508 objectclass->defaultObjectCategory); 1509 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn); 1510 talloc_free(dn); 1511 } else { 1512 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory); 1513 } 1514 1515 if (*pobjectcategory == NULL) { 1516 return ldb_oom(ldb); 1517 } 1518 1519 return LDB_SUCCESS; 1520 } -
vendor/current/source4/dsdb/samdb/ldb_modules/util.h
r740 r988 26 26 struct security_descriptor; 27 27 struct dom_sid; 28 struct netlogon_samlogon_response; 28 29 29 30 #include "librpc/gen_ndr/misc.h" 30 31 #include "dsdb/samdb/ldb_modules/util_proto.h" 31 32 #include "dsdb/common/util.h" 33 #include "../libcli/netlogon/netlogon.h" 32 34 33 35 /* extend the dsdb_request_add_controls() flags for module -
vendor/current/source4/dsdb/samdb/ldb_modules/wscript_build
r740 r988 3 3 bld.SAMBA_LIBRARY('dsdb-module', 4 4 source=[], 5 deps='DSDB_MODULE_HELPERS DSDB_MODULE_HELPER_ SCHEMA DSDB_MODULE_HELPER_RIDALLOC',5 deps='DSDB_MODULE_HELPERS DSDB_MODULE_HELPER_RIDALLOC', 6 6 private_library=True, 7 7 grouping_library=True) 8 8 9 9 bld.SAMBA_SUBSYSTEM('DSDB_MODULE_HELPERS', 10 source='util.c acl_util.c schema_util.c ',10 source='util.c acl_util.c schema_util.c netlogon.c', 11 11 autoproto='util_proto.h', 12 deps='ldb ndr samdb-common s ecurity'12 deps='ldb ndr samdb-common samba-security' 13 13 ) 14 14 … … 19 19 ) 20 20 21 bld.SAMBA_SUBSYSTEM('DSDB_MODULE_HELPER_SCHEMA', 22 source='schema.c', 23 autoproto='schema.h', 24 deps='SAMDB_SCHEMA' 25 ) 26 27 bld.SAMBA_MODULE('ldb_samba_dsdb', 28 source='samba_dsdb.c', 29 subsystem='ldb', 30 init_function='ldb_samba_dsdb_module_init', 31 module_init_name='ldb_init_module', 32 deps='samdb talloc events ndr DSDB_MODULE_HELPERS', 33 internal_module=False, 34 ) 35 36 37 bld.SAMBA_MODULE('ldb_samba_secrets', 38 source='samba_secrets.c', 39 subsystem='ldb', 40 init_function='ldb_samba_secrets_module_init', 41 module_init_name='ldb_init_module', 42 internal_module=False, 43 deps='samdb talloc events ndr' 44 ) 45 46 47 bld.SAMBA_MODULE('ldb_objectguid', 48 source='objectguid.c', 49 subsystem='ldb', 50 init_function='ldb_objectguid_module_init', 51 module_init_name='ldb_init_module', 52 internal_module=False, 53 deps='samdb talloc events ndr DSDB_MODULE_HELPERS' 54 ) 55 56 57 bld.SAMBA_MODULE('ldb_repl_meta_data', 58 source='repl_meta_data.c', 59 subsystem='ldb', 60 init_function='ldb_repl_meta_data_module_init', 61 module_init_name='ldb_init_module', 62 internal_module=False, 63 deps='samdb talloc events ndr NDR_DRSUAPI NDR_DRSBLOBS ndr DSDB_MODULE_HELPERS security' 64 ) 65 66 67 bld.SAMBA_MODULE('ldb_schema_load', 68 source='schema_load.c', 69 subsystem='ldb', 70 init_function='ldb_schema_load_module_init', 71 module_init_name='ldb_init_module', 72 internal_module=False, 73 deps='samdb talloc events DSDB_MODULE_HELPERS' 74 ) 75 76 77 bld.SAMBA_MODULE('ldb_schema_data', 78 source='schema_data.c', 79 subsystem='ldb', 80 init_function='ldb_schema_data_module_init', 81 module_init_name='ldb_init_module', 82 internal_module=False, 83 deps='samdb talloc events DSDB_MODULE_HELPERS' 84 ) 85 86 87 bld.SAMBA_MODULE('ldb_naming_fsmo', 88 source='naming_fsmo.c', 89 subsystem='ldb', 90 init_function='ldb_naming_fsmo_module_init', 91 module_init_name='ldb_init_module', 92 internal_module=False, 93 deps='samdb talloc events DSDB_MODULE_HELPERS' 94 ) 95 96 97 bld.SAMBA_MODULE('ldb_pdc_fsmo', 98 source='pdc_fsmo.c', 99 subsystem='ldb', 100 init_function='ldb_pdc_fsmo_module_init', 101 module_init_name='ldb_init_module', 102 internal_module=False, 103 deps='samdb talloc events DSDB_MODULE_HELPERS' 104 ) 105 106 107 bld.SAMBA_MODULE('ldb_samldb', 108 source='samldb.c', 109 subsystem='ldb', 110 init_function='ldb_samldb_module_init', 111 module_init_name='ldb_init_module', 112 internal_module=False, 113 deps='talloc events samdb DSDB_MODULE_HELPERS DSDB_MODULE_HELPER_RIDALLOC' 114 ) 115 116 117 bld.SAMBA_MODULE('ldb_samba3sam', 118 source='samba3sam.c', 119 subsystem='ldb', 120 init_function='ldb_samba3sam_module_init', 121 module_init_name='ldb_init_module', 122 internal_module=False, 123 deps='talloc events ldb smbpasswdparser security NDR_SECURITY' 124 ) 125 126 127 bld.SAMBA_MODULE('ldb_samba3sid', 128 source='samba3sid.c', 129 subsystem='ldb', 130 init_function='ldb_samba3sid_module_init', 131 module_init_name='ldb_init_module', 132 internal_module=False, 133 deps='talloc events ldb security NDR_SECURITY ldbsamba DSDB_MODULE_HELPERS' 134 ) 135 136 137 bld.SAMBA_MODULE('ldb_simple_ldap_map', 138 source='simple_ldap_map.c', 139 subsystem='ldb', 140 init_function='ldb_simple_ldap_map_module_init', 141 module_init_name='ldb_init_module', 142 internal_module=False, 143 deps='talloc events ldb ndr ldbsamba' 144 ) 145 146 147 bld.SAMBA_MODULE('ldb_rootdse', 148 source='rootdse.c', 149 subsystem='ldb', 150 init_function='ldb_rootdse_module_init', 151 module_init_name='ldb_init_module', 152 internal_module=False, 153 deps='talloc events samdb MESSAGING security DSDB_MODULE_HELPERS' 154 ) 155 156 157 bld.SAMBA_MODULE('ldb_password_hash', 158 source='password_hash.c', 159 subsystem='ldb', 160 init_function='ldb_password_hash_module_init', 161 module_init_name='ldb_init_module', 162 internal_module=False, 163 deps='talloc events samdb LIBCLI_AUTH NDR_DRSBLOBS authkrb5 krb5 DSDB_MODULE_HELPERS' 164 ) 165 166 167 bld.SAMBA_MODULE('ldb_local_password', 168 source='local_password.c', 169 subsystem='ldb', 170 init_function='ldb_local_password_module_init', 171 module_init_name='ldb_init_module', 172 internal_module=False, 173 deps='talloc events ndr samdb' 174 ) 175 176 bld.SAMBA_MODULE('ldb_extended_dn_in', 177 source='extended_dn_in.c', 178 subsystem='ldb', 179 init_function='ldb_extended_dn_in_module_init', 180 module_init_name='ldb_init_module', 181 internal_module=False, 182 deps='ldb talloc events samba-util' 183 ) 184 185 186 bld.SAMBA_MODULE('ldb_extended_dn_out', 187 source='extended_dn_out.c', 188 init_function='ldb_extended_dn_out_module_init', 189 module_init_name='ldb_init_module', 190 subsystem='ldb', 191 deps='talloc events ndr samba-util samdb', 192 internal_module=False, 193 ) 194 195 196 bld.SAMBA_MODULE('ldb_extended_dn_store', 197 source='extended_dn_store.c', 198 subsystem='ldb', 199 init_function='ldb_extended_dn_store_module_init', 200 module_init_name='ldb_init_module', 201 internal_module=False, 202 deps='talloc events samba-util samdb DSDB_MODULE_HELPERS' 203 ) 204 205 206 bld.SAMBA_MODULE('ldb_show_deleted', 207 source='show_deleted.c', 208 subsystem='ldb', 209 init_function='ldb_show_deleted_module_init', 210 module_init_name='ldb_init_module', 211 internal_module=False, 212 deps='talloc events samba-util DSDB_MODULE_HELPERS' 213 ) 214 215 216 bld.SAMBA_MODULE('ldb_partition', 217 source='partition.c partition_init.c', 218 autoproto='partition_proto.h', 219 subsystem='ldb', 220 init_function='ldb_partition_module_init', 221 module_init_name='ldb_init_module', 222 internal_module=False, 223 deps='talloc events samdb DSDB_MODULE_HELPERS' 224 ) 225 226 227 bld.SAMBA_MODULE('ldb_new_partition', 228 source='new_partition.c', 229 subsystem='ldb', 230 init_function='ldb_new_partition_module_init', 231 module_init_name='ldb_init_module', 232 internal_module=False, 233 deps='talloc events samdb DSDB_MODULE_HELPERS' 234 ) 235 236 237 bld.SAMBA_MODULE('ldb_update_keytab', 238 source='update_keytab.c', 239 subsystem='ldb', 240 init_function='ldb_update_keytab_module_init', 241 module_init_name='ldb_init_module', 242 internal_module=False, 243 deps='talloc events credentials ldb com_err KERBEROS_UTIL DSDB_MODULE_HELPERS' 244 ) 245 246 247 bld.SAMBA_MODULE('ldb_objectclass', 248 source='objectclass.c', 249 subsystem='ldb', 250 init_function='ldb_objectclass_module_init', 251 module_init_name='ldb_init_module', 252 internal_module=False, 253 deps='talloc events security NDR_SECURITY samdb DSDB_MODULE_HELPERS samba-util DSDB_MODULE_HELPER_SCHEMA' 254 ) 255 256 257 bld.SAMBA_MODULE('ldb_objectclass_attrs', 258 source='objectclass_attrs.c', 259 subsystem='ldb', 260 init_function='ldb_objectclass_attrs_module_init', 261 module_init_name='ldb_init_module', 262 deps='talloc samdb samba-util', 263 internal_module=False, 264 ) 265 266 267 bld.SAMBA_MODULE('ldb_subtree_rename', 268 source='subtree_rename.c', 269 subsystem='ldb', 270 init_function='ldb_subtree_rename_module_init', 271 module_init_name='ldb_init_module', 272 internal_module=False, 273 deps='talloc events samba-util ldb samdb-common' 274 ) 275 276 277 bld.SAMBA_MODULE('ldb_subtree_delete', 278 source='subtree_delete.c', 279 subsystem='ldb', 280 init_function='ldb_subtree_delete_module_init', 281 module_init_name='ldb_init_module', 282 internal_module=False, 283 deps='talloc events samba-util DSDB_MODULE_HELPERS' 284 ) 285 286 287 bld.SAMBA_MODULE('ldb_linked_attributes', 288 source='linked_attributes.c', 289 subsystem='ldb', 290 init_function='ldb_linked_attributes_module_init', 291 module_init_name='ldb_init_module', 292 internal_module=False, 293 deps='talloc events samdb DSDB_MODULE_HELPERS' 294 ) 295 296 297 bld.SAMBA_MODULE('ldb_ranged_results', 298 source='ranged_results.c', 299 subsystem='ldb', 300 init_function='ldb_ranged_results_module_init', 301 module_init_name='ldb_init_module', 302 internal_module=False, 303 deps='talloc events samba-util ldb' 304 ) 305 306 307 bld.SAMBA_MODULE('ldb_anr', 308 source='anr.c', 309 subsystem='ldb', 310 init_function='ldb_anr_module_init', 311 module_init_name='ldb_init_module', 312 internal_module=False, 313 deps='talloc events samba-util samdb' 314 ) 315 316 317 bld.SAMBA_MODULE('ldb_instancetype', 318 source='instancetype.c', 319 subsystem='ldb', 320 init_function='ldb_instancetype_module_init', 321 module_init_name='ldb_init_module', 322 internal_module=False, 323 deps='talloc events samba-util samdb DSDB_MODULE_HELPERS' 324 ) 325 326 327 bld.SAMBA_MODULE('ldb_operational', 328 source='operational.c', 329 subsystem='ldb', 330 init_function='ldb_operational_module_init', 331 module_init_name='ldb_init_module', 332 internal_module=False, 333 deps='talloc tevent samba-util samdb-common DSDB_MODULE_HELPERS samdb' 334 ) 335 336 337 bld.SAMBA_MODULE('ldb_descriptor', 338 source='descriptor.c', 339 subsystem='ldb', 340 init_function='ldb_descriptor_module_init', 341 module_init_name='ldb_init_module', 342 internal_module=False, 343 deps='talloc events security NDR_SECURITY samdb DSDB_MODULE_HELPERS DSDB_MODULE_HELPER_SCHEMA' 344 ) 345 346 347 bld.SAMBA_MODULE('ldb_resolve_oids', 348 source='resolve_oids.c', 349 subsystem='ldb', 350 init_function='ldb_resolve_oids_module_init', 351 module_init_name='ldb_init_module', 352 internal_module=False, 353 deps='samdb talloc events ndr' 354 ) 355 356 357 bld.SAMBA_MODULE('ldb_acl', 358 source='acl.c', 359 subsystem='ldb', 360 init_function='ldb_acl_module_init', 361 module_init_name='ldb_init_module', 362 internal_module=False, 363 deps='talloc events security samdb DSDB_MODULE_HELPERS DSDB_MODULE_HELPER_SCHEMA' 364 ) 365 366 367 bld.SAMBA_MODULE('ldb_lazy_commit', 368 source='lazy_commit.c', 369 subsystem='ldb', 370 internal_module=False, 371 module_init_name='ldb_init_module', 372 init_function='ldb_lazy_commit_module_init', 373 deps='samdb DSDB_MODULE_HELPERS' 374 ) 375 376 bld.SAMBA_MODULE('ldb_aclread', 377 source='acl_read.c', 378 subsystem='ldb', 379 init_function='ldb_aclread_module_init', 380 module_init_name='ldb_init_module', 381 internal_module=False, 382 deps='talloc events security samdb DSDB_MODULE_HELPERS', 383 ) 384 385 bld.SAMBA_MODULE('ldb_simple_dn', 386 source='simple_dn.c', 387 subsystem='ldb', 388 init_function='ldb_simple_dn_module_init', 389 module_init_name='ldb_init_module', 390 internal_module=False, 391 deps='talloc DSDB_MODULE_HELPERS' 392 ) 21 if bld.AD_DC_BUILD_IS_ENABLED(): 22 bld.PROCESS_SEPARATE_RULE("server") -
vendor/current/source4/dsdb/samdb/samdb.c
r740 r988 45 45 46 46 /* 47 make sure the static credentials are not freed 48 */ 49 static int samdb_credentials_destructor(struct cli_credentials *creds) 50 { 51 return -1; 52 } 53 54 /* 55 this returns a static set of system credentials. It is static so 56 that we always get the same pointer in ldb_wrap_connect() 57 */ 58 struct cli_credentials *samdb_credentials(struct loadparm_context *lp_ctx) 59 { 60 static struct cli_credentials *static_credentials; 61 struct cli_credentials *cred; 62 char *error_string; 63 64 if (static_credentials) { 65 return static_credentials; 66 } 67 68 cred = cli_credentials_init(talloc_autofree_context()); 69 if (!cred) { 70 return NULL; 71 } 72 cli_credentials_set_conf(cred, lp_ctx); 73 74 /* We don't want to use krb5 to talk to our samdb - recursion 75 * here would be bad, and this account isn't in the KDC 76 * anyway */ 77 cli_credentials_set_kerberos_state(cred, CRED_DONT_USE_KERBEROS); 78 79 if (!NT_STATUS_IS_OK(cli_credentials_set_secrets(cred, lp_ctx, NULL, NULL, 80 SECRETS_LDAP_FILTER, &error_string))) { 81 DEBUG(5, ("(normal if no LDAP backend) %s", error_string)); 82 /* Perfectly OK - if not against an LDAP backend */ 83 talloc_free(cred); 84 return NULL; 85 } 86 static_credentials = cred; 87 talloc_set_destructor(cred, samdb_credentials_destructor); 88 return cred; 89 } 90 91 /* 92 connect to the SAM database 47 connect to the SAM database specified by URL 93 48 return an opaque context pointer on success, or NULL on failure 94 49 */ 95 struct ldb_context *samdb_connect (TALLOC_CTX *mem_ctx,50 struct ldb_context *samdb_connect_url(TALLOC_CTX *mem_ctx, 96 51 struct tevent_context *ev_ctx, 97 52 struct loadparm_context *lp_ctx, 98 53 struct auth_session_info *session_info, 99 int flags)54 unsigned int flags, const char *url) 100 55 { 101 56 struct ldb_context *ldb; 102 struct dsdb_schema *schema;103 const char *url;104 struct cli_credentials *credentials;105 57 int ret; 106 58 107 url = lpcfg_sam_url(lp_ctx); 108 credentials = samdb_credentials(lp_ctx); 109 110 ldb = ldb_wrap_find(url, ev_ctx, lp_ctx, session_info, credentials, flags); 59 ldb = ldb_wrap_find(url, ev_ctx, lp_ctx, session_info, NULL, flags); 111 60 if (ldb != NULL) 112 61 return talloc_reference(mem_ctx, ldb); 113 62 114 ldb = samba_ldb_init(mem_ctx, ev_ctx, lp_ctx, session_info, credentials);63 ldb = samba_ldb_init(mem_ctx, ev_ctx, lp_ctx, session_info, NULL); 115 64 116 65 if (ldb == NULL) … … 125 74 } 126 75 127 schema = dsdb_get_schema(ldb, NULL); 128 /* make the resulting schema global */ 129 if (schema) { 130 dsdb_make_schema_global(ldb, schema); 131 } 132 133 if (!ldb_wrap_add(url, ev_ctx, lp_ctx, session_info, credentials, flags, ldb)) { 76 if (!ldb_wrap_add(url, ev_ctx, lp_ctx, session_info, NULL, flags, ldb)) { 134 77 talloc_free(ldb); 135 78 return NULL; … … 139 82 } 140 83 84 85 /* 86 connect to the SAM database 87 return an opaque context pointer on success, or NULL on failure 88 */ 89 struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx, 90 struct tevent_context *ev_ctx, 91 struct loadparm_context *lp_ctx, 92 struct auth_session_info *session_info, 93 unsigned int flags) 94 { 95 return samdb_connect_url(mem_ctx, ev_ctx, lp_ctx, session_info, flags, "sam.ldb"); 96 } 141 97 142 98 /**************************************************************************** … … 181 137 } 182 138 183 /*184 * Finally add the "standard" sids.185 * The only difference between guest and "anonymous"186 * is the addition of Authenticated_Users.187 */188 189 if (session_info_flags & AUTH_SESSION_INFO_DEFAULT_GROUPS) {190 ptoken->sids = talloc_realloc(ptoken, ptoken->sids, struct dom_sid, ptoken->num_sids + 2);191 NT_STATUS_HAVE_NO_MEMORY(ptoken->sids);192 193 if (!dom_sid_parse(SID_WORLD, &ptoken->sids[ptoken->num_sids])) {194 return NT_STATUS_INTERNAL_ERROR;195 }196 ptoken->num_sids++;197 198 if (!dom_sid_parse(SID_NT_NETWORK, &ptoken->sids[ptoken->num_sids])) {199 return NT_STATUS_INTERNAL_ERROR;200 }201 ptoken->num_sids++;202 }203 204 if (session_info_flags & AUTH_SESSION_INFO_AUTHENTICATED) {205 ptoken->sids = talloc_realloc(ptoken, ptoken->sids, struct dom_sid, ptoken->num_sids + 1);206 NT_STATUS_HAVE_NO_MEMORY(ptoken->sids);207 208 if (!dom_sid_parse(SID_NT_AUTHENTICATED_USERS, &ptoken->sids[ptoken->num_sids])) {209 return NT_STATUS_INTERNAL_ERROR;210 }211 ptoken->num_sids++;212 }213 214 139 /* The caller may have requested simple privilages, for example if there isn't a local DB */ 215 140 if (session_info_flags & AUTH_SESSION_INFO_SIMPLE_PRIVILEGES) { -
vendor/current/source4/dsdb/samdb/samdb.h
r740 r988 30 30 struct tevent_context; 31 31 32 struct dsdb_trust_routing_table; 33 32 34 #include "librpc/gen_ndr/security.h" 33 35 #include <ldb.h> … … 54 56 }; 55 57 58 59 /* 60 flags in dsdb_repl_flags to control replication logic 61 */ 62 #define DSDB_REPL_FLAG_PRIORITISE_INCOMING 1 63 #define DSDB_REPL_FLAG_PARTIAL_REPLICA 2 64 #define DSDB_REPL_FLAG_ADD_NCNAME 4 65 #define DSDB_REPL_FLAG_EXPECT_NO_SECRETS 8 66 67 56 68 #define DSDB_CONTROL_REPLICATED_UPDATE_OID "1.3.6.1.4.1.7165.4.3.3" 57 /* DSDB_CONTROL_REPLICATED_UPDATE_OID has NULL data */ 69 struct dsdb_control_replicated_update { 70 uint32_t dsdb_repl_flags; 71 }; 58 72 59 73 #define DSDB_CONTROL_DN_STORAGE_FORMAT_OID "1.3.6.1.4.1.7165.4.3.4" … … 82 96 83 97 #define DSDB_CONTROL_PASSWORD_CHANGE_OID "1.3.6.1.4.1.7165.4.3.10" 84 85 98 struct dsdb_control_password_change { 86 99 const struct samr_Password *old_nt_pwd_hash; … … 103 116 */ 104 117 #define DSDB_CONTROL_CHANGEREPLMETADATA_OID "1.3.6.1.4.1.7165.4.3.14" 118 119 /* passed when we want to get the behaviour of the non-global catalog port */ 120 #define DSDB_CONTROL_NO_GLOBAL_CATALOG "1.3.6.1.4.1.7165.4.3.17" 121 122 /* passed when we want special behaviour for partial replicas */ 123 #define DSDB_CONTROL_PARTIAL_REPLICA "1.3.6.1.4.1.7165.4.3.18" 124 125 /* passed when we want special behaviour for dbcheck */ 126 #define DSDB_CONTROL_DBCHECK "1.3.6.1.4.1.7165.4.3.19" 127 128 /* passed when dbcheck wants to modify a read only replica (very special case) */ 129 #define DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA "1.3.6.1.4.1.7165.4.3.19.1" 130 131 /* passed when importing plain text password on upgrades */ 132 #define DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID "1.3.6.1.4.1.7165.4.3.20" 133 134 /* 135 * passed from the descriptor module in order to 136 * store the recalucated nTSecurityDescriptor without 137 * modifying the replPropertyMetaData. 138 */ 139 #define DSDB_CONTROL_SEC_DESC_PROPAGATION_OID "1.3.6.1.4.1.7165.4.3.21" 140 141 /* 142 * passed when creating a interdomain trust account through LSA 143 * to relax constraints in the samldb ldb module. 144 */ 145 #define DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID "1.3.6.1.4.1.7165.4.3.23" 146 147 /* 148 * Internal control to mark requests as being part of Tombstone restoring 149 * procedure - it requires slightly special behavior like: 150 * - a bit different security checks 151 * - restoring certain attributes to their default values, etc 152 */ 153 #define DSDB_CONTROL_RESTORE_TOMBSTONE_OID "1.3.6.1.4.1.7165.4.3.24" 154 155 /** 156 OID used to allow the replacement of replPropertyMetaData. 157 It is used when the current replmetadata needs only to be re-sorted, but not edited. 158 */ 159 #define DSDB_CONTROL_CHANGEREPLMETADATA_RESORT_OID "1.3.6.1.4.1.7165.4.3.25" 105 160 106 161 #define DSDB_EXTENDED_REPLICATED_OBJECTS_OID "1.3.6.1.4.1.7165.4.4.1" … … 108 163 struct ldb_message *msg; 109 164 struct ldb_val guid_value; 165 struct ldb_val parent_guid_value; 110 166 const char *when_changed; 111 167 struct replPropertyMetaDataBlob *meta_data; 168 169 /* Only used for internal processing in repl_meta_data */ 170 struct ldb_dn *last_known_parent; 112 171 }; 113 172 … … 117 176 * version 0: initial implementation 118 177 */ 119 #define DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION 1178 #define DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION 2 120 179 uint32_t version; 180 181 /* DSDB_REPL_FLAG_* flags */ 182 uint32_t dsdb_repl_flags; 121 183 122 184 struct ldb_dn *partition_dn; … … 130 192 uint32_t linked_attributes_count; 131 193 const struct drsuapi_DsReplicaLinkedAttribute *linked_attributes; 132 };133 134 struct dsdb_naming_fsmo {135 bool we_are_master;136 struct ldb_dn *master_dn;137 };138 139 struct dsdb_pdc_fsmo {140 bool we_are_master;141 struct ldb_dn *master_dn;142 194 }; 143 195 … … 152 204 */ 153 205 #define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2" 206 207 #define DSDB_EXTENDED_SCHEMA_UPGRADE_IN_PROGRESS_OID "1.3.6.1.4.1.7165.4.4.6" 154 208 155 209 #define DSDB_OPENLDAP_DEREFERENCE_CONTROL "1.3.6.1.4.1.4203.666.5.16" … … 175 229 }; 176 230 231 struct samldb_msds_intid_persistant { 232 uint32_t msds_intid; 233 uint64_t usn; 234 }; 235 236 #define SAMLDB_MSDS_INTID_OPAQUE "SAMLDB_MSDS_INTID_OPAQUE" 237 177 238 #define DSDB_PARTITION_DN "@PARTITION" 178 239 #define DSDB_PARTITION_ATTR "partition" … … 183 244 }; 184 245 246 #define DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME "DSDB_OPAQUE_LAST_SCHEMA_UPDATE" 185 247 #define DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME "DSDB_OPAQUE_PARTITION_MODULE_MSG" 186 248 … … 193 255 }; 194 256 257 /* 258 * passed from the descriptor module in order to 259 * store the recalucated nTSecurityDescriptor without 260 * modifying the replPropertyMetaData. 261 */ 262 #define DSDB_EXTENDED_SEC_DESC_PROPAGATION_OID "1.3.6.1.4.1.7165.4.4.7" 263 struct dsdb_extended_sec_desc_propagation_op { 264 struct ldb_dn *nc_root; 265 struct ldb_dn *dn; 266 bool include_self; 267 }; 268 269 #define DSDB_ACL_CHECKS_DIRSYNC_FLAG 0x1 270 #define DSDB_SAMDB_MINIMUM_ALLOWED_RID 1000 271 272 #define DSDB_METADATA_SCHEMA_SEQ_NUM "SCHEMA_SEQ_NUM" 195 273 #endif /* __SAMDB_H__ */
Note:
See TracChangeset
for help on using the changeset viewer.