LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules - util.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 502 799 62.8 %
Date: 2024-06-13 04:01:37 Functions: 37 46 80.4 %

          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     8654217 : 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     8654217 :         tmp_ctx = talloc_new(mem_ctx);
      51             : 
      52     8654217 :         res = talloc_zero(tmp_ctx, struct ldb_result);
      53     8654217 :         if (!res) {
      54           0 :                 talloc_free(tmp_ctx);
      55           0 :                 return ldb_oom(ldb_module_get_ctx(module));
      56             :         }
      57             : 
      58     8654217 :         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     8654217 :         LDB_REQ_SET_LOCATION(req);
      68     8654217 :         if (ret != LDB_SUCCESS) {
      69           0 :                 talloc_free(tmp_ctx);
      70           0 :                 return ret;
      71             :         }
      72             : 
      73     8654217 :         ret = dsdb_request_add_controls(req, dsdb_flags);
      74     8654217 :         if (ret != LDB_SUCCESS) {
      75           0 :                 talloc_free(tmp_ctx);
      76           0 :                 return ret;
      77             :         }
      78             : 
      79     8654217 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
      80           0 :                 ldb_req_mark_trusted(req);
      81             :         }
      82             : 
      83             :         /* Run the new request */
      84     8654217 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
      85     8653943 :                 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     8654217 :         if (ret == LDB_SUCCESS) {
      94     8654215 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
      95             :         }
      96             : 
      97     8654217 :         if (ret != LDB_SUCCESS) {
      98      156039 :                 talloc_free(tmp_ctx);
      99      156039 :                 return ret;
     100             :         }
     101             : 
     102     8498178 :         if (res->count != 1) {
     103             :                 /* we may be reading a DB that does not have the 'check base on search' option... */
     104       11856 :                 ret = LDB_ERR_NO_SUCH_OBJECT;
     105       11856 :                 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     8486322 :                 *_res = talloc_steal(mem_ctx, res);
     110             :         }
     111     8498178 :         talloc_free(tmp_ctx);
     112     8498178 :         return ret;
     113             : }
     114             : 
     115     9048343 : 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     9048343 :         tmp_ctx = talloc_new(mem_ctx);
     131             : 
     132             :         /* cross-partitions searches with a basedn break multi-domain support */
     133     9048343 :         SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
     134             : 
     135     9048343 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     136     9048343 :         if (!res) {
     137           0 :                 talloc_free(tmp_ctx);
     138           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     139             :         }
     140             : 
     141     9048343 :         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     9048343 :         LDB_REQ_SET_LOCATION(req);
     151     9048343 :         if (ret != LDB_SUCCESS) {
     152           0 :                 talloc_free(tmp_ctx);
     153           0 :                 return ret;
     154             :         }
     155             : 
     156     9048343 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     157     9048343 :         if (ret != LDB_SUCCESS) {
     158           0 :                 talloc_free(tmp_ctx);
     159           0 :                 return ret;
     160             :         }
     161             : 
     162     9048343 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     163           0 :                 ldb_req_mark_trusted(req);
     164             :         }
     165             : 
     166     9048343 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     167     9048343 :                 ret = ldb_next_request(module, req);
     168           0 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     169           0 :                 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     9048343 :         if (ret == LDB_SUCCESS) {
     176     9048343 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     177             :         }
     178             : 
     179     9048343 :         if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
     180     7267964 :                 if (res->count == 0) {
     181        6965 :                         talloc_free(tmp_ctx);
     182        6965 :                         return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
     183             :                 }
     184     7260999 :                 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     9041378 :         talloc_free(req);
     192     9041378 :         if (ret == LDB_SUCCESS) {
     193     9040620 :                 *_res = talloc_steal(mem_ctx, res);
     194             :         }
     195     9041378 :         talloc_free(tmp_ctx);
     196     9041378 :         return ret;
     197             : }
     198             : 
     199             : /*
     200             :   search for attrs in the modules below
     201             :  */
     202     9047103 : 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     9047103 :         SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
     219             : 
     220     9047103 :         tmp_ctx = talloc_new(mem_ctx);
     221             : 
     222     9047103 :         if (format) {
     223     8608498 :                 va_start(ap, format);
     224     8608498 :                 expression = talloc_vasprintf(tmp_ctx, format, ap);
     225     8608498 :                 va_end(ap);
     226             : 
     227     8608498 :                 if (!expression) {
     228           0 :                         talloc_free(tmp_ctx);
     229           0 :                         return ldb_oom(ldb_module_get_ctx(module));
     230             :                 }
     231             :         } else {
     232      438605 :                 expression = NULL;
     233             :         }
     234             : 
     235     9047103 :         tree = ldb_parse_tree(tmp_ctx, expression);
     236     9047103 :         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     9047103 :         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     9047103 :         talloc_free(tmp_ctx);
     254     9047103 :         return ret;
     255             : }
     256             : 
     257             : /*
     258             :   find a DN given a GUID. This searches across all partitions
     259             :  */
     260       38027 : 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       38027 :         const char *attrs[] = { NULL };
     266       38027 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     267             :         int ret;
     268             : 
     269       38027 :         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       38027 :         if (ret != LDB_SUCCESS) {
     278           0 :                 talloc_free(tmp_ctx);
     279           0 :                 return ret;
     280             :         }
     281       38027 :         if (res->count == 0) {
     282          40 :                 talloc_free(tmp_ctx);
     283          40 :                 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
     284             :         }
     285       37987 :         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       37987 :         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
     293             : 
     294       37987 :         talloc_free(tmp_ctx);
     295       37987 :         return LDB_SUCCESS;
     296             : }
     297             : 
     298             : /*
     299             :   find a GUID given a DN.
     300             :  */
     301       12417 : int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
     302             :                            struct ldb_request *parent)
     303             : {
     304       12417 :         const char *attrs[] = { NULL };
     305             :         struct ldb_result *res;
     306       12417 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     307             :         int ret;
     308             :         NTSTATUS status;
     309             : 
     310       12417 :         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       12417 :         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       12414 :         status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
     323       12414 :         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       12414 :         talloc_free(tmp_ctx);
     329       12414 :         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    11977304 : 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    11977304 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     350    11977304 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     351             :         struct ldb_result *res;
     352             : 
     353    11977304 :         if (_res != NULL) {
     354    11643867 :                 (*_res) = NULL;
     355             :         }
     356             : 
     357    11977304 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     358    11977304 :         if (!res) {
     359           0 :                 talloc_free(tmp_ctx);
     360           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     361             :         }
     362             : 
     363    11977304 :         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    11977304 :         LDB_REQ_SET_LOCATION(req);
     372    11977304 :         if (ret != LDB_SUCCESS) {
     373           0 :                 talloc_free(tmp_ctx);
     374           0 :                 return ret;
     375             :         }
     376             : 
     377    11977304 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     378    11977304 :         if (ret != LDB_SUCCESS) {
     379           0 :                 talloc_free(tmp_ctx);
     380           0 :                 return ret;
     381             :         }
     382             : 
     383    11977304 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     384      333437 :                 ldb_req_mark_trusted(req);
     385             :         }
     386             : 
     387             :         /* Run the new request */
     388    11977304 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     389    11643867 :                 ret = ldb_next_request(module, req);
     390      333437 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     391      333437 :                 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    11977304 :         if (ret == LDB_SUCCESS) {
     398    11977304 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     399             :         }
     400             : 
     401    11977304 :         if (_res != NULL && ret == LDB_SUCCESS) {
     402    11643867 :                 (*_res) = talloc_steal(mem_ctx, res);
     403             :         }
     404             : 
     405    11977304 :         talloc_free(tmp_ctx);
     406    11977304 :         return ret;
     407             : }
     408             : 
     409             : 
     410             : /*
     411             :   a ldb_modify request operating on modules below the
     412             :   current module
     413             :  */
     414      235260 : 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      235260 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     422      235260 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     423             :         struct ldb_result *res;
     424             : 
     425      235260 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     426      235260 :         if (!res) {
     427           0 :                 talloc_free(tmp_ctx);
     428           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     429             :         }
     430             : 
     431      235260 :         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
     432             :                                 message,
     433             :                                 NULL,
     434             :                                 res,
     435             :                                 ldb_modify_default_callback,
     436             :                                 parent);
     437      235260 :         LDB_REQ_SET_LOCATION(mod_req);
     438      235260 :         if (ret != LDB_SUCCESS) {
     439           0 :                 talloc_free(tmp_ctx);
     440           0 :                 return ret;
     441             :         }
     442             : 
     443      235260 :         ret = dsdb_request_add_controls(mod_req, dsdb_flags);
     444      235260 :         if (ret != LDB_SUCCESS) {
     445           0 :                 talloc_free(tmp_ctx);
     446           0 :                 return ret;
     447             :         }
     448             : 
     449      235260 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     450           0 :                 ldb_req_mark_trusted(mod_req);
     451             :         }
     452             : 
     453             :         /* Run the new request */
     454      235260 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     455       91115 :                 ret = ldb_next_request(module, mod_req);
     456      144145 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     457           0 :                 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
     458             :         } else {
     459      144145 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     460      144145 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     461      144145 :                 ret = ops->modify(module, mod_req);
     462             :         }
     463      235260 :         if (ret == LDB_SUCCESS) {
     464      235260 :                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
     465             :         }
     466             : 
     467      235260 :         talloc_free(tmp_ctx);
     468      235260 :         return ret;
     469             : }
     470             : 
     471             : 
     472             : 
     473             : /*
     474             :   a ldb_rename request operating on modules below the
     475             :   current module
     476             :  */
     477      110998 : 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      110998 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     485      110998 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     486             :         struct ldb_result *res;
     487             : 
     488      110998 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     489      110998 :         if (!res) {
     490           0 :                 talloc_free(tmp_ctx);
     491           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     492             :         }
     493             : 
     494      110998 :         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      110998 :         LDB_REQ_SET_LOCATION(req);
     502      110998 :         if (ret != LDB_SUCCESS) {
     503           0 :                 talloc_free(tmp_ctx);
     504           0 :                 return ret;
     505             :         }
     506             : 
     507      110998 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     508      110998 :         if (ret != LDB_SUCCESS) {
     509           0 :                 talloc_free(tmp_ctx);
     510           0 :                 return ret;
     511             :         }
     512             : 
     513      110998 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     514           0 :                 ldb_req_mark_trusted(req);
     515             :         }
     516             : 
     517             :         /* Run the new request */
     518      110998 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     519      110476 :                 ret = ldb_next_request(module, req);
     520         522 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     521           0 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     522             :         } else {
     523         522 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     524         522 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     525         522 :                 ret = ops->rename(module, req);
     526             :         }
     527      110998 :         if (ret == LDB_SUCCESS) {
     528      110996 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     529             :         }
     530             : 
     531      110998 :         talloc_free(tmp_ctx);
     532      110998 :         return ret;
     533             : }
     534             : 
     535             : /*
     536             :   a ldb_add request operating on modules below the
     537             :   current module
     538             :  */
     539        1127 : 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        1127 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     547        1127 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     548             :         struct ldb_result *res;
     549             : 
     550        1127 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     551        1127 :         if (!res) {
     552           0 :                 talloc_free(tmp_ctx);
     553           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     554             :         }
     555             : 
     556        1127 :         ret = ldb_build_add_req(&req, ldb, tmp_ctx,
     557             :                                 message,
     558             :                                 NULL,
     559             :                                 res,
     560             :                                 ldb_modify_default_callback,
     561             :                                 parent);
     562        1127 :         LDB_REQ_SET_LOCATION(req);
     563        1127 :         if (ret != LDB_SUCCESS) {
     564           0 :                 talloc_free(tmp_ctx);
     565           0 :                 return ret;
     566             :         }
     567             : 
     568        1127 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     569        1127 :         if (ret != LDB_SUCCESS) {
     570           0 :                 talloc_free(tmp_ctx);
     571           0 :                 return ret;
     572             :         }
     573             : 
     574        1127 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     575           0 :                 ldb_req_mark_trusted(req);
     576             :         }
     577             : 
     578             :         /* Run the new request */
     579        1127 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     580        1067 :                 ret = ldb_next_request(module, req);
     581          60 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     582          60 :                 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        1127 :         if (ret == LDB_SUCCESS) {
     589        1127 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     590             :         }
     591             : 
     592        1127 :         talloc_free(tmp_ctx);
     593        1127 :         return ret;
     594             : }
     595             : 
     596             : /*
     597             :   a ldb_delete request operating on modules below the
     598             :   current module
     599             :  */
     600       18377 : 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       18377 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     608       18377 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     609             :         struct ldb_result *res;
     610             : 
     611       18377 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     612       18377 :         if (!res) {
     613           0 :                 talloc_free(tmp_ctx);
     614           0 :                 return ldb_oom(ldb);
     615             :         }
     616             : 
     617       18377 :         ret = ldb_build_del_req(&req, ldb, tmp_ctx,
     618             :                                 dn,
     619             :                                 NULL,
     620             :                                 res,
     621             :                                 ldb_modify_default_callback,
     622             :                                 parent);
     623       18377 :         LDB_REQ_SET_LOCATION(req);
     624       18377 :         if (ret != LDB_SUCCESS) {
     625           0 :                 talloc_free(tmp_ctx);
     626           0 :                 return ret;
     627             :         }
     628             : 
     629       18377 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     630       18377 :         if (ret != LDB_SUCCESS) {
     631           0 :                 talloc_free(tmp_ctx);
     632           0 :                 return ret;
     633             :         }
     634             : 
     635       18377 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     636       18377 :                 ldb_req_mark_trusted(req);
     637             :         }
     638             : 
     639             :         /* Run the new request */
     640       18377 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     641           0 :                 ret = ldb_next_request(module, req);
     642       18377 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     643       18377 :                 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       18377 :         if (ret == LDB_SUCCESS) {
     650       18377 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     651             :         }
     652             : 
     653       18377 :         talloc_free(tmp_ctx);
     654       18377 :         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       40925 : int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
     664             :                                   const struct ldb_message_element *el)
     665             : {
     666       40925 :         bool found_active = false;
     667             :         unsigned int i;
     668             : 
     669       47407 :         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
     670        6692 :             el->num_values < 2) {
     671       40795 :                 return LDB_SUCCESS;
     672             :         }
     673             : 
     674         388 :         for (i=0; i<el->num_values; i++) {
     675         261 :                 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
     676         121 :                         if (found_active) {
     677           3 :                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     678             :                         }
     679         118 :                         found_active = true;
     680             :                 }
     681             :         }
     682             : 
     683         127 :         return LDB_SUCCESS;
     684             : }
     685             : 
     686             : 
     687      216026 : int dsdb_check_samba_compatible_feature(struct ldb_module *module,
     688             :                                         const char *feature,
     689             :                                         bool *found)
     690             : {
     691      216026 :         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      216026 :         struct ldb_dn *samba_dsdb_dn = NULL;
     699      216026 :         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
     700      216026 :         if (tmp_ctx == NULL) {
     701           0 :                 *found = false;
     702           0 :                 return ldb_oom(ldb);
     703             :         }
     704      216026 :         *found = false;
     705             : 
     706      216026 :         samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
     707      216026 :         if (samba_dsdb_dn == NULL) {
     708           0 :                 TALLOC_FREE(tmp_ctx);
     709           0 :                 return ldb_oom(ldb);
     710             :         }
     711             : 
     712      216026 :         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      216026 :         if (ret == LDB_SUCCESS) {
     720      216026 :                 *found = ldb_msg_check_string_attribute(
     721      216026 :                         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      216026 :         TALLOC_FREE(tmp_ctx);
     729      216026 :         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       81086 : int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
     743             : {
     744             :         TALLOC_CTX *tmp_ctx;
     745       81086 :         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       81086 :         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       81086 :         tmp_ctx = talloc_new(ldb);
     756             : 
     757       81086 :         feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
     758       81086 :         if (feature_dn == NULL) {
     759           0 :                 talloc_free(tmp_ctx);
     760           0 :                 return ldb_operr(ldb_module_get_ctx(module));
     761             :         }
     762             : 
     763       81086 :         *feature_enabled = false;
     764             : 
     765       81086 :         ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
     766       81086 :         if (ret != LDB_SUCCESS) {
     767        1273 :                 ldb_asprintf_errstring(ldb,
     768             :                                 "Could not find the feature object - dn: %s\n",
     769             :                                 ldb_dn_get_linearized(feature_dn));
     770        1273 :                 talloc_free(tmp_ctx);
     771        1273 :                 return LDB_ERR_NO_SUCH_OBJECT;
     772             :         }
     773       79813 :         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       79813 :         talloc_free(tmp_ctx);
     800       79813 :         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        1212 : 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        1212 :         attrs[0] = attribute;
     845        1212 :         attrs[1] = NULL;
     846             : 
     847        1212 :         ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
     848             :                                     DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
     849        1212 :         if (ret != LDB_SUCCESS) {
     850           0 :                 return ret;
     851             :         }
     852             : 
     853        1212 :         *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
     854        1212 :                                       mem_ctx, res->msgs[0], attribute);
     855        1212 :         if (!*dn) {
     856          28 :                 ldb_reset_err_string(ldb_module_get_ctx(module));
     857          28 :                 talloc_free(res);
     858          28 :                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
     859             :         }
     860             : 
     861        1184 :         talloc_free(res);
     862        1184 :         return LDB_SUCCESS;
     863             : }
     864             : 
     865             : /*
     866             :   find the RID Manager$ DN via the rIDManagerReference attribute in the
     867             :   base DN
     868             :  */
     869         356 : 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         356 :         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   104854748 : int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
     881             : {
     882   104854748 :         struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
     883             : 
     884   104854748 :         if (!ares) {
     885           0 :                 return ldb_module_done(up_req, NULL, NULL,
     886             :                                        LDB_ERR_OPERATIONS_ERROR);
     887             :         }
     888             : 
     889   104854748 :         if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
     890    35335991 :                 return ldb_module_done(up_req, ares->controls,
     891             :                                        ares->response, ares->error);
     892             :         }
     893             : 
     894             :         /* Otherwise pass on the callback */
     895    69518757 :         switch (ares->type) {
     896    66870113 :         case LDB_REPLY_ENTRY:
     897    66870113 :                 return ldb_module_send_entry(up_req, ares->message,
     898             :                                              ares->controls);
     899             : 
     900     2648644 :         case LDB_REPLY_REFERRAL:
     901     2648644 :                 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      155328 : 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      155328 :         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      155328 :         msg = ldb_msg_new(module);
    1013      155328 :         if (msg == NULL) {
    1014           0 :                 return ldb_module_oom(module);
    1015             :         }
    1016             : 
    1017      155328 :         msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
    1018      155328 :         if (msg->dn == NULL) {
    1019           0 :                 talloc_free(msg);
    1020           0 :                 return ldb_operr(ldb_module_get_ctx(module));
    1021             :         }
    1022             : 
    1023      155328 :         res = talloc_zero(msg, struct ldb_result);
    1024      155328 :         if (!res) {
    1025           0 :                 talloc_free(msg);
    1026           0 :                 return ldb_module_oom(module);
    1027             :         }
    1028             : 
    1029      155328 :         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
    1030      155328 :         if (ret != LDB_SUCCESS) {
    1031           0 :                 talloc_free(msg);
    1032           0 :                 return ret;
    1033             :         }
    1034      155328 :         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
    1035             : 
    1036             :         /* urgent_uSN is optional so may not be stored */
    1037      155328 :         if (urgent_uSN) {
    1038       24840 :                 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
    1039             :                                            urgent_uSN);
    1040       24840 :                 if (ret != LDB_SUCCESS) {
    1041           0 :                         talloc_free(msg);
    1042           0 :                         return ret;
    1043             :                 }
    1044       24840 :                 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
    1045             :         }
    1046             : 
    1047             : 
    1048      155328 :         p_ctrl = talloc(msg, struct dsdb_control_current_partition);
    1049      155328 :         if (p_ctrl == NULL) {
    1050           0 :                 talloc_free(msg);
    1051           0 :                 return ldb_oom(ldb);
    1052             :         }
    1053      155328 :         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
    1054      155328 :         p_ctrl->dn = dn;
    1055      155328 :         ret = ldb_build_mod_req(&req, ldb, msg,
    1056             :                                 msg,
    1057             :                                 NULL,
    1058             :                                 res,
    1059             :                                 ldb_modify_default_callback,
    1060             :                                 parent);
    1061      155328 :         LDB_REQ_SET_LOCATION(req);
    1062      156024 : again:
    1063      156024 :         if (ret != LDB_SUCCESS) {
    1064           0 :                 talloc_free(msg);
    1065           0 :                 return ret;
    1066             :         }
    1067             : 
    1068      156024 :         ret = ldb_request_add_control(req,
    1069             :                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
    1070             :                                       false, p_ctrl);
    1071      156024 :         if (ret != LDB_SUCCESS) {
    1072           0 :                 talloc_free(msg);
    1073           0 :                 return ret;
    1074             :         }
    1075             : 
    1076             :         /* Run the new request */
    1077      156024 :         ret = ldb_next_request(module, req);
    1078             : 
    1079      156024 :         if (ret == LDB_SUCCESS) {
    1080      156024 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    1081             :         }
    1082      156024 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
    1083         696 :                 ret = ldb_build_add_req(&req, ldb, msg,
    1084             :                                         msg,
    1085             :                                         NULL,
    1086             :                                         res,
    1087             :                                         ldb_modify_default_callback,
    1088             :                                         parent);
    1089         696 :                 LDB_REQ_SET_LOCATION(req);
    1090         696 :                 goto again;
    1091             :         }
    1092             : 
    1093      155328 :         talloc_free(msg);
    1094             : 
    1095      155328 :         return ret;
    1096             : }
    1097             : 
    1098    31567170 : bool dsdb_module_am_system(struct ldb_module *module)
    1099             : {
    1100    31567170 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1101    27956993 :         struct auth_session_info *session_info
    1102    31567170 :                 = talloc_get_type(
    1103             :                         ldb_get_opaque(ldb, DSDB_SESSION_INFO),
    1104             :                         struct auth_session_info);
    1105    31567170 :         return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
    1106             : }
    1107             : 
    1108    19963001 : bool dsdb_module_am_administrator(struct ldb_module *module)
    1109             : {
    1110    19963001 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1111    17718927 :         struct auth_session_info *session_info
    1112    19963001 :                 = talloc_get_type(
    1113             :                         ldb_get_opaque(ldb, DSDB_SESSION_INFO),
    1114             :                         struct auth_session_info);
    1115    19963001 :         return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
    1116             : }
    1117             : 
    1118             : /*
    1119             :   check if the recyclebin is enabled
    1120             :  */
    1121       81086 : int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
    1122             : {
    1123       81086 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1124             :         struct GUID recyclebin_guid;
    1125             :         int ret;
    1126             : 
    1127       81086 :         GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
    1128             : 
    1129       81086 :         ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
    1130       81086 :         if (ret != LDB_SUCCESS) {
    1131        1273 :                 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
    1132        1273 :                 return ret;
    1133             :         }
    1134             : 
    1135       79813 :         return LDB_SUCCESS;
    1136             : }
    1137             : 
    1138       46608 : 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       46608 :         if (old_val) {
    1149       23279 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
    1150       23279 :                 if (ret != LDB_SUCCESS) {
    1151           0 :                         return ret;
    1152             :                 }
    1153       23279 :                 el->num_values = 1;
    1154       23279 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1155       23279 :                 if (!el->values) {
    1156           0 :                         return ldb_module_oom(module);
    1157             :                 }
    1158       23279 :                 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
    1159       23279 :                 if (!vstring) {
    1160           0 :                         return ldb_module_oom(module);
    1161             :                 }
    1162       23279 :                 *el->values = data_blob_string_const(vstring);
    1163             :         }
    1164             : 
    1165       46608 :         if (new_val) {
    1166       23404 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
    1167       23404 :                 if (ret != LDB_SUCCESS) {
    1168           0 :                         return ret;
    1169             :                 }
    1170       23404 :                 el->num_values = 1;
    1171       23404 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1172       23404 :                 if (!el->values) {
    1173           0 :                         return ldb_module_oom(module);
    1174             :                 }
    1175       23404 :                 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
    1176       23404 :                 if (!vstring) {
    1177           0 :                         return ldb_module_oom(module);
    1178             :                 }
    1179       23404 :                 *el->values = data_blob_string_const(vstring);
    1180             :         }
    1181             : 
    1182       46608 :         return LDB_SUCCESS;
    1183             : }
    1184             : 
    1185       46608 : 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       46608 :         return dsdb_msg_constrainted_update_int32(module, msg, attr,
    1192             :                                                   (const int32_t *)old_val,
    1193             :                                                   (const int32_t *)new_val);
    1194             : }
    1195             : 
    1196       46713 : 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       46713 :         if (old_val) {
    1207         196 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
    1208         196 :                 if (ret != LDB_SUCCESS) {
    1209           0 :                         return ret;
    1210             :                 }
    1211         196 :                 el->num_values = 1;
    1212         196 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1213         196 :                 if (!el->values) {
    1214           0 :                         return ldb_module_oom(module);
    1215             :                 }
    1216         196 :                 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
    1217         196 :                 if (!vstring) {
    1218           0 :                         return ldb_module_oom(module);
    1219             :                 }
    1220         196 :                 *el->values = data_blob_string_const(vstring);
    1221             :         }
    1222             : 
    1223       46713 :         if (new_val) {
    1224         320 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
    1225         320 :                 if (ret != LDB_SUCCESS) {
    1226           0 :                         return ret;
    1227             :                 }
    1228         320 :                 el->num_values = 1;
    1229         320 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1230         320 :                 if (!el->values) {
    1231           0 :                         return ldb_module_oom(module);
    1232             :                 }
    1233         320 :                 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
    1234         320 :                 if (!vstring) {
    1235           0 :                         return ldb_module_oom(module);
    1236             :                 }
    1237         320 :                 *el->values = data_blob_string_const(vstring);
    1238             :         }
    1239             : 
    1240       46713 :         return LDB_SUCCESS;
    1241             : }
    1242             : 
    1243       46608 : 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       46608 :         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           0 : 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           0 :         msg = ldb_msg_new(module);
    1268           0 :         if (msg == NULL) {
    1269           0 :                 return ldb_module_oom(module);
    1270             :         }
    1271           0 :         msg->dn = dn;
    1272             : 
    1273           0 :         ret = dsdb_msg_constrainted_update_int32(module,
    1274             :                                                  msg, attr,
    1275             :                                                  old_val,
    1276             :                                                  new_val);
    1277           0 :         if (ret != LDB_SUCCESS) {
    1278           0 :                 talloc_free(msg);
    1279           0 :                 return ret;
    1280             :         }
    1281             : 
    1282           0 :         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
    1283           0 :         talloc_free(msg);
    1284           0 :         return ret;
    1285             : }
    1286             : 
    1287           0 : 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           0 :         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         105 : 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         105 :         msg = ldb_msg_new(module);
    1313         105 :         if (msg == NULL) {
    1314           0 :                 return ldb_module_oom(module);
    1315             :         }
    1316         105 :         msg->dn = dn;
    1317             : 
    1318         105 :         ret = dsdb_msg_constrainted_update_int64(module,
    1319             :                                                  msg, attr,
    1320             :                                                  old_val,
    1321             :                                                  new_val);
    1322         105 :         if (ret != LDB_SUCCESS) {
    1323           0 :                 talloc_free(msg);
    1324           0 :                 return ret;
    1325             :         }
    1326             : 
    1327         105 :         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
    1328         105 :         talloc_free(msg);
    1329         105 :         return ret;
    1330             : }
    1331             : 
    1332         105 : 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         105 :         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     1048319 : 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     1048319 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1352             :         static const char *attrs[] = { "dSHeuristics", NULL };
    1353             :         struct ldb_result *res;
    1354             : 
    1355     1048319 :         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
    1356     1048319 :         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     1048319 :         ret = dsdb_module_search_dn(module, mem_ctx, &res,
    1362             :                                     new_dn,
    1363             :                                     attrs,
    1364             :                                     DSDB_FLAG_NEXT_MODULE,
    1365             :                                     parent);
    1366     1048319 :         if (ret == LDB_SUCCESS && res->count == 1) {
    1367      893901 :                 talloc_free(new_dn);
    1368      893901 :                 return ldb_msg_find_ldb_val(res->msgs[0],
    1369             :                                             "dSHeuristics");
    1370             :         }
    1371      154418 :         talloc_free(new_dn);
    1372      154418 :         return NULL;
    1373             : }
    1374             : 
    1375      108429 : bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
    1376             : {
    1377      108429 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
    1378             :         bool result;
    1379      108429 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1380             :                                                                      tmp_ctx, parent);
    1381      108429 :         if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
    1382       96964 :                 result = true;
    1383       11465 :         } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
    1384          17 :                 result = false;
    1385             :         } else {
    1386       11448 :                 result = true;
    1387             :         }
    1388             : 
    1389      108429 :         talloc_free(tmp_ctx);
    1390      108429 :         return result;
    1391             : }
    1392             : 
    1393      923610 : bool dsdb_user_password_support(struct ldb_module *module,
    1394             :                                 TALLOC_CTX *mem_ctx,
    1395             :                                 struct ldb_request *parent)
    1396             : {
    1397      923610 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1398             :         bool result;
    1399      923610 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1400             :                                                                      tmp_ctx,
    1401             :                                                                      parent);
    1402      923610 :         if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
    1403      898834 :                 result = false;
    1404       43404 :         } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
    1405       24748 :                    (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
    1406         860 :                 result = false;
    1407             :         } else {
    1408       23916 :                 result = true;
    1409             :         }
    1410             : 
    1411      923610 :         talloc_free(tmp_ctx);
    1412      923610 :         return result;
    1413             : }
    1414             : 
    1415       16280 : bool dsdb_do_list_object(struct ldb_module *module,
    1416             :                          TALLOC_CTX *mem_ctx,
    1417             :                          struct ldb_request *parent)
    1418             : {
    1419       16280 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1420             :         bool result;
    1421       16280 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1422             :                                                                      tmp_ctx,
    1423             :                                                                      parent);
    1424       16280 :         if (hr_val == NULL || hr_val->length < DS_HR_DOLISTOBJECT) {
    1425          26 :                 result = false;
    1426       16254 :         } else if (hr_val->data[DS_HR_DOLISTOBJECT -1] == '1') {
    1427        8064 :                 result = true;
    1428             :         } else {
    1429        8190 :                 result = false;
    1430             :         }
    1431             : 
    1432       16280 :         talloc_free(tmp_ctx);
    1433       16280 :         return result;
    1434             : }
    1435             : 
    1436           0 : bool dsdb_attribute_authz_on_ldap_add(struct ldb_module *module,
    1437             :                                       TALLOC_CTX *mem_ctx,
    1438             :                                       struct ldb_request *parent)
    1439             : {
    1440           0 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1441           0 :         bool result = false;
    1442           0 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1443             :                                                                      tmp_ctx,
    1444             :                                                                      parent);
    1445           0 :         if (hr_val != NULL && hr_val->length >= DS_HR_ATTR_AUTHZ_ON_LDAP_ADD) {
    1446           0 :                 uint8_t val = hr_val->data[DS_HR_ATTR_AUTHZ_ON_LDAP_ADD - 1];
    1447           0 :                 if (val != '0' && val != '2') {
    1448           0 :                         result = true;
    1449             :                 }
    1450             :         }
    1451             : 
    1452           0 :         talloc_free(tmp_ctx);
    1453           0 :         return result;
    1454             : }
    1455             : 
    1456           0 : bool dsdb_block_owner_implicit_rights(struct ldb_module *module,
    1457             :                                       TALLOC_CTX *mem_ctx,
    1458             :                                       struct ldb_request *parent)
    1459             : {
    1460           0 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1461           0 :         bool result = false;
    1462           0 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1463             :                                                                      tmp_ctx,
    1464             :                                                                      parent);
    1465           0 :         if (hr_val != NULL && hr_val->length >= DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS) {
    1466           0 :                 uint8_t val = hr_val->data[DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS - 1];
    1467           0 :                 if (val != '0' && val != '2') {
    1468           0 :                         result = true;
    1469             :                 }
    1470             :         }
    1471             : 
    1472           0 :         talloc_free(tmp_ctx);
    1473           0 :         return result;
    1474             : }
    1475             : 
    1476             : /*
    1477             :   show the chain of requests, useful for debugging async requests
    1478             :  */
    1479           0 : void dsdb_req_chain_debug(struct ldb_request *req, int level)
    1480             : {
    1481           0 :         char *s = ldb_module_call_chain(req, req);
    1482           0 :         DEBUG(level, ("%s\n", s));
    1483           0 :         talloc_free(s);
    1484           0 : }
    1485             : 
    1486             : /*
    1487             :  * Get all the values that *might* be added by an ldb message, as a composite
    1488             :  * ldb element.
    1489             :  *
    1490             :  * This is useful when we need to check all the possible values against some
    1491             :  * criteria.
    1492             :  *
    1493             :  * In cases where a modify message mixes multiple ADDs, DELETEs, and REPLACES,
    1494             :  * the returned element might contain more values than would actually end up
    1495             :  * in the database if the message was run to its conclusion.
    1496             :  *
    1497             :  * If the operation is not LDB_ADD or LDB_MODIFY, an operations error is
    1498             :  * returned.
    1499             :  *
    1500             :  * The returned element might not be new, and should not be modified or freed
    1501             :  * before the message is finished.
    1502             :  */
    1503             : 
    1504      252004 : int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
    1505             :                                  const struct ldb_message *msg,
    1506             :                                  const char *attr_name,
    1507             :                                  struct ldb_message_element **el,
    1508             :                                  enum ldb_request_type operation)
    1509             : {
    1510             :         unsigned int i;
    1511      252004 :         unsigned int el_count = 0;
    1512      252004 :         unsigned int val_count = 0;
    1513      252004 :         struct ldb_val *v = NULL;
    1514      252004 :         struct ldb_message_element *_el = NULL;
    1515      252004 :         *el = NULL;
    1516             : 
    1517      252004 :         if (operation != LDB_ADD && operation != LDB_MODIFY) {
    1518           0 :                 DBG_ERR("inapplicable operation type: %d\n", operation);
    1519           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1520             :         }
    1521             : 
    1522             :         /* count the adding or replacing elements */
    1523     4490534 :         for (i = 0; i < msg->num_elements; i++) {
    1524     4238530 :                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
    1525             :                         unsigned int tmp;
    1526      261899 :                         if ((operation == LDB_MODIFY) &&
    1527       27778 :                             (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
    1528             :                                                 == LDB_FLAG_MOD_DELETE)) {
    1529       10670 :                                 continue;
    1530             :                         }
    1531      232433 :                         el_count++;
    1532      232433 :                         tmp = val_count + msg->elements[i].num_values;
    1533      232433 :                         if (unlikely(tmp < val_count)) {
    1534           0 :                                 DBG_ERR("too many values for one element!");
    1535           0 :                                 return LDB_ERR_OPERATIONS_ERROR;
    1536             :                         }
    1537      232433 :                         val_count = tmp;
    1538             :                 }
    1539             :         }
    1540      252004 :         if (el_count == 0) {
    1541             :                 /* nothing to see here */
    1542       19580 :                 return LDB_SUCCESS;
    1543             :         }
    1544             : 
    1545      232424 :         if (el_count == 1 || val_count == 0) {
    1546             :                 /*
    1547             :                  * There is one effective element, which we can return as-is,
    1548             :                  * OR there are only elements with zero values -- any of which
    1549             :                  * will do.
    1550             :                  */
    1551     1522613 :                 for (i = 0; i < msg->num_elements; i++) {
    1552     1522613 :                         if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
    1553      261831 :                                 if ((operation == LDB_MODIFY) &&
    1554       27736 :                                     (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
    1555             :                                      == LDB_FLAG_MOD_DELETE)) {
    1556       10646 :                                         continue;
    1557             :                                 }
    1558      232415 :                                 *el = &msg->elements[i];
    1559      232415 :                                 return LDB_SUCCESS;
    1560             :                         }
    1561             :                 }
    1562             :         }
    1563             : 
    1564           9 :         _el = talloc_zero(mem_ctx, struct ldb_message_element);
    1565           9 :         if (_el == NULL) {
    1566           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1567             :         }
    1568           9 :         _el->name = attr_name;
    1569             : 
    1570           9 :         if (val_count == 0) {
    1571             :                 /*
    1572             :                  * Seems unlikely, but sometimes we might be adding zero
    1573             :                  * values in multiple separate elements. The talloc zero has
    1574             :                  * already set the expected values = NULL, num_values = 0.
    1575             :                  */
    1576           0 :                 *el = _el;
    1577           0 :                 return LDB_SUCCESS;
    1578             :         }
    1579             : 
    1580           9 :         _el->values = talloc_array(_el, struct ldb_val, val_count);
    1581           9 :         if (_el->values == NULL) {
    1582           0 :                 talloc_free(_el);
    1583           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1584             :         }
    1585           9 :         _el->num_values = val_count;
    1586             : 
    1587           9 :         v = _el->values;
    1588             : 
    1589          36 :         for (i = 0; i < msg->num_elements; i++) {
    1590          27 :                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
    1591          18 :                         const struct ldb_message_element *tmp_el = &msg->elements[i];
    1592          28 :                         if ((operation == LDB_MODIFY) &&
    1593          18 :                             (LDB_FLAG_MOD_TYPE(tmp_el->flags)
    1594             :                                                 == LDB_FLAG_MOD_DELETE)) {
    1595           0 :                                 continue;
    1596             :                         }
    1597          18 :                         if (tmp_el->values == NULL || tmp_el->num_values == 0) {
    1598           0 :                                 continue;
    1599             :                         }
    1600          28 :                         memcpy(v,
    1601          18 :                                tmp_el->values,
    1602          18 :                                tmp_el->num_values * sizeof(*v));
    1603          18 :                         v += tmp_el->num_values;
    1604             :                 }
    1605             :         }
    1606             : 
    1607           9 :         *el = _el;
    1608           9 :         return LDB_SUCCESS;
    1609             : }
    1610             : 
    1611             : 
    1612             : /*
    1613             :  * Get the value of a single-valued attribute from an ADDed message. 'val' will only live as
    1614             :  * long as 'msg' and 'original_val' do, and must not be freed.
    1615             :  */
    1616           0 : int dsdb_msg_add_get_single_value(const struct ldb_message *msg,
    1617             :                                   const char *attr_name,
    1618             :                                   const struct ldb_val **val)
    1619             : {
    1620           0 :         const struct ldb_message_element *el = NULL;
    1621             : 
    1622             :         /*
    1623             :          * The ldb_msg_normalize() call in ldb_request() ensures that
    1624             :          * there is at most one message element for each
    1625             :          * attribute. Thus, we don't need a loop to deal with an
    1626             :          * LDB_ADD.
    1627             :          */
    1628           0 :         el = ldb_msg_find_element(msg, attr_name);
    1629           0 :         if (el == NULL) {
    1630           0 :                 *val = NULL;
    1631           0 :                 return LDB_SUCCESS;
    1632             :         }
    1633           0 :         if (el->num_values != 1) {
    1634           0 :                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1635             :         }
    1636             : 
    1637           0 :         *val = &el->values[0];
    1638           0 :         return LDB_SUCCESS;
    1639             : }
    1640             : 
    1641             : /*
    1642             :  * Get the value of a single-valued attribute after processing a
    1643             :  * message. 'operation' is either LDB_ADD or LDB_MODIFY. 'val' will only live as
    1644             :  * long as 'msg' and 'original_val' do, and must not be freed.
    1645             :  */
    1646        1247 : int dsdb_msg_get_single_value(const struct ldb_message *msg,
    1647             :                               const char *attr_name,
    1648             :                               const struct ldb_val *original_val,
    1649             :                               const struct ldb_val **val,
    1650             :                               enum ldb_request_type operation)
    1651             : {
    1652             :         unsigned idx;
    1653             : 
    1654        1247 :         *val = NULL;
    1655             : 
    1656        1247 :         if (operation == LDB_ADD) {
    1657           0 :                 if (original_val != NULL) {
    1658             :                         /* This is an error on the caller's part. */
    1659           0 :                         return LDB_ERR_CONSTRAINT_VIOLATION;
    1660             :                 }
    1661           0 :                 return dsdb_msg_add_get_single_value(msg, attr_name, val);
    1662             :         }
    1663             : 
    1664        1247 :         SMB_ASSERT(operation == LDB_MODIFY);
    1665             : 
    1666        1247 :         *val = original_val;
    1667             : 
    1668        2821 :         for (idx = 0; idx < msg->num_elements; ++idx) {
    1669        1574 :                 const struct ldb_message_element *el = &msg->elements[idx];
    1670             : 
    1671        1574 :                 if (ldb_attr_cmp(el->name, attr_name) != 0) {
    1672        1496 :                         continue;
    1673             :                 }
    1674             : 
    1675          78 :                 switch (el->flags & LDB_FLAG_MOD_MASK) {
    1676           0 :                 case LDB_FLAG_MOD_ADD:
    1677           0 :                         if (el->num_values != 1) {
    1678           0 :                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1679             :                         }
    1680           0 :                         if (*val != NULL) {
    1681           0 :                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1682             :                         }
    1683             : 
    1684           0 :                         *val = &el->values[0];
    1685             : 
    1686           0 :                         break;
    1687             : 
    1688          78 :                 case LDB_FLAG_MOD_REPLACE:
    1689          78 :                         if (el->num_values > 1) {
    1690           0 :                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1691             :                         }
    1692             : 
    1693          78 :                         *val = el->num_values ? &el->values[0] : NULL;
    1694             : 
    1695          78 :                         break;
    1696             : 
    1697           0 :                 case LDB_FLAG_MOD_DELETE:
    1698           0 :                         if (el->num_values > 1) {
    1699           0 :                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1700             :                         }
    1701             : 
    1702             :                         /*
    1703             :                          * If a value was specified for the delete, we don't
    1704             :                          * bother checking it matches the value we currently
    1705             :                          * have. Any mismatch will be caught later (e.g. in
    1706             :                          * ldb_kv_modify_internal).
    1707             :                          */
    1708             : 
    1709           0 :                         *val = NULL;
    1710             : 
    1711           0 :                         break;
    1712             :                 }
    1713             :         }
    1714             : 
    1715        1247 :         return LDB_SUCCESS;
    1716             : }
    1717             : 
    1718             : /*
    1719             :  * This function determines the (last) structural or 88 object class of a passed
    1720             :  * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
    1721             :  * Without schema this does not work and hence NULL is returned.
    1722             :  */
    1723     5206996 : const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
    1724             :                                                         const struct ldb_message_element *element)
    1725             : {
    1726             :         const struct dsdb_class *last_class;
    1727             : 
    1728     5206996 :         if (schema == NULL) {
    1729           0 :                 return NULL;
    1730             :         }
    1731             : 
    1732     5206996 :         if (element->num_values == 0) {
    1733           0 :                 return NULL;
    1734             :         }
    1735             : 
    1736     5206996 :         last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
    1737     5206996 :                                                            &element->values[element->num_values-1]);
    1738     5206996 :         if (last_class == NULL) {
    1739           0 :                 return NULL;
    1740             :         }
    1741     5206996 :         if (last_class->objectClassCategory > 1) {
    1742           3 :                 return NULL;
    1743             :         }
    1744             : 
    1745     5206993 :         return last_class;
    1746             : }
    1747             : 
    1748     3886353 : const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
    1749             :                                                          const struct ldb_message *msg)
    1750             : {
    1751             :         struct ldb_message_element *oc_el;
    1752             : 
    1753     3886353 :         oc_el = ldb_msg_find_element(msg, "objectClass");
    1754     3886353 :         if (!oc_el) {
    1755           0 :                 return NULL;
    1756             :         }
    1757             : 
    1758     3886353 :         return dsdb_get_last_structural_class(schema, oc_el);
    1759             : }
    1760             : 
    1761             : /*
    1762             :   Get the parent class of an objectclass, or NULL if none exists.
    1763             :  */
    1764           0 : const struct dsdb_class *dsdb_get_parent_class(const struct dsdb_schema *schema,
    1765             :                                                const struct dsdb_class *objectclass)
    1766             : {
    1767           0 :         if (ldb_attr_cmp(objectclass->lDAPDisplayName, "top") == 0) {
    1768           0 :                 return NULL;
    1769             :         }
    1770             : 
    1771           0 :         if (objectclass->subClassOf == NULL) {
    1772           0 :                 return NULL;
    1773             :         }
    1774             : 
    1775           0 :         return dsdb_class_by_lDAPDisplayName(schema, objectclass->subClassOf);
    1776             : }
    1777             : 
    1778             : /*
    1779             :   Return true if 'struct_objectclass' is a subclass of 'other_objectclass'. The
    1780             :   two objectclasses must originate from the same schema, to allow for
    1781             :   pointer-based identity comparison.
    1782             :  */
    1783         153 : bool dsdb_is_subclass_of(const struct dsdb_schema *schema,
    1784             :                          const struct dsdb_class *struct_objectclass,
    1785             :                          const struct dsdb_class *other_objectclass)
    1786             : {
    1787         250 :         while (struct_objectclass != NULL) {
    1788             :                 /* Pointer comparison can be used due to the same schema str. */
    1789         153 :                 if (struct_objectclass == other_objectclass) {
    1790         153 :                         return true;
    1791             :                 }
    1792             : 
    1793           0 :                 struct_objectclass = dsdb_get_parent_class(schema, struct_objectclass);
    1794             :         }
    1795             : 
    1796           0 :         return false;
    1797             : }
    1798             : 
    1799             : /* Fix the DN so that the relative attribute names are in upper case so that the DN:
    1800             :    cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
    1801             :    CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
    1802             : */
    1803           0 : int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
    1804             : {
    1805             :         int i, ret;
    1806             :         char *upper_rdn_attr;
    1807             : 
    1808           0 :         for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
    1809             :                 /* We need the attribute name in upper case */
    1810           0 :                 upper_rdn_attr = strupper_talloc(dn,
    1811             :                                                  ldb_dn_get_component_name(dn, i));
    1812           0 :                 if (!upper_rdn_attr) {
    1813           0 :                         return ldb_oom(ldb);
    1814             :                 }
    1815           0 :                 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
    1816           0 :                                            *ldb_dn_get_component_val(dn, i));
    1817           0 :                 talloc_free(upper_rdn_attr);
    1818           0 :                 if (ret != LDB_SUCCESS) {
    1819           0 :                         return ret;
    1820             :                 }
    1821             :         }
    1822           0 :         return LDB_SUCCESS;
    1823             : }
    1824             : 
    1825             : /**
    1826             :  * Make most specific objectCategory for the objectClass of passed object
    1827             :  * NOTE: In this implementation we count that it is called on already
    1828             :  * verified objectClass attribute value. See objectclass.c thorough
    1829             :  * implementation for all the magic that involves
    1830             :  *
    1831             :  * @param ldb   ldb context
    1832             :  * @param schema cached schema for ldb. We may get it, but it is very time consuming.
    1833             :  *                      Hence leave the responsibility to the caller.
    1834             :  * @param obj   AD object to determint objectCategory for
    1835             :  * @param mem_ctx Memory context - usually it is obj actually
    1836             :  * @param pobjectcategory location to store found objectCategory
    1837             :  *
    1838             :  * @return LDB_SUCCESS or error including out of memory error
    1839             :  */
    1840         274 : int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
    1841             :                               const struct ldb_message *obj,
    1842             :                               TALLOC_CTX *mem_ctx, const char **pobjectcategory)
    1843             : {
    1844             :         const struct dsdb_class                 *objectclass;
    1845             :         struct ldb_message_element              *objectclass_element;
    1846             :         struct dsdb_extended_dn_store_format    *dn_format;
    1847             : 
    1848         274 :         objectclass_element = ldb_msg_find_element(obj, "objectClass");
    1849         274 :         if (!objectclass_element) {
    1850           0 :                 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
    1851           0 :                                        ldb_dn_get_linearized(obj->dn));
    1852           0 :                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
    1853             :         }
    1854         274 :         if (objectclass_element->num_values == 0) {
    1855           0 :                 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
    1856           0 :                                        ldb_dn_get_linearized(obj->dn));
    1857           0 :                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1858             :         }
    1859             : 
    1860             :         /*
    1861             :          * Get the new top-most structural object class and check for
    1862             :          * unrelated structural classes
    1863             :          */
    1864         274 :         objectclass = dsdb_get_last_structural_class(schema,
    1865             :                                                      objectclass_element);
    1866         274 :         if (objectclass == NULL) {
    1867           0 :                 ldb_asprintf_errstring(ldb,
    1868             :                                        "Failed to find a structural class for %s",
    1869           0 :                                        ldb_dn_get_linearized(obj->dn));
    1870           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
    1871             :         }
    1872             : 
    1873         274 :         dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
    1874             :                                     struct dsdb_extended_dn_store_format);
    1875         274 :         if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
    1876             :                 /* Strip off extended components */
    1877           0 :                 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
    1878           0 :                                                objectclass->defaultObjectCategory);
    1879           0 :                 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
    1880           0 :                 talloc_free(dn);
    1881             :         } else {
    1882         274 :                 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
    1883             :         }
    1884             : 
    1885         274 :         if (*pobjectcategory == NULL) {
    1886           0 :                 return ldb_oom(ldb);
    1887             :         }
    1888             : 
    1889         274 :         return LDB_SUCCESS;
    1890             : }

Generated by: LCOV version 1.13