Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

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  
    22   Unix SMB/CIFS implementation.
    33
    4    endpoint server for the drsuapi pipe
     4   crachnames implementation for the drsuapi pipe
    55   DsCrackNames()
    66
    77   Copyright (C) Stefan Metzmacher 2004
    88   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
     9   Copyright (C) Matthieu Patou <mat@matws.net> 2012
    910
    1011   This program is free software; you can redistribute it and/or modify
     
    2526#include "librpc/gen_ndr/drsuapi.h"
    2627#include "lib/events/events.h"
    27 #include "rpc_server/common/common.h"
    2828#include <ldb.h>
    2929#include <ldb_errors.h>
    30 #include "system/kerberos.h"
    3130#include "auth/kerberos/kerberos.h"
    3231#include "libcli/ldap/ldap_ndr.h"
     
    4443                                   struct ldb_dn *name_dn, const char *name,
    4544                                   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);
    4746static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
    4847                                        enum drsuapi_DsNameFormat format_offered,
     
    5857        krb5_principal principal;
    5958        /* perhaps it's a principal with a realm, so return the right 'domain only' response */
    60         const char *realm;
     59        char *realm;
    6160        ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name,
    6261                                    KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &principal);
     
    6665        }
    6766
    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);
    7068
    7169        info1->dns_domain_name  = talloc_strdup(mem_ctx, realm);
    7270        krb5_free_principal(smb_krb5_context->krb5_context, principal);
     71        free(realm);
    7372
    7473        W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name);
     
    114113
    115114        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)));
    117116                return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    118117        } 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));
    120119                return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    121120        } else if (res->count != 1) {
    122121                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));
    124123                return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    125124        }
     
    127126        spnmappings = ldb_msg_find_element(res->msgs[0], "sPNMappings");
    128127        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));
    130129                talloc_free(tmp_ctx);
    131130                return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
     
    187186        krb5_error_code ret;
    188187        krb5_principal principal;
     188        const krb5_data *component;
    189189        const char *service, *dns_name;
    190190        char *new_service;
     
    196196                                    name, KRB5_PRINCIPAL_PARSE_NO_REALM, &principal);
    197197        if (ret) {
    198                 DEBUG(2, ("Could not parse principal: %s: %s",
     198                DEBUG(2, ("Could not parse principal: %s: %s\n",
    199199                          name, smb_get_krb5_error_message(smb_krb5_context->krb5_context,
    200200                                                           ret, mem_ctx)));
     
    205205
    206206        /* 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) {
    208208                info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    209209                krb5_free_principal(smb_krb5_context->krb5_context, principal);
    210210                return WERR_OK;
    211211        }
    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;
    214218
    215219        /* MAP it */
     
    233237        }
    234238
    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) {
    239242                krb5_free_principal(smb_krb5_context->krb5_context, principal);
    240243                return WERR_NOMEM;
    241244        }
    242245
    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 
    252246        wret = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, format_offered, format_desired,
    253247                                  new_princ, info1);
    254         free(new_princ);
     248        talloc_free(new_princ);
    255249        if (W_ERROR_IS_OK(wret) && (info1->status == DRSUAPI_DS_NAME_STATUS_NOT_FOUND)) {
    256250                info1->status           = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
     
    278272        krb5_error_code ret;
    279273        krb5_principal principal;
    280         const char *realm;
     274        char *realm;
    281275        char *unparsed_name_short;
    282276        const char *domain_attrs[] = { NULL };
     
    296290        }
    297291
    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);
    300294
    301295        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);
    308305
    309306        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)));
    311308                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    312309                krb5_free_principal(smb_krb5_context->krb5_context, principal);
     
    327324        }
    328325
     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         */
    329332        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);
    331336        krb5_free_principal(smb_krb5_context->krb5_context, principal);
    332337
     
    350355                                      format_flags, format_offered, format_desired,
    351356                                      NULL, unparsed_name_short, domain_filter, result_filter,
    352                                       info1);
     357                                      info1, LDB_SCOPE_SUBTREE, NULL);
    353358        free(unparsed_name_short);
    354359
    355360        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 */
     374static 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;
    356451}
    357452
     
    367462        const char *result_filter = NULL;
    368463        struct ldb_dn *name_dn = NULL;
     464        struct ldb_dn *search_dn = NULL;
    369465
    370466        struct smb_krb5_context *smb_krb5_context = NULL;
     467        int scope = LDB_SCOPE_SUBTREE;
    371468
    372469        info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     
    381478         *       - handle format_flags
    382479         */
    383 
     480        if (format_desired == DRSUAPI_DS_NAME_FORMAT_UNKNOWN) {
     481                return WERR_OK;
     482        }
    384483        /* here we need to set the domain_filter and/or the result_filter */
    385484        switch (format_offered) {
     
    401500                                return werr;
    402501                        }
    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                        {
    404506                                return werr;
    405507                        }
     
    412514        {
    413515                char *str, *s, *account;
     516                scope = LDB_SCOPE_ONELEVEL;
    414517
    415518                if (strlen(name) == 0) {
     
    441544                s++;
    442545
    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);
    445550                W_ERROR_HAVE_NO_MEMORY(domain_filter);
    446551
    447552                /* 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;
    455564                        }
    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;
    461567                }
    462568                break;
     
    465571                char *p;
    466572                char *domain;
    467                 struct ldb_dn *dn_domain;
    468573                const char *account = NULL;
    469574
     
    483588                }
    484589
    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 
    489590                domain_filter = talloc_asprintf(mem_ctx,
    490                                                 "(&(&(|(nETBIOSName=%s)(nCName=%s))(objectclass=crossRef))(ncName=*))",
     591                                                "(&(objectClass=crossRef)(netbiosName=%s)(systemFlags:%s:=%u))",
    491592                                                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);
    493595                W_ERROR_HAVE_NO_MEMORY(domain_filter);
    494596                if (account) {
     
    552654                domain_filter = NULL;
    553655                if (!sid) {
     656                        info1->dns_domain_name = NULL;
    554657                        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    555658                        return WERR_OK;
     
    570673
    571674                ret = smb_krb5_init_context(mem_ctx,
    572                                             ldb_get_event_context(sam_ctx),
    573675                                            (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
    574676                                            &smb_krb5_context);
     
    587689                domain_filter = NULL;
    588690
    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);
    591703                if (ret) {
    592704                        krb5_free_principal(smb_krb5_context->krb5_context, principal);
     
    607719                krb5_principal principal;
    608720                char *unparsed_name_short;
     721                const krb5_data *component;
    609722                char *service;
    610723
    611724                ret = smb_krb5_init_context(mem_ctx,
    612                                             ldb_get_event_context(sam_ctx),
    613725                                            (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
    614726                                            &smb_krb5_context);
     
    619731
    620732                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) {
    622736                        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
    623737                        krb5_free_principal(smb_krb5_context->krb5_context, principal);
     
    642756                }
    643757
    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)) {
    646764                        /* the 'cn' attribute is just the leading part of the name */
    647765                        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, "."));
    650771                        if (computer_name == NULL) {
    651772                                krb5_free_principal(smb_krb5_context->krb5_context, principal);
     
    683804                                    name_dn, name,
    684805                                    domain_filter, result_filter,
    685                                     info1);
     806                                    info1, scope, search_dn);
    686807}
    687808
     
    735856                                   struct ldb_dn *name_dn, const char *name,
    736857                                   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)
    738860{
    739861        int ldb_ret;
     
    803925
    804926                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)));
    806928                        info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    807929                        return WERR_OK;
     
    831953                struct ldb_result *res;
    832954                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                        }
    838980                } 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                }
    843986                /* search with the 'phantom root' flag */
    844987                ret = dsdb_search(sam_ctx, mem_ctx, &res,
    845                                   search_dn,
    846                                   LDB_SCOPE_SUBTREE,
     988                                  real_search_dn,
     989                                  scope,
    847990                                  result_attrs,
    848                                   DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
     991                                  dsdb_flags,
    849992                                  "%s", result_filter);
    850993                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,
    852997                                  ldb_errstring(sam_ctx)));
    853998                        info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
     
    8661011        } else {
    8671012                /* 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"));
    8691014                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    8701015                return WERR_OK;
     
    8931038                return WERR_OK;
    8941039        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)));
    8961041                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    8971042                return WERR_OK;
     
    9241069                        }
    9251070                }
     1071                /* FALL TROUGH */
    9261072                default:
    9271073                        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
     
    9621108                const struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, result, "objectSid");
    9631109                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.  */
    9671120                        ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
    9681121                                                     partitions_basedn,
     
    9721125
    9731126                        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)));
    9751128                                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    9761129                                return WERR_OK;
     
    10131166
    10141167                                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)));
    10161169                                        info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    10171170                                        return WERR_OK;
     
    10361189
    10371190                                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)));
    10391192                                        info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    10401193                                        return WERR_OK;
     
    10911244        case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN:
    10921245        case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
     1246                info1->dns_domain_name = NULL;
    10931247                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    10941248                return WERR_OK;
     
    13461500                                                                   server_dn);
    13471501                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",
    13491503                                  ldb_dn_get_linearized(server_dn)));
    13501504                }
     
    13661520        WERROR status;
    13671521
    1368         *ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
     1522        *ctr1 = talloc_zero(mem_ctx, struct drsuapi_DsNameCtr1);
    13691523        W_ERROR_HAVE_NO_MEMORY(*ctr1);
    13701524
     
    13901544        return WERR_OK;
    13911545}
     1546
     1547WERROR 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  
    4040#include "param/param.h"
    4141#include "dsdb/samdb/ldb_modules/util.h"
    42 #include "dsdb/samdb/ldb_modules/schema.h"
    4342#include "lib/util/tsort.h"
    4443#include "system/kerberos.h"
     
    5150
    5251struct acl_private {
    53         bool acl_perform;
     52        bool acl_search;
    5453        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;
    5558};
    5659
     
    5962        struct ldb_request *req;
    6063        bool am_system;
     64        bool am_administrator;
     65        bool modify_search;
     66        bool constructed_attrs;
    6167        bool allowedAttributes;
    6268        bool allowedAttributesEffective;
     
    7480        struct acl_private *data;
    7581        int ret;
    76         unsigned int i;
     82        unsigned int i, n, j;
    7783        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        };
    7988        struct ldb_result *res;
    8089        struct ldb_message *msg;
     
    9099        }
    91100
    92         data = talloc(module, struct acl_private);
     101        data = talloc_zero(module, struct acl_private);
    93102        if (data == NULL) {
    94103                return ldb_oom(ldb);
    95104        }
    96105
    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);
    100108        ldb_module_set_private(module, data);
    101109
     
    108116                                    ldb_dn_new(mem_ctx, ldb, "@KLUDGEACL"),
    109117                                    attrs,
    110                                     DSDB_FLAG_NEXT_MODULE, NULL);
     118                                    DSDB_FLAG_NEXT_MODULE |
     119                                    DSDB_FLAG_AS_SYSTEM,
     120                                    NULL);
    111121        if (ret != LDB_SUCCESS) {
    112122                goto done;
     
    127137                goto done;
    128138        }
    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);
    130142        if (!data->password_attrs) {
    131143                talloc_free(mem_ctx);
    132144                return ldb_oom(ldb);
    133145        }
     146
     147        n = 0;
    134148        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;
    136150                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;
    139177
    140178done:
     
    154192        const char **attr_list;
    155193        int i, ret;
     194        const struct dsdb_class *objectclass;
    156195
    157196        /* If we don't have a schema yet, we can't do anything... */
     
    178217                return LDB_ERR_OPERATIONS_ERROR;
    179218        }
     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
    180232        if (ac->allowedAttributes) {
    181233                for (i=0; attr_list && attr_list[i]; i++) {
     
    225277                                                            sid,
    226278                                                            SEC_ADS_WRITE_PROP,
    227                                                             attr);
     279                                                            attr,
     280                                                            objectclass);
    228281                        if (ret == LDB_SUCCESS) {
    229282                                ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]);
     
    336389
    337390                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);
    345404                        if (ret == LDB_SUCCESS) {
    346405                                ldb_msg_add_string(msg, "allowedChildClassesEffective",
     
    374433                                 struct acl_context *ac)
    375434{
     435        struct ldb_context *ldb = ldb_module_get_ctx(module);
    376436        struct ldb_message_element *rightsEffective;
    377437        int ret;
     
    394454        if (ac->am_system || as_system) {
    395455                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
    398471                /* 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);
    400473                if (ret != LDB_SUCCESS) {
    401474                        return ret;
     
    407480                                                    sid,
    408481                                                    SEC_STD_WRITE_OWNER,
    409                                                     NULL);
     482                                                    attr,
     483                                                    objectclass);
    410484                if (ret == LDB_SUCCESS) {
    411485                        flags |= SECINFO_OWNER | SECINFO_GROUP;
     
    416490                                                    sid,
    417491                                                    SEC_STD_WRITE_DAC,
    418                                                     NULL);
     492                                                    attr,
     493                                                    objectclass);
    419494                if (ret == LDB_SUCCESS) {
    420495                        flags |= SECINFO_DACL;
     
    425500                                                    sid,
    426501                                                    SEC_FLAG_SYSTEM_SECURITY,
    427                                                     NULL);
     502                                                    attr,
     503                                                    objectclass);
    428504                if (ret == LDB_SUCCESS) {
    429505                        flags |= SECINFO_SACL;
     
    450526        char *serviceType;
    451527        char *serviceName;
    452         const char *realm;
    453528        const char *forest_name = samdb_forest_name(ldb, mem_ctx);
    454529        const char *base_domain = samdb_default_domain_name(ldb, mem_ctx);
     
    458533                (userAccountControl & UF_PARTIAL_SECRETS_ACCOUNT);
    459534
     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
    460541        kerr = smb_krb5_init_context_basic(mem_ctx,
    461542                                           lp_ctx,
     
    472553        }
    473554
    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);
    479566        } else {
    480567                serviceName = NULL;
     
    504591        /* instanceName can be samAccountName without $ or dnsHostName
    505592         * 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) {
    507595                goto success;
    508         } else if (strcasecmp(instanceName, dnsHostName) == 0) {
     596        } else if (dnsHostName != NULL && strcasecmp(instanceName, dnsHostName) == 0) {
    509597                goto success;
    510598        } else if (is_dc) {
     
    534622                         struct security_descriptor *sd,
    535623                         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)
    538626{
    539627        int ret;
     
    569657                                          sid,
    570658                                          SEC_ADS_WRITE_PROP,
    571                                           attr) == LDB_SUCCESS) {
     659                                          attr, objectclass) == LDB_SUCCESS) {
    572660                talloc_free(tmp_ctx);
    573661                return LDB_SUCCESS;
     
    592680                                    acl_attrs,
    593681                                    DSDB_FLAG_NEXT_MODULE |
    594                                     DSDB_SEARCH_SHOW_DELETED, req);
     682                                    DSDB_FLAG_AS_SYSTEM |
     683                                    DSDB_SEARCH_SHOW_RECYCLED,
     684                                    req);
    595685        if (ret != LDB_SUCCESS) {
    596686                talloc_free(tmp_ctx);
     
    606696                                 LDB_SCOPE_ONELEVEL,
    607697                                 netbios_attrs,
    608                                  DSDB_FLAG_NEXT_MODULE,
     698                                 DSDB_FLAG_NEXT_MODULE |
     699                                 DSDB_FLAG_AS_SYSTEM,
    609700                                 req,
    610701                                 "(ncName=%s)",
     
    655746{
    656747        int ret;
    657         struct ldb_dn *parent = ldb_dn_get_parent(req, req->op.add.message->dn);
     748        struct ldb_dn *parent;
    658749        struct ldb_context *ldb;
    659750        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);
    665761        if (as_system != NULL) {
    666762                as_system->critical = 0;
     
    670766                return ldb_next_request(module, req);
    671767        }
    672         if (ldb_dn_is_special(req->op.add.message->dn)) {
    673                 return ldb_next_request(module, req);
    674         }
    675768
    676769        ldb = ldb_module_get_ctx(module);
    677770
    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        }
    690775
    691776        schema = dsdb_get_schema(ldb, req);
     
    694779        }
    695780
    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));
    699786                return ldb_module_done(req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
    700787        }
    701788
    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));
    706872                return ret;
    707873        }
     
    715881                                     struct security_descriptor *sd,
    716882                                     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)
    719885{
    720886        int ret;
     
    729895                                          sid,
    730896                                          SEC_ADS_WRITE_PROP,
    731                                           attr) == LDB_SUCCESS) {
     897                                          attr, objectclass) == LDB_SUCCESS) {
    732898                return LDB_SUCCESS;
    733899        }
     
    771937                                     struct security_descriptor *sd,
    772938                                     struct dom_sid *sid,
    773                                      const struct GUID *oc_guid,
     939                                     const struct dsdb_class *objectclass,
    774940                                     bool userPassword)
    775941{
     
    8511017}
    8521018
     1019
    8531020static int acl_modify(struct ldb_module *module, struct ldb_request *req)
    8541021{
     
    8571024        const struct dsdb_schema *schema;
    8581025        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;
    8641027        struct ldb_result *acl_res;
    8651028        struct security_descriptor *sd;
    8661029        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;
    8701035        static const char *acl_attrs[] = {
    8711036                "nTSecurityDescriptor",
     
    8751040        };
    8761041
     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);
    8771047        if (as_system != NULL) {
    8781048                as_system->critical = 0;
    8791049        }
    8801050
     1051        is_undelete = ldb_request_get_control(req, DSDB_CONTROL_RESTORE_TOMBSTONE_OID);
     1052
    8811053        /* 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));
    8851056        }
    8861057        if (dsdb_module_am_system(module) || as_system) {
    8871058                return ldb_next_request(module, req);
    8881059        }
    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,
    8931067                                    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);
    8951072
    8961073        if (ret != LDB_SUCCESS) {
    8971074                goto fail;
    8981075        }
     1076
     1077        userPassword = dsdb_user_password_support(module, req, req);
    8991078
    9001079        schema = dsdb_get_schema(ldb, tmp_ctx);
    9011080        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.");
    9041084        }
    9051085
     
    9151095        }
    9161096
    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) {
    9191099                talloc_free(tmp_ctx);
    9201100                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.");
    9221102        }
    9231103        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];
    9311106                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));
    9451152                                dsdb_acl_debug(sd,
    9461153                                               acl_user_token(module),
    947                                                req->op.mod.message->dn,
     1154                                               msg->dn,
    9481155                                               true,
    9491156                                               10);
     
    9511158                                goto fail;
    9521159                        }
    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) {
    9551161                        ret = acl_check_self_membership(tmp_ctx,
    9561162                                                        module,
     
    9581164                                                        sd,
    9591165                                                        sid,
    960                                                         guid,
    961                                                         attr);
     1166                                                        attr,
     1167                                                        objectclass);
    9621168                        if (ret != LDB_SUCCESS) {
    9631169                                goto fail;
    9641170                        }
    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) {
    9671172                        /* this one is not affected by any rights, we should let it through
    9681173                           so that passwords_hash returns the correct error */
    9691174                        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) {
    9741178                        ret = acl_check_password_rights(tmp_ctx,
    9751179                                                        module,
     
    9771181                                                        sd,
    9781182                                                        sid,
    979                                                         guid,
     1183                                                        objectclass,
    9801184                                                        userPassword);
    9811185                        if (ret != LDB_SUCCESS) {
    9821186                                goto fail;
    9831187                        }
    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) {
    9851189                        ret = acl_check_spn(tmp_ctx,
    9861190                                            module,
     
    9881192                                            sd,
    9891193                                            sid,
    990                                             guid,
    991                                             attr);
     1194                                            attr,
     1195                                            objectclass);
    9921196                        if (ret != LDB_SUCCESS) {
    9931197                                goto fail;
    9941198                        }
     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;
    9951207                } 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;
    10081225                                goto fail;
    10091226                        }
    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;
    10441227                }
    10451228        }
     
    10581241{
    10591242        int ret;
    1060         struct ldb_dn *parent = ldb_dn_get_parent(req, req->op.del.dn);
     1243        struct ldb_dn *parent;
    10611244        struct ldb_context *ldb;
    10621245        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);
    10651264        if (as_system != NULL) {
    10661265                as_system->critical = 0;
    10671266        }
    10681267
    1069         DEBUG(10, ("ldb:acl_delete: %s\n", ldb_dn_get_linearized(req->op.del.dn)));
    10701268        if (dsdb_module_am_system(module) || as_system) {
    10711269                return ldb_next_request(module, req);
    10721270        }
    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)));
    10761273
    10771274        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        }
    10781280
    10791281        /* Make sure we aren't deleting a NC */
     
    10921294        talloc_free(nc_root);
    10931295
     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
    10941340        /* 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);
    10971344        if (ret == LDB_SUCCESS) {
    10981345                return ldb_next_request(module, req);
     
    11021349         * child on the parent */
    11031350        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);
    11051354        if (ret != LDB_SUCCESS) {
    11061355                return ret;
     
    11081357
    11091358        return ldb_next_request(module, req);
     1359}
     1360static 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);
    11101395}
    11111396
     
    11131398{
    11141399        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;
    11171402        const struct dsdb_schema *schema;
     1403        const struct dsdb_class *objectclass;
     1404        const struct dsdb_attribute *attr = NULL;
    11181405        struct ldb_context *ldb;
    11191406        struct security_descriptor *sd = NULL;
    11201407        struct dom_sid *sid = NULL;
    11211408        struct ldb_result *acl_res;
    1122         const struct GUID *guid;
    11231409        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;
    11301413        const char *rdn_name;
    11311414        static const char *acl_attrs[] = {
     
    11361419        };
    11371420
     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);
    11381426        if (as_system != NULL) {
    11391427                as_system->critical = 0;
     
    11441432                return ldb_next_request(module, req);
    11451433        }
    1146         if (ldb_dn_is_special(req->op.rename.olddn)) {
    1147                 return ldb_next_request(module, req);
    1148         }
    11491434
    11501435        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        }
    11511450
    11521451        /* Make sure we aren't renaming/moving a NC */
     
    11631462                                       LDB_ERR_UNWILLING_TO_PERFORM);
    11641463        }
     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        }
    11651475        talloc_free(nc_root);
    11661476
     
    11701480                                    req->op.rename.olddn, acl_attrs,
    11711481                                    DSDB_FLAG_NEXT_MODULE |
     1482                                    DSDB_FLAG_AS_SYSTEM |
    11721483                                    DSDB_SEARCH_SHOW_RECYCLED, req);
    11731484        /* we sould be able to find the parent */
     
    11791490        }
    11801491
     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
    11811502        schema = dsdb_get_schema(ldb, acl_res);
    11821503        if (!schema) {
     
    11851506        }
    11861507
    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) {
    11901519                talloc_free(tmp_ctx);
    11911520                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);
    12361531                dsdb_acl_debug(sd,
    12371532                          acl_user_token(module),
     
    12431538        }
    12441539
     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
    12451569        if (ldb_dn_compare(oldparent, newparent) == 0) {
    12461570                /* regular rename, not move, nothing more to do */
     
    12501574
    12511575        /* 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));
    12641583                talloc_free(tmp_ctx);
    12651584                return ret;
    12661585        }
     1586
    12671587        /* 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        }
    12871609        talloc_free(tmp_ctx);
    12881610
     
    12901612}
    12911613
     1614static 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
    12921671static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares)
    12931672{
    1294         struct ldb_context *ldb;
    12951673        struct acl_context *ac;
    12961674        struct acl_private *data;
     
    13071685        ac = talloc_get_type(req->context, struct acl_context);
    13081686        data = talloc_get_type(ldb_module_get_private(ac->module), struct acl_private);
    1309         ldb = ldb_module_get_ctx(ac->module);
    1310 
    13111687        if (!ares) {
    13121688                return ldb_module_done(ac->req, NULL, NULL,
     
    13201696        switch (ares->type) {
    13211697        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) {
    13271699                        ret = dsdb_module_search_dn(ac->module, ac, &acl_res, ares->message->dn,
    13281700                                                    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);
    13301705                        if (ret != LDB_SUCCESS) {
    13311706                                return ldb_module_done(ac->req, NULL, NULL, ret);
    13321707                        }
    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;
    13371764                                }
    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
    13731787                return ldb_module_send_entry(ac->req, ares->message, ares->controls);
    13741788
     
    13881802        struct ldb_context *ldb;
    13891803        struct acl_context *ac;
     1804        struct ldb_parse_tree *down_tree;
    13901805        struct ldb_request *down_req;
    13911806        struct acl_private *data;
     
    13931808        unsigned int i;
    13941809
     1810        if (ldb_dn_is_special(req->op.search.base)) {
     1811                return ldb_next_request(module, req);
     1812        }
     1813
    13951814        ldb = ldb_module_get_ctx(module);
    13961815
     
    14041823        ac->req = req;
    14051824        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;
    14061828        ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes");
    14071829        ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective");
     
    14091831        ac->allowedChildClassesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedChildClassesEffective");
    14101832        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;
    14121834        ac->schema = dsdb_get_schema(ldb, ac);
    14131835
    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        }
    14171845        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
    14331891        ret = ldb_build_search_req_ex(&down_req,
    14341892                                      ldb, ac,
    14351893                                      req->op.search.base,
    14361894                                      req->op.search.scope,
    1437                                       req->op.search.tree,
     1895                                      down_tree,
    14381896                                      req->op.search.attrs,
    14391897                                      req->controls,
  • vendor/current/source4/dsdb/samdb/ldb_modules/acl_read.c

    r740 r988  
    4545        const char * const *attrs;
    4646        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;
    5053};
    5154
     
    5558
    5659static void aclread_mark_inaccesslible(struct ldb_message_element *el) {
    57          el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
     60        el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
    5861}
    5962
     
    6467static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares)
    6568{
    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,
    99122                                                         "instanceType", 0);
    100                  if (!ldb_dn_is_null(msg->dn) && !(instanceType & INSTANCE_TYPE_IS_NC_HEAD))
    101                  {
     123                if (!ldb_dn_is_null(msg->dn) && !(instanceType & INSTANCE_TYPE_IS_NC_HEAD))
     124                {
    102125                        /* the object has a parent, so we have to check for visibility */
    103126                        struct ldb_dn *parent_dn = ldb_dn_get_parent(tmp_ctx, msg->dn);
     127
    104128                        ret = dsdb_module_check_access_on_dn(ac->module,
    105129                                                             tmp_ctx,
     
    111135                                return LDB_SUCCESS;
    112136                        } 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));
    113142                                goto fail;
    114143                        }
    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",
    130162                                              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,
    209305                                        ares->response, LDB_SUCCESS);
    210306
    211          }
    212          return LDB_SUCCESS;
     307        }
     308        return LDB_SUCCESS;
    213309fail:
    214          talloc_free(tmp_ctx);
    215          return ldb_module_done(ac->req, NULL, NULL, ret);
     310        talloc_free(tmp_ctx);
     311        return ldb_module_done(ac->req, NULL, NULL, ret);
    216312}
    217313
     
    224320        struct ldb_request *down_req;
    225321        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);
    226323        struct ldb_result *res;
    227324        struct aclread_private *p;
     325        bool need_sd = false;
     326        bool explicit_sd_flags = false;
    228327        bool is_untrusted = ldb_req_is_untrusted(req);
     328        static const char * const _all_attrs[] = { "*", NULL };
     329        bool all_attrs = false;
    229330        const char * const *attrs = NULL;
    230331        uint32_t instanceType;
    231332        static const char *acl_attrs[] = {
    232                  "instanceType",
    233                  NULL
     333                "instanceType",
     334                NULL
    234335        };
    235336
     
    254355                                            acl_attrs,
    255356                                            DSDB_FLAG_NEXT_MODULE |
    256                                             DSDB_SEARCH_SHOW_DELETED, req);
     357                                            DSDB_FLAG_AS_SYSTEM |
     358                                            DSDB_SEARCH_SHOW_RECYCLED,
     359                                            req);
    257360                if (ret != LDB_SUCCESS) {
    258361                        return ldb_error(ldb, ret,
    259                                          "acl_read: Error retrieving instanceType for base.");
     362                                        "acl_read: Error retrieving instanceType for base.");
    260363                }
    261364                instanceType = ldb_msg_find_attr_as_uint(res->msgs[0],
    262                                                          "instanceType", 0);
     365                                                        "instanceType", 0);
    263366                if (instanceType != 0 && !(instanceType & INSTANCE_TYPE_IS_NC_HEAD))
    264367                {
     
    284387        ac->req = req;
    285388        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        }
    286394        if (!ac->schema) {
    287395                return ldb_operr(ldb);
    288396        }
    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;
    296431                }
    297432                if (!ldb_attr_in_list(req->op.search.attrs, "objectSid")) {
    298                         ac->object_sid = true;
    299433                        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) {
    309449                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
    311456        ac->attrs = req->op.search.attrs;
    312457        ret = ldb_build_search_req_ex(&down_req,
     
    334479                return ldb_module_oom(module);
    335480        }
    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);
    337482        ldb_module_set_private(module, p);
    338483        return ldb_next_init(module);
  • vendor/current/source4/dsdb/samdb/ldb_modules/acl_util.c

    r740 r988  
    7575                                    acl_attrs,
    7676                                    DSDB_FLAG_NEXT_MODULE |
     77                                    DSDB_FLAG_AS_SYSTEM |
    7778                                    DSDB_SEARCH_SHOW_RECYCLED,
    7879                                    parent);
    7980        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));
    8184                return ret;
    8285        }
     
    8992}
    9093
    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                 NULL
    104         };
    105         struct ldb_context *ldb = ldb_module_get_ctx(module);
    106         struct auth_session_info *session_info
    107                 = (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 
    13094int acl_check_access_on_attribute(struct ldb_module *module,
    13195                                  TALLOC_CTX *mem_ctx,
     
    13397                                  struct dom_sid *rp_sid,
    13498                                  uint32_t access_mask,
    135                                   const struct dsdb_attribute *attr)
     99                                  const struct dsdb_attribute *attr,
     100                                  const struct dsdb_class *objectclass)
    136101{
    137102        int ret;
     
    142107        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    143108        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;
    161126                }
    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
    172137        status = sec_access_check_ds(sd, token,
    173138                                     access_mask,
     
    188153}
    189154
     155int 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;
     189fail:
     190        talloc_free(tmp_ctx);
     191        return ldb_operr(ldb_module_get_ctx(module));
     192}
    190193
    191194/* checks for validated writes */
     
    201204        uint32_t access_granted;
    202205        struct object_tree *root = NULL;
    203         struct object_tree *new_node = NULL;
    204206        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    205207
     
    207209
    208210        if (!insert_in_object_tree(tmp_ctx, &right, right_type,
    209                                    &root, &new_node)) {
     211                                   NULL, &root)) {
    210212                DEBUG(10, ("acl_ext_right: cannot add to object tree\n"));
    211213                talloc_free(tmp_ctx);
     
    239241                               session_info->info->account_name);
    240242}
     243
     244uint32_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
     281int 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  
    4040#include "librpc/gen_ndr/ndr_security.h"
    4141#include "libcli/security/security.h"
    42 #include "dsdb/samdb/ldb_modules/schema.h"
    4342#include "auth/auth.h"
    4443#include "param/param.h"
    45 #include "util.h"
     44#include "dsdb/samdb/ldb_modules/util.h"
     45#include "lib/util/binsearch.h"
     46
     47struct 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};
    4656
    4757struct descriptor_data {
    48         int _dummy;
     58        TALLOC_CTX *trans_mem;
     59        struct descriptor_changes *changes;
    4960};
    5061
     
    5869        struct ldb_message_element *sd_element;
    5970        struct ldb_val *sd_val;
     71        uint32_t sd_flags;
    6072        int (*step_fn)(struct descriptor_context *);
    6173};
    6274
    63 struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,
     75static struct dom_sid *get_default_ag(TALLOC_CTX *mem_ctx,
    6476                               struct ldb_dn *dn,
    6577                               struct security_token *token,
     
    88100                } else if (security_token_has_sid(token, da_sid)) {
    89101                        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);
    90104                } else {
    91105                        dag_sid = NULL;
     
    96110                } else if (security_token_has_sid(token, da_sid)) {
    97111                        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);
    98114                } else {
    99115                        dag_sid = NULL;
     
    104120                } else if (security_token_has_sid(token, ea_sid)) {
    105121                                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);
    106124                } else {
    107125                        dag_sid = NULL;
     
    136154                                         struct dom_sid *dag)
    137155{
    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;
    143166}
    144167
     
    159182
    160183        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                }
    162187                final_sd->type |= new_sd->type & SEC_DESC_OWNER_DEFAULTED;
    163188        }
    164189        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                }
    166193                final_sd->type |= old_sd->type & SEC_DESC_OWNER_DEFAULTED;
    167194        }
    168195
    169196        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                }
    171200                final_sd->type |= new_sd->type & SEC_DESC_GROUP_DEFAULTED;
    172201        }
    173202        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                }
    175206                final_sd->type |= old_sd->type & SEC_DESC_GROUP_DEFAULTED;
    176207        }
     
    231262        struct dom_sid *default_owner;
    232263        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        }
    233275
    234276        if (object) {
     
    246288                }
    247289        } else {
    248                 user_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
     290                user_descriptor = default_descriptor;
    249291        }
    250292
     
    279321        }
    280322
     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
    281389        default_owner = get_default_ag(mem_ctx, dn,
    282390                                       session_info->security_token, ldb);
    283391        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,
    286399                                            session_info->security_token,
    287400                                            default_owner, default_group,
     
    386499{
    387500        struct descriptor_context *ac;
    388         struct ldb_control *sd_control;
    389501        struct ldb_val *sd_val = NULL;
    390502        struct ldb_message_element *sd_el;
    391503        DATA_BLOB *show_sd;
    392         int ret;
    393         uint32_t sd_flags = 0;
     504        int ret = LDB_SUCCESS;
    394505
    395506        ac = talloc_get_type(req->context, struct descriptor_context);
     
    404515        }
    405516
    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 bits
    414                            equals all 4 bits */
    415                         sd_flags = 0xF;
    416                 }
    417         }
    418 
    419517        switch (ares->type) {
    420518        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
    427524                if (sd_val) {
    428525                        show_sd = descr_get_descriptor_to_show(ac->module, ac->req,
    429                                                                sd_val, sd_flags);
     526                                                               sd_val, ac->sd_flags);
    430527                        if (!show_sd) {
    431528                                ret = LDB_ERR_OPERATIONS_ERROR;
     
    455552static int descriptor_add(struct ldb_module *module, struct ldb_request *req)
    456553{
    457         struct ldb_context *ldb;
     554        struct ldb_context *ldb = ldb_module_get_ctx(module);
    458555        struct ldb_request *add_req;
    459556        struct ldb_message *msg;
     
    461558        const struct ldb_val *parent_sd = NULL;
    462559        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;
    464562        struct ldb_message_element *objectclass_element, *sd_element;
    465563        int ret;
     
    468566        const struct dsdb_class *objectclass;
    469567        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
    473577        user_sd = ldb_msg_find_ldb_val(req->op.add.message, "nTSecurityDescriptor");
    474578        sd_element = ldb_msg_find_element(req->op.add.message, "nTSecurityDescriptor");
     
    480584        ldb_debug(ldb, LDB_DEBUG_TRACE,"descriptor_add: %s\n", ldb_dn_get_linearized(dn));
    481585
    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
    503619                /* we aren't any NC */
    504620                ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
    505621                                            parent_attrs,
    506                                             DSDB_FLAG_NEXT_MODULE,
     622                                            DSDB_FLAG_NEXT_MODULE |
     623                                            DSDB_FLAG_AS_SYSTEM |
     624                                            DSDB_SEARCH_SHOW_RECYCLED,
    507625                                            req);
    508626                if (ret != LDB_SUCCESS) {
     
    524642        }
    525643
    526         objectclass = get_last_structural_class(schema, objectclass_element, req);
     644        objectclass = dsdb_get_last_structural_class(schema,
     645                                                     objectclass_element);
    527646        if (objectclass == NULL) {
    528647                return ldb_operr(ldb);
    529648        }
    530649
     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
    531656        sd = get_new_descriptor(module, dn, req,
    532657                                objectclass, parent_sd,
    533                                 user_sd, NULL, 0);
     658                                user_sd, NULL, sd_flags);
     659        if (sd == NULL) {
     660                return ldb_operr(ldb);
     661        }
    534662        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;
    545674                }
    546675        }
     
    562691static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
    563692{
    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);
    566694        struct ldb_request *mod_req;
    567695        struct ldb_message *msg;
     
    570698        const struct ldb_val *parent_sd = NULL;
    571699        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;
    574703        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);
    576707        const struct dsdb_schema *schema;
    577708        DATA_BLOB *sd;
     
    581712                                                      "instanceType",
    582713                                                      "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;
    595716
    596717        /* do not manipulate our control entries */
     
    599720        }
    600721
     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
    601770        ret = dsdb_module_search_dn(module, req, &current_res, dn,
    602771                                    current_attrs,
    603                                     DSDB_FLAG_NEXT_MODULE,
     772                                    DSDB_FLAG_NEXT_MODULE |
     773                                    DSDB_FLAG_AS_SYSTEM |
     774                                    DSDB_SEARCH_SHOW_RECYCLED,
    604775                                    req);
    605776        if (ret != LDB_SUCCESS) {
     
    621792                ret = dsdb_module_search_dn(module, req, &parent_res, parent_dn,
    622793                                            parent_attrs,
    623                                             DSDB_FLAG_NEXT_MODULE,
     794                                            DSDB_FLAG_NEXT_MODULE |
     795                                            DSDB_FLAG_AS_SYSTEM |
     796                                            DSDB_SEARCH_SHOW_RECYCLED,
    624797                                            req);
    625798                if (ret != LDB_SUCCESS) {
     
    633806                parent_sd = ldb_msg_find_ldb_val(parent_res->msgs[0], "nTSecurityDescriptor");
    634807        }
    635         sd_flags_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID);
    636808
    637809        schema = dsdb_get_schema(ldb, req);
     
    642814        }
    643815
    644         objectclass = get_last_structural_class(schema, objectclass_element, req);
     816        objectclass = dsdb_get_last_structural_class(schema,
     817                                                     objectclass_element);
    645818        if (objectclass == NULL) {
    646819                return ldb_operr(ldb);
    647820        }
    648821
    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;
    657833        }
    658834
     
    660836                                objectclass, parent_sd,
    661837                                user_sd, old_sd, sd_flags);
     838        if (sd == NULL) {
     839                return ldb_operr(ldb);
     840        }
    662841        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;
    693887        }
    694888
     
    711905        int ret;
    712906        struct ldb_context *ldb;
    713         struct ldb_control *sd_control;
    714907        struct ldb_request *down_req;
    715908        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) {
    719920                return ldb_next_request(module, req);
    720921        }
     
    725926                return ldb_operr(ldb);
    726927        }
     928        ac->sd_flags = sd_flags;
    727929
    728930        ret = ldb_build_search_req_ex(&down_req, ldb, ac,
     
    738940                return ret;
    739941        }
    740         /* mark it as handled */
    741         if (sd_control) {
    742                 sd_control->critical = 0;
    743         }
    744942
    745943        return ldb_next_request(ac->module, down_req);
    746944}
    747 /* TODO */
     945
    748946static int descriptor_rename(struct ldb_module *module, struct ldb_request *req)
    749947{
    750948        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;
    752952
    753953        /* do not manipulate our control entries */
     
    756956        }
    757957
     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
    758976        return ldb_next_request(module, req);
    759977}
    760978
     979static 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
     1060static 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
    7611069static int descriptor_init(struct ldb_module *module)
    7621070{
    763         int ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
    7641071        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);
    7651076        if (ret != LDB_SUCCESS) {
    7661077                ldb_debug(ldb, LDB_DEBUG_ERROR,
     
    7681079                return ldb_operr(ldb);
    7691080        }
     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
    7701089        return ldb_next_init(module);
    7711090}
    7721091
     1092static 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
     1159static 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
     1171static 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
     1180static 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
     1326static 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
     1345static 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
     1369static 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
     1381static 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}
    7731392
    7741393static 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,
    7811405};
    7821406
  • vendor/current/source4/dsdb/samdb/ldb_modules/extended_dn_in.c

    r740 r988  
    3434#include <ldb_errors.h>
    3535#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"
    3639
    3740/*
     
    4548        struct ldb_request *req;
    4649        struct ldb_dn *basedn;
     50        struct ldb_dn *dn;
    4751        char *wellknown_object;
    4852        int extended_type;
    4953};
     54
     55static const char *wkattr[] = {
     56        "wellKnownObjects",
     57        "otherWellKnownObjects",
     58        NULL
     59};
     60
     61static const struct ldb_module_ops ldb_extended_dn_in_openldap_module_ops;
    5062
    5163/* An extra layer of indirection because LDB does not allow the original request to be altered */
     
    8698        struct ldb_message_element *el;
    8799        int ret;
    88         unsigned int i;
     100        unsigned int i, j;
    89101        size_t wkn_len = 0;
    90102        char *valstr = NULL;
     
    104116        switch (ares->type) {
    105117        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
    106130                if (!ac->wellknown_object) {
    107131                        ac->basedn = talloc_steal(ac, ares->message->dn);
     
    111135                wkn_len = strlen(ac->wellknown_object);
    112136
    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;
    131142                                continue;
    132143                        }
    133144
    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                        }
    136166                }
    137167
     
    157187                if (!ac->basedn) {
    158188                        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));
    160190                        ldb_set_errstring(ldb_module_get_ctx(ac->module), str);
    161191                        return ldb_module_done(ac->req, NULL, NULL,
     
    249279}
    250280
     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*/
     299static 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
     316struct 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 */
     328static 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 */
     342static 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 */
     514static 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 */
    251570static int extended_dn_in_fix(struct ldb_module *module, struct ldb_request *req, struct ldb_dn *dn)
    252571{
     
    262581                NULL
    263582        };
    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        }
    269601
    270602        if (!ldb_dn_has_extended(dn)) {
     
    274606                /* It looks like we need to map the DN */
    275607                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)) {
    298610                        return ldb_error(ldb_module_get_ctx(module),
    299611                                         LDB_ERR_INVALID_DN_SYNTAX, "invalid number of DN components");
     
    304616                wkguid_val = ldb_dn_get_extended_component(dn, "WKGUID");
    305617
    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)",
    310638                                                         ldb_binary_encode(req, *sid_val));
    311639                        if (!base_dn_filter) {
     
    314642                        base_dn_scope = LDB_SCOPE_SUBTREE;
    315643                        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 
    329644
    330645                } else if (wkguid_val) {
     
    374689                ac->module = module;
    375690                ac->req = req;
     691                ac->dn = dn;
    376692                ac->basedn = NULL;  /* Filled in if the search finds the DN by SID/GUID etc */
    377693                ac->wellknown_object = wellknown_object;
     
    386702                                           base_dn_filter,
    387703                                           base_dn_attrs,
    388                                            req->controls,
     704                                           NULL,
    389705                                           ac, extended_base_callback,
    390706                                           req);
     
    394710                }
    395711
    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;
    407715                }
    408716
     
    440748};
    441749
     750static 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
    442758int ldb_extended_dn_in_module_init(const char *version)
    443759{
     760        int ret;
    444761        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        }
    445766        return ldb_register_module(&ldb_extended_dn_in_module_ops);
    446767}
  • vendor/current/source4/dsdb/samdb/ldb_modules/extended_dn_out.c

    r740 r988  
    4141#include "librpc/ndr/libndr.h"
    4242#include "dsdb/samdb/samdb.h"
    43 #include "util.h"
     43#include "dsdb/samdb/ldb_modules/util.h"
    4444
    4545struct extended_dn_out_private {
     
    7777
    7878        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) {
    8080                        continue;
    8181                }
     
    8383                        = talloc_realloc(p, dereference_control->dereference,
    8484                                         struct dsdb_openldap_dereference *, i + 2);
    85                 if (!dereference_control) {
     85                if (!dereference_control->dereference) {
    8686                        return ldb_oom(ldb);
    8787                }
     
    139139
    140140        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 becomes
    145    CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
    146 */
    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;
    171141}
    172142
     
    350320};
    351321
     322
     323/*
     324   fix one-way links to have the right string DN, to cope with
     325   renames of the target
     326*/
     327static 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 */
    352391static int extended_callback(struct ldb_request *req, struct ldb_reply *ares,
    353392                int (*handle_dereference)(struct ldb_dn *dn,
     
    391430
    392431        if (p && p->normalise) {
    393                 ret = fix_dn(ldb, ares->message->dn);
     432                ret = dsdb_fix_dn_rdncase(ldb, ares->message->dn);
    394433                if (ret != LDB_SUCCESS) {
    395434                        return ldb_module_done(ac->req, NULL, NULL, ret);
     
    439478                bool make_extended_dn;
    440479                const struct dsdb_attribute *attribute;
     480
    441481                attribute = dsdb_attribute_by_lDAPDisplayName(ac->schema, msg->elements[i].name);
    442482                if (!attribute) {
     
    461501
    462502                /* 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) {
    464504                        continue;
    465505                }
     
    477517                        struct dsdb_dn *dsdb_dn = NULL;
    478518                        struct ldb_val *plain_dn = &msg->elements[i].values[j];         
     519                        bool is_deleted_objects = false;
    479520
    480521                        if (!checked_reveal_control) {
     
    512553                        dn = dsdb_dn->dn;
    513554
     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
    514566                        /* don't let users see the internal extended
    515567                           GUID components */
    516568                        if (!have_reveal_control) {
    517                                 const char *accept[] = { "GUID", "SID", "WKGUID", NULL };
     569                                const char *accept[] = { "GUID", "SID", NULL };
    518570                                ldb_dn_extended_filter(dn, accept);
    519571                        }
    520572
    521573                        if (p->normalise) {
    522                                 ret = fix_dn(ldb, dn);
     574                                ret = dsdb_fix_dn_rdncase(ldb, dn);
    523575                                if (ret != LDB_SUCCESS) {
    524576                                        talloc_free(dsdb_dn);
     
    545597                                }
    546598                        }
     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                        }
    547624                       
    548625                        if (make_extended_dn) {
     
    602679        struct ldb_context *ldb = ldb_module_get_ctx(module);
    603680        int ret;
    604         bool critical;
    605681
    606682        struct extended_dn_out_private *p = talloc_get_type(ldb_module_get_private(module), struct extended_dn_out_private);
     
    701777        /* mark extended DN and storage format controls as done */
    702778        if (control) {
    703                 critical = control->critical;
    704779                control->critical = 0;
    705780        }
  • vendor/current/source4/dsdb/samdb/ldb_modules/extended_dn_store.c

    r740 r988  
    277277
    278278        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);
    280282        if (ret != LDB_SUCCESS) {
    281283                talloc_free(os);
     
    326328
    327329                /* 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) {
    329331                        continue;
    330332                }
     
    401403
    402404                /* 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) {
    404406                        continue;
    405407                }
  • vendor/current/source4/dsdb/samdb/ldb_modules/instancetype.c

    r740 r988  
    7878                        /*
    7979                         * 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                                }
    8596                        }
     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                         */
    86103                }
    87104
     
    135152        el = ldb_msg_find_element(req->op.mod.message, "instanceType");
    136153        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                }
    139159        }
    140 
    141160        return ldb_next_request(module, req);
    142161}
  • vendor/current/source4/dsdb/samdb/ldb_modules/linked_attributes.c

    r740 r988  
    44   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007
    55   Copyright (C) Simo Sorce <idra@samba.org> 2008
     6   Copyright (C) Matthieu Patou <mat@matws.net> 2011
     7   Copyright (C) Andrew Tridgell 2009
    68
    79   This program is free software; you can redistribute it and/or modify
     
    4648        struct GUID guid;
    4749        char *name;
    48         char *value;
    4950};
    5051
     
    6061        struct ldb_module *module;
    6162        struct ldb_request *req;
    62         struct ldb_dn *add_dn;
    63         struct ldb_dn *del_dn;
     63        struct ldb_dn *mod_dn;
    6464        struct replace_context *rc;
    6565        struct la_op_store *ops;
    6666        struct ldb_extended *op_response;
    6767        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;
    6873};
     74
     75
     76static 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}
    69120
    70121static struct la_context *linked_attributes_init(struct ldb_module *module,
     
    92143  turn a DN into a GUID
    93144 */
    94 static int la_guid_from_dn(struct la_context *ac, struct ldb_dn *dn, struct GUID *guid)
     145static int la_guid_from_dn(struct ldb_module *module,
     146                           struct ldb_request *parent,
     147                           struct ldb_dn *dn, struct GUID *guid)
    95148{
    96149        NTSTATUS status;
     
    104157                DEBUG(4,(__location__ ": Unable to parse GUID for dn %s\n",
    105158                         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);
    110163        if (ret != LDB_SUCCESS) {
    111164                DEBUG(4,(__location__ ": Failed to find GUID for dn %s\n",
     
    144197        os->op = op;
    145198
    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);
    147200        talloc_free(op_dn);
    148201        if (ret == LDB_ERR_NO_SUCH_OBJECT && ac->req->operation == LDB_DELETE) {
     
    167220        /* Do deletes before adds */
    168221        if (op == LA_OP_ADD) {
    169                 DLIST_ADD_END(ac->ops, os, struct la_op_store *);
     222                DLIST_ADD_END(ac->ops, os);
    170223        } else {
    171224                /* By adding to the head of the list, we do deletes before
     
    191244        struct ldb_control *ctrl;
    192245        unsigned int i, j;
     246        struct ldb_control *control;
    193247        int ret;
    194248
     
    200254        }
    201255
    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 
    208256        ac = linked_attributes_init(module, req);
    209257        if (!ac) {
    210258                return ldb_operr(ldb);
    211259        }
     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;
    212275
    213276        if (!ac->schema) {
     
    216279                return ldb_next_request(module, req);
    217280        }
     281
    218282
    219283        /* Need to ensure we only have forward links being specified */
     
    229293                        return LDB_ERR_OBJECT_CLASS_VIOLATION;
    230294                }
    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) {
    233299                        continue;
    234300                }
    235301
    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);
    242304
    243305                /* 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);
    245307                if (!target_attr) {
    246308                        /*
     
    320382                }
    321383
    322                 ac->add_dn = ac->del_dn = talloc_steal(ac, ares->message->dn);
     384                ac->mod_dn = talloc_steal(ac, ares->message->dn);
    323385
    324386                /* We don't populate 'rc' for ADD - it can't be deleting elements anyway */
     
    346408                        }
    347409
    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);
    349411                        if (!target_attr) {
    350412                                /*
     
    413475        /* Apply the modify to the linked entry */
    414476
     477        struct ldb_control *control;
    415478        struct ldb_context *ldb;
    416479        unsigned int i, j;
     
    428491        }
    429492
    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 
    436493        ac = linked_attributes_init(module, req);
    437494        if (!ac) {
    438495                return ldb_operr(ldb);
    439496        }
     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;
    440512
    441513        if (!ac->schema) {
     
    469541                }
    470542
    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
    477546                /* 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);
    479548                if (!target_attr) {
    480549                        /*
     
    573642                /* We need to figure out our own extended DN, to fill in as the backlink target */
    574643                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);
    578647                }
    579648                if (ret == LDB_SUCCESS) {
     
    593662
    594663static int linked_attributes_fix_links(struct ldb_module *module,
     664                                       struct GUID self_guid,
    595665                                       struct ldb_dn *old_dn, struct ldb_dn *new_dn,
    596666                                       struct ldb_message_element *el, struct dsdb_schema *schema,
     
    619689                struct ldb_message *msg;
    620690                struct ldb_message_element *el2;
     691                struct GUID link_guid;
    621692
    622693                dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &el->values[i], schema_attr->syntax->ldap_oid);
     
    626697                }
    627698
    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);
    634700                if (ret != LDB_SUCCESS) {
    635                         ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - remote not found - %s",
     701                        ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - GUID not found - %s",
    636702                                               el->name, target->lDAPDisplayName,
    637703                                               ldb_dn_get_linearized(old_dn),
     
    641707                        return ret;
    642708                }
     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
    643747                msg = res->msgs[0];
    644748
     
    664768                for (j=0; j<el2->num_values; j++) {
    665769                        struct dsdb_dn *dsdb_dn2;
     770                        struct GUID link_guid2;
     771
    666772                        dsdb_dn2 = dsdb_dn_parse(msg, ldb, &el2->values[j], target->syntax->ldap_oid);
    667773                        if (dsdb_dn2 == NULL) {
     
    669775                                return LDB_ERR_INVALID_DN_SYNTAX;
    670776                        }
    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)) {
    672795                                continue;
    673796                        }
     797
    674798                        ret = ldb_dn_update_components(dsdb_dn2->dn, new_dn);
    675799                        if (ret != LDB_SUCCESS) {
     
    718842        struct dsdb_schema *schema;
    719843        int ret;
     844        struct GUID guid;
     845
    720846        /*
    721847           - load the current msg
     
    727853                                    NULL,
    728854                                    DSDB_FLAG_NEXT_MODULE |
     855                                    DSDB_SEARCH_SHOW_EXTENDED_DN |
    729856                                    DSDB_SEARCH_SHOW_RECYCLED, req);
    730857        if (ret != LDB_SUCCESS) {
     
    738865
    739866        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        }
    740872
    741873        for (i=0; i<msg->num_elements; i++) {
     
    746878                        continue;
    747879                }
    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,
    749881                                                  schema, schema_attr, req);
    750882                if (ret != LDB_SUCCESS) {
     
    8681000
    8691001                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);
    8731005                }
    8741006                if (ret != LDB_SUCCESS) {
     
    9311063                             struct GUID *guid, struct ldb_dn **dn)
    9321064{
    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);
    9341066}
    9351067
     
    9411073        struct ldb_context *ldb;
    9421074        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        }
    9431080
    9441081        ldb = ldb_module_get_ctx(ac->module);
     
    9701107        }
    9711108        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));
    9771110
    9781111        /* a backlink should never be single valued. Unfortunately the
     
    9971130        ret = dsdb_module_modify(module, new_msg, DSDB_FLAG_NEXT_MODULE, ac->req);
    9981131        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",
    10001133                          ldb_errstring(ldb),
    10011134                          ldb_ldif_message_string(ldb, op, LDB_CHANGETYPE_MODIFY, new_msg));
     
    10951228}
    10961229
     1230static 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
    10971244
    10981245static const struct ldb_module_ops ldb_linked_attributes_module_ops = {
     
    11011248        .modify            = linked_attributes_modify,
    11021249        .rename            = linked_attributes_rename,
     1250        .init_context      = linked_attributes_ldb_init,
    11031251        .start_transaction = linked_attributes_start_transaction,
    11041252        .prepare_commit    = linked_attributes_prepare_commit,
  • vendor/current/source4/dsdb/samdb/ldb_modules/local_password.c

    r740 r988  
    4444
    4545   This allows the password database to be synchronised in a multi-master
    46    fashion, seperate to the more difficult concerns of the main
     46   fashion, separate to the more difficult concerns of the main
    4747   database. (With passwords, the last writer always wins)
    4848
     
    182182        }
    183183
    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);
    185185        if (remote_message == NULL) {
    186186                return ldb_operr(ldb);
  • vendor/current/source4/dsdb/samdb/ldb_modules/new_partition.c

    r740 r988  
    3737#include "dsdb/samdb/samdb.h"
    3838#include "../libds/common/flags.h"
     39#include "dsdb/common/util.h"
    3940
    4041struct np_context {
     
    6566
    6667        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);
    6869                return ldb_module_done(ac->req, NULL, NULL,
    6970                                        LDB_ERR_OPERATIONS_ERROR);
     
    123124                                     ldb, ac, DSDB_EXTENDED_CREATE_PARTITION_OID, ex_op,
    124125                                     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
    125137       
    126138        LDB_REQ_SET_LOCATION(ac->part_add);
     
    154166
    155167                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)));
    162168                        return ldb_next_request(module, req);
    163169                }
  • vendor/current/source4/dsdb/samdb/ldb_modules/objectclass.c

    r740 r988  
    44   Copyright (C) Simo Sorce  2006-2008
    55   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
    77
    88   This program is free software; you can redistribute it and/or modify
     
    3838#include "includes.h"
    3939#include "ldb_module.h"
    40 #include "util/dlinklist.h"
    4140#include "dsdb/samdb/samdb.h"
    4241#include "librpc/ndr/libndr.h"
     
    4645#include "param/param.h"
    4746#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"
    5048
    5149struct oc_context {
     
    5957
    6058        int (*step_fn)(struct oc_context *);
    61 };
    62 
    63 struct class_list {
    64         struct class_list *prev, *next;
    65         const struct dsdb_class *objectclass;
    6659};
    6760
     
    8982static int objectclass_do_add(struct oc_context *ac);
    9083
    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.
    9389 */
    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)) {
     90static 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) {
    176113                        continue;
    177114                }
    178115
    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;
    220137}
    221138
     
    270187}
    271188
    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 
    302189/* Fix up the DN to be in the standard form, taking particular care to match the parent DN
    303190
     
    355242
    356243
    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) */
    358245        return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr, *rdn_val);
    359246}
    360247
    361 
    362 static int objectclass_do_add(struct oc_context *ac);
    363248
    364249static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
     
    436321        }
    437322
     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
    438330        ac->step_fn = objectclass_do_add;
    439331
     
    450342        struct ldb_control *rodc_control;
    451343
    452         if (strcasecmp(objectclass->lDAPDisplayName, "nTDSDSA") != 0) {
     344        if (ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSDSA") != 0) {
    453345                return false;
    454346        }
     
    468360        struct ldb_message_element *objectclass_element, *el;
    469361        struct ldb_message *msg;
    470         TALLOC_CTX *mem_ctx;
    471         struct class_list *sorted, *current;
    472362        const char *rdn_name = NULL;
    473363        char *value;
     
    516406
    517407        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
    518414                objectclass_element = ldb_msg_find_element(msg, "objectClass");
    519415                if (!objectclass_element) {
     
    528424                }
    529425
    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);
    539430                if (ret != LDB_SUCCESS) {
    540                         talloc_free(mem_ctx);
    541431                        return ret;
    542432                }
    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) {
    587441                        ldb_asprintf_errstring(ldb,
    588442                                               "Failed to find a structural class for %s",
    589443                                               ldb_dn_get_linearized(msg->dn));
    590444                        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;
    591452                }
    592453
     
    735596                                || ldb_attr_cmp(objectclass->lDAPDisplayName, "serversContainer") == 0
    736597                                || 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);
    737600                        systemFlags |= (int32_t)(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
    738 
    739601                } else if (ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLink") == 0
     602                                || ldb_attr_cmp(objectclass->lDAPDisplayName, "subnet") == 0
    740603                                || ldb_attr_cmp(objectclass->lDAPDisplayName, "siteLinkBridge") == 0
    741604                                || ldb_attr_cmp(objectclass->lDAPDisplayName, "nTDSConnection") == 0) {
    742605                        systemFlags |= (int32_t)(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
    743606                }
    744 
    745607                /* TODO: If parent object is site or subnet, also add (SYSTEM_FLAG_CONFIG_ALLOW_RENAME) */
    746608
     
    763625        }
    764626
    765         ret = ldb_msg_sanity_check(ldb, msg);
    766         if (ret != LDB_SUCCESS) {
    767                 return ret;
    768         }
    769 
    770627        ret = ldb_build_add_req(&add_req, ldb, ac,
    771628                                msg,
    772629                                ac->req->controls,
    773                                 ac, oc_op_callback,
     630                                ac->req, dsdb_next_callback,
    774631                                ac->req);
    775632        LDB_REQ_SET_LOCATION(add_req);
     
    857714        }
    858715
    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        }
    864729        LDB_REQ_SET_LOCATION(down_req);
    865730        if (ret != LDB_SUCCESS) {
     
    917782        }
    918783
     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
    919791        ac->step_fn = objectclass_do_mod;
    920792
     
    931803        struct ldb_context *ldb;
    932804        struct ldb_request *mod_req;
    933         char *value;
    934805        struct ldb_message_element *oc_el_entry, *oc_el_change;
    935806        struct ldb_val *vals;
    936807        struct ldb_message *msg;
    937         TALLOC_CTX *mem_ctx;
    938         struct class_list *sorted, *current;
    939808        const struct dsdb_class *objectclass;
    940809        unsigned int i, j, k;
    941         bool found, replace = false;
     810        bool found;
    942811        int ret;
    943812
     
    963832
    964833        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         }
    970834
    971835        /* We've to walk over all "objectClass" message elements */
     
    989853                                                                       (int)oc_el_change->values[i].length,
    990854                                                                       (const char *)oc_el_change->values[i].data);
    991                                                 talloc_free(mem_ctx);
    992855                                                return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
    993856                                        }
     
    999862                                                      oc_el_entry->num_values + 1);
    1000863                                if (vals == NULL) {
    1001                                         talloc_free(mem_ctx);
    1002864                                        return ldb_module_oom(ac->module);
    1003865                                }
     
    1008870                        }
    1009871
    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 
    1028872                        break;
    1029873
    1030874                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;
    1041880
    1042881                        break;
    1043882
    1044883                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 
    1054884                        /* Merge the two message elements */
    1055885                        for (i = 0; i < oc_el_change->num_values; i++) {
     
    1078908                                                               (int)oc_el_change->values[i].length,
    1079909                                                               (const char *)oc_el_change->values[i].data);
    1080                                         talloc_free(mem_ctx);
    1081910                                        return LDB_ERR_NO_SUCH_ATTRIBUTE;
    1082911                                }
    1083912                        }
    1084913
    1085                         /* Make sure that the top-most structural object class
    1086                          * 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 
    1111914                        break;
    1112915                }
    1113916
    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);
    1119920                if (ret != LDB_SUCCESS) {
    1120                         talloc_free(mem_ctx);
    1121921                        return ret;
    1122922                }
    1123923
    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        }
    1174951
    1175952        /* Now we have the real and definitive change left to do */
     
    1178955                                msg,
    1179956                                ac->req->controls,
    1180                                 ac, oc_op_callback,
     957                                ac->req, dsdb_next_callback,
    1181958                                ac->req);
    1182959        LDB_REQ_SET_LOCATION(mod_req);
     
    12361013           deletes will be refused as we will think the target parent
    12371014           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);
    12411018        if (ret != LDB_SUCCESS) {
    12421019                return ret;
     
    12861063        }
    12871064
     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
    12881072        ac->step_fn = objectclass_do_rename2;
    12891073
     
    13221106                        return ldb_operr(ldb);
    13231107                }
    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);
    13251110                if (objectclass == NULL) {
    13261111                        /* existing entry without a valid object class? */
     
    14081193                                   ac->req->op.rename.olddn, fixed_dn,
    14091194                                   ac->req->controls,
    1410                                    ac, oc_op_callback,
     1195                                   ac->req, dsdb_next_callback,
    14111196                                   ac->req);
    14121197        LDB_REQ_SET_LOCATION(rename_req);
     
    14251210        static const char * const attrs[] = { "nCName", "objectClass",
    14261211                                              "systemFlags",
     1212                                              "isDeleted",
    14271213                                              "isCriticalSystemObject", NULL };
    14281214        struct ldb_context *ldb;
     
    14641250        }
    14651251
     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
    14661259        ac->step_fn = objectclass_do_delete;
    14671260
     
    14881281
    14891282        /* 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) {
    14911284                ldb_asprintf_errstring(ldb, "objectclass: Cannot delete %s, it's the DC's ntDSDSA object!",
    14921285                                       ldb_dn_get_linearized(ac->req->op.del.dn));
     
    14961289        /* DC's rIDSet object */
    14971290        /* 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 . */
    14991292        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));
    15011298                return ret;
    15021299        }
     
    15091306                }
    15101307                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;
    15111319        }
    15121320
     
    15501358                                                                   "isCriticalSystemObject", false);
    15511359                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,
    15531378                                               "objectclass: Cannot tree-delete %s, it's a critical system object!",
    15541379                                               ldb_dn_get_linearized(ac->req->op.del.dn));
    15551380                        return LDB_ERR_UNWILLING_TO_PERFORM;
     1381                        }
    15561382                }
    15571383        }
  • vendor/current/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c

    r740 r988  
    7373static int oc_op_callback(struct ldb_request *req, struct ldb_reply *ares);
    7474
    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 */
    7779static int oc_validate_dsheuristics(struct ldb_message_element *el)
    7880{
    7981        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 */
     126static 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        }
    88159        return LDB_SUCCESS;
    89160}
     
    122193                                                         msg->elements[i].name);
    123194                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                        }
    124201                        ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' was not found in the schema!",
    125202                                               msg->elements[i].name,
     
    128205                }
    129206
    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)) {
    131210                        /* Odd is for the target.  Illegal to modify */
    132211                        ldb_asprintf_errstring(ldb,
     
    140219                        werr = attr->syntax->validate_ldb(&syntax_ctx, attr,
    141220                                                          &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)) {
    143223                                ldb_asprintf_errstring(ldb, "objectclass_attrs: attribute '%s' on entry '%s' contains at least one invalid value!",
    144224                                                       msg->elements[i].name,
     
    167247                }
    168248
     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
    169257                /* Substitute the attribute name to match in case */
    170258                msg->elements[i].name = attr->lDAPDisplayName;
    171259        }
    172260
     261no_attribute:
    173262        if (ac->req->operation == LDB_ADD) {
    174263                ret = ldb_build_add_req(&child_req, ldb, ac,
     
    211300        unsigned int i;
    212301        bool found;
     302        bool isSchemaAttr = false;
    213303
    214304        ldb = ldb_module_get_ctx(ac->module);
     
    241331         *  manipulated by client machines over the LDAPv3 transport."
    242332         */
    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) {
    249338                                ldb_asprintf_errstring(ldb, "objectclass_attrs: LSA objectclasses (entry '%s') cannot be created or changed over LDAP!",
    250339                                                       ldb_dn_get_linearized(ac->search_res->message->dn));
    251340                                return LDB_ERR_UNWILLING_TO_PERFORM;
    252341                        }
     342                }
     343                if (strcmp(attname, "attributeSchema") == 0) {
     344                        isSchemaAttr = true;
    253345                }
    254346        }
     
    296388                                                         msg->elements[i].name);
    297389                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                        }
    298395                        return ldb_operr(ldb);
    299396                }
     
    312409                }
    313410                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) {
    322424                ldb_asprintf_errstring(ldb, "objectclass_attrs: at least one mandatory attribute ('%s') on entry '%s' wasn't specified!",
    323425                                       found_must_contain[0],
     
    326428        }
    327429
     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        }
    328455        return ldb_module_done(ac->req, ac->mod_ares->controls,
    329456                               ac->mod_ares->response, LDB_SUCCESS);
     
    474601{
    475602        struct ldb_context *ldb;
     603        struct ldb_control *sd_propagation_control;
     604        int ret;
     605
    476606        struct oc_context *ac;
    477607
     
    482612        /* do not manipulate our control entries */
    483613        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
    484629                return ldb_next_request(module, req);
    485630        }
  • vendor/current/source4/dsdb/samdb/ldb_modules/operational.c

    r740 r988  
    8585};
    8686
     87enum search_type {
     88        TOKEN_GROUPS,
     89        TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL,
     90        TOKEN_GROUPS_NO_GC_ACCEPTABLE
     91};
     92
    8793/*
    8894  construct a canonical name from a message
     
    128134  construct the token groups for SAM objects from a message
    129135*/
    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);;
     136static 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);
    135143        TALLOC_CTX *tmp_ctx = talloc_new(msg);
    136144        unsigned int i;
    137145        int ret;
    138         const char *filter;
     146        const char *filter = NULL;
    139147
    140148        NTSTATUS status;
     
    190198
    191199        /* 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
    194212        if (!filter) {
    195213                talloc_free(tmp_ctx);
     
    254272
    255273        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]);
    257275                if (ret) {
    258276                        talloc_free(tmp_ctx);
     
    264282}
    265283
     284static 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
     297static 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
     310static 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}
    266318/*
    267319  construct the parent GUID for an entry from a message
     
    284336                                    DSDB_FLAG_NEXT_MODULE |
    285337                                    DSDB_SEARCH_SHOW_RECYCLED, parent);
     338        if (ret != LDB_SUCCESS) {
     339                return ret;
     340        }
    286341
    287342        instanceType = ldb_msg_find_attr_as_uint(res->msgs[0],
     
    307362        /* not NC, so the object should have a parent*/
    308363        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)));
    312367        } else if (ret != LDB_SUCCESS) {
    313368                return ret;
     
    320375        }
    321376
    322         v = data_blob_dup_talloc(parent_res, parent_guid);
     377        v = data_blob_dup_talloc(parent_res, *parent_guid);
    323378        if (!v.data) {
    324379                talloc_free(parent_res);
     
    328383        talloc_free(parent_res);
    329384        return ret;
     385}
     386
     387static 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");
    330421}
    331422
     
    372463        if (!ldb) {
    373464                DEBUG(4, (__location__ ": Failed to get ldb \n"));
    374                 return ldb_operr(ldb);
     465                return LDB_ERR_OPERATIONS_ERROR;
    375466        }
    376467
     
    527618                return LDB_SUCCESS;
    528619        }
    529         if (!omd_value) {
    530                 return LDB_SUCCESS;
    531         }
    532620
    533621        omd = talloc(msg, struct replPropertyMetaDataBlob);
     
    568656}
    569657
     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*/
     672static 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*/
     752static 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*/
     815static 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
    570849struct op_controls_flags {
    571850        bool sd;
     
    574853
    575854static 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 ) {
    577856                return true;
    578857        }
     
    593872
    594873
     874struct 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
     882static const char *objectSid_attr[] =
     883{
     884        "objectSid",
     885        NULL
     886};
     887
     888
     889static const char *objectCategory_attr[] =
     890{
     891        "objectCategory",
     892        NULL
     893};
     894
     895
     896static const char *user_account_control_computed_attrs[] =
     897{
     898        "lockoutTime",
     899        "pwdLastSet",
     900        NULL
     901};
     902
     903
     904static const char *user_password_expiry_time_computed_attrs[] =
     905{
     906        "pwdLastSet",
     907        NULL
     908};
     909
     910
    595911/*
    596912  a list of attribute names that are hidden, but can be searched for
    597913  using another (non-hidden) name to produce the correct result
    598914*/
    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[] = {
     915static const struct op_attributes_replace search_sub[] = {
    605916        { "createTimeStamp", "whenCreated", NULL , NULL },
    606         { "modifyTimeStamp", "whenChanged", NULL , NULL },
     917        { "modifyTimeStamp", "whenChanged", NULL , construct_modifyTimeStamp},
    607918        { "structuralObjectClass", "objectClass", NULL , NULL },
    608919        { "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 },
    611924        { "parentGUID", NULL, NULL, construct_parent_guid },
    612925        { "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 }
    615932};
    616933
     
    629946  Some of these are attributes that were once stored, but are now calculated
    630947*/
    631 static const struct {
     948struct op_attributes_operations {
    632949        const char *attr;
    633950        enum op_remove op;
    634 } operational_remove[] = {
     951};
     952
     953static const struct op_attributes_operations operational_remove[] = {
    635954        { "nTSecurityDescriptor",    OPERATIONAL_SD_FLAGS },
    636955        { "msDS-KeyVersionNumber",   OPERATIONAL_REMOVE_UNLESS_CONTROL  },
     
    654973                                           const char * const *attrs_searched_for,
    655974                                           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,
    656979                                           struct ldb_request *parent)
    657980{
     
    663986
    664987        /* 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)) {
    696995                        continue;
    697996                }
    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) {
    7131003                                goto failed;
    7141004                        }
     1005                } else if (ldb_msg_copy_attr(msg,
     1006                                             list_replace[a].replace,
     1007                                             list_replace[a].attr) != LDB_SUCCESS) {
     1008                        goto failed;
    7151009                }
    7161010        }
     
    7211015         */
    7221016        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++) {
    7241018                        /* remove the added search helper attributes, unless
    7251019                         * 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                                }
    7331031                        }
    7341032                }
     
    7541052        const char * const *attrs;
    7551053        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;
    7561058};
    7571059
     
    7811083                                                      ac->attrs,
    7821084                                                      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);
    7841091                if (ret != 0) {
    7851092                        return ldb_module_done(ac->req, NULL, NULL,
     
    7991106        talloc_free(ares);
    8001107        return LDB_SUCCESS;
     1108}
     1109
     1110static 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;
    8011176}
    8021177
     
    8451220                (ldb_request_get_control(req, LDB_CONTROL_BYPASS_OPERATIONAL_OID) != NULL);
    8461221
     1222        ac->attrs_to_replace = NULL;
     1223        ac->attrs_to_replace_size = 0;
    8471224        /* in the list of attributes we are looking for, rename any
    8481225           attributes to the alias for any hidden attributes that can
     
    8531230                }
    8541231                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++) {
    8611253                                        search_attrs2 = ldb_attr_list_copy_add(req, search_attrs
    8621254                                                                               ? search_attrs
    8631255                                                                               : ac->attrs,
    864                                                                                search_sub[i].extra_attr);
     1256                                                                               search_sub[i].extra_attrs[j]);
    8651257                                        if (search_attrs2 == NULL) {
    8661258                                                return ldb_operr(ldb);
     
    8701262                                        search_attrs = search_attrs2;
    8711263                                }
    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);
    8781270                                }
    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;
    8851286        ret = ldb_build_search_req_ex(&down_req, ldb, ac,
    8861287                                        req->op.search.base,
  • vendor/current/source4/dsdb/samdb/ldb_modules/partition.c

    r740 r988  
    135135        struct ldb_request *nreq;
    136136        int ret;
    137         struct partition_private_data *data;
    138137        struct ldb_control *partition_ctrl;
    139138
    140139        ac = talloc_get_type(req->context, struct partition_context);
    141         data = talloc_get_type(ldb_module_get_private(ac->module), struct partition_private_data);
    142140
    143141        if (!ares) {
     
    399397}
    400398
     399
     400/**
     401 * send an operation to the top partition, then copy the resulting
     402 * object to all other partitions
     403 */
     404static 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
    401466/**
    402467 * Figure out which backend a request needs to be aimed at.  Some
     
    428493                                }
    429494                               
    430                                 return partition_send_all(module, ac, req);
     495                                return partition_copy_all(module, ac, req, dn);
    431496                        }
    432497                }
     
    477542        struct ldb_control *search_control = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID);
    478543        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);
    479545       
    480546        struct ldb_search_options_control *search_options = NULL;
     
    484550        bool domain_scope = false, phantom_root = false;
    485551
    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 
    492552        p = find_partition(data, NULL, req);
    493553        if (p != NULL) {
     
    518578        }
    519579
     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
    520585        /* Locate the options */
    521586        domain_scope = (search_options
     
    543608        /* Search from the base DN */
    544609        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                }
    545613                return partition_send_all(module, ac, req);
    546614        }
     
    548616        for (i=0; data->partitions[i]; i++) {
    549617                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                }
    550629
    551630                if (phantom_root) {
     
    615694                                /* Initialise the referrals list */
    616695                                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);
    618698                                        if (ac->referrals == NULL) {
    619699                                                return ldb_oom(ldb);
     
    726806static int partition_start_trans(struct ldb_module *module)
    727807{
    728         unsigned int i;
     808        int i;
    729809        int ret;
    730810        struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
     
    733813        /* Figure out which partition it is under */
    734814        /* 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) {
    736816                ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_start_trans() -> (metadata partition)");
    737817        }
     
    743823        ret = partition_reload_if_required(module, data, NULL);
    744824        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);
    745832                return ret;
    746833        }
     
    758845                        }
    759846                        ldb_next_del_trans(module);
     847                        partition_metadata_del_trans(module);
    760848                        return ret;
    761849                }
     
    773861        struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
    774862                                                              struct partition_private_data);
     863        int ret;
    775864
    776865        for (i=0; data && data->partitions && data->partitions[i]; i++) {
    777                 int ret;
    778 
    779866                if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
    780867                        ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_prepare_commit() -> %s",
     
    793880                ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_prepare_commit() -> (metadata partition)");
    794881        }
    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);
    796891}
    797892
     
    812907        } else {
    813908                data->in_transaction--;
     909        }
     910
     911        ret2 = partition_metadata_end_trans(module);
     912        if (ret2 != LDB_SUCCESS) {
     913                ret = ret2;
    814914        }
    815915
     
    845945        struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
    846946                                                              struct partition_private_data);
     947        ret = partition_metadata_del_trans(module);
     948        if (ret != LDB_SUCCESS) {
     949                final_ret = ret;
     950        }
     951
    847952        for (i=0; data && data->partitions && data->partitions[i]; i++) {
    848953                if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
     
    876981
    877982int 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)
    879985{
    880986        int ret;
    881987        struct ldb_result *res;
    882988        struct ldb_seqnum_request *tseq;
    883         struct ldb_request *treq;
    884989        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) {
    887993                return ldb_oom(ldb_module_get_ctx(module));
    888994        }
    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) {
    8911010                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);
    9311017        return LDB_SUCCESS;
    9321018}
    9331019
    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 */
     1024int partition_sequence_number_from_partitions(struct ldb_module *module,
     1025                                              uint64_t *seqr)
    9361026{
    9371027        int ret;
    9381028        unsigned int i;
    9391029        uint64_t seq_number = 0;
    940         uint64_t timestamp_sequence = 0;
    941         uint64_t timestamp = 0;
    9421030        struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
    9431031                                                              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);
    10311044                if (res == NULL) {
    10321045                        return ldb_oom(ldb_module_get_ctx(module));
    10331046                }
    1034 
    10351047                tseq = talloc_zero(res, struct ldb_seqnum_request);
    10361048                if (tseq == NULL) {
     
    10381050                        return ldb_oom(ldb_module_get_ctx(module));
    10391051                }
    1040                 tseq->type = LDB_SEQ_HIGHEST_TIMESTAMP;
    1041 
     1052                tseq->type = LDB_SEQ_HIGHEST_SEQ;
     1053               
    10421054                ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res,
    10431055                                             LDB_EXTENDED_SEQUENCE_NUMBER,
     
    10461058                                             res,
    10471059                                             ldb_extended_default_callback,
    1048                                              req);
     1060                                             NULL);
    10491061                LDB_REQ_SET_LOCATION(treq);
    10501062                if (ret != LDB_SUCCESS) {
     
    10521064                        return ret;
    10531065                }
    1054 
    1055                 ret = ldb_next_request(module, treq);
     1066               
     1067                ret = partition_request(data->partitions[i]->module, treq);
    10561068                if (ret != LDB_SUCCESS) {
    10571069                        talloc_free(res);
     
    10631075                        return ret;
    10641076                }
    1065 
    10661077                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;
    10701080                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 */
     1091static 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                }
    11261106                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");
    11271118        }
    11281119
    11291120        ext = talloc_zero(req, struct ldb_extended);
    11301121        if (!ext) {
    1131                 return ldb_oom(ldb_module_get_ctx(module));
     1122                return ldb_module_oom(module);
    11321123        }
    11331124        seqr = talloc_zero(ext, struct ldb_seqnum_result);
    11341125        if (seqr == NULL) {
    11351126                talloc_free(ext);
    1136                 return ldb_oom(ldb_module_get_ctx(module));
     1127                return ldb_module_oom(module);
    11371128        }
    11381129        ext->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
    11391130        ext->data = seqr;
    11401131
    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;
    11671134
    11681135        /* send request done */
     
    11831150        }
    11841151
    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);
    11891157        }
    11901158       
  • vendor/current/source4/dsdb/samdb/ldb_modules/partition.h

    r740 r988  
    2222#include <ldb_errors.h>
    2323#include <ldb_module.h>
     24#include "lib/tdb_wrap/tdb_wrap.h"
    2425#include "dsdb/samdb/samdb.h"
    2526#include "dsdb/samdb/ldb_modules/util.h"
     
    3233        const char *backend_url;
    3334        DATA_BLOB orig_record;
     35        bool partial_replica; /* a GC partition */
    3436};
    3537
     
    3941};
    4042
     43struct partition_metadata {
     44        struct tdb_wrap *db;
     45        int in_transaction;
     46};
     47
    4148struct partition_private_data {
    4249        struct dsdb_partition **partitions;
    4350        struct ldb_dn **replicate;
     51        struct partition_metadata *metadata;
    4452       
    4553        struct partition_module **modules;
  • vendor/current/source4/dsdb/samdb/ldb_modules/partition_init.c

    r740 r988  
    139139        struct ldb_result *res;
    140140        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 };
    142143        /* perform search for @PARTITION, looking for module, replicateEntries and ldapBackend */
    143144        ret = dsdb_module_search_dn(module, mem_ctx, &res,
     
    209210        int ret;
    210211
    211         (*partition) = talloc(mem_ctx, struct dsdb_partition);
     212        (*partition) = talloc_zero(mem_ctx, struct dsdb_partition);
    212213        if (!*partition) {
    213214                return ldb_oom(ldb);
     
    384385        struct ldb_message *msg;
    385386        struct ldb_message_element *partition_attributes;
     387        struct ldb_message_element *partial_replicas;
    386388        TALLOC_CTX *mem_ctx;
    387389
     
    396398        }
    397399
    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);
    399401        if (ret != LDB_SUCCESS) {
    400402                talloc_free(mem_ctx);
     
    415417
    416418        partition_attributes = ldb_msg_find_element(msg, "partition");
     419        partial_replicas     = ldb_msg_find_element(msg, "partialReplica");
    417420
    418421        for (i=0; partition_attributes && i < partition_attributes->num_values; i++) {
     
    514517                        partition->ctrl->dn = talloc_steal(partition->ctrl, dn_res->msgs[0]->dn);
    515518                        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                        }
    516526                } else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
    517527                        ldb_asprintf_errstring(ldb,
     
    522532                        talloc_free(mem_ctx);
    523533                        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);
    524543                }
    525544
     
    696715        }
    697716
     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
    698723        for (i=0; data->partitions && data->partitions[i]; i++) {
    699724                if (ldb_dn_compare(data->partitions[i]->ctrl->dn, dn) == 0) {
     
    759784                        return ret;
    760785                }
     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                }
    761798               
    762799                /* Perform modify on @PARTITION record */
     
    852889        }
    853890
     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
    854897        return ldb_next_init(module);
    855898}
  • vendor/current/source4/dsdb/samdb/ldb_modules/password_hash.c

    r746 r988  
    4444#include "../lib/crypto/crypto.h"
    4545#include "param/param.h"
     46#include "lib/krb5_wrap/krb5_samba.h"
    4647
    4748/* If we have decided there is a reason to work on this request, then
     
    9697        bool hash_values;
    9798        bool userPassword;
     99        bool pwd_last_set_bypass;
    98100};
    99101
     
    301303                }
    302304
     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
    303321                if (scpp) {
    304322                        struct package_PackagesBlob *p;
     
    629647        struct ldb_context *ldb;
    630648        krb5_error_code krb5_ret;
    631         Principal *salt_principal;
    632         krb5_salt salt;
     649        krb5_principal salt_principal;
     650        krb5_data salt;
    633651        krb5_keyblock key;
    634652        krb5_data cleartext_data;
    635653
    636654        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;
    638656        cleartext_data.length = io->n.cleartext_utf8->length;
    639657
    640658        /* Many, many thanks to lukeh@padl.com for this
    641659         * algorithm, described in his Nov 10 2004 mail to
    642          * samba-technical@samba.org */
     660         * samba-technical@lists.samba.org */
    643661
    644662        /*
     
    664682                }
    665683               
    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,
    667685                                               &salt_principal,
    668686                                               io->ac->status->domain_data.realm,
     
    682700                }
    683701
    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,
    685703                                               &salt_principal,
    686704                                               io->ac->status->domain_data.realm,
    687705                                               user_principal_name, NULL);
    688706        } 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,
    690708                                               &salt_principal,
    691709                                               io->ac->status->domain_data.realm,
     
    704722         * create salt from salt_principal
    705723         */
    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,
    707725                                    salt_principal, &salt);
    708726        krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal);
     
    717735        /* create a talloc copy */
    718736        io->g.salt = talloc_strndup(io->ac,
    719                                     (char *)salt.saltvalue.data,
    720                                     salt.saltvalue.length);
    721         krb5_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);
    722740        if (!io->g.salt) {
    723741                return ldb_oom(ldb);
    724742        }
    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);
    727746
    728747        /*
     
    730749         * the salt and the cleartext password
    731750         */
    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);
    737757        if (krb5_ret) {
    738758                ldb_asprintf_errstring(ldb,
     
    744764        }
    745765        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));
    748768        krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
    749769        if (!io->g.aes_256.data) {
     
    755775         * the salt and the cleartext password
    756776         */
    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);
    762783        if (krb5_ret) {
    763784                ldb_asprintf_errstring(ldb,
     
    769790        }
    770791        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));
    773794        krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
    774795        if (!io->g.aes_128.data) {
     
    780801         * the salt and the cleartext password
    781802         */
    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);
    787809        if (krb5_ret) {
    788810                ldb_asprintf_errstring(ldb,
     
    794816        }
    795817        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));
    798820        krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
    799821        if (!io->g.des_md5.data) {
     
    805827         * the salt and the cleartext password
    806828         */
    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);
    812835        if (krb5_ret) {
    813836                ldb_asprintf_errstring(ldb,
     
    819842        }
    820843        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));
    823846        krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
    824847        if (!io->g.des_crc.data) {
     
    16641687static int setup_last_set_field(struct setup_password_fields_io *io)
    16651688{
     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
    16661719        /* set it as now */
    16671720        unix_to_nt_time(&io->g.last_set, time(NULL));
     
    16901743                                           g->cleartext_utf8->length,
    16911744                                           (void *)&cleartext_utf16_blob->data,
    1692                                            &cleartext_utf16_blob->length,
    1693                                            false)) {
     1745                                           &cleartext_utf16_blob->length)) {
    16941746                        if (g->cleartext_utf8->length != 0) {
    16951747                                talloc_free(cleartext_utf16_blob);
     
    17181770                                           g->cleartext_utf16->length,
    17191771                                           (void *)&cleartext_utf8_blob->data,
    1720                                            &cleartext_utf8_blob->length,
    1721                                            false)) {
     1772                                           &cleartext_utf8_blob->length)) {
    17221773                        if (g->cleartext_utf16->length != 0) {
    17231774                                /* We must bail out here, the input wasn't even
     
    18281879}
    18291880
     1881static 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
     1977done:
     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
    18301987static int check_password_restrictions(struct setup_password_fields_io *io)
    18311988{
    18321989        struct ldb_context *ldb;
    18331990        int ret;
    1834         enum samr_ValidationStatus stat;
    18351991
    18361992        ldb = ldb_module_get_ctx(io->ac->module);
     
    18522008                   has no problems at all */
    18532009                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);
    18732012                        }
    18742013
     
    18812020                 * (as the SAMR operations request it). */
    18822021                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);
    19032025                        }
    19042026                }
     
    19082030                /* FIXME: Is this right? */
    19092031                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;
    19102045        }
    19112046
     
    19162051         */
    19172052        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) {
    19222058                case SAMR_VALIDATION_STATUS_SUCCESS:
    19232059                                /* perfect -> proceed! */
     
    19842120                /* checks the LM hash password history */
    19852121                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);
    19872123                        if (ret == 0) {
    19882124                                ret = LDB_ERR_CONSTRAINT_VIOLATION;
     
    20152151                        "%08X: %s - check_password_restrictions: "
    20162152                        "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!",
    20282153                        W_ERROR_V(WERR_PASSWORD_RESTRICTION),
    20292154                        ldb_strerror(ret));
     
    21032228        const struct ldb_val *quoted_utf16, *old_quoted_utf16, *lm_hash, *old_lm_hash;
    21042229        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);
    21082232        int ret;
    21092233
     
    21132237
    21142238        if (smb_krb5_init_context(ac,
    2115                                   ldb_get_event_context(ldb),
    21162239                                  (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm"),
    21172240                                  &io->smb_krb5_context) != 0) {
     
    21382261        }
    21392262
     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
    21402279        /* Only non-trust accounts have restrictions (possibly this test is the
    21412280         * wrong way around, but we like to be restrictive if possible */
     
    21432282                & (UF_INTERDOMAIN_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT
    21442283                        | 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         }
    21502284
    21512285        if (ac->userPassword) {
     
    21602294                        return ret;
    21612295                }
     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;
    21622319        }
    21632320
     
    21982355
    21992356        /* Checks and converts the actual "unicodePwd" attribute */
    2200         if (quoted_utf16 &&
     2357        if (!ac->hash_values &&
     2358            quoted_utf16 &&
    22012359            quoted_utf16->length >= 4 &&
    22022360            quoted_utf16->data[0] == '"' &&
     
    22542412
    22552413        /* Checks and converts the previous "unicodePwd" attribute */
    2256         if (old_quoted_utf16 &&
     2414        if (!ac->hash_values &&
     2415            old_quoted_utf16 &&
    22572416            old_quoted_utf16->length >= 4 &&
    22582417            old_quoted_utf16->data[0] == '"' &&
     
    24852644                ctrl->critical = false;
    24862645        }
     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        }
    24872656}
    24882657
     
    25382707        struct ph_context *ac;
    25392708        struct loadparm_context *lp_ctx;
    2540         int ret;
     2709        int ret = LDB_SUCCESS;
    25412710
    25422711        ac = talloc_get_type(req->context, struct ph_context);
     
    25872756                        ac->status->domain_data.pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
    25882757
    2589                 talloc_free(ares);
    2590 
    25912758                /* For a domain DN, this puts things in dotted notation */
    25922759                /* For builtin domains, this will give details for the host,
     
    26032770                ac->status->reject_reason = SAM_PWD_CHANGE_NO_ERROR;
    26042771
     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);
    26052781                ret = LDB_SUCCESS;
    26062782                break;
     
    26702846                                              "minPwdAge",
    26712847                                              "minPwdLength",
     2848                                              "lockoutThreshold",
     2849                                              "lockOutObservationWindow",
    26722850                                              NULL };
    26732851        int ret;
     
    27012879
    27022880        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) {
    27092881                return ldb_next_request(module, req);
    27102882        }
     
    29033075        }
    29043076       
    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 
    29113077        bypass = ldb_request_get_control(req,
    29123078                                         DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
     
    30873253        struct ldb_context *ldb;
    30883254        struct ph_context *ac;
    3089         int ret;
     3255        int ret = LDB_SUCCESS;
    30903256
    30913257        ac = talloc_get_type(req->context, struct ph_context);
     
    31673333        static const char * const attrs[] = { "objectClass",
    31683334                                              "userAccountControl",
     3335                                              "msDS-User-Account-Control-Computed",
    31693336                                              "pwdLastSet",
    31703337                                              "sAMAccountName",
     
    31763343                                              "dBCSPwd",
    31773344                                              "unicodePwd",
     3345                                              "badPasswordTime",
     3346                                              "badPwdCount",
     3347                                              "lockoutTime",
    31783348                                              NULL };
    31793349        struct ldb_request *search_req;
     
    32293399        }
    32303400       
    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
    32363424        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                 */
    32373429                return ldb_operr(ldb);
    32383430        }
  • vendor/current/source4/dsdb/samdb/ldb_modules/proxy.c

    r740 r988  
    139139
    140140        ret = ldb_connect(proxy->upstream, url, 0, NULL);
    141         if (ret != 0) {
     141        if (ret != LDB_SUCCESS) {
    142142                ldb_debug(ldb, LDB_DEBUG_FATAL, "proxy failed to connect to %s\n", url);
    143143                goto failed;
     
    340340
    341341        newtree = proxy_convert_tree(ac, proxy, req->op.search.tree);
     342        if (newtree == NULL) {
     343                goto failed;
     344        }
    342345
    343346        /* convert the basedn of this search */
  • vendor/current/source4/dsdb/samdb/ldb_modules/ranged_results.c

    r740 r988  
    9696                char *p, *new_attr;
    9797                const char *end_str;
    98                 unsigned int start, end, orig_num_values;
     98                unsigned int start, end;
    9999                struct ldb_message_element *el;
    100100                struct ldb_val *orig_values;
     
    147147                } else {
    148148                        orig_values = el->values;
    149                         orig_num_values = el->num_values;
    150149                       
    151150                        if ((start + end < start) || (start + end < end)) {
  • vendor/current/source4/dsdb/samdb/ldb_modules/repl_meta_data.c

    r740 r988  
    33
    44   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
    77   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
    99
    1010   This program is free software; you can redistribute it and/or modify
     
    5151#include "lib/util/tsort.h"
    5252
     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 */
     57static const NTTIME DELETED_OBJECT_CONTAINER_CHANGE_TIME = 2650466015990000000ULL;
     58
    5359struct replmd_private {
    5460        TALLOC_CTX *la_ctx;
     
    6268                uint64_t mod_usn_urgent;
    6369        } *ncs;
     70        struct ldb_dn *schema_dn;
    6471};
    6572
     
    8794        uint64_t seq_num;
    8895        bool is_urgent;
     96
     97        bool isDeleted;
    8998};
     99
     100static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar);
     101static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete);
    90102
    91103enum urgent_situation {
     
    95107};
    96108
     109enum 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
     117static 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}
    97173
    98174static const struct {
     
    147223
    148224
    149 static int replmd_replicated_apply_next(struct replmd_replicated_request *ar);
     225static int replmd_replicated_apply_isDeleted(struct replmd_replicated_request *ar);
    150226
    151227/*
     
    165241        }
    166242        ldb_module_set_private(module, replmd_private);
     243
     244        replmd_private->schema_dn = ldb_get_schema_basedn(ldb);
    167245
    168246        return ldb_next_init(module);
     
    255333
    256334        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) {
    258345                ldb_asprintf_errstring(ldb, "Failed to %s backlink from %s to %s - %s",
    259346                                       bl->active?"add":"remove",
     
    387474
    388475        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)));
    390477                return ldb_module_done(ac->req, controls,
    391478                                        ares->response, ares->error);
     
    440527
    441528        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);
    446530                if (ret != LDB_SUCCESS) {
    447531                        return ldb_module_done(ac->req, NULL, NULL, ret);
     
    580664                                                   const uint32_t *rdn_attid)
    581665{
    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) {
    583675                return 0;
    584676        }
     
    589681         * which means m1 is greater than m2
    590682         */
    591         if (m1->attid == *rdn_attid) {
     683        if (attid_1 == *rdn_attid) {
    592684                return 1;
    593685        }
     
    598690         * which means m2 is greater than m1
    599691         */
    600         if (m2->attid == *rdn_attid) {
     692        if (attid_2 == *rdn_attid) {
    601693                return -1;
    602694        }
    603695
    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
     705static 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
     734static 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)
    610738{
    611739        const char *rdn_name;
     
    614742        rdn_name = ldb_dn_get_rdn_name(dn);
    615743        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;
    618748        }
    619749
    620750        rdn_sa = dsdb_attribute_by_lDAPDisplayName(schema, rdn_name);
    621751        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;
    624756        }
    625757
     
    627759                 rdn_sa->attributeID_id, rdn_name, ldb_dn_get_linearized(dn)));
    628760
    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);
    632764}
    633765
     
    737869static int replmd_add(struct ldb_module *module, struct ldb_request *req)
    738870{
     871        struct samldb_msds_intid_persistant *msds_intid_struct;
    739872        struct ldb_context *ldb;
    740873        struct ldb_control *control;
     
    758891        bool remove_current_guid = false;
    759892        bool is_urgent = false;
     893        bool is_schema_nc = false;
    760894        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);
    761897
    762898        /* check if there's a show relax control (used by provision to say 'I know what I'm doing') */
     
    8731009        }
    8741010
     1011        is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
     1012
    8751013        for (i=0; i < msg->num_elements; i++) {
    8761014                struct ldb_message_element *e = &msg->elements[i];
     
    9071045                }
    9081046
    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                }
    9121072                m->originating_invocation_id    = *our_invocation_id;
    9131073                m->originating_usn              = ac->seq_num;
     
    9221082         * sort meta data array, and move the rdn attribute entry to the end
    9231083         */
    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));
    9261087                talloc_free(ac);
    9271088                return ret;
     
    9771138        replmd_ldb_message_sort(msg, ac->schema);
    9781139
     1140        /*
     1141         * Assert that we do have an objectClass
     1142         */
    9791143        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        }
    9801151        is_urgent = replmd_check_urgent_objectclass(objectclass_el,
    9811152                                                        REPL_URGENT_ON_CREATE);
     
    10171188                control->critical = 0;
    10181189        }
    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        }
    10201198        /* go on with the call chain */
    10211199        return ldb_next_request(module, down_req);
     
    10341212                                      uint64_t *seq_num,
    10351213                                      const struct GUID *our_invocation_id,
    1036                                       NTTIME now)
     1214                                      NTTIME now,
     1215                                      bool is_schema_nc,
     1216                                      struct ldb_request *req)
    10371217{
    10381218        uint32_t i;
    10391219        const struct dsdb_attribute *a;
    10401220        struct replPropertyMetaData1 *md1;
     1221        bool may_skip = false;
     1222        uint32_t attid;
    10411223
    10421224        a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
    10431225        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
    10441232                DEBUG(0,(__location__ ": Unable to find attribute %s in schema\n",
    10451233                         el->name));
     
    10471235        }
    10481236
     1237        attid = dsdb_attribute_get_attid(a, is_schema_nc);
     1238
    10491239        if ((a->systemFlags & DS_FLAG_ATTR_NOT_REPLICATED) || (a->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED)) {
    10501240                return LDB_SUCCESS;
    10511241        }
    10521242
    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                }
    10561279        }
    10571280
    10581281        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                }
    10601298        }
    10611299
     
    10961334        md1 = &omd->ctr.ctr1.array[i];
    10971335        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        }
    11001359        md1->originating_invocation_id = *our_invocation_id;
    11011360        md1->originating_usn           = *seq_num;
     
    11271386                              const struct dsdb_schema *schema,
    11281387                              struct ldb_request *req,
     1388                              const char * const *rename_attrs,
    11291389                              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)
    11321392{
    11331393        const struct ldb_val *omd_value;
     
    11381398        const struct GUID *our_invocation_id;
    11391399        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 };
    11421403        struct ldb_result *res;
    11431404        struct ldb_context *ldb;
    11441405        struct ldb_message_element *objectclass_el;
    11451406        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        }
    11471415
    11481416        ldb = ldb_module_get_ctx(module);
     
    11601428        if (ldb_request_get_control(req, DSDB_CONTROL_CHANGEREPLMETADATA_OID)) {
    11611429                rmd_is_provided = true;
     1430                if (ldb_request_get_control(req, DSDB_CONTROL_CHANGEREPLMETADATA_RESORT_OID)) {
     1431                        rmd_is_just_resorted = true;
     1432                }
    11621433        } else {
    11631434                rmd_is_provided = false;
     
    11681439        if (ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")) {
    11691440                situation = REPL_URGENT_ON_DELETE;
     1441        } else if (rename_attrs) {
     1442                situation = REPL_URGENT_ON_CREATE | REPL_URGENT_ON_DELETE;
    11701443        } else {
    11711444                situation = REPL_URGENT_ON_UPDATE;
     
    11761449                /* We check that it's the only attribute that is provided
    11771450                 * (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 than
     1451                 * We also check that the highest local_usn is bigger or the same as
    11791452                 * uSNChanged. */
    11801453                uint64_t db_seq;
     
    11861459                        return LDB_ERR_OPERATIONS_ERROR;
    11871460                }
    1188                 if (situation == REPL_URGENT_ON_DELETE) {
     1461                if (situation != REPL_URGENT_ON_UPDATE) {
    11891462                        DEBUG(0,(__location__ ": changereplmetada control can't be called when deleting an object\n"));
    11901463                        return LDB_ERR_OPERATIONS_ERROR;
     
    12031476                        return LDB_ERR_OPERATIONS_ERROR;
    12041477                }
    1205                 *seq_num = find_max_local_usn(omd);
    12061478
    12071479                ret = dsdb_module_search_dn(module, msg, &res, msg->dn, attrs2,
     
    12121484                                            DSDB_SEARCH_REVEAL_INTERNALS, req);
    12131485
    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                        }
    12321506                }
    12331507
     
    12441518                                            DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
    12451519                                            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;
    12561522                }
    12571523
     
    12811547                        old_el = ldb_msg_find_element(res->msgs[0], msg->elements[i].name);
    12821548                        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);
    12841552                        if (ret != LDB_SUCCESS) {
    12851553                                return ret;
    12861554                        }
    12871555
    1288                         if (is_urgent && !*is_urgent && (situation == REPL_URGENT_ON_UPDATE)) {
     1556                        if (!*is_urgent && (situation == REPL_URGENT_ON_UPDATE)) {
    12891557                                *is_urgent = replmd_check_urgent_attribute(&msg->elements[i]);
    12901558                        }
     
    12921560                }
    12931561        }
     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
    12941583        /*
    12951584         * replmd_update_rpmd_element has done an update if the
    12961585         * seq_num is set
    12971586         */
    1298         if (*seq_num != 0) {
     1587        if (*seq_num != 0 || rmd_is_just_resorted == true) {
    12991588                struct ldb_val *md_value;
    13001589                struct ldb_message_element *el;
    13011590
    13021591                /*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);
    13051597                        if (ret != LDB_SUCCESS) {
    13061598                                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!");
    13091601                                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");
    13101608                        }
    13111609                }
     
    13171615                }
    13181616
    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);
    13201618                if (ret != LDB_SUCCESS) {
     1619                        ldb_asprintf_errstring(ldb, "%s: %s", __func__, ldb_errstring(ldb));
    13211620                        return ret;
    13221621                }
     
    14261725                                ldb_asprintf_errstring(ldb, "Unable to find GUID for DN %s\n",
    14271726                                                       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                                }
    14281732                                return ret;
    14291733                        }
     
    15711875static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
    15721876                                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,
    15741878                                uint32_t version, bool deleted)
    15751879{
     
    15941898        tval = data_blob_string_const(tstring);
    15951899
    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);
    15971901        if (!usn_string) {
    15981902                return LDB_ERR_OPERATIONS_ERROR;
     
    16251929                old_addtime = &tval;
    16261930        }
    1627         if (dsdb_dn != old_dsdb_dn) {
     1931        if (dsdb_dn != old_dsdb_dn ||
     1932            ldb_dn_get_extended_component(dn, "RMD_ADDTIME") == NULL) {
    16281933                ret = ldb_dn_set_extended_component(dn, "RMD_ADDTIME", old_addtime);
    16291934                if (ret != LDB_SUCCESS) return ret;
     
    17422047                                                       el->name, GUID_string(tmp_ctx, p->guid));
    17432048                                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                                }
    17452056                        }
    17462057                        ret = replmd_update_la_val(old_el->values, p->v, dns[i].dsdb_dn, p->dsdb_dn,
     
    18542165                        ldb_asprintf_errstring(ldb, "Attribute %s doesn't exist for target GUID %s",
    18552166                                               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                        }
    18572172                }
    18582173                rmd_flags = dsdb_dn_rmd_flags(p2->dsdb_dn->dn);
     
    18602175                        ldb_asprintf_errstring(ldb, "Attribute %s already deleted for target GUID %s",
    18612176                                               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                        }
    18632182                }
    18642183        }
     
    19982317                                            old_num_values, p->guid, NULL)) != NULL) {
    19992318                        /* 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,
    20012320                                                   old_p->dsdb_dn, invocation_id,
    20022321                                                   seq_num, seq_num, now, 0, false);
     
    21202439                }
    21212440                if ((schema_attr->linkID & 1) == 1) {
     2441                        if (parent && ldb_request_get_control(parent, DSDB_CONTROL_DBCHECK)) {
     2442                                continue;
     2443                        }
    21222444                        /* Odd is for the target.  Illegal to modify */
    21232445                        ldb_asprintf_errstring(ldb,
     
    21422464                        return LDB_ERR_UNWILLING_TO_PERFORM;
    21432465                }
     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
    21442477                if (ret != LDB_SUCCESS) {
    21452478                        return ret;
     
    21702503static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
    21712504{
     2505        struct samldb_msds_intid_persistant *msds_intid_struct;
    21722506        struct ldb_context *ldb;
    21732507        struct replmd_replicated_request *ac;
     
    21762510        time_t t = time(NULL);
    21772511        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;
    21812514        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);
    21832519
    21842520        /* do not manipulate our control entries */
     
    21872523        }
    21882524
     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
    21892540        ldb = ldb_module_get_ctx(module);
    21902541
    21912542        ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n");
    21922543
    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) {
    21952546                ldb_set_errstring(ldb,
    21962547                                  "replmd_modify: it's not allowed to change the objectGUID!");
     
    22042555
    22052556        functional_level = dsdb_functional_level(ldb);
    2206 
    2207         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
    2208                                  struct loadparm_context);
    22092557
    22102558        /* we have to copy the message as the caller might have it as a const */
     
    22192567        ldb_msg_remove_attr(msg, "uSNChanged");
    22202568
    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
    22232581                referral = talloc_asprintf(req,
    22242582                                           "ldap://%s/%s",
     
    22272585                ret = ldb_module_send_referral(req, referral);
    22282586                talloc_free(ac);
    2229                 return ldb_module_done(req, NULL, NULL, ret);
     2587                return ret;
    22302588        }
    22312589
     
    22882646                if (ret != LDB_SUCCESS) {
    22892647                        talloc_free(ac);
     2648                        ldb_operr(ldb);
    22902649                        return ret;
    22912650                }
     
    22942653                if (ret != LDB_SUCCESS) {
    22952654                        talloc_free(ac);
     2655                        ldb_operr(ldb);
    22962656                        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;
    22972665                }
    22982666        }
     
    23512719{
    23522720        struct ldb_context *ldb;
    2353         struct replmd_replicated_request *ac;
    23542721        struct ldb_request *down_req;
    23552722        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, };
    23562727        time_t t = time(NULL);
    23572728        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
    23602737        ldb = ldb_module_get_ctx(ac->module);
    23612738
     
    23732750        }
    23742751
    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 
    23812752        /* TODO:
    23822753         * - replace the old object with the newly constructed one
     
    23902761
    23912762        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;
    23922882
    23932883        ret = ldb_build_mod_req(&down_req, ldb, ac,
     
    24182908        if (ret != LDB_SUCCESS) {
    24192909                talloc_free(ac);
     2910                ldb_operr(ldb);
    24202911                return ret;
    24212912        }
     
    24242915        if (ret != LDB_SUCCESS) {
    24252916                talloc_free(ac);
     2917                ldb_operr(ldb);
    24262918                return ret;
    24272919        }
     
    24322924
    24332925/*
    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 *
    24362931 */
    24372932static int replmd_delete_remove_link(struct ldb_module *module,
     
    25143009  This also handles the mapping of delete to a rename operation
    25153010  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
    25163016 */
    2517 static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
     3017static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete)
    25183018{
    25193019        int ret = LDB_ERR_OTHER;
     
    25413041                "whenChanged", NULL};
    25423042        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 };
    25453043        enum deletion_state deletion_state, next_deletion_state;
    2546         bool enabled;
    25473044
    25483045        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 */
    25493060                return ldb_next_request(module, req);
    25503061        }
     
    25583069        schema = dsdb_get_schema(ldb, tmp_ctx);
    25593070        if (!schema) {
     3071                talloc_free(tmp_ctx);
    25603072                return LDB_ERR_OPERATIONS_ERROR;
    25613073        }
     
    25713083                                    DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req);
    25723084        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)));
    25733090                talloc_free(tmp_ctx);
    25743091                return ret;
     
    25763093        old_msg = res->msgs[0];
    25773094
    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;
    26033103        }
    26043104
    26053105        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;
    26173125        }
    26183126
     
    26333141        msg->dn = old_dn;
    26343142
    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)) {
    26553161                        new_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
    26563162                        if (new_dn == NULL) {
     
    26593165                                return LDB_ERR_OPERATIONS_ERROR;
    26603166                        }
    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) {
    26633188                /* get the objects GUID from the search we just did */
    26643189                guid = samdb_result_guid(old_msg, "objectGUID");
     
    26663191                /* Add a formatted child */
    26673192                retb = ldb_dn_add_child_fmt(new_dn, "%s=%s\\0ADEL:%s",
    2668                                                 rdn_name,
    2669                                                 ldb_dn_escape_value(tmp_ctx, *rdn_value),
    2670                                                 GUID_string(tmp_ctx, &guid));
     3193                                            rdn_name,
     3194                                            ldb_dn_escape_value(tmp_ctx, *rdn_value),
     3195                                            GUID_string(tmp_ctx, &guid));
    26713196                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));
    26743200                        talloc_free(tmp_ctx);
    26753201                        return LDB_ERR_OPERATIONS_ERROR;
     
    26783204                ret = ldb_msg_add_string(msg, "isDeleted", "TRUE");
    26793205                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");
    26823208                        talloc_free(tmp_ctx);
    26833209                        return ret;
    26843210                }
    26853211                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                }
    26863238        }
    26873239
     
    27033255         */
    27043256
    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);
    27203268                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)));
    27233276                        talloc_free(tmp_ctx);
    27243277                        return ret;
    27253278                }
    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);
    27343295                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));
    27373300                        talloc_free(tmp_ctx);
    27383301                        return ret;
    27393302                }
    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) {
    27573320
    27583321        case OBJECT_RECYCLED:
    27593322        case OBJECT_TOMBSTONE:
    27603323
    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) {
    27643344                        ret = ldb_msg_add_string(msg, "isRecycled", "TRUE");
    27653345                        if (ret != LDB_SUCCESS) {
     
    27693349                                return ret;
    27703350                        }
    2771                         msg->elements[el_count++].flags = LDB_FLAG_MOD_ADD;
     3351                        msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
    27723352                }
    27733353
     
    27853365                                continue;
    27863366                        }
    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                                 */
    27883376                                ret = replmd_delete_remove_link(module, schema, old_dn, el, sa, req);
    27893377                                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);
    27903386                                        talloc_free(tmp_ctx);
    27913387                                        return LDB_ERR_OPERATIONS_ERROR;
    27923388                                }
     3389                                /* now we continue, which means we
     3390                                   won't remove this backlink
     3391                                   directly
     3392                                */
    27933393                                continue;
    27943394                        }
    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                                }
    27973402                        }
    27983403                        ret = ldb_msg_add_empty(msg, el->name, LDB_FLAG_MOD_DELETE, &el);
     
    28033408                        }
    28043409                }
     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
    28053445                break;
    28063446
     
    28453485        }
    28463486
     3487        /*
     3488         * TODO: Per MS-DRSR 5.160 RemoveObj we should remove links directly, not as an originating update!
     3489         *
     3490         */
     3491
    28473492        ret = dsdb_module_modify(module, msg, DSDB_FLAG_OWN_MODULE, req);
    28483493        if (ret != LDB_SUCCESS) {
     
    28533498        }
    28543499
    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) {
    28563505                /* now rename onto the new DN */
    28573506                ret = dsdb_module_rename(module, old_dn, new_dn, DSDB_FLAG_NEXT_MODULE, req);
     
    28713520}
    28723521
     3522static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
     3523{
     3524        return replmd_delete_internals(module, req, false);
     3525}
    28733526
    28743527
     
    28853538}
    28863539
    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
     3541static struct replPropertyMetaData1 *
     3542replmd_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
    29943556
    29953557/*
     
    30243586}
    30253587
    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 */
     3592static 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 */
     3631static 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
     3688failed:
     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 */
     3703static 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 */
     3769static 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
     3961failed:
     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 */
     3974static 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 */
     3993static 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 */
     4001static 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
     4153static 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
     4270static 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}
    30414319
    30424320/*
     
    30454323static int replmd_replicated_handle_rename(struct replmd_replicated_request *ar,
    30464324                                           struct ldb_message *msg,
    3047                                            struct replPropertyMetaDataBlob *rmd,
    3048                                            struct replPropertyMetaDataBlob *omd,
    30494325                                           struct ldb_request *parent)
    30504326{
    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",
    30824333                 ldb_dn_get_linearized(ar->search_msg->dn),
    30834334                 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;
    30854371}
    30864372
     
    31014387        unsigned int removed_attrs = 0;
    31024388        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;
    31034396
    31044397        ldb = ldb_module_get_ctx(ar->module);
    31054398        msg = ar->objs->objects[ar->index_current].msg;
     4399
    31064400        rmd = ar->objs->objects[ar->index_current].meta_data;
    31074401        ZERO_STRUCT(omd);
     
    31234417        }
    31244418
    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) {
    31284480                ldb_debug(ldb, LDB_DEBUG_FATAL,
    31294481                          "replmd_replicated_request rename %s => %s failed - %s\n",
     
    31484500        }
    31494501
     4502        ar->seq_num = 0;
    31504503        /* now merge in the new meta data */
    31514504        for (i=0; i < rmd->ctr.ctr1.count; i++) {
     
    31594512                        }
    31604513
    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                        }
    31634534                        if (cmp) {
    31644535                                /* replace the entry */
    31654536                                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                                }
    31664554                                found = true;
    31674555                                break;
     
    31864574
    31874575                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                }
    31884593                ni++;
    31894594        }
     
    32014606         * sort the new meta data array
    32024607         */
    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));
    32054611                return ret;
    32064612        }
     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;
    32074627
    32084628        /*
     
    32134633                          ar->index_current);
    32144634
    3215                 ar->index_current++;
    3216                 return replmd_replicated_apply_next(ar);
     4635                return replmd_replicated_apply_isDeleted(ar);
    32174636        }
    32184637
     
    32204639                  ar->index_current, msg->num_elements);
    32214640
    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                }
    32294652        }
    32304653
     
    32594682        for (i=0; i < msg->num_elements; i++) {
    32604683                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                }
    32614692        }
    32624693
     
    32734704                                ar->controls,
    32744705                                ar,
    3275                                 replmd_op_callback,
     4706                                callback,
    32764707                                ar->req);
    32774708        LDB_REQ_SET_LOCATION(change_req);
     
    33144745
    33154746        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;
    33174825                        ret = replmd_replicated_apply_merge(ar);
    3318                 } else {
    3319                         ret = replmd_replicated_apply_add(ar);
    33204826                }
    33214827                if (ret != LDB_SUCCESS) {
    33224828                        return ldb_module_done(ar->req, NULL, NULL, ret);
    33234829                }
     4830        }
    33244831        }
    33254832
     
    33374844        char *filter;
    33384845        struct ldb_request *search_req;
    3339         struct ldb_search_options_control *options;
    33404846
    33414847        if (ar->index_current >= ar->objs->num_objects) {
     
    33464852        ldb = ldb_module_get_ctx(ar->module);
    33474853        ar->search_msg = NULL;
     4854        ar->isDeleted = false;
    33484855
    33494856        tmp_str = ldb_binary_encode(ar, ar->objs->objects[ar->index_current].guid_value);
     
    33674874        LDB_REQ_SET_LOCATION(search_req);
    33684875
    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
    33714878        if (ret != LDB_SUCCESS) {
    33724879                return ret;
    33734880        }
    33744881
    3375         /* we need to cope with cross-partition links, so search for
    3376            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 
    33914882        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 */
     4890static 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);
    33924960}
    33934961
     
    34104978
    34114979        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);
    34134981                return ldb_module_done(ar->req, NULL, NULL,
    34144982                                        LDB_ERR_OPERATIONS_ERROR);
     
    34545022        unix_to_nt_time(&now, t);
    34555023
     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
    34565033        instanceType = ldb_msg_find_attr_as_uint(ar->search_msg, "instanceType", 0);
    34575034        if (! (instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
     
    34845061         * plus optional values from our old vector and the one from the source_dsa
    34855062         */
    3486         nuv.ctr.ctr2.count = 1 + ouv.ctr.ctr2.count;
     5063        nuv.ctr.ctr2.count = ouv.ctr.ctr2.count;
    34875064        if (ruv) nuv.ctr.ctr2.count += ruv->count;
    34885065        nuv.ctr.ctr2.cursors = talloc_array(ar,
     
    34995076        /* get our invocation_id if we have one already attached to the ldb */
    35005077        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        }
    35015082
    35025083        /* merge in the source_dsa vector is available */
     
    35185099                        found = true;
    35195100
    3520                         /*
    3521                          * we update only the highest_usn and not the latest_sync_success time,
    3522                          * because the last success stands for direct replication
    3523                          */
    35245101                        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];
    35265103                        }
    35275104                        break;
     
    35325109                /* if it's not there yet, add it */
    35335110                nuv.ctr.ctr2.cursors[ni] = ruv->cursors[i];
    3534                 ni++;
    3535         }
    3536 
    3537         /*
    3538          * merge in the current highwatermark for the source_dsa
    3539          */
    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 time
    3551                  * because we're directly replicating from the source_dsa
    3552                  *
    3553                  * and use the tmp_highest_usn because this is what we have just applied
    3554                  * to our ldb
    3555                  */
    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 time
    3563                  * because we're directly replicating from the source_dsa
    3564                  *
    3565                  * and use the tmp_highest_usn because this is what we have just applied
    3566                  * to our ldb
    3567                  */
    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;
    35715111                ni++;
    35725112        }
     
    36075147        nrf.version                                     = 1;
    36085148        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;
    36105152
    36115153        /*
     
    36855227        nrf_el->flags = LDB_FLAG_MOD_REPLACE;
    36865228
    3687         if (DEBUGLVL(4)) {
     5229        if (CHECK_DEBUGLVL(4)) {
    36885230                char *s = ldb_ldif_message_string(ldb, ar, LDB_CHANGETYPE_MODIFY, msg);
    36895231                DEBUG(4, ("DRS replication uptodate modify message:\n%s\n", s));
     
    37335275
    37345276        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);
    37405278                if (ret != LDB_SUCCESS) {
    37415279                        return ldb_module_done(ar->req, NULL, NULL, ret);
     
    37925330        struct replmd_private *replmd_private =
    37935331                talloc_get_type(ldb_module_get_private(module), struct replmd_private);
     5332        struct dsdb_control_replicated_update *rep_update;
    37945333
    37955334        ldb = ldb_module_get_ctx(module);
     
    38325371        }
    38335372
    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);
    38365382        if (ret != LDB_SUCCESS) {
    38375383                return ret;
     
    38935439        struct ldb_context *ldb = ldb_module_get_ctx(module);
    38945440        struct ldb_message *msg;
     5441        struct ldb_message *target_msg = NULL;
    38955442        TALLOC_CTX *tmp_ctx = talloc_new(la_entry);
    38965443        const struct dsdb_schema *schema = dsdb_get_schema(ldb, tmp_ctx);
     
    39035450        time_t t = time(NULL);
    39045451        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 };
    39065455        struct parsed_dn *pdn_list, *pdn;
    39075456        struct GUID guid = GUID_zero();
     
    39095458        bool active = (la->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)?true:false;
    39105459        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;
    39115463
    39125464/*
     
    39545506
    39555507        attrs[0] = attr->lDAPDisplayName;
    3956         attrs[1] = NULL;
     5508        attrs[1] = "isDeleted";
     5509        attrs[2] = "isRecycled";
     5510        attrs[3] = NULL;
    39575511
    39585512        /* get the existing message from the db for the object with
     
    39795533        msg = res->msgs[0];
    39805534
    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) {
    39825552                ret = ldb_msg_add_empty(msg, attr->lDAPDisplayName, LDB_FLAG_MOD_REPLACE, &old_el);
    39835553                if (ret != LDB_SUCCESS) {
     
    39875557                }
    39885558        } else {
    3989                 old_el = &msg->elements[0];
    39905559                old_el->flags = LDB_FLAG_MOD_REPLACE;
    39915560        }
     
    40165585                ldb_asprintf_errstring(ldb, "Failed to parsed linked attribute blob for %s on %s - %s\n",
    40175586                                       old_el->name, ldb_dn_get_linearized(msg->dn), win_errstr(status));
     5587                talloc_free(tmp_ctx);
    40185588                return LDB_ERR_OPERATIONS_ERROR;
    40195589        }
    40205590
    40215591        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)) {
    40235618                ldb_asprintf_errstring(ldb, "Failed to find GUID in linked attribute blob for %s on %s from %s",
    40245619                                       old_el->name,
    40255620                                       ldb_dn_get_linearized(dsdb_dn->dn),
    40265621                                       ldb_dn_get_linearized(msg->dn));
     5622                talloc_free(tmp_ctx);
    40275623                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",
    40355647                         GUID_string(tmp_ctx, &guid),
    40365648                         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;
    40375672        }
    40385673
     
    41395774        /* we only change whenChanged and uSNChanged if the seq_num
    41405775           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) {
    41425778                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) {
    41485785                talloc_free(tmp_ctx);
    4149                 return ldb_operr(ldb);
     5786                ldb_operr(ldb);
     5787                return ret;
    41505788        }
    41515789
  • vendor/current/source4/dsdb/samdb/ldb_modules/resolve_oids.c

    r740 r988  
    413413static int resolve_oids_callback(struct ldb_request *req, struct ldb_reply *ares)
    414414{
    415         struct ldb_context *ldb;
    416415        struct resolve_oids_context *ac;
    417416
    418417        ac = talloc_get_type_abort(req->context, struct resolve_oids_context);
    419         ldb = ldb_module_get_ctx(ac->module);
    420418
    421419        if (!ares) {
  • vendor/current/source4/dsdb/samdb/ldb_modules/ridalloc.c

    r740 r988  
    3535#include "param/param.h"
    3636#include "librpc/gen_ndr/ndr_misc.h"
     37#include "dsdb/samdb/ldb_modules/ridalloc.h"
    3738
    3839/*
     
    6465  completely run out of RIDs
    6566 */
    66 static void ridalloc_poke_rid_manager(struct ldb_module *module)
     67static int ridalloc_poke_rid_manager(struct ldb_module *module)
    6768{
    68         struct messaging_context *msg;
    69         struct server_id *server;
     69        struct imessaging_context *msg;
     70        unsigned num_servers;
     71        struct server_id *servers;
    7072        struct ldb_context *ldb = ldb_module_get_ctx(module);
    7173        struct loadparm_context *lp_ctx =
    7274                (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
    7375        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,
    7679                                    ldb_get_event_context(ldb));
    7780        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");
    7884                DEBUG(3,(__location__ ": Failed to create messaging context\n"));
    7985                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");
    8595                /* this means the drepl service is not running */
    8696                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
    93113        talloc_free(tmp_ctx);
     114        return LDB_SUCCESS;
    94115}
    95116
     
    263284                .used_pool      = 0,
    264285        };
     286        const char *no_attrs[] = { NULL };
     287        struct ldb_result *res;
    265288
    266289        /*
     
    339362        msg->dn = machine_dn;
    340363
    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));
    342379        if (ret != LDB_SUCCESS) {
    343380                talloc_free(tmp_ctx);
     
    372409        int ret;
    373410        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;
    374414
    375415        /* work out who is the RID Manager */
     
    391431        }
    392432
    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                }
    396456                talloc_free(tmp_ctx);
    397457                return LDB_ERR_UNWILLING_TO_PERFORM;
     
    413473        int ret;
    414474        struct ldb_context *ldb = ldb_module_get_ctx(module);
     475        bool is_us;
    415476
    416477        /* work out who is the RID Manager */
     
    432493        }
    433494
    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                }
    437511                talloc_free(tmp_ctx);
    438512                return LDB_ERR_UNWILLING_TO_PERFORM;
     
    528602                         */
    529603                        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                         }
    535604                        if (ret != LDB_SUCCESS) {
     605                                ldb_asprintf_errstring(ldb, "NO RID values available: %s",
     606                                                       ldb_errstring(ldb));
    536607                                talloc_free(tmp_ctx);
    537608                                return ret;
     
    566637         * if we are half-exhausted then try to get a new pool.
    567638         */
    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) {
    569641                /*
    570642                 * if we are the RID Manager,
     
    575647                ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
    576648                if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
    577                         ridalloc_poke_rid_manager(module);
     649                        ldb_reset_err_string(ldb);
    578650                        ret = LDB_SUCCESS;
    579651                }
  • vendor/current/source4/dsdb/samdb/ldb_modules/rootdse.c

    r740 r988  
    66   Copyright (C) Andrew Tridgell 2005
    77   Copyright (C) Simo Sorce 2005-2008
     8   Copyright (C) Matthieu Patou <mat@matws.net> 2011
    89
    910   This program is free software; you can redistribute it and/or modify
     
    3435#include "lib/messaging/irpc.h"
    3536#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
     41struct rootdse_private_data {
    3842        unsigned int num_controls;
    3943        char **controls;
     
    4145        struct ldb_dn **partitions;
    4246        bool block_anonymous;
     47        struct tevent_context *saved_ev;
     48        struct tevent_context *private_ev;
     49};
     50
     51struct rootdse_context {
     52        struct ldb_module *module;
     53        struct ldb_request *req;
     54        struct ldb_val netlogon;
    4355};
    4456
     
    7789        struct ldb_context *ldb;
    7890        int edn_type = 0;
     91        unsigned int i;
     92        struct ldb_message_element *el;
    7993
    8094        ldb = ldb_module_get_ctx(module);
     
    8599        }
    86100
    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 */
     185static 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;
    89209                talloc_free(tmp_ctx);
    90210                return LDB_SUCCESS;
    91211        }
    92212
    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)));
    95217                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       
    158221        talloc_free(tmp_ctx);
    159 
    160222        return LDB_SUCCESS;
    161223}
    162 
    163224
    164225/*
    165226  add dynamically generated attributes to rootDSE result
    166227*/
    167 static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *msg,
    168                                const char * const *attrs, struct ldb_request *req)
     228static int rootdse_add_dynamic(struct rootdse_context *ac, struct ldb_message *msg)
    169229{
    170230        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;
    172233        char **server_sasl;
    173234        const struct dsdb_schema *schema;
     
    177238                "configurationNamingContext",
    178239                "defaultNamingContext",
    179                 "dsServiceName",
    180240                "rootDomainNamingContext",
    181241                "schemaNamingContext",
    182242                "serverName",
     243                "validFSMOs",
     244                "namingContexts",
    183245                NULL
    184246        };
    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);
    187254        schema = dsdb_get_schema(ldb, NULL);
    188255
     
    205272                int ret;
    206273                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);
    209279                if (ret == LDB_SUCCESS) {
    210280                        const char *hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
    211281                        if (hostname != NULL) {
    212                                 if (ldb_msg_add_string(msg, "dNSHostName", hostname)) {
     282                                if (ldb_msg_add_string(msg, "dnsHostName", hostname)) {
    213283                                        goto failed;
    214284                                }
     
    223293                char *ldap_service_name, *hostname;
    224294
    225                 hostname = talloc_strdup(msg, lpcfg_netbios_name(lp_ctx));
     295                hostname = strlower_talloc(msg, lpcfg_netbios_name(lp_ctx));
    226296                if (hostname == NULL) {
    227297                        goto failed;
    228298                }
    229                 strlower_m(hostname);
    230299
    231300                ldap_service_name = talloc_asprintf(msg, "%s:%s$@%s",
     
    250319
    251320        if (priv && do_attribute(attrs, "supportedControl")) {
    252                 unsigned int i;
    253321                for (i = 0; i < priv->num_controls; i++) {
    254322                        char *control = talloc_strdup(msg, priv->controls[i]);
     
    264332
    265333        if (priv && do_attribute(attrs, "namingContexts")) {
    266                 unsigned int i;
    267334                for (i = 0; i < priv->num_partitions; i++) {
    268335                        struct ldb_dn *dn = priv->partitions[i];
     
    277344                                       char *);
    278345        if (server_sasl && do_attribute(attrs, "supportedSASLMechanisms")) {
    279                 unsigned int i;
    280346                for (i = 0; server_sasl && server_sasl[i]; i++) {
    281347                        char *sasl_name = talloc_strdup(msg, server_sasl[i]);
     
    338404
    339405        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;
    350417                        }
    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;
    372421                        }
    373422                }
     
    418467
    419468        if (do_attribute_explicit(attrs, "tokenGroups")) {
    420                 unsigned int i;
    421469                /* Obtain the user's session_info */
    422470                struct auth_session_info *session_info
     
    434482        }
    435483
     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
    436490        /* TODO: lots more dynamic attributes should be added here */
    437491
    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        }
    439544
    440545        /* if the client sent us the EXTENDED_DN control then we need
     
    442547           this */
    443548        if (edn_control) {
    444                 unsigned int i;
    445549                int ret;
    446550                for (i=0; dn_attrs[i]; i++) {
    447551                        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);
    450554                        if (ret != LDB_SUCCESS) {
    451555                                DEBUG(0,(__location__ ": Failed to expand DN in rootDSE for %s\n",
     
    466570*/
    467571
    468 struct rootdse_context {
    469         struct ldb_module *module;
    470         struct ldb_request *req;
    471 };
    472 
    473572static struct rootdse_context *rootdse_init_context(struct ldb_module *module,
    474573                                                    struct ldb_request *req)
     
    509608        switch (ares->type) {
    510609        case LDB_REPLY_ENTRY:
    511                 /*
    512                  * if the client explicit asks for the 'netlogon' attribute
    513                  * the reply_entry needs to be skipped
    514                  */
    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 
    521610                /* for each record returned post-process to add any dynamic
    522611                   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);
    525613                if (ret != LDB_SUCCESS) {
    526614                        talloc_free(ares);
     
    568656{
    569657        unsigned int i, j;
    570         struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data);
     658        struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
    571659        bool is_untrusted;
    572660
     
    614702                }
    615703
    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) {
    617709                        req->controls[i]->critical = 0;
    618710                }
     
    627719{
    628720        struct auth_session_info *session_info;
    629         struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data);
     721        struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
    630722        bool is_untrusted = ldb_req_is_untrusted(req);
    631723        bool is_anonymous = true;
     
    652744}
    653745
     746static 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;
     797failed:
     798        talloc_free(tmp_ctx);
     799        return ret;
     800}
     801
    654802static int rootdse_search(struct ldb_module *module, struct ldb_request *req)
    655803{
     
    680828        if (ac == NULL) {
    681829                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                }
    682838        }
    683839
     
    701857static int rootdse_register_control(struct ldb_module *module, struct ldb_request *req)
    702858{
    703         struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data);
     859        struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
    704860        char **list;
    705861
     
    722878static int rootdse_register_partition(struct ldb_module *module, struct ldb_request *req)
    723879{
    724         struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data);
     880        struct rootdse_private_data *priv = talloc_get_type(ldb_module_get_private(module), struct rootdse_private_data);
    725881        struct ldb_dn **list;
    726882
     
    762918        struct ldb_context *ldb;
    763919        struct ldb_result *res;
    764         struct private_data *data;
     920        struct rootdse_private_data *data;
    765921        const char *attrs[] = { "msDS-Behavior-Version", NULL };
    766922        const char *ds_attrs[] = { "dsServiceName", NULL };
     
    769925        ldb = ldb_module_get_ctx(module);
    770926
    771         data = talloc_zero(module, struct private_data);
     927        data = talloc_zero(module, struct rootdse_private_data);
    772928        if (data == NULL) {
    773929                return ldb_oom(ldb);
     
    804960        ret = dsdb_module_search(module, mem_ctx, &res,
    805961                                 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);
    807966        if (ret == LDB_SUCCESS && res->count == 1) {
    808967                int domain_behaviour_version
     
    826985        ret = dsdb_module_search(module, mem_ctx, &res,
    827986                                 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);
    829991        if (ret == LDB_SUCCESS && res->count == 1) {
    830992                int forest_behaviour_version
     
    8501012        ret = dsdb_module_search(module, mem_ctx, &res,
    8511013                                 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);
    8531018        if (ret == LDB_SUCCESS && res->count == 1) {
    8541019                struct ldb_dn *ds_dn
     
    8571022                if (ds_dn) {
    8581023                        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);
    8601028                        if (ret == LDB_SUCCESS && res->count == 1) {
    8611029                                int domain_controller_behaviour_version
     
    9501118                                 NULL,
    9511119                                 DSDB_FLAG_NEXT_MODULE |
     1120                                 DSDB_FLAG_AS_SYSTEM |
    9521121                                 DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
    9531122                                 parent,
     
    9971166
    9981167        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);
    10001169        if (!ntds_settings_dn) {
    1001                 DEBUG(0, (__location__ ": Failed to find NTDS settings DN\n"));
    1002                 ret = LDB_ERR_OPERATIONS_ERROR;
    10031170                talloc_free(tmp_ctx);
    1004                 return ret;
     1171                return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "Failed to find NTDS settings DN");
    10051172        }
    10061173
    10071174        ntds_settings_dn = ldb_dn_copy(tmp_ctx, ntds_settings_dn);
    10081175        if (!ntds_settings_dn) {
    1009                 DEBUG(0, (__location__ ": Failed to copy NTDS settings DN\n"));
    1010                 ret = LDB_ERR_OPERATIONS_ERROR;
    10111176                talloc_free(tmp_ctx);
    1012                 return ret;
     1177                return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "Failed to copy NTDS settings DN");
    10131178        }
    10141179
    10151180        msg = ldb_msg_new(tmp_ctx);
     1181        if (msg == NULL) {
     1182                talloc_free(tmp_ctx);
     1183                return ldb_module_oom(module);
     1184        }
    10161185        msg->dn = ntds_settings_dn;
    10171186
     
    11381307}
    11391308
     1309static 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
    11401338static int rootdse_add(struct ldb_module *module, struct ldb_request *req)
    11411339{
     
    11641362}
    11651363
     1364static 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
     1385static 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
     1405static 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
     1425struct 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 */
     1434static 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
    11661475static int rootdse_become_master(struct ldb_module *module,
    11671476                                 struct ldb_request *req,
    11681477                                 enum drepl_role_master role)
    11691478{
    1170         struct drepl_takeFSMORole r;
    1171         struct messaging_context *msg;
     1479        struct imessaging_context *msg;
    11721480        struct ldb_context *ldb = ldb_module_get_ctx(module);
    11731481        TALLOC_CTX *tmp_ctx = talloc_new(req);
    11741482        struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm");
    1175         NTSTATUS status_call;
    1176         WERROR status_fn;
    11771483        bool am_rodc;
    11781484        struct dcerpc_binding_handle *irpc_handle;
    11791485        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        }
    11801496
    11811497        ret = samdb_rodc(ldb, &am_rodc);
     
    11891505        }
    11901506
    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,
    11921515                                    ldb_get_event_context(ldb));
    11931516        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));
    11951518                return LDB_ERR_OPERATIONS_ERROR;
    11961519        }
     
    12011524                return ldb_oom(ldb);
    12021525        }
    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;
    12141554}
    12151555
     
    12611601                return rootdse_enableoptionalfeature(module, req);
    12621602        }
     1603        if (ldb_msg_find_element(req->op.mod.message, "schemaUpgradeInProgress")) {
     1604                return rootdse_schemaupgradeinprogress(module, req);
     1605        }
    12631606
    12641607        ldb_set_errstring(ldb, "rootdse_modify: unknown attribute to change!");
     
    13361679
    13371680static 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
    13471693};
    13481694
  • vendor/current/source4/dsdb/samdb/ldb_modules/samba_dsdb.c

    r740 r988  
    3838#include "dsdb/samdb/samdb.h"
    3939#include "librpc/ndr/libndr.h"
     40#include "auth/credentials/credentials.h"
     41#include "param/secrets.h"
     42#include "lib/ldb-samba/ldb_wrap.h"
    4043
    4144static int read_at_rootdse_record(struct ldb_context *ldb, struct ldb_module *module, TALLOC_CTX *mem_ctx,
     
    103106
    104107        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);
    106110        } 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);
    108113        }
    109114        if (!backend_full_list) {
     
    130135}
    131136
    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
     143static 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}
    133230
    134231static int samba_dsdb_init(struct ldb_module *module)
     
    138235        TALLOC_CTX *tmp_ctx = talloc_new(module);
    139236        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;
    142239        struct ldb_module *backend_module, *module_chain;
    143240        const char **final_module_list, **reverse_module_list;
     
    151248          - objectclass must be before password_hash and samldb since these LDB
    152249            modules require the expanded "objectClass" list
     250          - objectclass must be before descriptor and acl, as both assume that
     251            objectClass values are sorted
    153252          - objectclass_attrs must be behind operational in order to see all
    154253            attributes (the operational module protects and therefore
     
    161260          based on the parameters loaded from the database.
    162261        */
    163         static const char *modules_list[] = {"resolve_oids",
     262        static const char *modules_list1[] = {"resolve_oids",
    164263                                             "rootdse",
     264                                             "schema_load",
    165265                                             "lazy_commit",
     266                                             "dirsync",
    166267                                             "paged_results",
    167268                                             "ranged_results",
     
    170271                                             "asq",
    171272                                             "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",
    174276                                             "descriptor",
    175277                                             "acl",
     
    178280                                             "password_hash",
    179281                                             "operational",
    180                                              "schema_load",
    181282                                             "instancetype",
    182283                                             "objectclass_attrs",
     
    200301        const char *extended_dn_module_fds = "extended_dn_out_fds";
    201302        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",
    204307                                              "new_partition",
    205308                                              "partition",
     
    210313                "nsuniqueid", "paged_searches", "simple_dn", NULL };
    211314        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;
    216321
    217322        if (!tmp_ctx) {
     
    227332        samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
    228333        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) {
    229340                talloc_free(tmp_ctx);
    230341                return ldb_oom(ldb);
     
    243354        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
    244355                backendType = "ldb";
    245                 serverRole = "domain controller";
    246356        } else if (ret == LDB_SUCCESS) {
    247357                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");
    249358        } else {
    250359                talloc_free(tmp_ctx);
     
    257366                link_modules = tdb_modules_list;
    258367        } 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                }
    259382                if (strcasecmp(backendType, "fedora-ds") == 0) {
    260383                        link_modules = fedora_ds_modules;
     
    265388                        backend_modules = openldap_backend_modules;
    266389                        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                        }
    267394                } else {
    268395                        return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "invalid backend type");
     
    271398                if (ret != LDB_SUCCESS) {
    272399                        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                        }
    273408                }
    274409        }
     
    282417        } while (0)
    283418
    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);
    285426        CHECK_MODULE_LIST;
    286427
     
    300441        partition_msg = ldb_msg_new(tmp_ctx);
    301442        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);
    314443
    315444        ret = prepare_modules_line(ldb, tmp_ctx,
  • vendor/current/source4/dsdb/samdb/ldb_modules/samba_secrets.c

    r740 r988  
    5353        */
    5454        static const char *modules_list[] = {"update_keytab",
     55                                             "secrets_tdb_sync",
    5556                                             "objectguid",
    5657                                             "rdn_name",
  • vendor/current/source4/dsdb/samdb/ldb_modules/samldb.c

    r740 r988  
    22   SAM ldb module
    33
    4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
     4   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2014
    55   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
    78
    89   This program is free software; you can redistribute it and/or modify
     
    3334#include "libcli/ldap/ldap_ndr.h"
    3435#include "ldb_module.h"
     36#include "auth/auth.h"
    3537#include "dsdb/samdb/samdb.h"
    3638#include "dsdb/samdb/ldb_modules/util.h"
     
    4143#include "param/param.h"
    4244#include "libds/common/flag_mapping.h"
     45#include "system/network.h"
    4346
    4447struct samldb_ctx;
     48enum samldb_add_type {
     49        SAMLDB_TYPE_USER,
     50        SAMLDB_TYPE_GROUP,
     51        SAMLDB_TYPE_CLASS,
     52        SAMLDB_TYPE_ATTRIBUTE
     53};
    4554
    4655typedef int (*samldb_step_fn_t)(struct samldb_ctx *);
     
    5665
    5766        /* used for add operations */
    58         const char *type;
     67        enum samldb_add_type type;
    5968
    6069        /* the resulting message */
     
    170179        int ret;
    171180        struct ldb_result *res;
    172         const char *noattrs[] = { NULL };
     181        const char * const noattrs[] = { NULL };
    173182
    174183        if (ldb_msg_find_element(ac->msg, "sAMAccountName") == NULL) {
     
    188197
    189198        ret = dsdb_module_search(ac->module, ac, &res,
    190                                  NULL, LDB_SCOPE_SUBTREE, noattrs,
     199                                 ldb_get_default_basedn(ldb), LDB_SCOPE_SUBTREE, noattrs,
    191200                                 DSDB_FLAG_NEXT_MODULE,
    192201                                 ac->req,
     
    258267        TALLOC_CTX *tmp_ctx = talloc_new(ac);
    259268        struct ldb_result *res;
    260         const char *no_attrs[] = { NULL };
     269        const char * const no_attrs[] = { NULL };
    261270        int ret;
    262271
    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)),
    264274                                 LDB_SCOPE_SUBTREE, no_attrs,
    265275                                 DSDB_FLAG_NEXT_MODULE,
     
    336346                                   newpass, strlen(newpass),
    337347                                   (void *)&newpass_utf16.data,
    338                                    &newpass_utf16.length, false)) {
     348                                   &newpass_utf16.length)) {
    339349                ldb_asprintf_errstring(ldb,
    340350                                       "samldb_rodc_add: "
     
    354364        struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
    355365        struct ldb_result *res;
    356         const char *no_attrs[] = { NULL };
     366        const char * const no_attrs[] = { NULL };
    357367        int ret;
    358368
     
    380390        }
    381391
     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
    382416        ac->res_dn = ac->dn;
    383417
     
    398432        struct ldb_result *ldb_res;
    399433        struct ldb_dn *schema_dn;
     434        struct samldb_msds_intid_persistant *msds_intid_struct;
     435        struct dsdb_schema *schema;
    400436
    401437        ldb = ldb_module_get_ctx(ac->module);
     
    429465                return LDB_SUCCESS;
    430466        }
    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        }
    436488
    437489        /* probe id values until unique one is found */
    438490        do {
     491                uint64_t current_usn;
    439492                msds_intid++;
    440493                if (msds_intid > 0xBFFFFFFF) {
    441494                        msds_intid = 0x80000001;
    442495                }
    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                                                     &current_usn, NULL, NULL);
    450516                if (ret != LDB_SUCCESS) {
    451517                        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",
    454519                                      ldb_errstring(ldb));
    455520                        return ldb_operr(ldb);
    456521                }
    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
    460554        } while(id_exists);
     555        msds_intid_struct->msds_intid = msds_intid;
     556        ldb_set_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE, msds_intid_struct);
    461557
    462558        return samdb_msg_add_int(ldb, ac->msg, ac->msg, "msDS-IntId",
     
    493589        }
    494590        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);
    497592                return ldb_module_done(ac->req, NULL, NULL,
    498593                                        LDB_ERR_OPERATIONS_ERROR);
     
    558653
    559654        /* Add information for the different account types */
    560         if (strcmp(ac->type, "user") == 0) {
     655        switch(ac->type) {
     656        case SAMLDB_TYPE_USER: {
    561657                struct ldb_control *rodc_control = ldb_request_get_control(ac->req,
    562658                                                                           LDB_CONTROL_RODC_DCPROMO_OID);
     
    574670                ret = samldb_add_step(ac, samldb_add_entry);
    575671                if (ret != LDB_SUCCESS) return ret;
    576 
    577         } else if (strcmp(ac->type, "group") == 0) {
     672                break;
     673        }
     674
     675        case SAMLDB_TYPE_GROUP: {
    578676                /* check if we have a valid sAMAccountName */
    579677                ret = samldb_add_step(ac, samldb_check_sAMAccountName);
     
    582680                ret = samldb_add_step(ac, samldb_add_entry);
    583681                if (ret != LDB_SUCCESS) return ret;
    584 
    585         } else if (strcmp(ac->type, "classSchema") == 0) {
     682                break;
     683        }
     684
     685        case SAMLDB_TYPE_CLASS: {
    586686                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                }
    587694
    588695                ret = samdb_find_or_add_attribute(ldb, ac->msg,
     
    590697                if (ret != LDB_SUCCESS) return ret;
    591698
    592                 /* do not allow to mark an attributeSchema as RODC filtered if it
     699                /* do not allow one to mark an attributeSchema as RODC filtered if it
    593700                 * is system-critical */
    594701                if (check_rodc_critical_attribute(ac->msg)) {
     
    662769                if (ret != LDB_SUCCESS) return ret;
    663770
    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: {
    665783                const struct ldb_val *rdn_value;
     784                struct ldb_message_element *el;
    666785                rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
    667786                if (rdn_value == NULL) {
     
    679798                }
    680799
    681                 /* do not allow to mark an attributeSchema as RODC filtered if it
     800                /* do not allow one to mark an attributeSchema as RODC filtered if it
    682801                 * is system-critical */
    683802                if (check_rodc_critical_attribute(ac->msg)) {
     
    703822                }
    704823
     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
    705856                /* handle msDS-IntID attribute */
    706857                ret = samldb_add_handle_msDS_IntId(ac);
     
    709860                ret = samldb_add_step(ac, samldb_add_entry);
    710861                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!");
    715867                return LDB_ERR_OPERATIONS_ERROR;
     868                break;
    716869        }
    717870
     
    780933
    781934        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);
    783938        if (ret != LDB_SUCCESS) {
    784939                ldb_asprintf_errstring(ldb,
     
    790945        return LDB_SUCCESS;
    791946}
     947
     948static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid);
     949static 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);
    792953
    793954/*
     
    802963{
    803964        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");
    806967        struct ldb_message_element *el, *el2;
    807         enum sid_generator sid_generator;
    808968        struct dom_sid *sid;
    809969        int ret;
     
    831991
    832992        /* 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;
    8431001
    8441002                /* 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);
    8711004                if (ret != LDB_SUCCESS) return ret;
    8721005
     
    8821015                        }
    8831016                        uac_generated = true;
     1017                        uac_add_flags = true;
    8841018                }
    8851019
    8861020                el = ldb_msg_find_element(ac->msg, "userAccountControl");
    8871021                if (el != NULL) {
    888                         uint32_t user_account_control, account_type;
    889 
     1022                        uint32_t user_account_control;
    8901023                        /* Step 1.3: "userAccountControl" -> "sAMAccountType" mapping */
    8911024                        user_account_control = ldb_msg_find_attr_as_uint(ac->msg,
    8921025                                                                         "userAccountControl",
    8931026                                                                         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);
    9081051                        if (ret != LDB_SUCCESS) {
    9091052                                return ret;
    9101053                        }
    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 */
    9141072                        if (user_account_control &
    9151073                            (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");
    9191076                                if (ret != LDB_SUCCESS) {
    9201077                                        return ret;
     
    9231080                                                           "isCriticalSystemObject");
    9241081                                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");
    9321085                                if (ret != LDB_SUCCESS) {
    9331086                                        return ret;
    9341087                                }
    9351088                                el2 = ldb_msg_find_element(ac->msg,
    936                                                            "primaryGroupID");
     1089                                                           "isCriticalSystemObject");
    9371090                                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                                }
    9381111                        }
    9391112
     
    9431116                         * Server) */
    9441117                        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                                }
    9471122
    9481123                                ret = samdb_msg_set_uint(ldb, ac->msg, ac->msg,
     
    9531128                                }
    9541129                        }
    955                 }
    956 
    957         } else if (strcmp(ac->type, "group") == 0) {
     1130
     1131                }
     1132                break;
     1133        }
     1134
     1135        case SAMLDB_TYPE_GROUP: {
    9581136                const char *tempstr;
    9591137
     
    9971175                        el2->flags = LDB_FLAG_MOD_REPLACE;
    9981176                }
     1177                break;
     1178        }
     1179
     1180        default:
     1181                ldb_asprintf_errstring(ldb,
     1182                                "Invalid entry type!");
     1183                return LDB_ERR_OPERATIONS_ERROR;
     1184                break;
    9991185        }
    10001186
     
    10101196 */
    10111197
    1012 static int samldb_prim_group_set(struct samldb_ctx *ac)
     1198static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid)
    10131199{
    10141200        struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
    1015         uint32_t rid;
    10161201        struct dom_sid *sid;
    10171202        struct ldb_result *res;
    10181203        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 };
    10311205
    10321206        sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
     
    10351209        }
    10361210
    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,
    10381214                                 noattrs, DSDB_FLAG_NEXT_MODULE,
    10391215                                 ac->req,
     
    10551231}
    10561232
     1233static 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
    10571252static int samldb_prim_group_change(struct samldb_ctx *ac)
    10581253{
    10591254        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 };
    10611260        struct ldb_result *res, *group_res;
    10621261        struct ldb_message_element *el;
    10631262        struct ldb_message *msg;
    1064         uint32_t prev_rid, new_rid;
     1263        uint32_t prev_rid, new_rid, uac;
    10651264        struct dom_sid *prev_sid, *new_sid;
    10661265        struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
    10671266        int ret;
    1068         const char *noattrs[] = { NULL };
     1267        const char * const noattrs[] = { NULL };
    10691268
    10701269        el = dsdb_get_single_valued_attr(ac->msg, "primaryGroupID",
     
    10771276        /* Fetch information from the existing object */
    10781277
    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);
    10871285
    10881286        /* Finds out the DN of the old primary group */
     
    11251323        }
    11261324
    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,
    11281346                                 noattrs, DSDB_FLAG_NEXT_MODULE,
    11291347                                 ac->req,
     
    11431361        }
    11441362
    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,
    11461366                                 noattrs, DSDB_FLAG_NEXT_MODULE,
    11471367                                 ac->req,
     
    12201440}
    12211441
     1442static 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 */
     1550static 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
     1733static 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 */
    12221755static int samldb_user_account_control_change(struct samldb_ctx *ac)
    12231756{
    12241757        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;
    12261770        struct ldb_message_element *el;
     1771        struct ldb_val *val;
     1772        struct ldb_val computer_val;
    12271773        struct ldb_message *tmp_msg;
     1774        struct dom_sid *sid;
    12281775        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;
    12291789
    12301790        el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
    12311791                                         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;
    12351797        }
    12361798
     
    12441806                return ret;
    12451807        }
    1246         user_account_control = ldb_msg_find_attr_as_uint(tmp_msg,
    1247                                                         "userAccountControl",
    1248                                                         0);
     1808        raw_uac = ldb_msg_find_attr_as_uint(tmp_msg,
     1809                                            "userAccountControl",
     1810                                            0);
    12491811        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);
    12531919                return LDB_ERR_OTHER;
    12541920        }
    12551921
    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) {
    12711947                ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
    1272                                          "TRUE");
     1948                                         new_is_critical ? "TRUE": "FALSE");
    12731949                if (ret != LDB_SUCCESS) {
    12741950                        return ret;
     
    12791955        }
    12801956
    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
    12831967                ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
    1284                                          "primaryGroupID", rid);
     1968                                         "primaryGroupID", new_pgrid);
    12851969                if (ret != LDB_SUCCESS) {
    12861970                        return ret;
     
    12901974                el->flags = LDB_FLAG_MOD_REPLACE;
    12911975        }
     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
     1997static 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;
    12922041
    12932042        return LDB_SUCCESS;
     
    13022051        int ret;
    13032052        struct ldb_result *res;
    1304         const char *attrs[] = { "groupType", NULL };
     2053        const char * const attrs[] = { "groupType", NULL };
    13052054
    13062055        el = dsdb_get_single_valued_attr(ac->msg, "groupType",
     
    13242073
    13252074        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);
    13272077        if (ret != LDB_SUCCESS) {
    13282078                return ret;
     
    13932143{
    13942144        struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
    1395         const char *no_attrs[] = { NULL };
     2145        const char * const no_attrs[] = { NULL };
    13962146        struct ldb_result *res;
    13972147        const char *sam_accountname, *enc_str;
     
    14162166                return ret;
    14172167        }
    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));
    14202172        talloc_free(tmp_msg);
    14212173
     
    14342186        /* Make sure that a "sAMAccountName" is only used once */
    14352187
    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,
    14372191                                 DSDB_FLAG_NEXT_MODULE, ac->req,
    14382192                                 "(sAMAccountName=%s)", enc_str);
     
    14572211static int samldb_member_check(struct samldb_ctx *ac)
    14582212{
    1459         static const char * const attrs[] = { "objectSid", "member", NULL };
     2213        const char * const attrs[] = { "objectSid", NULL };
    14602214        struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
    14612215        struct ldb_message_element *el;
     
    14652219        struct dom_sid *group_sid;
    14662220        unsigned int i, j;
    1467         int cnt;
    14682221        int ret;
    14692222
     
    14712224
    14722225        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);
    14742227        if (ret != LDB_SUCCESS) {
    14752228                return ret;
     
    14932246                el = &ac->msg->elements[i];
    14942247                for (j = 0; j < el->num_values; j++) {
    1495                         struct ldb_message_element *mo;
    14962248                        struct ldb_result *group_res;
    14972249                        const char *group_attrs[] = { "primaryGroupID" , NULL };
    14982250                        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                        }
    14992260
    15002261                        member_dn = ldb_dn_from_ldb_val(ac, ldb,
     
    15022263                        if (!ldb_dn_validate(member_dn)) {
    15032264                                return ldb_operr(ldb);
    1504                         }
    1505 
    1506                         /* The "member" attribute can be modified with the
    1507                          * following restrictions (beside a valid DN):
    1508                          *
    1509                          * - "add" operations can only be performed when the
    1510                          *   member still doesn't exist - if not then return
    1511                          *   ERR_ENTRY_ALREADY_EXISTS (not
    1512                          *   ERR_ATTRIBUTE_OR_VALUE_EXISTS!)
    1513                          * - "delete" operations can only be performed when the
    1514                          *   member does exist - if not then return
    1515                          *   ERR_UNWILLING_TO_PERFORM (not
    1516                          *   ERR_NO_SUCH_ATTRIBUTE!)
    1517                          * - primary group check
    1518                          */
    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;
    15342265                        }
    15352266
     
    15622293
    15632294                        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);
    15642298                                return LDB_ERR_ENTRY_ALREADY_EXISTS;
    15652299                        }
     
    16192353        struct ldb_message_element *el = NULL, *el2 = NULL;
    16202354        struct ldb_message *msg;
    1621         const char *attrs[] = { "servicePrincipalName", NULL };
     2355        const char * const attrs[] = { "servicePrincipalName", NULL };
    16222356        struct ldb_result *res;
    16232357        const char *dns_hostname = NULL, *old_dns_hostname = NULL,
    16242358                   *sam_accountname = NULL, *old_sam_accountname = NULL;
    1625         unsigned int i;
     2359        unsigned int i, j;
    16262360        int ret;
    16272361
     
    16462380                        return ret;
    16472381                }
    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                       
    16502388                talloc_free(msg);
    16512389
     
    16592397        /* Create a temporary message for fetching the "sAMAccountName" */
    16602398        if (el2 != NULL) {
    1661                 char *tempstr, *tempstr2;
     2399                char *tempstr, *tempstr2 = NULL;
    16622400                const char *acct_attrs[] = { "sAMAccountName", NULL };
    16632401
     
    17022440        }
    17032441        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)) {
    17052443                /* The "dNSHostName" didn't change */
    17062444                dns_hostname = NULL;
     
    17122450        }
    17132451        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)) {
    17152453                /* The "sAMAccountName" didn't change */
    17162454                sam_accountname = NULL;
     
    17642502
    17652503        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
    17672506                 * locally, that means we do always substitute the current
    17682507                 * "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                }
    17712520
    17722521                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;
    17742524                        const char *tok;
     2525                        struct ldb_val *vals;
     2526                        bool found = false;
    17752527
    17762528                        old_str = (char *)
     
    17852537                        while ((tok = strtok_r(NULL, "/", &pos)) != NULL) {
    17862538                                if ((dns_hostname != NULL) &&
    1787                                     (strcasecmp(tok, old_dns_hostname) == 0)) {
     2539                                    (strcasecmp_m(tok, old_dns_hostname) == 0)) {
    17882540                                        tok = dns_hostname;
    17892541                                }
    17902542                                if ((sam_accountname != NULL) &&
    1791                                     (strcasecmp(tok, old_sam_accountname) == 0)) {
     2543                                    (strcasecmp_m(tok, old_sam_accountname) == 0)) {
    17922544                                        tok = sam_accountname;
    17932545                                }
     
    18002552                        }
    18012553
    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                }
    18122582        }
    18132583
    18142584        talloc_free(res);
     2585
     2586        return LDB_SUCCESS;
     2587}
     2588
     2589/* This checks the "fSMORoleOwner" attributes */
     2590static 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 */
     2653static 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
     2737static 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 */
     2782static 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
     2882static 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        }
    18152908
    18162909        return LDB_SUCCESS;
     
    18232916        struct ldb_context *ldb;
    18242917        struct samldb_ctx *ac;
     2918        struct ldb_message_element *el;
    18252919        int ret;
    18262920
     
    18312925        if (ldb_dn_is_special(req->op.add.message->dn)) {
    18322926                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);
    18332936        }
    18342937
     
    18472950        }
    18482951
     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
    18492960        if (samdb_find_attribute(ldb, ac->msg,
    18502961                                 "objectclass", "user") != NULL) {
    1851                 ac->type = "user";
     2962                ac->type = SAMLDB_TYPE_USER;
    18522963
    18532964                ret = samldb_prim_group_trigger(ac);
     
    18662977        if (samdb_find_attribute(ldb, ac->msg,
    18672978                                 "objectclass", "group") != NULL) {
    1868                 ac->type = "group";
     2979                ac->type = SAMLDB_TYPE_GROUP;
    18692980
    18702981                ret = samldb_objectclass_trigger(ac);
     
    18913002                }
    18923003
    1893                 ac->type = "classSchema";
     3004                ac->type = SAMLDB_TYPE_CLASS;
    18943005                return samldb_fill_object(ac);
    18953006        }
     
    19033014                }
    19043015
    1905                 ac->type = "attributeSchema";
     3016                ac->type = SAMLDB_TYPE_ATTRIBUTE;
    19063017                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. */
    19073029        }
    19083030
     
    19193041        struct samldb_ctx *ac;
    19203042        struct ldb_message_element *el, *el2;
     3043        struct ldb_control *is_undelete;
    19213044        bool modified = false;
    19223045        int ret;
     
    19293052        ldb = ldb_module_get_ctx(module);
    19303053
     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
    19313061        /* make sure that "objectSid" is not specified */
    19323062        el = ldb_msg_find_element(req->op.mod.message, "objectSid");
    19333063        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                }
    19443078        }
    19453079        /* make sure that "isCriticalSystemObject" is not specified */
     
    19623096        }
    19633097
     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
    19643107        ac = samldb_ctx_init(module, req);
    19653108        if (ac == NULL) {
     
    19763119        }
    19773120
    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                        }
    19833128                }
    19843129        }
     
    19933138        }
    19943139
     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
    19953149        el = ldb_msg_find_element(ac->msg, "groupType");
    19963150        if (el != NULL) {
     
    20313185                modified = true;
    20323186                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);
    20333195                if (ret != LDB_SUCCESS) {
    20343196                        return ret;
     
    20693231        int ret;
    20703232        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 };
    20733235
    20743236        ldb = ldb_module_get_ctx(ac->module);
    20753237
    20763238        /* 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;
    20803249        }
    20813250
     
    20933262                return LDB_SUCCESS;
    20943263        }
     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        }
    20953269
    20963270        /* 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,
    20983274                                 DSDB_FLAG_NEXT_MODULE,
    20993275                                 ac->req,
     
    21323308
    21333309        return ldb_next_request(module, req);
     3310}
     3311
     3312/* rename */
     3313
     3314static 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
     3489static 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 */
     3544static 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);
    21343585}
    21353586
     
    21733624        .modify        = samldb_modify,
    21743625        .del           = samldb_delete,
     3626        .rename        = samldb_rename,
    21753627        .extended      = samldb_extended
    21763628};
  • vendor/current/source4/dsdb/samdb/ldb_modules/schema_data.c

    r740 r988  
    140140        const char *oid_attr = NULL;
    141141        const char *oid = NULL;
     142        struct ldb_dn *parent_dn = NULL;
     143        int cmp;
    142144        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);
    145149
    146150        ldb = ldb_module_get_ctx(module);
     
    169173                ldb_debug_set(ldb, LDB_DEBUG_ERROR,
    170174                          "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));
    171205                return LDB_ERR_UNWILLING_TO_PERFORM;
    172206        }
     
    212246}
    213247
     248static 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
     349static 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
    214399static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
    215400                                  const struct dsdb_schema *schema)
     
    219404
    220405        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);
    222411                if (ret != LDB_SUCCESS) {
    223412                        return ret;
     
    231420        const struct dsdb_attribute *attribute;
    232421        int ret;
    233        
     422
    234423        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);
    236429                if (ret != LDB_SUCCESS) {
    237430                        return ret;
     
    275468                }
    276469
    277                 ret = ldb_msg_add_string(msg, "extendedAttributeInfo", val);
     470                ret = ldb_msg_add_steal_string(msg, "extendedAttributeInfo", val);
    278471                if (ret != LDB_SUCCESS) {
    279472                        return ret;
     
    297490                }
    298491
    299                 ret = ldb_msg_add_string(msg, "extendedClassInfo", val);
     492                ret = ldb_msg_add_steal_string(msg, "extendedClassInfo", val);
    300493                if (ret != LDB_SUCCESS) {
    301494                        return ret;
     
    335528
    336529        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);
    338535                if (ret != LDB_SUCCESS) {
    339536                        return ret;
     
    481678        .init_context   = schema_data_init,
    482679        .add            = schema_data_add,
     680        .modify         = schema_data_modify,
     681        .del            = schema_data_del,
    483682        .search         = schema_data_search
    484683};
  • vendor/current/source4/dsdb/samdb/ldb_modules/schema_load.c

    r740 r988  
    3030#include "librpc/gen_ndr/ndr_drsblobs.h"
    3131#include "param/param.h"
     32#include <tdb.h>
     33#include "lib/tdb_wrap/tdb_wrap.h"
    3234#include "dsdb/samdb/ldb_modules/util.h"
    3335
     36#include "system/filesys.h"
    3437struct schema_load_private_data {
    3538        bool in_transaction;
     39        struct tdb_wrap *metadata;
    3640};
    3741
    38 static int dsdb_schema_from_db(struct ldb_module *module, struct ldb_dn *schema_dn, uint64_t current_usn,
     42static 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,
    3946                               struct dsdb_schema **schema);
    4047
    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 */
     51static 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
     108static 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
     161static 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;
    44166        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;
    50167        struct ldb_context *ldb = ldb_module_get_ctx(module);
    51168        struct dsdb_schema *new_schema;
     169        struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb);
     170        time_t ts, lastts;     
    52171       
    53172        struct schema_load_private_data *private_data = talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
     
    62181        }
    63182
    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) {
    66187                return NULL;
    67188        }
    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, &current_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);
    83231        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);
    99240        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);
    118245                return schema;
    119246        }
    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, &current_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        
    134247        if (is_global_schema) {
    135248                dsdb_make_schema_global(ldb, new_schema);
    136249        }
     250        TALLOC_FREE(mem_ctx);
    137251        return new_schema;
    138252}
     
    143257*/
    144258
    145 static int dsdb_schema_from_db(struct ldb_module *module, struct ldb_dn *schema_dn, uint64_t current_usn,
     259static 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,
    146263                               struct dsdb_schema **schema)
    147264{
     
    150267        char *error_string;
    151268        int ret;
     269        struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb);
    152270        struct ldb_result *schema_res;
    153         struct ldb_result *a_res;
    154         struct ldb_result *c_res;
     271        struct ldb_result *res;
    155272        static const char *schema_attrs[] = {
    156273                "prefixMap",
     
    191308         * load the attribute definitions
    192309         */
    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,
    209311                                 schema_dn, LDB_SCOPE_ONELEVEL, NULL,
    210312                                 DSDB_FLAG_NEXT_MODULE |
    211313                                 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
    212314                                 NULL,
    213                                  "(objectClass=classSchema)");
     315                                 "(|(objectClass=attributeSchema)(objectClass=classSchema))");
    214316        if (ret != LDB_SUCCESS) {
    215317                ldb_asprintf_errstring(ldb,
    216                                        "dsdb_schema: failed to search classSchema objects: %s",
     318                                       "dsdb_schema: failed to search attributeSchema and classSchema objects: %s",
    217319                                       ldb_errstring(ldb));
    218320                goto failed;
     
    220322
    221323        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);
    223325        if (ret != LDB_SUCCESS) {
    224326                ldb_asprintf_errstring(ldb,
     
    228330        }
    229331
    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);
    258337
    259338failed:
     
    270349{
    271350        struct schema_load_private_data *private_data;
     351        struct ldb_context *ldb = ldb_module_get_ctx(module);
    272352        struct dsdb_schema *schema;
    273         struct ldb_context *ldb = ldb_module_get_ctx(module);
     353        void *readOnlySchema;
    274354        int ret;
    275         uint64_t current_usn;
    276         struct ldb_dn *schema_dn;
    277355
    278356        private_data = talloc_zero(module, struct schema_load_private_data);
     
    288366        }
    289367
    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
    291384                return LDB_SUCCESS;
    292385        }
    293386
    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, &current_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
     434static 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;
    313440        struct schema_load_private_data *private_data =
    314441                talloc_get_type(ldb_module_get_private(module), struct schema_load_private_data);
    315442
    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
     459static int schema_load_start_transaction(struct ldb_module *module)
    322460{
    323461        struct schema_load_private_data *private_data =
    324462                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
     486static int schema_load_end_transaction(struct ldb_module *module)
    332487{
    333488        struct schema_load_private_data *private_data =
     
    336491        private_data->in_transaction = false;
    337492
     493        return ldb_next_end_trans(module);
     494}
     495
     496static 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
    338503        return ldb_next_del_trans(module);
    339504}
     
    341506static int schema_load_extended(struct ldb_module *module, struct ldb_request *req)
    342507{
    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;
    346511
    347512        if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
    348513                return ldb_next_request(module, req);
    349514        }
    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);
    353527}
    354528
     
    358532        .init_context   = schema_load_init,
    359533        .extended       = schema_load_extended,
     534        .search         = schema_search,
    360535        .start_transaction = schema_load_start_transaction,
    361536        .end_transaction   = schema_load_end_transaction,
  • vendor/current/source4/dsdb/samdb/ldb_modules/schema_util.c

    r740 r988  
    144144{
    145145        int ldb_err;
    146         struct ldb_message *msg;
     146        struct ldb_message *msg = NULL;
    147147        TALLOC_CTX *temp_ctx;
    148148
     
    241241        temp_ctx = talloc_new(ldb_module);
    242242        if (temp_ctx == NULL) {
    243                 return ldb_module_oom(temp_ctx);
     243                return ldb_module_oom(ldb_module);
    244244        }
    245245
  • vendor/current/source4/dsdb/samdb/ldb_modules/show_deleted.c

    r740 r988  
    3737#include "dsdb/samdb/ldb_modules/util.h"
    3838
     39struct show_deleted_state {
     40        bool need_refresh;
     41        bool recycle_bin_enabled;
     42};
     43
    3944static int show_deleted_search(struct ldb_module *module, struct ldb_request *req)
    4045{
     
    4348        struct ldb_request *down_req;
    4449        struct ldb_parse_tree *new_tree = req->op.search.tree;
     50        struct show_deleted_state *state;
    4551        int ret;
     52        const char *attr_filter = NULL;
    4653
    4754        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        */
    4881
    4982        /* check if there's a show deleted control */
     
    5285        show_rec = ldb_request_get_control(req, LDB_CONTROL_SHOW_RECYCLED_OID);
    5386
    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
    59101                 */
    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) {
    62116                new_tree = talloc(req, struct ldb_parse_tree);
    63117                if (!new_tree) {
     
    79133                }
    80134                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;
    82136                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.1
    88                  *
    89                  * Filter: (&(!(isRecycled=TRUE))(...))
    90                  */
    91                 /* FIXME: we could use a constant tree here once we are sure
    92                  * 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 
    115137                new_tree->u.list.elements[1] = req->op.search.tree;
    116138        }
     
    145167        struct ldb_context *ldb;
    146168        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;
    147176
    148177        ldb = ldb_module_get_ctx(module);
     
    162191        }
    163192
    164         return ldb_next_init(module);
     193        ret = ldb_next_init(module);
     194
     195        ldb_module_set_private(module, state);
     196
     197        return ret;
    165198}
    166199
  • vendor/current/source4/dsdb/samdb/ldb_modules/simple_dn.c

    r740 r988  
    4545        new_base = ldb_dn_copy(req, req->op.search.base);
    4646        if (!new_base) {
    47                 ldb_module_oom(module);
     47                return ldb_module_oom(module);
    4848        }
    4949
  • vendor/current/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c

    r740 r988  
    3434#include "librpc/ndr/libndr.h"
    3535#include "dsdb/samdb/samdb.h"
     36#include "dsdb/common/util.h"
    3637#include <ldb_handlers.h>
    3738
     
    176177        unsigned long long usn = strtoull((const char *)val->data, NULL, 10);
    177178        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)));
    179186        return out;
    180187}
     
    362369        {
    363370                .local_name = "distinguishedName",
    364                 .type = LDB_MAP_RENAME,
     371                .type = LDB_MAP_RENDROP,
    365372                .u = {
    366373                        .rename = {
     
    476483        "usnChanged",
    477484        "memberOf",
     485        "name",
     486        "distinguishedName",
    478487        NULL
    479488};
     
    822831        int ret;
    823832        struct map_private *map_private;
    824         struct entryuuid_private *entryuuid_private;
    825833        unsigned long long seq_num = 0;
    826834        struct ldb_request *search_req;
     
    842850
    843851        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        }
    846857
    847858        /* All this to get the DN of the parition, so we can search the right thing */
     
    903914                break;
    904915        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
    910919        seqr->flags = 0;
    911         seqr->flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
    912920        seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
    913921
  • vendor/current/source4/dsdb/samdb/ldb_modules/subtree_delete.c

    r740 r988  
    3939
    4040
     41static 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
    4154static int subtree_delete(struct ldb_module *module, struct ldb_request *req)
    4255{
     
    6275                return ret;
    6376        }
    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        }
    7781
    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        }
    8494
    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;
    90120                }
    91121        }
     122
    92123        talloc_free(res);
    93124
  • vendor/current/source4/dsdb/samdb/ldb_modules/subtree_rename.c

    r740 r988  
    44   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007
    55   Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
     6   Copyright (C) Matthias Dieter Wallnöfer <mdw@samba.org> 2010-2011
    67
    78   This program is free software; you can redistribute it and/or modify
     
    3435#include "libds/common/flags.h"
    3536#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"
    4238
    4339struct subtree_rename_context {
    4440        struct ldb_module *module;
    4541        struct ldb_request *req;
    46 
    47         struct subren_msg_store *list;
    48         struct subren_msg_store *current;
    4942};
    5043
     
    5245                                                      struct ldb_request *req)
    5346{
    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
    5849
    5950        ac = talloc_zero(req, struct subtree_rename_context);
     
    6859}
    6960
    70 static int subtree_rename_next_request(struct subtree_rename_context *ac);
    71 
    7261static int subtree_rename_callback(struct ldb_request *req,
    7362                                   struct ldb_reply *ares)
     
    7564        struct ldb_context *ldb;
    7665        struct subtree_rename_context *ac;
    77         int ret;
    7866
    7967        ac = talloc_get_type(req->context, struct subtree_rename_context);
     
    9583
    9684        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);
    9886                return ldb_module_done(ac->req, NULL, NULL,
    9987                                        LDB_ERR_OPERATIONS_ERROR);
    10088        }
    10189
    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 
    11390        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
     94static 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;
    12199        int ret;
    122100
    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 the
    157          * relax control specified or if the returned objects is already
    158          * 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 the
    244                          * "ALLOW_LIMITED_MOVE" flag. This means that the
    245                          * grand-grand-parents of two objects have to be equal
    246                          * in order to perform the move (this is used for
    247                          * 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 
    308101        ac = talloc_get_type(req->context, struct subtree_rename_context);
    309102
    310         if (!ares || !ac->current) {
     103        if (!ares) {
    311104                return ldb_module_done(ac->req, NULL, NULL,
    312105                                        LDB_ERR_OPERATIONS_ERROR);
     
    319112        switch (ares->type) {
    320113        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))) {
    339123                        return ldb_module_done(ac->req, NULL, NULL,
    340124                                                LDB_ERR_OPERATIONS_ERROR);
    341125                }
    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)) {
    351128                        return ldb_module_done(ac->req, NULL, NULL,
    352129                                                LDB_ERR_OPERATIONS_ERROR);
    353130                }
    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);
    362132                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        }
    368140        case LDB_REPLY_REFERRAL:
    369141                /* ignore */
     
    372144        case LDB_REPLY_DONE:
    373145
    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);
    380153                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
    387161        return LDB_SUCCESS;
    388162}
     
    392166{
    393167        struct ldb_context *ldb;
    394         static const char * const attrs[] = { "objectClass", "systemFlags",
    395                                               "isDeleted", NULL };
     168        static const char * const no_attrs[] = {NULL};
    396169        struct ldb_request *search_req;
    397170        struct subtree_rename_context *ac;
     
    418191        }
    419192
    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,
    432196                                   "(objectClass=*)",
    433                                    attrs,
     197                                   no_attrs,
    434198                                   NULL,
    435                                    ac, 
    436                                    subtree_rename_search_callback,
     199                                   ac,
     200                                   subtree_rename_search_onelevel_callback,
    437201                                   req);
    438202        LDB_REQ_SET_LOCATION(search_req);
     
    447211        }
    448212
    449         return ldb_next_request(module, search_req);
     213        return ldb_next_request(ac->module, search_req);
    450214}
    451215
  • vendor/current/source4/dsdb/samdb/ldb_modules/update_keytab.c

    r740 r988  
    3535#include "system/kerberos.h"
    3636#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"
    3840
    3941struct dn_list {
     
    9092        int ret;
    9193
    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=*))");
    9496        if (!filter) {
    9597                return ldb_oom(ldb);
     
    108110                /* if it's not a kerberosSecret then we don't have anything to update */
    109111                talloc_free(res);
    110                 talloc_free(filter);
    111112                return LDB_SUCCESS;
    112113        }
     
    115116        if (!item) {
    116117                talloc_free(res);
    117                 talloc_free(filter);
    118118                return ldb_oom(ldb);
    119119        }
     
    123123        talloc_free(res);
    124124
    125         DLIST_ADD_END(data->changed_dns, item, struct dn_list *);
     125        DLIST_ADD_END(data->changed_dns, item);
    126126        return LDB_SUCCESS;
    127127}
     
    378378        struct dn_list *p;
    379379        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"),
    381382                                             &smb_krb5_context);
     383        TALLOC_CTX *tmp_ctx = NULL;
     384
    382385        if (krb5_ret != 0) {
    383                 talloc_free(data->changed_dns);
    384                 data->changed_dns = NULL;
    385386                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        }
    390395
    391396        for (p=data->changed_dns; p; p = p->next) {
    392397                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);
    394443                if (krb5_ret != 0) {
    395                         talloc_free(data->changed_dns);
    396                         data->changed_dns = NULL;
    397444                        ldb_asprintf_errstring(ldb, "Failed to update keytab from entry %s in %s: %s",
    398445                                               ldb_dn_get_linearized(p->msg->dn),
    399446                                               (const char *)ldb_get_opaque(ldb, "ldb_url"),
    400447                                               error_string);
    401                         return LDB_ERR_OPERATIONS_ERROR;
     448                        goto fail;
    402449                }
    403450        }
     
    405452        talloc_free(data->changed_dns);
    406453        data->changed_dns = NULL;
     454        talloc_free(tmp_ctx);
    407455
    408456        return ldb_next_prepare_commit(module);
     457
     458fail:
     459        talloc_free(data->changed_dns);
     460        data->changed_dns = NULL;
     461        talloc_free(tmp_ctx);
     462        return LDB_ERR_OPERATIONS_ERROR;
    409463}
    410464
  • vendor/current/source4/dsdb/samdb/ldb_modules/util.c

    r740 r988  
    55   Copyright (C) Andrew Tridgell 2009
    66   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
     7   Copyright (C) Matthieu Patou <mat@matws.net> 2011
    78
    89   This program is free software; you can redistribute it and/or modify
     
    2627#include "dsdb/samdb/ldb_modules/util.h"
    2728#include "dsdb/samdb/samdb.h"
    28 #include "util.h"
     29#include "dsdb/common/util.h"
    2930#include "libcli/security/security.h"
    3031
     
    110111}
    111112
    112 /*
    113   search for attrs in the modules below
    114  */
    115 int dsdb_module_search(struct ldb_module *module,
     113int dsdb_module_search_tree(struct ldb_module *module,
    116114                       TALLOC_CTX *mem_ctx,
    117115                       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,
    119119                       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)
    123122{
    124123        int ret;
     
    126125        TALLOC_CTX *tmp_ctx;
    127126        struct ldb_result *res;
    128         va_list ap;
    129         char *expression;
    130127
    131128        tmp_ctx = talloc_new(mem_ctx);
    132129
    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);
    145132
    146133        res = talloc_zero(tmp_ctx, struct ldb_result);
     
    150137        }
    151138
    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,
    153140                                   basedn,
    154141                                   scope,
    155                                    expression,
     142                                   tree,
    156143                                   attrs,
    157144                                   NULL,
     
    188175        }
    189176
     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
    190190        talloc_free(req);
    191191        if (ret == LDB_SUCCESS) {
    192192                *_res = talloc_steal(mem_ctx, res);
    193193        }
     194        talloc_free(tmp_ctx);
     195        return ret;
     196}
     197
     198/*
     199  search for attrs in the modules below
     200 */
     201int 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
    194252        talloc_free(tmp_ctx);
    195253        return ret;
     
    270328        return LDB_SUCCESS;
    271329}
     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 */
     339int 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
    272408
    273409/*
     
    547683}
    548684
    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 */
     694int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
    551695{
    552696        TALLOC_CTX *tmp_ctx;
     
    559703        unsigned int i;
    560704        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        }
    561714
    562715        *feature_enabled = false;
    563716
    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);
    569718        if (ret != LDB_SUCCESS) {
    570719                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));
    573722                talloc_free(tmp_ctx);
    574723                return LDB_ERR_OPERATIONS_ERROR;
    575724        }
    576725        if (res->msgs[0]->num_elements > 0) {
     726                const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
    577727
    578728                el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
    579 
    580                 attrs[0] = "msDS-OptionalFeatureGUID";
    581729
    582730                for (i=0; i<el->num_values; i++) {
    583731                        search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
    584732
    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);
    588735                        if (ret != LDB_SUCCESS) {
    589736                                ldb_asprintf_errstring(ldb,
     
    596743                        search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
    597744
    598                         if (GUID_compare(&search_guid, &op_feature_guid) == 0){
     745                        if (GUID_equal(&search_guid, &op_feature_guid)) {
    599746                                *feature_enabled = true;
    600747                                break;
     
    651798
    652799        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);
    654801        if (ret != LDB_SUCCESS) {
    655802                return ret;
     
    9021049{
    9031050        struct ldb_context *ldb = ldb_module_get_ctx(module);
    904         struct ldb_dn *partitions_dn;
    9051051        struct GUID recyclebin_guid;
    9061052        int ret;
    9071053
    908         partitions_dn = samdb_partitions_dn(ldb, module);
    909 
    9101054        GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
    9111055
    912         ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
     1056        ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
    9131057        if (ret != LDB_SUCCESS) {
    9141058                ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
    915                 talloc_free(partitions_dn);
    9161059                return LDB_ERR_UNWILLING_TO_PERFORM;
    9171060        }
    9181061
    919         talloc_free(partitions_dn);
    9201062        return LDB_SUCCESS;
    9211063}
     
    10511193
    10521194        msg = ldb_msg_new(module);
     1195        if (msg == NULL) {
     1196                return ldb_module_oom(module);
     1197        }
    10531198        msg->dn = dn;
    10541199
     
    10931238
    10941239        msg = ldb_msg_new(module);
     1240        if (msg == NULL) {
     1241                return ldb_module_oom(module);
     1242        }
    10951243        msg->dn = dn;
    10961244
     
    12351383        return el;
    12361384}
     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 */
     1391const 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
     1416const 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*/
     1433int 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 */
     1470int 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  
    2626struct security_descriptor;
    2727struct dom_sid;
     28struct netlogon_samlogon_response;
    2829
    2930#include "librpc/gen_ndr/misc.h"
    3031#include "dsdb/samdb/ldb_modules/util_proto.h"
    3132#include "dsdb/common/util.h"
     33#include "../libcli/netlogon/netlogon.h"
    3234
    3335/* extend the dsdb_request_add_controls() flags for module
  • vendor/current/source4/dsdb/samdb/ldb_modules/wscript_build

    r740 r988  
    33bld.SAMBA_LIBRARY('dsdb-module',
    44        source=[],
    5         deps='DSDB_MODULE_HELPERS DSDB_MODULE_HELPER_SCHEMA DSDB_MODULE_HELPER_RIDALLOC',
     5        deps='DSDB_MODULE_HELPERS DSDB_MODULE_HELPER_RIDALLOC',
    66        private_library=True,
    77        grouping_library=True)
    88
    99bld.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',
    1111        autoproto='util_proto.h',
    12         deps='ldb ndr samdb-common security'
     12        deps='ldb ndr samdb-common samba-security'
    1313        )
    1414
     
    1919        )
    2020
    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         )
     21if bld.AD_DC_BUILD_IS_ENABLED():
     22    bld.PROCESS_SEPARATE_RULE("server")
  • vendor/current/source4/dsdb/samdb/samdb.c

    r740 r988  
    4545
    4646/*
    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
    9348  return an opaque context pointer on success, or NULL on failure
    9449 */
    95 struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx,
     50struct ldb_context *samdb_connect_url(TALLOC_CTX *mem_ctx,
    9651                                  struct tevent_context *ev_ctx,
    9752                                  struct loadparm_context *lp_ctx,
    9853                                  struct auth_session_info *session_info,
    99                                   int flags)
     54                                  unsigned int flags, const char *url)
    10055{
    10156        struct ldb_context *ldb;
    102         struct dsdb_schema *schema;
    103         const char *url;
    104         struct cli_credentials *credentials;
    10557        int ret;
    10658
    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);
    11160        if (ldb != NULL)
    11261                return talloc_reference(mem_ctx, ldb);
    11362
    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);
    11564
    11665        if (ldb == NULL)
     
    12574        }
    12675
    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)) {
    13477                talloc_free(ldb);
    13578                return NULL;
     
    13982}
    14083
     84
     85/*
     86  connect to the SAM database
     87  return an opaque context pointer on success, or NULL on failure
     88 */
     89struct 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}
    14197
    14298/****************************************************************************
     
    181137        }
    182138
    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 
    214139        /* The caller may have requested simple privilages, for example if there isn't a local DB */
    215140        if (session_info_flags & AUTH_SESSION_INFO_SIMPLE_PRIVILEGES) {
  • vendor/current/source4/dsdb/samdb/samdb.h

    r740 r988  
    3030struct tevent_context;
    3131
     32struct dsdb_trust_routing_table;
     33
    3234#include "librpc/gen_ndr/security.h"
    3335#include <ldb.h>
     
    5456};
    5557
     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
    5668#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 */
     69struct dsdb_control_replicated_update {
     70        uint32_t dsdb_repl_flags;
     71};
    5872
    5973#define DSDB_CONTROL_DN_STORAGE_FORMAT_OID "1.3.6.1.4.1.7165.4.3.4"
     
    8296
    8397#define DSDB_CONTROL_PASSWORD_CHANGE_OID "1.3.6.1.4.1.7165.4.3.10"
    84 
    8598struct dsdb_control_password_change {
    8699        const struct samr_Password *old_nt_pwd_hash;
     
    103116*/
    104117#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"
    105160
    106161#define DSDB_EXTENDED_REPLICATED_OBJECTS_OID "1.3.6.1.4.1.7165.4.4.1"
     
    108163        struct ldb_message *msg;
    109164        struct ldb_val guid_value;
     165        struct ldb_val parent_guid_value;
    110166        const char *when_changed;
    111167        struct replPropertyMetaDataBlob *meta_data;
     168
     169        /* Only used for internal processing in repl_meta_data */
     170        struct ldb_dn *last_known_parent;
    112171};
    113172
     
    117176         * version 0: initial implementation
    118177         */
    119 #define DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION 1
     178#define DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION 2
    120179        uint32_t version;
     180
     181        /* DSDB_REPL_FLAG_* flags */
     182        uint32_t dsdb_repl_flags;
    121183
    122184        struct ldb_dn *partition_dn;
     
    130192        uint32_t linked_attributes_count;
    131193        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;
    142194};
    143195
     
    152204 */
    153205#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"
    154208
    155209#define DSDB_OPENLDAP_DEREFERENCE_CONTROL "1.3.6.1.4.1.4203.666.5.16"
     
    175229};
    176230
     231struct 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
    177238#define DSDB_PARTITION_DN "@PARTITION"
    178239#define DSDB_PARTITION_ATTR "partition"
     
    183244};
    184245
     246#define DSDB_OPAQUE_LAST_SCHEMA_UPDATE_MSG_OPAQUE_NAME "DSDB_OPAQUE_LAST_SCHEMA_UPDATE"
    185247#define DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME "DSDB_OPAQUE_PARTITION_MODULE_MSG"
    186248
     
    193255};
    194256
     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"
     263struct 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"
    195273#endif /* __SAMDB_H__ */
Note: See TracChangeset for help on using the changeset viewer.