LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules - util.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 461 678 68.0 %
Date: 2021-09-23 10:06:22 Functions: 37 40 92.5 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba utility functions
       4             : 
       5             :    Copyright (C) Andrew Tridgell 2009
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
       7             :    Copyright (C) Matthieu Patou <mat@matws.net> 2011
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "ldb.h"
      25             : #include "ldb_module.h"
      26             : #include "librpc/ndr/libndr.h"
      27             : #include "dsdb/samdb/ldb_modules/util.h"
      28             : #include "dsdb/samdb/samdb.h"
      29             : #include "dsdb/common/util.h"
      30             : #include "libcli/security/security.h"
      31             : 
      32             : #undef strcasecmp
      33             : 
      34             : /*
      35             :   search for attrs on one DN, in the modules below
      36             :  */
      37     9987776 : int dsdb_module_search_dn(struct ldb_module *module,
      38             :                           TALLOC_CTX *mem_ctx,
      39             :                           struct ldb_result **_res,
      40             :                           struct ldb_dn *basedn,
      41             :                           const char * const *attrs,
      42             :                           uint32_t dsdb_flags,
      43             :                           struct ldb_request *parent)
      44             : {
      45             :         int ret;
      46             :         struct ldb_request *req;
      47             :         TALLOC_CTX *tmp_ctx;
      48             :         struct ldb_result *res;
      49             : 
      50     9987776 :         tmp_ctx = talloc_new(mem_ctx);
      51             : 
      52     9987776 :         res = talloc_zero(tmp_ctx, struct ldb_result);
      53     9987776 :         if (!res) {
      54           0 :                 talloc_free(tmp_ctx);
      55           0 :                 return ldb_oom(ldb_module_get_ctx(module));
      56             :         }
      57             : 
      58     9987776 :         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
      59             :                                    basedn,
      60             :                                    LDB_SCOPE_BASE,
      61             :                                    NULL,
      62             :                                    attrs,
      63             :                                    NULL,
      64             :                                    res,
      65             :                                    ldb_search_default_callback,
      66             :                                    parent);
      67     9987776 :         LDB_REQ_SET_LOCATION(req);
      68     9987776 :         if (ret != LDB_SUCCESS) {
      69           0 :                 talloc_free(tmp_ctx);
      70           0 :                 return ret;
      71             :         }
      72             : 
      73     9987776 :         ret = dsdb_request_add_controls(req, dsdb_flags);
      74     9987776 :         if (ret != LDB_SUCCESS) {
      75           0 :                 talloc_free(tmp_ctx);
      76           0 :                 return ret;
      77             :         }
      78             : 
      79     9987776 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
      80           0 :                 ldb_req_mark_trusted(req);
      81             :         }
      82             : 
      83             :         /* Run the new request */
      84     9987776 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
      85     9987502 :                 ret = ldb_next_request(module, req);
      86         274 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
      87         274 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
      88             :         } else {
      89           0 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
      90           0 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
      91           0 :                 ret = ops->search(module, req);
      92             :         }
      93     9987776 :         if (ret == LDB_SUCCESS) {
      94     9987755 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
      95             :         }
      96             : 
      97     9987776 :         if (ret != LDB_SUCCESS) {
      98      251243 :                 talloc_free(tmp_ctx);
      99      251243 :                 return ret;
     100             :         }
     101             : 
     102     9736533 :         if (res->count != 1) {
     103             :                 /* we may be reading a DB that does not have the 'check base on search' option... */
     104       12098 :                 ret = LDB_ERR_NO_SUCH_OBJECT;
     105       12098 :                 ldb_asprintf_errstring(ldb_module_get_ctx(module), 
     106             :                                        "dsdb_module_search_dn: did not find base dn %s (%d results)", 
     107             :                                        ldb_dn_get_linearized(basedn), res->count);
     108             :         } else {
     109     9724435 :                 *_res = talloc_steal(mem_ctx, res);
     110             :         }
     111     9736533 :         talloc_free(tmp_ctx);
     112     9736533 :         return ret;
     113             : }
     114             : 
     115     9847957 : int dsdb_module_search_tree(struct ldb_module *module,
     116             :                        TALLOC_CTX *mem_ctx,
     117             :                        struct ldb_result **_res,
     118             :                        struct ldb_dn *basedn,
     119             :                        enum ldb_scope scope,
     120             :                        struct ldb_parse_tree *tree,
     121             :                        const char * const *attrs,
     122             :                        int dsdb_flags,
     123             :                        struct ldb_request *parent)
     124             : {
     125             :         int ret;
     126             :         struct ldb_request *req;
     127             :         TALLOC_CTX *tmp_ctx;
     128             :         struct ldb_result *res;
     129             : 
     130     9847957 :         tmp_ctx = talloc_new(mem_ctx);
     131             : 
     132             :         /* cross-partitions searches with a basedn break multi-domain support */
     133     9847957 :         SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
     134             : 
     135     9847957 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     136     9847957 :         if (!res) {
     137           0 :                 talloc_free(tmp_ctx);
     138           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     139             :         }
     140             : 
     141     9847957 :         ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
     142             :                                    basedn,
     143             :                                    scope,
     144             :                                    tree,
     145             :                                    attrs,
     146             :                                    NULL,
     147             :                                    res,
     148             :                                    ldb_search_default_callback,
     149             :                                    parent);
     150     9847957 :         LDB_REQ_SET_LOCATION(req);
     151     9847957 :         if (ret != LDB_SUCCESS) {
     152           0 :                 talloc_free(tmp_ctx);
     153           0 :                 return ret;
     154             :         }
     155             : 
     156     9847957 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     157     9847957 :         if (ret != LDB_SUCCESS) {
     158           0 :                 talloc_free(tmp_ctx);
     159           0 :                 return ret;
     160             :         }
     161             : 
     162     9847957 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     163           0 :                 ldb_req_mark_trusted(req);
     164             :         }
     165             : 
     166     9847957 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     167     9847954 :                 ret = ldb_next_request(module, req);
     168           3 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     169           3 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     170             :         } else {
     171           0 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     172           0 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     173           0 :                 ret = ops->search(module, req);
     174             :         }
     175     9847957 :         if (ret == LDB_SUCCESS) {
     176     9847957 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     177             :         }
     178             : 
     179     9847957 :         if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
     180     7902826 :                 if (res->count == 0) {
     181        6692 :                         talloc_free(tmp_ctx);
     182        6692 :                         return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
     183             :                 }
     184     7896134 :                 if (res->count != 1) {
     185           0 :                         talloc_free(tmp_ctx);
     186           0 :                         ldb_reset_err_string(ldb_module_get_ctx(module));
     187           0 :                         return LDB_ERR_CONSTRAINT_VIOLATION;
     188             :                 }
     189             :         }
     190             : 
     191     9841265 :         talloc_free(req);
     192     9841265 :         if (ret == LDB_SUCCESS) {
     193     9840298 :                 *_res = talloc_steal(mem_ctx, res);
     194             :         }
     195     9841265 :         talloc_free(tmp_ctx);
     196     9841265 :         return ret;
     197             : }
     198             : 
     199             : /*
     200             :   search for attrs in the modules below
     201             :  */
     202     9846614 : int dsdb_module_search(struct ldb_module *module,
     203             :                        TALLOC_CTX *mem_ctx,
     204             :                        struct ldb_result **_res,
     205             :                        struct ldb_dn *basedn, enum ldb_scope scope,
     206             :                        const char * const *attrs,
     207             :                        int dsdb_flags,
     208             :                        struct ldb_request *parent,
     209             :                        const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
     210             : {
     211             :         int ret;
     212             :         TALLOC_CTX *tmp_ctx;
     213             :         va_list ap;
     214             :         char *expression;
     215             :         struct ldb_parse_tree *tree;
     216             : 
     217             :         /* cross-partitions searches with a basedn break multi-domain support */
     218     9846614 :         SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
     219             : 
     220     9846614 :         tmp_ctx = talloc_new(mem_ctx);
     221             : 
     222     9846614 :         if (format) {
     223     9310076 :                 va_start(ap, format);
     224     9310076 :                 expression = talloc_vasprintf(tmp_ctx, format, ap);
     225     9310076 :                 va_end(ap);
     226             : 
     227     9310076 :                 if (!expression) {
     228           0 :                         talloc_free(tmp_ctx);
     229           0 :                         return ldb_oom(ldb_module_get_ctx(module));
     230             :                 }
     231             :         } else {
     232      517398 :                 expression = NULL;
     233             :         }
     234             : 
     235     9846614 :         tree = ldb_parse_tree(tmp_ctx, expression);
     236     9846614 :         if (tree == NULL) {
     237           0 :                 talloc_free(tmp_ctx);
     238           0 :                 ldb_set_errstring(ldb_module_get_ctx(module),
     239             :                                 "Unable to parse search expression");
     240           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     241             :         }
     242             : 
     243     9846614 :         ret = dsdb_module_search_tree(module,
     244             :                        mem_ctx,
     245             :                        _res,
     246             :                        basedn,
     247             :                        scope,
     248             :                        tree,
     249             :                        attrs,
     250             :                        dsdb_flags,
     251             :                        parent);
     252             : 
     253     9846614 :         talloc_free(tmp_ctx);
     254     9846614 :         return ret;
     255             : }
     256             : 
     257             : /*
     258             :   find a DN given a GUID. This searches across all partitions
     259             :  */
     260       35798 : int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
     261             :                            const struct GUID *guid, struct ldb_dn **dn,
     262             :                            struct ldb_request *parent)
     263             : {
     264             :         struct ldb_result *res;
     265       35798 :         const char *attrs[] = { NULL };
     266       35798 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     267             :         int ret;
     268             : 
     269       35798 :         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
     270             :                                  attrs,
     271             :                                  DSDB_FLAG_NEXT_MODULE |
     272             :                                  DSDB_SEARCH_SHOW_RECYCLED |
     273             :                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
     274             :                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
     275             :                                  parent,
     276             :                                  "objectGUID=%s", GUID_string(tmp_ctx, guid));
     277       35798 :         if (ret != LDB_SUCCESS) {
     278           0 :                 talloc_free(tmp_ctx);
     279           0 :                 return ret;
     280             :         }
     281       35798 :         if (res->count == 0) {
     282          56 :                 talloc_free(tmp_ctx);
     283          56 :                 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
     284             :         }
     285       35742 :         if (res->count != 1) {
     286           0 :                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
     287             :                                        GUID_string(tmp_ctx, guid));
     288           0 :                 talloc_free(tmp_ctx);
     289           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     290             :         }
     291             : 
     292       35742 :         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
     293             : 
     294       35742 :         talloc_free(tmp_ctx);
     295       35742 :         return LDB_SUCCESS;
     296             : }
     297             : 
     298             : /*
     299             :   find a GUID given a DN.
     300             :  */
     301       11123 : int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
     302             :                            struct ldb_request *parent)
     303             : {
     304       11123 :         const char *attrs[] = { NULL };
     305             :         struct ldb_result *res;
     306       11123 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     307             :         int ret;
     308             :         NTSTATUS status;
     309             : 
     310       11123 :         ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
     311             :                                     DSDB_FLAG_NEXT_MODULE |
     312             :                                     DSDB_SEARCH_SHOW_RECYCLED |
     313             :                                     DSDB_SEARCH_SHOW_EXTENDED_DN,
     314             :                                     parent);
     315       11123 :         if (ret != LDB_SUCCESS) {
     316           3 :                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
     317             :                                        ldb_dn_get_linearized(dn));
     318           3 :                 talloc_free(tmp_ctx);
     319           3 :                 return ret;
     320             :         }
     321             : 
     322       11120 :         status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
     323       11120 :         if (!NT_STATUS_IS_OK(status)) {
     324           0 :                 talloc_free(tmp_ctx);
     325           0 :                 return ldb_operr(ldb_module_get_ctx(module));
     326             :         }
     327             : 
     328       11120 :         talloc_free(tmp_ctx);
     329       11120 :         return LDB_SUCCESS;
     330             : }
     331             : 
     332             : 
     333             : /*
     334             :   a ldb_extended request operating on modules below the
     335             :   current module
     336             : 
     337             :   Note that this does not automatically start a transaction. If you
     338             :   need a transaction the caller needs to start it as needed.
     339             :  */
     340    14263475 : int dsdb_module_extended(struct ldb_module *module,
     341             :                          TALLOC_CTX *mem_ctx,
     342             :                          struct ldb_result **_res,
     343             :                          const char* oid, void* data,
     344             :                          uint32_t dsdb_flags,
     345             :                          struct ldb_request *parent)
     346             : {
     347             :         struct ldb_request *req;
     348             :         int ret;
     349    14263475 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     350    14263475 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     351             :         struct ldb_result *res;
     352             : 
     353    14263475 :         if (_res != NULL) {
     354    13933044 :                 (*_res) = NULL;
     355             :         }
     356             : 
     357    14263475 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     358    14263475 :         if (!res) {
     359           0 :                 talloc_free(tmp_ctx);
     360           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     361             :         }
     362             : 
     363    14263475 :         ret = ldb_build_extended_req(&req, ldb,
     364             :                         tmp_ctx,
     365             :                         oid,
     366             :                         data,
     367             :                         NULL,
     368             :                         res, ldb_extended_default_callback,
     369             :                         parent);
     370             : 
     371    14263475 :         LDB_REQ_SET_LOCATION(req);
     372    14263475 :         if (ret != LDB_SUCCESS) {
     373           0 :                 talloc_free(tmp_ctx);
     374           0 :                 return ret;
     375             :         }
     376             : 
     377    14263475 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     378    14263475 :         if (ret != LDB_SUCCESS) {
     379           0 :                 talloc_free(tmp_ctx);
     380           0 :                 return ret;
     381             :         }
     382             : 
     383    14263475 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     384      330431 :                 ldb_req_mark_trusted(req);
     385             :         }
     386             : 
     387             :         /* Run the new request */
     388    14263475 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     389    13933044 :                 ret = ldb_next_request(module, req);
     390      330431 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     391      330431 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     392             :         } else {
     393           0 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     394           0 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     395           0 :                 ret = ops->extended(module, req);
     396             :         }
     397    14263475 :         if (ret == LDB_SUCCESS) {
     398    14263475 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     399             :         }
     400             : 
     401    14263475 :         if (_res != NULL && ret == LDB_SUCCESS) {
     402    13933044 :                 (*_res) = talloc_steal(mem_ctx, res);
     403             :         }
     404             : 
     405    14263475 :         talloc_free(tmp_ctx);
     406    14263475 :         return ret;
     407             : }
     408             : 
     409             : 
     410             : /*
     411             :   a ldb_modify request operating on modules below the
     412             :   current module
     413             :  */
     414      275724 : int dsdb_module_modify(struct ldb_module *module,
     415             :                        const struct ldb_message *message,
     416             :                        uint32_t dsdb_flags,
     417             :                        struct ldb_request *parent)
     418             : {
     419             :         struct ldb_request *mod_req;
     420             :         int ret;
     421      275724 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     422      275724 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     423             :         struct ldb_result *res;
     424             : 
     425      275724 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     426      275724 :         if (!res) {
     427           0 :                 talloc_free(tmp_ctx);
     428           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     429             :         }
     430             : 
     431      275724 :         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
     432             :                                 message,
     433             :                                 NULL,
     434             :                                 res,
     435             :                                 ldb_modify_default_callback,
     436             :                                 parent);
     437      275724 :         LDB_REQ_SET_LOCATION(mod_req);
     438      275724 :         if (ret != LDB_SUCCESS) {
     439           0 :                 talloc_free(tmp_ctx);
     440           0 :                 return ret;
     441             :         }
     442             : 
     443      275724 :         ret = dsdb_request_add_controls(mod_req, dsdb_flags);
     444      275724 :         if (ret != LDB_SUCCESS) {
     445           0 :                 talloc_free(tmp_ctx);
     446           0 :                 return ret;
     447             :         }
     448             : 
     449      275724 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     450           0 :                 ldb_req_mark_trusted(mod_req);
     451             :         }
     452             : 
     453             :         /* Run the new request */
     454      275724 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     455      100874 :                 ret = ldb_next_request(module, mod_req);
     456      174850 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     457           2 :                 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
     458             :         } else {
     459      174848 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     460      174848 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     461      174848 :                 ret = ops->modify(module, mod_req);
     462             :         }
     463      275724 :         if (ret == LDB_SUCCESS) {
     464      275724 :                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
     465             :         }
     466             : 
     467      275724 :         talloc_free(tmp_ctx);
     468      275724 :         return ret;
     469             : }
     470             : 
     471             : 
     472             : 
     473             : /*
     474             :   a ldb_rename request operating on modules below the
     475             :   current module
     476             :  */
     477      121252 : int dsdb_module_rename(struct ldb_module *module,
     478             :                        struct ldb_dn *olddn, struct ldb_dn *newdn,
     479             :                        uint32_t dsdb_flags,
     480             :                        struct ldb_request *parent)
     481             : {
     482             :         struct ldb_request *req;
     483             :         int ret;
     484      121252 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     485      121252 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     486             :         struct ldb_result *res;
     487             : 
     488      121252 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     489      121252 :         if (!res) {
     490           0 :                 talloc_free(tmp_ctx);
     491           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     492             :         }
     493             : 
     494      121252 :         ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
     495             :                                    olddn,
     496             :                                    newdn,
     497             :                                    NULL,
     498             :                                    res,
     499             :                                    ldb_modify_default_callback,
     500             :                                    parent);
     501      121252 :         LDB_REQ_SET_LOCATION(req);
     502      121252 :         if (ret != LDB_SUCCESS) {
     503           0 :                 talloc_free(tmp_ctx);
     504           0 :                 return ret;
     505             :         }
     506             : 
     507      121252 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     508      121252 :         if (ret != LDB_SUCCESS) {
     509           0 :                 talloc_free(tmp_ctx);
     510           0 :                 return ret;
     511             :         }
     512             : 
     513      121252 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     514           0 :                 ldb_req_mark_trusted(req);
     515             :         }
     516             : 
     517             :         /* Run the new request */
     518      121252 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     519      120767 :                 ret = ldb_next_request(module, req);
     520         485 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     521           0 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     522             :         } else {
     523         485 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     524         485 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     525         485 :                 ret = ops->rename(module, req);
     526             :         }
     527      121252 :         if (ret == LDB_SUCCESS) {
     528      121250 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     529             :         }
     530             : 
     531      121252 :         talloc_free(tmp_ctx);
     532      121252 :         return ret;
     533             : }
     534             : 
     535             : /*
     536             :   a ldb_add request operating on modules below the
     537             :   current module
     538             :  */
     539        1296 : int dsdb_module_add(struct ldb_module *module,
     540             :                     const struct ldb_message *message,
     541             :                     uint32_t dsdb_flags,
     542             :                     struct ldb_request *parent)
     543             : {
     544             :         struct ldb_request *req;
     545             :         int ret;
     546        1296 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     547        1296 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     548             :         struct ldb_result *res;
     549             : 
     550        1296 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     551        1296 :         if (!res) {
     552           0 :                 talloc_free(tmp_ctx);
     553           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     554             :         }
     555             : 
     556        1296 :         ret = ldb_build_add_req(&req, ldb, tmp_ctx,
     557             :                                 message,
     558             :                                 NULL,
     559             :                                 res,
     560             :                                 ldb_modify_default_callback,
     561             :                                 parent);
     562        1296 :         LDB_REQ_SET_LOCATION(req);
     563        1296 :         if (ret != LDB_SUCCESS) {
     564           0 :                 talloc_free(tmp_ctx);
     565           0 :                 return ret;
     566             :         }
     567             : 
     568        1296 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     569        1296 :         if (ret != LDB_SUCCESS) {
     570           0 :                 talloc_free(tmp_ctx);
     571           0 :                 return ret;
     572             :         }
     573             : 
     574        1296 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     575           0 :                 ldb_req_mark_trusted(req);
     576             :         }
     577             : 
     578             :         /* Run the new request */
     579        1296 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     580        1226 :                 ret = ldb_next_request(module, req);
     581          70 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     582          70 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     583             :         } else {
     584           0 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     585           0 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     586           0 :                 ret = ops->add(module, req);
     587             :         }
     588        1296 :         if (ret == LDB_SUCCESS) {
     589        1296 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     590             :         }
     591             : 
     592        1296 :         talloc_free(tmp_ctx);
     593        1296 :         return ret;
     594             : }
     595             : 
     596             : /*
     597             :   a ldb_delete request operating on modules below the
     598             :   current module
     599             :  */
     600       25025 : int dsdb_module_del(struct ldb_module *module,
     601             :                     struct ldb_dn *dn,
     602             :                     uint32_t dsdb_flags,
     603             :                     struct ldb_request *parent)
     604             : {
     605             :         struct ldb_request *req;
     606             :         int ret;
     607       25025 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     608       25025 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     609             :         struct ldb_result *res;
     610             : 
     611       25025 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     612       25025 :         if (!res) {
     613           0 :                 talloc_free(tmp_ctx);
     614           0 :                 return ldb_oom(ldb);
     615             :         }
     616             : 
     617       25025 :         ret = ldb_build_del_req(&req, ldb, tmp_ctx,
     618             :                                 dn,
     619             :                                 NULL,
     620             :                                 res,
     621             :                                 ldb_modify_default_callback,
     622             :                                 parent);
     623       25025 :         LDB_REQ_SET_LOCATION(req);
     624       25025 :         if (ret != LDB_SUCCESS) {
     625           0 :                 talloc_free(tmp_ctx);
     626           0 :                 return ret;
     627             :         }
     628             : 
     629       25025 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     630       25025 :         if (ret != LDB_SUCCESS) {
     631           0 :                 talloc_free(tmp_ctx);
     632           0 :                 return ret;
     633             :         }
     634             : 
     635       25025 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     636       25025 :                 ldb_req_mark_trusted(req);
     637             :         }
     638             : 
     639             :         /* Run the new request */
     640       25025 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     641           0 :                 ret = ldb_next_request(module, req);
     642       25025 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     643       25025 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     644             :         } else {
     645           0 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     646           0 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     647           0 :                 ret = ops->del(module, req);
     648             :         }
     649       25025 :         if (ret == LDB_SUCCESS) {
     650       25025 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     651             :         }
     652             : 
     653       25025 :         talloc_free(tmp_ctx);
     654       25025 :         return ret;
     655             : }
     656             : 
     657             : /*
     658             :   check if a single valued link has multiple non-deleted values
     659             : 
     660             :   This is needed when we will be using the RELAX control to stop
     661             :   ldb_tdb from checking single valued links
     662             :  */
     663       37896 : int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
     664             :                                   const struct ldb_message_element *el)
     665             : {
     666       37896 :         bool found_active = false;
     667             :         unsigned int i;
     668             : 
     669       44741 :         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
     670        7079 :             el->num_values < 2) {
     671       37090 :                 return LDB_SUCCESS;
     672             :         }
     673             : 
     674         387 :         for (i=0; i<el->num_values; i++) {
     675         260 :                 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
     676         123 :                         if (found_active) {
     677           3 :                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     678             :                         }
     679         120 :                         found_active = true;
     680             :                 }
     681             :         }
     682             : 
     683         127 :         return LDB_SUCCESS;
     684             : }
     685             : 
     686             : 
     687      264906 : int dsdb_check_samba_compatible_feature(struct ldb_module *module,
     688             :                                         const char *feature,
     689             :                                         bool *found)
     690             : {
     691      264906 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     692             :         struct ldb_result *res;
     693             :         static const char *samba_dsdb_attrs[] = {
     694             :                 SAMBA_COMPATIBLE_FEATURES_ATTR,
     695             :                 NULL
     696             :         };
     697             :         int ret;
     698      264906 :         struct ldb_dn *samba_dsdb_dn = NULL;
     699      264906 :         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
     700      264906 :         if (tmp_ctx == NULL) {
     701           0 :                 *found = false;
     702           0 :                 return ldb_oom(ldb);
     703             :         }
     704      264906 :         *found = false;
     705             : 
     706      264906 :         samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
     707      264906 :         if (samba_dsdb_dn == NULL) {
     708           0 :                 TALLOC_FREE(tmp_ctx);
     709           0 :                 return ldb_oom(ldb);
     710             :         }
     711             : 
     712      264906 :         ret = dsdb_module_search_dn(module,
     713             :                                     tmp_ctx,
     714             :                                     &res,
     715             :                                     samba_dsdb_dn,
     716             :                                     samba_dsdb_attrs,
     717             :                                     DSDB_FLAG_NEXT_MODULE,
     718             :                                     NULL);
     719      264906 :         if (ret == LDB_SUCCESS) {
     720      264906 :                 *found = ldb_msg_check_string_attribute(
     721      264906 :                         res->msgs[0],
     722             :                         SAMBA_COMPATIBLE_FEATURES_ATTR,
     723             :                         feature);
     724           0 :         } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     725             :                 /* it is not an error not to find it */
     726           0 :                 ret = LDB_SUCCESS;
     727             :         }
     728      264906 :         TALLOC_FREE(tmp_ctx);
     729      264906 :         return ret;
     730             : }
     731             : 
     732             : 
     733             : /*
     734             :   check if an optional feature is enabled on our own NTDS DN
     735             : 
     736             :   Note that features can be marked as enabled in more than one
     737             :   place. For example, the recyclebin feature is marked as enabled both
     738             :   on the CN=Partitions,CN=Configurration object and on the NTDS DN of
     739             :   each DC in the forest. It seems likely that it is the job of the KCC
     740             :   to propagate between the two
     741             :  */
     742       83326 : int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
     743             : {
     744             :         TALLOC_CTX *tmp_ctx;
     745       83326 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     746             :         struct ldb_result *res;
     747             :         struct ldb_dn *search_dn;
     748             :         struct GUID search_guid;
     749       83326 :         const char *attrs[] = {"msDS-EnabledFeature", NULL};
     750             :         int ret;
     751             :         unsigned int i;
     752             :         struct ldb_message_element *el;
     753             :         struct ldb_dn *feature_dn;
     754             : 
     755       83326 :         tmp_ctx = talloc_new(ldb);
     756             : 
     757       83326 :         feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
     758       83326 :         if (feature_dn == NULL) {
     759           1 :                 talloc_free(tmp_ctx);
     760           1 :                 return ldb_operr(ldb_module_get_ctx(module));
     761             :         }
     762             : 
     763       83325 :         *feature_enabled = false;
     764             : 
     765       83325 :         ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
     766       83325 :         if (ret != LDB_SUCCESS) {
     767        1389 :                 ldb_asprintf_errstring(ldb,
     768             :                                 "Could not find the feature object - dn: %s\n",
     769             :                                 ldb_dn_get_linearized(feature_dn));
     770        1389 :                 talloc_free(tmp_ctx);
     771        1389 :                 return LDB_ERR_NO_SUCH_OBJECT;
     772             :         }
     773       81936 :         if (res->msgs[0]->num_elements > 0) {
     774           0 :                 const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
     775             : 
     776           0 :                 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
     777             : 
     778           0 :                 for (i=0; i<el->num_values; i++) {
     779           0 :                         search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
     780             : 
     781           0 :                         ret = dsdb_module_search_dn(module, tmp_ctx, &res,
     782             :                                                     search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
     783           0 :                         if (ret != LDB_SUCCESS) {
     784           0 :                                 ldb_asprintf_errstring(ldb,
     785             :                                                 "Could no find object dn: %s\n",
     786             :                                                 ldb_dn_get_linearized(search_dn));
     787           0 :                                 talloc_free(tmp_ctx);
     788           0 :                                 return LDB_ERR_OPERATIONS_ERROR;
     789             :                         }
     790             : 
     791           0 :                         search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
     792             : 
     793           0 :                         if (GUID_equal(&search_guid, &op_feature_guid)) {
     794           0 :                                 *feature_enabled = true;
     795           0 :                                 break;
     796             :                         }
     797             :                 }
     798             :         }
     799       81936 :         talloc_free(tmp_ctx);
     800       81936 :         return LDB_SUCCESS;
     801             : }
     802             : 
     803             : /*
     804             :   find the NTDS GUID from a computers DN record
     805             :  */
     806         397 : int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
     807             :                                            TALLOC_CTX *mem_ctx,
     808             :                                            struct ldb_dn *computer_dn,
     809             :                                            struct GUID *ntds_guid,
     810             :                                            struct ldb_request *parent)
     811             : {
     812             :         int ret;
     813             :         struct ldb_dn *dn;
     814             : 
     815         397 :         *ntds_guid = GUID_zero();
     816             : 
     817         397 :         ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
     818             :                                        "serverReferenceBL", &dn, parent);
     819         397 :         if (ret != LDB_SUCCESS) {
     820           0 :                 return ret;
     821             :         }
     822             : 
     823         397 :         if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
     824           0 :                 talloc_free(dn);
     825           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     826             :         }
     827             : 
     828         397 :         ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
     829         397 :         talloc_free(dn);
     830         397 :         return ret;
     831             : }
     832             : 
     833             : /*
     834             :   find a 'reference' DN that points at another object
     835             :   (eg. serverReference, rIDManagerReference etc)
     836             :  */
     837        1405 : int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
     838             :                              const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
     839             : {
     840             :         const char *attrs[2];
     841             :         struct ldb_result *res;
     842             :         int ret;
     843             : 
     844        1405 :         attrs[0] = attribute;
     845        1405 :         attrs[1] = NULL;
     846             : 
     847        1405 :         ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
     848             :                                     DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
     849        1405 :         if (ret != LDB_SUCCESS) {
     850           0 :                 return ret;
     851             :         }
     852             : 
     853        1405 :         *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
     854        1405 :                                       mem_ctx, res->msgs[0], attribute);
     855        1405 :         if (!*dn) {
     856          30 :                 ldb_reset_err_string(ldb_module_get_ctx(module));
     857          30 :                 talloc_free(res);
     858          30 :                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
     859             :         }
     860             : 
     861        1375 :         talloc_free(res);
     862        1375 :         return LDB_SUCCESS;
     863             : }
     864             : 
     865             : /*
     866             :   find the RID Manager$ DN via the rIDManagerReference attribute in the
     867             :   base DN
     868             :  */
     869         446 : int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
     870             :                                struct ldb_request *parent)
     871             : {
     872         446 :         return dsdb_module_reference_dn(module, mem_ctx,
     873             :                                         ldb_get_default_basedn(ldb_module_get_ctx(module)),
     874             :                                         "rIDManagerReference", dn, parent);
     875             : }
     876             : 
     877             : /*
     878             :   used to chain to the callers callback
     879             :  */
     880   107140610 : int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
     881             : {
     882   107140610 :         struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
     883             : 
     884   107140610 :         if (!ares) {
     885           0 :                 return ldb_module_done(up_req, NULL, NULL,
     886             :                                        LDB_ERR_OPERATIONS_ERROR);
     887             :         }
     888             : 
     889   107140610 :         if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
     890    34646817 :                 return ldb_module_done(up_req, ares->controls,
     891             :                                        ares->response, ares->error);
     892             :         }
     893             : 
     894             :         /* Otherwise pass on the callback */
     895    72493793 :         switch (ares->type) {
     896    70068171 :         case LDB_REPLY_ENTRY:
     897    70068171 :                 return ldb_module_send_entry(up_req, ares->message,
     898             :                                              ares->controls);
     899             : 
     900     2425622 :         case LDB_REPLY_REFERRAL:
     901     2425622 :                 return ldb_module_send_referral(up_req,
     902             :                                                 ares->referral);
     903           0 :         default:
     904             :                 /* Can't happen */
     905           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     906             :         }
     907             : }
     908             : 
     909             : /*
     910             :   load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
     911             :   object for a partition
     912             :  */
     913           0 : int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
     914             :                                    uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
     915             : {
     916           0 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     917             :         struct ldb_request *req;
     918             :         int ret;
     919           0 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     920             :         struct dsdb_control_current_partition *p_ctrl;
     921             :         struct ldb_result *res;
     922             : 
     923           0 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     924           0 :         if (!res) {
     925           0 :                 talloc_free(tmp_ctx);
     926           0 :                 return ldb_module_oom(module);
     927             :         }
     928             : 
     929           0 :         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
     930             :                                    ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
     931             :                                    LDB_SCOPE_BASE,
     932             :                                    NULL, NULL,
     933             :                                    NULL,
     934             :                                    res, ldb_search_default_callback,
     935             :                                    parent);
     936           0 :         LDB_REQ_SET_LOCATION(req);
     937           0 :         if (ret != LDB_SUCCESS) {
     938           0 :                 talloc_free(tmp_ctx);
     939           0 :                 return ret;
     940             :         }
     941             : 
     942           0 :         p_ctrl = talloc(req, struct dsdb_control_current_partition);
     943           0 :         if (p_ctrl == NULL) {
     944           0 :                 talloc_free(tmp_ctx);
     945           0 :                 return ldb_module_oom(module);
     946             :         }
     947           0 :         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
     948           0 :         p_ctrl->dn = dn;
     949             : 
     950             : 
     951           0 :         ret = ldb_request_add_control(req,
     952             :                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
     953             :                                       false, p_ctrl);
     954           0 :         if (ret != LDB_SUCCESS) {
     955           0 :                 talloc_free(tmp_ctx);
     956           0 :                 return ret;
     957             :         }
     958             : 
     959             :         /* Run the new request */
     960           0 :         ret = ldb_next_request(module, req);
     961             : 
     962           0 :         if (ret == LDB_SUCCESS) {
     963           0 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     964             :         }
     965             : 
     966           0 :         if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
     967             :                 /* it hasn't been created yet, which means
     968             :                    an implicit value of zero */
     969           0 :                 *uSN = 0;
     970           0 :                 talloc_free(tmp_ctx);
     971           0 :                 ldb_reset_err_string(ldb);
     972           0 :                 return LDB_SUCCESS;
     973             :         }
     974             : 
     975           0 :         if (ret != LDB_SUCCESS) {
     976           0 :                 talloc_free(tmp_ctx);
     977           0 :                 return ret;
     978             :         }
     979             : 
     980           0 :         if (res->count != 1) {
     981           0 :                 *uSN = 0;
     982           0 :                 if (urgent_uSN) {
     983           0 :                         *urgent_uSN = 0;
     984             :                 }
     985             :         } else {
     986           0 :                 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
     987           0 :                 if (urgent_uSN) {
     988           0 :                         *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
     989             :                 }
     990             :         }
     991             : 
     992           0 :         talloc_free(tmp_ctx);
     993             : 
     994           0 :         return LDB_SUCCESS;
     995             : }
     996             : 
     997             : /*
     998             :   save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
     999             :   partition
    1000             :  */
    1001      159376 : int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
    1002             :                                    uint64_t uSN, uint64_t urgent_uSN,
    1003             :                                    struct ldb_request *parent)
    1004             : {
    1005      159376 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1006             :         struct ldb_request *req;
    1007             :         struct ldb_message *msg;
    1008             :         struct dsdb_control_current_partition *p_ctrl;
    1009             :         int ret;
    1010             :         struct ldb_result *res;
    1011             : 
    1012      159376 :         msg = ldb_msg_new(module);
    1013      159376 :         if (msg == NULL) {
    1014           0 :                 return ldb_module_oom(module);
    1015             :         }
    1016             : 
    1017      159376 :         msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
    1018      159376 :         if (msg->dn == NULL) {
    1019           0 :                 talloc_free(msg);
    1020           0 :                 return ldb_operr(ldb_module_get_ctx(module));
    1021             :         }
    1022             : 
    1023      159376 :         res = talloc_zero(msg, struct ldb_result);
    1024      159376 :         if (!res) {
    1025           0 :                 talloc_free(msg);
    1026           0 :                 return ldb_module_oom(module);
    1027             :         }
    1028             : 
    1029      159376 :         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
    1030      159376 :         if (ret != LDB_SUCCESS) {
    1031           0 :                 talloc_free(msg);
    1032           0 :                 return ret;
    1033             :         }
    1034      159376 :         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
    1035             : 
    1036             :         /* urgent_uSN is optional so may not be stored */
    1037      159376 :         if (urgent_uSN) {
    1038       23478 :                 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
    1039             :                                            urgent_uSN);
    1040       23478 :                 if (ret != LDB_SUCCESS) {
    1041           0 :                         talloc_free(msg);
    1042           0 :                         return ret;
    1043             :                 }
    1044       23478 :                 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
    1045             :         }
    1046             : 
    1047             : 
    1048      159376 :         p_ctrl = talloc(msg, struct dsdb_control_current_partition);
    1049      159376 :         if (p_ctrl == NULL) {
    1050           0 :                 talloc_free(msg);
    1051           0 :                 return ldb_oom(ldb);
    1052             :         }
    1053      159376 :         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
    1054      159376 :         p_ctrl->dn = dn;
    1055      159376 :         ret = ldb_build_mod_req(&req, ldb, msg,
    1056             :                                 msg,
    1057             :                                 NULL,
    1058             :                                 res,
    1059             :                                 ldb_modify_default_callback,
    1060             :                                 parent);
    1061      159376 :         LDB_REQ_SET_LOCATION(req);
    1062      160295 : again:
    1063      160295 :         if (ret != LDB_SUCCESS) {
    1064           0 :                 talloc_free(msg);
    1065           0 :                 return ret;
    1066             :         }
    1067             : 
    1068      160295 :         ret = ldb_request_add_control(req,
    1069             :                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
    1070             :                                       false, p_ctrl);
    1071      160295 :         if (ret != LDB_SUCCESS) {
    1072           0 :                 talloc_free(msg);
    1073           0 :                 return ret;
    1074             :         }
    1075             : 
    1076             :         /* Run the new request */
    1077      160295 :         ret = ldb_next_request(module, req);
    1078             : 
    1079      160295 :         if (ret == LDB_SUCCESS) {
    1080      160295 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    1081             :         }
    1082      160295 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
    1083         919 :                 ret = ldb_build_add_req(&req, ldb, msg,
    1084             :                                         msg,
    1085             :                                         NULL,
    1086             :                                         res,
    1087             :                                         ldb_modify_default_callback,
    1088             :                                         parent);
    1089         919 :                 LDB_REQ_SET_LOCATION(req);
    1090         919 :                 goto again;
    1091             :         }
    1092             : 
    1093      159376 :         talloc_free(msg);
    1094             : 
    1095      159376 :         return ret;
    1096             : }
    1097             : 
    1098    40005729 : bool dsdb_module_am_system(struct ldb_module *module)
    1099             : {
    1100    40005729 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1101    34013540 :         struct auth_session_info *session_info
    1102    40005729 :                 = talloc_get_type(
    1103             :                         ldb_get_opaque(ldb, DSDB_SESSION_INFO),
    1104             :                         struct auth_session_info);
    1105    40005729 :         return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
    1106             : }
    1107             : 
    1108    16628807 : bool dsdb_module_am_administrator(struct ldb_module *module)
    1109             : {
    1110    16628807 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1111    14250237 :         struct auth_session_info *session_info
    1112    16628807 :                 = talloc_get_type(
    1113             :                         ldb_get_opaque(ldb, DSDB_SESSION_INFO),
    1114             :                         struct auth_session_info);
    1115    16628807 :         return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
    1116             : }
    1117             : 
    1118             : /*
    1119             :   check if the recyclebin is enabled
    1120             :  */
    1121       83326 : int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
    1122             : {
    1123       83326 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1124             :         struct GUID recyclebin_guid;
    1125             :         int ret;
    1126             : 
    1127       83326 :         GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
    1128             : 
    1129       83326 :         ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
    1130       83326 :         if (ret != LDB_SUCCESS) {
    1131        1390 :                 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
    1132        1390 :                 return ret;
    1133             :         }
    1134             : 
    1135       80303 :         return LDB_SUCCESS;
    1136             : }
    1137             : 
    1138       47681 : int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
    1139             :                                        struct ldb_message *msg,
    1140             :                                        const char *attr,
    1141             :                                        const int32_t *old_val,
    1142             :                                        const int32_t *new_val)
    1143             : {
    1144             :         struct ldb_message_element *el;
    1145             :         int ret;
    1146             :         char *vstring;
    1147             : 
    1148       47681 :         if (old_val) {
    1149       23800 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
    1150       23800 :                 if (ret != LDB_SUCCESS) {
    1151           0 :                         return ret;
    1152             :                 }
    1153       23800 :                 el->num_values = 1;
    1154       23800 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1155       23800 :                 if (!el->values) {
    1156           0 :                         return ldb_module_oom(module);
    1157             :                 }
    1158       23800 :                 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
    1159       23800 :                 if (!vstring) {
    1160           0 :                         return ldb_module_oom(module);
    1161             :                 }
    1162       23800 :                 *el->values = data_blob_string_const(vstring);
    1163             :         }
    1164             : 
    1165       47681 :         if (new_val) {
    1166       23945 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
    1167       23945 :                 if (ret != LDB_SUCCESS) {
    1168           0 :                         return ret;
    1169             :                 }
    1170       23945 :                 el->num_values = 1;
    1171       23945 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1172       23945 :                 if (!el->values) {
    1173           0 :                         return ldb_module_oom(module);
    1174             :                 }
    1175       23945 :                 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
    1176       23945 :                 if (!vstring) {
    1177           0 :                         return ldb_module_oom(module);
    1178             :                 }
    1179       23945 :                 *el->values = data_blob_string_const(vstring);
    1180             :         }
    1181             : 
    1182       47340 :         return LDB_SUCCESS;
    1183             : }
    1184             : 
    1185       47680 : int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
    1186             :                                         struct ldb_message *msg,
    1187             :                                         const char *attr,
    1188             :                                         const uint32_t *old_val,
    1189             :                                         const uint32_t *new_val)
    1190             : {
    1191       47680 :         return dsdb_msg_constrainted_update_int32(module, msg, attr,
    1192             :                                                   (const int32_t *)old_val,
    1193             :                                                   (const int32_t *)new_val);
    1194             : }
    1195             : 
    1196       47799 : int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
    1197             :                                        struct ldb_message *msg,
    1198             :                                        const char *attr,
    1199             :                                        const int64_t *old_val,
    1200             :                                        const int64_t *new_val)
    1201             : {
    1202             :         struct ldb_message_element *el;
    1203             :         int ret;
    1204             :         char *vstring;
    1205             : 
    1206       47799 :         if (old_val) {
    1207         209 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
    1208         209 :                 if (ret != LDB_SUCCESS) {
    1209           0 :                         return ret;
    1210             :                 }
    1211         209 :                 el->num_values = 1;
    1212         209 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1213         209 :                 if (!el->values) {
    1214           0 :                         return ldb_module_oom(module);
    1215             :                 }
    1216         209 :                 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
    1217         209 :                 if (!vstring) {
    1218           0 :                         return ldb_module_oom(module);
    1219             :                 }
    1220         209 :                 *el->values = data_blob_string_const(vstring);
    1221             :         }
    1222             : 
    1223       47799 :         if (new_val) {
    1224         353 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
    1225         353 :                 if (ret != LDB_SUCCESS) {
    1226           0 :                         return ret;
    1227             :                 }
    1228         353 :                 el->num_values = 1;
    1229         353 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1230         353 :                 if (!el->values) {
    1231           0 :                         return ldb_module_oom(module);
    1232             :                 }
    1233         353 :                 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
    1234         353 :                 if (!vstring) {
    1235           0 :                         return ldb_module_oom(module);
    1236             :                 }
    1237         353 :                 *el->values = data_blob_string_const(vstring);
    1238             :         }
    1239             : 
    1240       47459 :         return LDB_SUCCESS;
    1241             : }
    1242             : 
    1243       47680 : int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
    1244             :                                         struct ldb_message *msg,
    1245             :                                         const char *attr,
    1246             :                                         const uint64_t *old_val,
    1247             :                                         const uint64_t *new_val)
    1248             : {
    1249       47680 :         return dsdb_msg_constrainted_update_int64(module, msg, attr,
    1250             :                                                   (const int64_t *)old_val,
    1251             :                                                   (const int64_t *)new_val);
    1252             : }
    1253             : 
    1254             : /*
    1255             :   update an int32 attribute safely via a constrained delete/add
    1256             :  */
    1257           1 : int dsdb_module_constrainted_update_int32(struct ldb_module *module,
    1258             :                                           struct ldb_dn *dn,
    1259             :                                           const char *attr,
    1260             :                                           const int32_t *old_val,
    1261             :                                           const int32_t *new_val,
    1262             :                                           struct ldb_request *parent)
    1263             : {
    1264             :         struct ldb_message *msg;
    1265             :         int ret;
    1266             : 
    1267           1 :         msg = ldb_msg_new(module);
    1268           1 :         if (msg == NULL) {
    1269           0 :                 return ldb_module_oom(module);
    1270             :         }
    1271           1 :         msg->dn = dn;
    1272             : 
    1273           1 :         ret = dsdb_msg_constrainted_update_int32(module,
    1274             :                                                  msg, attr,
    1275             :                                                  old_val,
    1276             :                                                  new_val);
    1277           1 :         if (ret != LDB_SUCCESS) {
    1278           0 :                 talloc_free(msg);
    1279           0 :                 return ret;
    1280             :         }
    1281             : 
    1282           1 :         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
    1283           1 :         talloc_free(msg);
    1284           1 :         return ret;
    1285             : }
    1286             : 
    1287           1 : int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
    1288             :                                            struct ldb_dn *dn,
    1289             :                                            const char *attr,
    1290             :                                            const uint32_t *old_val,
    1291             :                                            const uint32_t *new_val,
    1292             :                                            struct ldb_request *parent)
    1293             : {
    1294           1 :         return dsdb_module_constrainted_update_int32(module, dn, attr,
    1295             :                                                      (const int32_t *)old_val,
    1296             :                                                      (const int32_t *)new_val, parent);
    1297             : }
    1298             : 
    1299             : /*
    1300             :   update an int64 attribute safely via a constrained delete/add
    1301             :  */
    1302         119 : int dsdb_module_constrainted_update_int64(struct ldb_module *module,
    1303             :                                           struct ldb_dn *dn,
    1304             :                                           const char *attr,
    1305             :                                           const int64_t *old_val,
    1306             :                                           const int64_t *new_val,
    1307             :                                           struct ldb_request *parent)
    1308             : {
    1309             :         struct ldb_message *msg;
    1310             :         int ret;
    1311             : 
    1312         119 :         msg = ldb_msg_new(module);
    1313         119 :         if (msg == NULL) {
    1314           0 :                 return ldb_module_oom(module);
    1315             :         }
    1316         119 :         msg->dn = dn;
    1317             : 
    1318         119 :         ret = dsdb_msg_constrainted_update_int64(module,
    1319             :                                                  msg, attr,
    1320             :                                                  old_val,
    1321             :                                                  new_val);
    1322         119 :         if (ret != LDB_SUCCESS) {
    1323           0 :                 talloc_free(msg);
    1324           0 :                 return ret;
    1325             :         }
    1326             : 
    1327         119 :         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
    1328         119 :         talloc_free(msg);
    1329         119 :         return ret;
    1330             : }
    1331             : 
    1332         119 : int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
    1333             :                                            struct ldb_dn *dn,
    1334             :                                            const char *attr,
    1335             :                                            const uint64_t *old_val,
    1336             :                                            const uint64_t *new_val,
    1337             :                                            struct ldb_request *parent)
    1338             : {
    1339         119 :         return dsdb_module_constrainted_update_int64(module, dn, attr,
    1340             :                                                      (const int64_t *)old_val,
    1341             :                                                      (const int64_t *)new_val,
    1342             :                                                      parent);
    1343             : }
    1344             : 
    1345             : 
    1346     1317249 : const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
    1347             :                                                     TALLOC_CTX *mem_ctx, struct ldb_request *parent)
    1348             : {
    1349             :         int ret;
    1350             :         struct ldb_dn *new_dn;
    1351     1317249 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1352             :         static const char *attrs[] = { "dSHeuristics", NULL };
    1353             :         struct ldb_result *res;
    1354             : 
    1355     1317249 :         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
    1356     1317249 :         if (!ldb_dn_add_child_fmt(new_dn,
    1357             :                                    "CN=Directory Service,CN=Windows NT,CN=Services")) {
    1358           0 :                 talloc_free(new_dn);
    1359           0 :                 return NULL;
    1360             :         }
    1361     1317249 :         ret = dsdb_module_search_dn(module, mem_ctx, &res,
    1362             :                                     new_dn,
    1363             :                                     attrs,
    1364             :                                     DSDB_FLAG_NEXT_MODULE,
    1365             :                                     parent);
    1366     1317249 :         if (ret == LDB_SUCCESS && res->count == 1) {
    1367     1067922 :                 talloc_free(new_dn);
    1368     1067922 :                 return ldb_msg_find_ldb_val(res->msgs[0],
    1369             :                                             "dSHeuristics");
    1370             :         }
    1371      249327 :         talloc_free(new_dn);
    1372      249327 :         return NULL;
    1373             : }
    1374             : 
    1375      132901 : bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
    1376             : {
    1377      132901 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
    1378             :         bool result;
    1379      132901 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1380             :                                                                      tmp_ctx, parent);
    1381      132901 :         if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
    1382      122093 :                 result = true;
    1383        6035 :         } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
    1384          18 :                 result = false;
    1385             :         } else {
    1386        6017 :                 result = true;
    1387             :         }
    1388             : 
    1389      132901 :         talloc_free(tmp_ctx);
    1390      132901 :         return result;
    1391             : }
    1392             : 
    1393     1168040 : bool dsdb_user_password_support(struct ldb_module *module,
    1394             :                                 TALLOC_CTX *mem_ctx,
    1395             :                                 struct ldb_request *parent)
    1396             : {
    1397     1168040 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1398             :         bool result;
    1399     1168040 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1400             :                                                                      tmp_ctx,
    1401             :                                                                      parent);
    1402     1168040 :         if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
    1403     1038461 :                 result = false;
    1404       35696 :         } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
    1405       20442 :                    (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
    1406         184 :                 result = false;
    1407             :         } else {
    1408       20286 :                 result = true;
    1409             :         }
    1410             : 
    1411     1168040 :         talloc_free(tmp_ctx);
    1412     1168040 :         return result;
    1413             : }
    1414             : 
    1415       16308 : bool dsdb_do_list_object(struct ldb_module *module,
    1416             :                          TALLOC_CTX *mem_ctx,
    1417             :                          struct ldb_request *parent)
    1418             : {
    1419       16308 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1420             :         bool result;
    1421       16308 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1422             :                                                                      tmp_ctx,
    1423             :                                                                      parent);
    1424       16308 :         if (hr_val == NULL || hr_val->length < DS_HR_DOLISTOBJECT) {
    1425           0 :                 result = false;
    1426       16308 :         } else if (hr_val->data[DS_HR_DOLISTOBJECT -1] == '1') {
    1427        8064 :                 result = true;
    1428             :         } else {
    1429        8244 :                 result = false;
    1430             :         }
    1431             : 
    1432       16308 :         talloc_free(tmp_ctx);
    1433       16308 :         return result;
    1434             : }
    1435             : 
    1436             : /*
    1437             :   show the chain of requests, useful for debugging async requests
    1438             :  */
    1439           0 : void dsdb_req_chain_debug(struct ldb_request *req, int level)
    1440             : {
    1441           0 :         char *s = ldb_module_call_chain(req, req);
    1442           0 :         DEBUG(level, ("%s\n", s));
    1443           0 :         talloc_free(s);
    1444           0 : }
    1445             : 
    1446             : /*
    1447             :  * Gets back a single-valued attribute by the rules of the DSDB triggers when
    1448             :  * performing a modify operation.
    1449             :  *
    1450             :  * In order that the constraint checking by the "objectclass_attrs" LDB module
    1451             :  * does work properly, the change request should remain similar or only be
    1452             :  * enhanced (no other modifications as deletions, variations).
    1453             :  */
    1454      263958 : struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
    1455             :                                                         const char *attr_name,
    1456             :                                                         enum ldb_request_type operation)
    1457             : {
    1458      263958 :         struct ldb_message_element *el = NULL;
    1459             :         unsigned int i;
    1460             : 
    1461             :         /* We've to walk over all modification entries and consider the last
    1462             :          * non-delete one which belongs to "attr_name".
    1463             :          *
    1464             :          * If "el" is NULL afterwards then that means there was no interesting
    1465             :          * change entry. */
    1466     4678668 :         for (i = 0; i < msg->num_elements; i++) {
    1467     4414710 :                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
    1468      306764 :                         if ((operation == LDB_MODIFY) &&
    1469       44062 :                             (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
    1470             :                                                 == LDB_FLAG_MOD_DELETE)) {
    1471       18714 :                                 continue;
    1472             :                         }
    1473      222374 :                         el = &msg->elements[i];
    1474             :                 }
    1475             :         }
    1476             : 
    1477      263958 :         return el;
    1478             : }
    1479             : 
    1480             : /*
    1481             :  * This function determines the (last) structural or 88 object class of a passed
    1482             :  * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
    1483             :  * Without schema this does not work and hence NULL is returned.
    1484             :  */
    1485     3705055 : const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
    1486             :                                                         const struct ldb_message_element *element)
    1487             : {
    1488             :         const struct dsdb_class *last_class;
    1489             : 
    1490     3705055 :         if (schema == NULL) {
    1491           0 :                 return NULL;
    1492             :         }
    1493             : 
    1494     3705055 :         if (element->num_values == 0) {
    1495           0 :                 return NULL;
    1496             :         }
    1497             : 
    1498     3705055 :         last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
    1499     3705055 :                                                            &element->values[element->num_values-1]);
    1500     3705055 :         if (last_class == NULL) {
    1501           0 :                 return NULL;
    1502             :         }
    1503     3705055 :         if (last_class->objectClassCategory > 1) {
    1504           3 :                 return NULL;
    1505             :         }
    1506             : 
    1507     3705052 :         return last_class;
    1508             : }
    1509             : 
    1510     1947444 : const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
    1511             :                                                          const struct ldb_message *msg)
    1512             : {
    1513             :         struct ldb_message_element *oc_el;
    1514             : 
    1515     1947444 :         oc_el = ldb_msg_find_element(msg, "objectClass");
    1516     1947444 :         if (!oc_el) {
    1517           0 :                 return NULL;
    1518             :         }
    1519             : 
    1520     1947444 :         return dsdb_get_last_structural_class(schema, oc_el);
    1521             : }
    1522             : 
    1523             : /* Fix the DN so that the relative attribute names are in upper case so that the DN:
    1524             :    cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
    1525             :    CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
    1526             : */
    1527           0 : int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
    1528             : {
    1529             :         int i, ret;
    1530             :         char *upper_rdn_attr;
    1531             : 
    1532           0 :         for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
    1533             :                 /* We need the attribute name in upper case */
    1534           0 :                 upper_rdn_attr = strupper_talloc(dn,
    1535             :                                                  ldb_dn_get_component_name(dn, i));
    1536           0 :                 if (!upper_rdn_attr) {
    1537           0 :                         return ldb_oom(ldb);
    1538             :                 }
    1539           0 :                 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
    1540           0 :                                            *ldb_dn_get_component_val(dn, i));
    1541           0 :                 talloc_free(upper_rdn_attr);
    1542           0 :                 if (ret != LDB_SUCCESS) {
    1543           0 :                         return ret;
    1544             :                 }
    1545             :         }
    1546           0 :         return LDB_SUCCESS;
    1547             : }
    1548             : 
    1549             : /**
    1550             :  * Make most specific objectCategory for the objectClass of passed object
    1551             :  * NOTE: In this implementation we count that it is called on already
    1552             :  * verified objectClass attribute value. See objectclass.c thorough
    1553             :  * implementation for all the magic that involves
    1554             :  *
    1555             :  * @param ldb   ldb context
    1556             :  * @param schema cached schema for ldb. We may get it, but it is very time consuming.
    1557             :  *                      Hence leave the responsibility to the caller.
    1558             :  * @param obj   AD object to determint objectCategory for
    1559             :  * @param mem_ctx Memory context - usually it is obj actually
    1560             :  * @param pobjectcategory location to store found objectCategory
    1561             :  *
    1562             :  * @return LDB_SUCCESS or error including out of memory error
    1563             :  */
    1564         274 : int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
    1565             :                               const struct ldb_message *obj,
    1566             :                               TALLOC_CTX *mem_ctx, const char **pobjectcategory)
    1567             : {
    1568             :         const struct dsdb_class                 *objectclass;
    1569             :         struct ldb_message_element              *objectclass_element;
    1570             :         struct dsdb_extended_dn_store_format    *dn_format;
    1571             : 
    1572         274 :         objectclass_element = ldb_msg_find_element(obj, "objectClass");
    1573         274 :         if (!objectclass_element) {
    1574           0 :                 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
    1575           0 :                                        ldb_dn_get_linearized(obj->dn));
    1576           0 :                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
    1577             :         }
    1578         274 :         if (objectclass_element->num_values == 0) {
    1579           0 :                 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
    1580           0 :                                        ldb_dn_get_linearized(obj->dn));
    1581           0 :                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1582             :         }
    1583             : 
    1584             :         /*
    1585             :          * Get the new top-most structural object class and check for
    1586             :          * unrelated structural classes
    1587             :          */
    1588         274 :         objectclass = dsdb_get_last_structural_class(schema,
    1589             :                                                      objectclass_element);
    1590         274 :         if (objectclass == NULL) {
    1591           0 :                 ldb_asprintf_errstring(ldb,
    1592             :                                        "Failed to find a structural class for %s",
    1593           0 :                                        ldb_dn_get_linearized(obj->dn));
    1594           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
    1595             :         }
    1596             : 
    1597         274 :         dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
    1598             :                                     struct dsdb_extended_dn_store_format);
    1599         274 :         if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
    1600             :                 /* Strip off extended components */
    1601           0 :                 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
    1602           0 :                                                objectclass->defaultObjectCategory);
    1603           0 :                 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
    1604           0 :                 talloc_free(dn);
    1605             :         } else {
    1606         274 :                 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
    1607             :         }
    1608             : 
    1609         274 :         if (*pobjectcategory == NULL) {
    1610           0 :                 return ldb_oom(ldb);
    1611             :         }
    1612             : 
    1613         274 :         return LDB_SUCCESS;
    1614             : }

Generated by: LCOV version 1.13