LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules - util.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 634 898 70.6 %
Date: 2023-11-21 12:31:41 Functions: 44 47 93.6 %

          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    13438769 : 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      595649 :         int ret;
      46      595649 :         struct ldb_request *req;
      47      595649 :         TALLOC_CTX *tmp_ctx;
      48      595649 :         struct ldb_result *res;
      49             : 
      50    13438769 :         tmp_ctx = talloc_new(mem_ctx);
      51             : 
      52    13438769 :         res = talloc_zero(tmp_ctx, struct ldb_result);
      53    13438769 :         if (!res) {
      54           0 :                 talloc_free(tmp_ctx);
      55           0 :                 return ldb_oom(ldb_module_get_ctx(module));
      56             :         }
      57             : 
      58    13438769 :         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    13438769 :         LDB_REQ_SET_LOCATION(req);
      68    13438769 :         if (ret != LDB_SUCCESS) {
      69           0 :                 talloc_free(tmp_ctx);
      70           0 :                 return ret;
      71             :         }
      72             : 
      73    13438769 :         ret = dsdb_request_add_controls(req, dsdb_flags);
      74    13438769 :         if (ret != LDB_SUCCESS) {
      75           0 :                 talloc_free(tmp_ctx);
      76           0 :                 return ret;
      77             :         }
      78             : 
      79    13438769 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
      80           0 :                 ldb_req_mark_trusted(req);
      81             :         }
      82             : 
      83             :         /* Run the new request */
      84    13438769 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
      85    13438495 :                 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    13438769 :         if (ret == LDB_SUCCESS) {
      94    13438746 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
      95             :         }
      96             : 
      97    13438769 :         if (ret != LDB_SUCCESS) {
      98      494765 :                 talloc_free(tmp_ctx);
      99      494765 :                 return ret;
     100             :         }
     101             : 
     102    12944004 :         if (res->count != 1) {
     103             :                 /* we may be reading a DB that does not have the 'check base on search' option... */
     104       20752 :                 ret = LDB_ERR_NO_SUCH_OBJECT;
     105       20752 :                 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    12923252 :                 *_res = talloc_steal(mem_ctx, res);
     110             :         }
     111    12944004 :         talloc_free(tmp_ctx);
     112    12944004 :         return ret;
     113             : }
     114             : 
     115    13011584 : 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      164071 :         int ret;
     126      164071 :         struct ldb_request *req;
     127      164071 :         TALLOC_CTX *tmp_ctx;
     128      164071 :         struct ldb_result *res;
     129             : 
     130    13011584 :         tmp_ctx = talloc_new(mem_ctx);
     131             : 
     132             :         /* cross-partitions searches with a basedn break multi-domain support */
     133    13011584 :         SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
     134             : 
     135    13011584 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     136    13011584 :         if (!res) {
     137           0 :                 talloc_free(tmp_ctx);
     138           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     139             :         }
     140             : 
     141    13011584 :         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    13011584 :         LDB_REQ_SET_LOCATION(req);
     151    13011584 :         if (ret != LDB_SUCCESS) {
     152           0 :                 talloc_free(tmp_ctx);
     153           0 :                 return ret;
     154             :         }
     155             : 
     156    13011584 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     157    13011584 :         if (ret != LDB_SUCCESS) {
     158           0 :                 talloc_free(tmp_ctx);
     159           0 :                 return ret;
     160             :         }
     161             : 
     162    13011584 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     163           0 :                 ldb_req_mark_trusted(req);
     164             :         }
     165             : 
     166    13011584 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     167    13011581 :                 ret = ldb_next_request(module, req);
     168           3 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     169           3 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     170             :         } else {
     171           0 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     172           0 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     173           0 :                 ret = ops->search(module, req);
     174             :         }
     175    13011584 :         if (ret == LDB_SUCCESS) {
     176    13011584 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     177             :         }
     178             : 
     179    13011584 :         if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
     180    10466449 :                 if (res->count == 0) {
     181        7411 :                         talloc_free(tmp_ctx);
     182        7411 :                         return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
     183             :                 }
     184    10459038 :                 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    13004173 :         talloc_free(req);
     192    13004173 :         if (ret == LDB_SUCCESS) {
     193    13003116 :                 *_res = talloc_steal(mem_ctx, res);
     194             :         }
     195    13004173 :         talloc_free(tmp_ctx);
     196    13004173 :         return ret;
     197             : }
     198             : 
     199             : /*
     200             :   search for attrs in the modules below
     201             :  */
     202    13010032 : 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      164071 :         int ret;
     212      164071 :         TALLOC_CTX *tmp_ctx;
     213      164071 :         va_list ap;
     214      164071 :         char *expression;
     215      164071 :         struct ldb_parse_tree *tree;
     216             : 
     217             :         /* cross-partitions searches with a basedn break multi-domain support */
     218    13010032 :         SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
     219             : 
     220    13010032 :         tmp_ctx = talloc_new(mem_ctx);
     221             : 
     222    13010032 :         if (format) {
     223    12279089 :                 va_start(ap, format);
     224    12279089 :                 expression = talloc_vasprintf(tmp_ctx, format, ap);
     225    12279089 :                 va_end(ap);
     226             : 
     227    12279089 :                 if (!expression) {
     228           0 :                         talloc_free(tmp_ctx);
     229           0 :                         return ldb_oom(ldb_module_get_ctx(module));
     230             :                 }
     231             :         } else {
     232      706871 :                 expression = NULL;
     233             :         }
     234             : 
     235    13010032 :         tree = ldb_parse_tree(tmp_ctx, expression);
     236    13010032 :         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    13010032 :         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    13010032 :         talloc_free(tmp_ctx);
     254    13010032 :         return ret;
     255             : }
     256             : 
     257             : /*
     258             :   find an object given a GUID. This searches across all partitions
     259             :  */
     260       77813 : int dsdb_module_obj_by_guid(struct ldb_module *module,
     261             :                             TALLOC_CTX *mem_ctx,
     262             :                             struct ldb_message **_msg,
     263             :                             const struct GUID *guid,
     264             :                             const char * const *attrs,
     265             :                             struct ldb_request *parent)
     266             : {
     267        1602 :         struct ldb_result *res;
     268       77813 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     269        1602 :         int ret;
     270             : 
     271       77813 :         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
     272             :                                  attrs,
     273             :                                  DSDB_FLAG_NEXT_MODULE |
     274             :                                  DSDB_SEARCH_SHOW_RECYCLED |
     275             :                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
     276             :                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
     277             :                                  parent,
     278             :                                  "objectGUID=%s", GUID_string(tmp_ctx, guid));
     279       77813 :         if (ret != LDB_SUCCESS) {
     280           0 :                 talloc_free(tmp_ctx);
     281           0 :                 return ret;
     282             :         }
     283       77813 :         if (res->count == 0) {
     284          40 :                 talloc_free(tmp_ctx);
     285          40 :                 return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
     286             :         }
     287       77773 :         if (res->count != 1) {
     288           0 :                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
     289             :                                        GUID_string(tmp_ctx, guid));
     290           0 :                 talloc_free(tmp_ctx);
     291           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     292             :         }
     293             : 
     294       77773 :         *_msg = talloc_steal(mem_ctx, res->msgs[0]);
     295             : 
     296       77773 :         talloc_free(tmp_ctx);
     297       77773 :         return LDB_SUCCESS;
     298             : }
     299             : 
     300             : /*
     301             :   find a DN given a GUID. This searches across all partitions
     302             :  */
     303        3381 : int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
     304             :                            const struct GUID *guid, struct ldb_dn **dn,
     305             :                            struct ldb_request *parent)
     306             : {
     307        3381 :         struct ldb_message *msg = NULL;
     308           0 :         static const char * const attrs[] = { NULL };
     309        3381 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     310           0 :         int ret;
     311             : 
     312        3381 :         ret = dsdb_module_obj_by_guid(module,
     313             :                                       tmp_ctx,
     314             :                                       &msg,
     315             :                                       guid,
     316             :                                       attrs,
     317             :                                       parent);
     318        3381 :         if (ret != LDB_SUCCESS) {
     319          21 :                 talloc_free(tmp_ctx);
     320          21 :                 return ret;
     321             :         }
     322             : 
     323        3360 :         *dn = talloc_steal(mem_ctx, msg->dn);
     324             : 
     325        3360 :         talloc_free(tmp_ctx);
     326        3360 :         return LDB_SUCCESS;
     327             : }
     328             : 
     329             : /*
     330             :   find a GUID given a DN.
     331             :  */
     332       26614 : int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
     333             :                            struct ldb_request *parent)
     334             : {
     335          46 :         static const char * const attrs[] = { NULL };
     336          46 :         struct ldb_result *res;
     337       26614 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     338          46 :         int ret;
     339          46 :         NTSTATUS status;
     340             : 
     341       26614 :         ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
     342             :                                     DSDB_FLAG_NEXT_MODULE |
     343             :                                     DSDB_SEARCH_SHOW_RECYCLED |
     344             :                                     DSDB_SEARCH_SHOW_EXTENDED_DN,
     345             :                                     parent);
     346       26614 :         if (ret != LDB_SUCCESS) {
     347           3 :                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
     348             :                                        ldb_dn_get_linearized(dn));
     349           3 :                 talloc_free(tmp_ctx);
     350           3 :                 return ret;
     351             :         }
     352             : 
     353       26611 :         status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
     354       26611 :         if (!NT_STATUS_IS_OK(status)) {
     355           0 :                 talloc_free(tmp_ctx);
     356           0 :                 return ldb_operr(ldb_module_get_ctx(module));
     357             :         }
     358             : 
     359       26611 :         talloc_free(tmp_ctx);
     360       26611 :         return LDB_SUCCESS;
     361             : }
     362             : 
     363             : 
     364             : /*
     365             :   a ldb_extended request operating on modules below the
     366             :   current module
     367             : 
     368             :   Note that this does not automatically start a transaction. If you
     369             :   need a transaction the caller needs to start it as needed.
     370             :  */
     371    19578138 : int dsdb_module_extended(struct ldb_module *module,
     372             :                          TALLOC_CTX *mem_ctx,
     373             :                          struct ldb_result **_res,
     374             :                          const char* oid, void* data,
     375             :                          uint32_t dsdb_flags,
     376             :                          struct ldb_request *parent)
     377             : {
     378     1122694 :         struct ldb_request *req;
     379     1122694 :         int ret;
     380    19578138 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     381    19578138 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     382     1122694 :         struct ldb_result *res;
     383             : 
     384    19578138 :         if (_res != NULL) {
     385    19208049 :                 (*_res) = NULL;
     386             :         }
     387             : 
     388    19578138 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     389    19578138 :         if (!res) {
     390           0 :                 talloc_free(tmp_ctx);
     391           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     392             :         }
     393             : 
     394    19578138 :         ret = ldb_build_extended_req(&req, ldb,
     395             :                         tmp_ctx,
     396             :                         oid,
     397             :                         data,
     398             :                         NULL,
     399             :                         res, ldb_extended_default_callback,
     400             :                         parent);
     401             : 
     402    19578138 :         LDB_REQ_SET_LOCATION(req);
     403    19578138 :         if (ret != LDB_SUCCESS) {
     404           0 :                 talloc_free(tmp_ctx);
     405           0 :                 return ret;
     406             :         }
     407             : 
     408    19578138 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     409    19578138 :         if (ret != LDB_SUCCESS) {
     410           0 :                 talloc_free(tmp_ctx);
     411           0 :                 return ret;
     412             :         }
     413             : 
     414    19578138 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     415      370089 :                 ldb_req_mark_trusted(req);
     416             :         }
     417             : 
     418             :         /* Run the new request */
     419    19578138 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     420    19208049 :                 ret = ldb_next_request(module, req);
     421      370089 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     422      370089 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     423             :         } else {
     424           0 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     425           0 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     426           0 :                 ret = ops->extended(module, req);
     427             :         }
     428    19578138 :         if (ret == LDB_SUCCESS) {
     429    19578138 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     430             :         }
     431             : 
     432    19578138 :         if (_res != NULL && ret == LDB_SUCCESS) {
     433    19208049 :                 (*_res) = talloc_steal(mem_ctx, res);
     434             :         }
     435             : 
     436    19578138 :         talloc_free(tmp_ctx);
     437    19578138 :         return ret;
     438             : }
     439             : 
     440             : 
     441             : /*
     442             :   a ldb_modify request operating on modules below the
     443             :   current module
     444             :  */
     445      403893 : int dsdb_module_modify(struct ldb_module *module,
     446             :                        const struct ldb_message *message,
     447             :                        uint32_t dsdb_flags,
     448             :                        struct ldb_request *parent)
     449             : {
     450        8038 :         struct ldb_request *mod_req;
     451        8038 :         int ret;
     452      403893 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     453      403893 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     454        8038 :         struct ldb_result *res;
     455             : 
     456      403893 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     457      403893 :         if (!res) {
     458           0 :                 talloc_free(tmp_ctx);
     459           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     460             :         }
     461             : 
     462      403893 :         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
     463             :                                 message,
     464             :                                 NULL,
     465             :                                 res,
     466             :                                 ldb_modify_default_callback,
     467             :                                 parent);
     468      403893 :         LDB_REQ_SET_LOCATION(mod_req);
     469      403893 :         if (ret != LDB_SUCCESS) {
     470           0 :                 talloc_free(tmp_ctx);
     471           0 :                 return ret;
     472             :         }
     473             : 
     474      403893 :         ret = dsdb_request_add_controls(mod_req, dsdb_flags);
     475      403893 :         if (ret != LDB_SUCCESS) {
     476           0 :                 talloc_free(tmp_ctx);
     477           0 :                 return ret;
     478             :         }
     479             : 
     480      403893 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     481           0 :                 ldb_req_mark_trusted(mod_req);
     482             :         }
     483             : 
     484             :         /* Run the new request */
     485      403893 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     486      159155 :                 ret = ldb_next_request(module, mod_req);
     487      244738 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     488           2 :                 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
     489             :         } else {
     490      244736 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     491      244736 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     492      244736 :                 ret = ops->modify(module, mod_req);
     493             :         }
     494      403893 :         if (ret == LDB_SUCCESS) {
     495      403893 :                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
     496             :         }
     497             : 
     498      403893 :         talloc_free(tmp_ctx);
     499      403893 :         return ret;
     500             : }
     501             : 
     502             : 
     503             : 
     504             : /*
     505             :   a ldb_rename request operating on modules below the
     506             :   current module
     507             :  */
     508      162158 : int dsdb_module_rename(struct ldb_module *module,
     509             :                        struct ldb_dn *olddn, struct ldb_dn *newdn,
     510             :                        uint32_t dsdb_flags,
     511             :                        struct ldb_request *parent)
     512             : {
     513         297 :         struct ldb_request *req;
     514         297 :         int ret;
     515      162158 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     516      162158 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     517         297 :         struct ldb_result *res;
     518             : 
     519      162158 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     520      162158 :         if (!res) {
     521           0 :                 talloc_free(tmp_ctx);
     522           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     523             :         }
     524             : 
     525      162158 :         ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
     526             :                                    olddn,
     527             :                                    newdn,
     528             :                                    NULL,
     529             :                                    res,
     530             :                                    ldb_modify_default_callback,
     531             :                                    parent);
     532      162158 :         LDB_REQ_SET_LOCATION(req);
     533      162158 :         if (ret != LDB_SUCCESS) {
     534           0 :                 talloc_free(tmp_ctx);
     535           0 :                 return ret;
     536             :         }
     537             : 
     538      162158 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     539      162158 :         if (ret != LDB_SUCCESS) {
     540           0 :                 talloc_free(tmp_ctx);
     541           0 :                 return ret;
     542             :         }
     543             : 
     544      162158 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     545           0 :                 ldb_req_mark_trusted(req);
     546             :         }
     547             : 
     548             :         /* Run the new request */
     549      162158 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     550      161585 :                 ret = ldb_next_request(module, req);
     551         573 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     552           0 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     553             :         } else {
     554         573 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     555         573 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     556         573 :                 ret = ops->rename(module, req);
     557             :         }
     558      162158 :         if (ret == LDB_SUCCESS) {
     559      162156 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     560             :         }
     561             : 
     562      162158 :         talloc_free(tmp_ctx);
     563      162158 :         return ret;
     564             : }
     565             : 
     566             : /*
     567             :   a ldb_add request operating on modules below the
     568             :   current module
     569             :  */
     570        1421 : int dsdb_module_add(struct ldb_module *module,
     571             :                     const struct ldb_message *message,
     572             :                     uint32_t dsdb_flags,
     573             :                     struct ldb_request *parent)
     574             : {
     575         152 :         struct ldb_request *req;
     576         152 :         int ret;
     577        1421 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     578        1421 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     579         152 :         struct ldb_result *res;
     580             : 
     581        1421 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     582        1421 :         if (!res) {
     583           0 :                 talloc_free(tmp_ctx);
     584           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     585             :         }
     586             : 
     587        1421 :         ret = ldb_build_add_req(&req, ldb, tmp_ctx,
     588             :                                 message,
     589             :                                 NULL,
     590             :                                 res,
     591             :                                 ldb_modify_default_callback,
     592             :                                 parent);
     593        1421 :         LDB_REQ_SET_LOCATION(req);
     594        1421 :         if (ret != LDB_SUCCESS) {
     595           0 :                 talloc_free(tmp_ctx);
     596           0 :                 return ret;
     597             :         }
     598             : 
     599        1421 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     600        1421 :         if (ret != LDB_SUCCESS) {
     601           0 :                 talloc_free(tmp_ctx);
     602           0 :                 return ret;
     603             :         }
     604             : 
     605        1421 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     606           0 :                 ldb_req_mark_trusted(req);
     607             :         }
     608             : 
     609             :         /* Run the new request */
     610        1421 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     611        1347 :                 ret = ldb_next_request(module, req);
     612          74 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     613          74 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     614             :         } else {
     615           0 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     616           0 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     617           0 :                 ret = ops->add(module, req);
     618             :         }
     619        1421 :         if (ret == LDB_SUCCESS) {
     620        1421 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     621             :         }
     622             : 
     623        1421 :         talloc_free(tmp_ctx);
     624        1421 :         return ret;
     625             : }
     626             : 
     627             : /*
     628             :   a ldb_delete request operating on modules below the
     629             :   current module
     630             :  */
     631       29333 : int dsdb_module_del(struct ldb_module *module,
     632             :                     struct ldb_dn *dn,
     633             :                     uint32_t dsdb_flags,
     634             :                     struct ldb_request *parent)
     635             : {
     636           3 :         struct ldb_request *req;
     637           3 :         int ret;
     638       29333 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     639       29333 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     640           3 :         struct ldb_result *res;
     641             : 
     642       29333 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     643       29333 :         if (!res) {
     644           0 :                 talloc_free(tmp_ctx);
     645           0 :                 return ldb_oom(ldb);
     646             :         }
     647             : 
     648       29333 :         ret = ldb_build_del_req(&req, ldb, tmp_ctx,
     649             :                                 dn,
     650             :                                 NULL,
     651             :                                 res,
     652             :                                 ldb_modify_default_callback,
     653             :                                 parent);
     654       29333 :         LDB_REQ_SET_LOCATION(req);
     655       29333 :         if (ret != LDB_SUCCESS) {
     656           0 :                 talloc_free(tmp_ctx);
     657           0 :                 return ret;
     658             :         }
     659             : 
     660       29333 :         ret = dsdb_request_add_controls(req, dsdb_flags);
     661       29333 :         if (ret != LDB_SUCCESS) {
     662           0 :                 talloc_free(tmp_ctx);
     663           0 :                 return ret;
     664             :         }
     665             : 
     666       29333 :         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
     667       29333 :                 ldb_req_mark_trusted(req);
     668             :         }
     669             : 
     670             :         /* Run the new request */
     671       29333 :         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
     672           0 :                 ret = ldb_next_request(module, req);
     673       29333 :         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
     674       29333 :                 ret = ldb_request(ldb_module_get_ctx(module), req);
     675             :         } else {
     676           0 :                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
     677           0 :                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
     678           0 :                 ret = ops->del(module, req);
     679             :         }
     680       29333 :         if (ret == LDB_SUCCESS) {
     681       29333 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     682             :         }
     683             : 
     684       29333 :         talloc_free(tmp_ctx);
     685       29333 :         return ret;
     686             : }
     687             : 
     688             : /*
     689             :   check if a single valued link has multiple non-deleted values
     690             : 
     691             :   This is needed when we will be using the RELAX control to stop
     692             :   ldb_tdb from checking single valued links
     693             :  */
     694       81182 : int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
     695             :                                   const struct ldb_message_element *el)
     696             : {
     697       81182 :         bool found_active = false;
     698        1095 :         unsigned int i;
     699             : 
     700       81182 :         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
     701       12307 :             el->num_values < 2) {
     702       79959 :                 return LDB_SUCCESS;
     703             :         }
     704             : 
     705         382 :         for (i=0; i<el->num_values; i++) {
     706         257 :                 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
     707         121 :                         if (found_active) {
     708           3 :                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     709             :                         }
     710         118 :                         found_active = true;
     711             :                 }
     712             :         }
     713             : 
     714         125 :         return LDB_SUCCESS;
     715             : }
     716             : 
     717             : 
     718      360450 : int dsdb_check_samba_compatible_feature(struct ldb_module *module,
     719             :                                         const char *feature,
     720             :                                         bool *found)
     721             : {
     722      360450 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     723       11948 :         struct ldb_result *res;
     724       11948 :         static const char * const samba_dsdb_attrs[] = {
     725             :                 SAMBA_COMPATIBLE_FEATURES_ATTR,
     726             :                 NULL
     727             :         };
     728       11948 :         int ret;
     729      360450 :         struct ldb_dn *samba_dsdb_dn = NULL;
     730      360450 :         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
     731      360450 :         if (tmp_ctx == NULL) {
     732           0 :                 *found = false;
     733           0 :                 return ldb_oom(ldb);
     734             :         }
     735      360450 :         *found = false;
     736             : 
     737      360450 :         samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
     738      360450 :         if (samba_dsdb_dn == NULL) {
     739           0 :                 TALLOC_FREE(tmp_ctx);
     740           0 :                 return ldb_oom(ldb);
     741             :         }
     742             : 
     743      360450 :         ret = dsdb_module_search_dn(module,
     744             :                                     tmp_ctx,
     745             :                                     &res,
     746             :                                     samba_dsdb_dn,
     747             :                                     samba_dsdb_attrs,
     748             :                                     DSDB_FLAG_NEXT_MODULE,
     749             :                                     NULL);
     750      360450 :         if (ret == LDB_SUCCESS) {
     751      360450 :                 *found = ldb_msg_check_string_attribute(
     752      360450 :                         res->msgs[0],
     753             :                         SAMBA_COMPATIBLE_FEATURES_ATTR,
     754             :                         feature);
     755           0 :         } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     756             :                 /* it is not an error not to find it */
     757           0 :                 ret = LDB_SUCCESS;
     758             :         }
     759      360450 :         TALLOC_FREE(tmp_ctx);
     760      360450 :         return ret;
     761             : }
     762             : 
     763             : 
     764             : /*
     765             :   check if an optional feature is enabled on our own NTDS DN
     766             : 
     767             :   Note that features can be marked as enabled in more than one
     768             :   place. For example, the recyclebin feature is marked as enabled both
     769             :   on the CN=Partitions,CN=Configuration object and on the NTDS DN of
     770             :   each DC in the forest. It seems likely that it is the job of the KCC
     771             :   to propagate between the two
     772             :  */
     773      118518 : int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
     774             : {
     775        2172 :         TALLOC_CTX *tmp_ctx;
     776      118518 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     777        2172 :         struct ldb_result *res;
     778        2172 :         struct ldb_dn *search_dn;
     779        2172 :         struct GUID search_guid;
     780        2172 :         static const char * const attrs[] = {"msDS-EnabledFeature", NULL};
     781        2172 :         int ret;
     782        2172 :         unsigned int i;
     783        2172 :         struct ldb_message_element *el;
     784        2172 :         struct ldb_dn *feature_dn;
     785             : 
     786      118518 :         tmp_ctx = talloc_new(ldb);
     787             : 
     788      118518 :         feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
     789      118518 :         if (feature_dn == NULL) {
     790           0 :                 talloc_free(tmp_ctx);
     791           0 :                 return ldb_operr(ldb_module_get_ctx(module));
     792             :         }
     793             : 
     794      118518 :         *feature_enabled = false;
     795             : 
     796      118518 :         ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
     797      118518 :         if (ret != LDB_SUCCESS) {
     798        1726 :                 ldb_asprintf_errstring(ldb,
     799             :                                 "Could not find the feature object - dn: %s\n",
     800             :                                 ldb_dn_get_linearized(feature_dn));
     801        1726 :                 talloc_free(tmp_ctx);
     802        1726 :                 return LDB_ERR_NO_SUCH_OBJECT;
     803             :         }
     804      116792 :         if (res->msgs[0]->num_elements > 0) {
     805           0 :                 static const char * const attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
     806             : 
     807           0 :                 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
     808             : 
     809           0 :                 for (i=0; i<el->num_values; i++) {
     810           0 :                         search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
     811             : 
     812           0 :                         ret = dsdb_module_search_dn(module, tmp_ctx, &res,
     813             :                                                     search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
     814           0 :                         if (ret != LDB_SUCCESS) {
     815           0 :                                 ldb_asprintf_errstring(ldb,
     816             :                                                 "Could no find object dn: %s\n",
     817             :                                                 ldb_dn_get_linearized(search_dn));
     818           0 :                                 talloc_free(tmp_ctx);
     819           0 :                                 return LDB_ERR_OPERATIONS_ERROR;
     820             :                         }
     821             : 
     822           0 :                         search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
     823             : 
     824           0 :                         if (GUID_equal(&search_guid, &op_feature_guid)) {
     825           0 :                                 *feature_enabled = true;
     826           0 :                                 break;
     827             :                         }
     828             :                 }
     829             :         }
     830      116792 :         talloc_free(tmp_ctx);
     831      116792 :         return LDB_SUCCESS;
     832             : }
     833             : 
     834             : /*
     835             :   find the NTDS GUID from a computers DN record
     836             :  */
     837         397 : int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
     838             :                                            TALLOC_CTX *mem_ctx,
     839             :                                            struct ldb_dn *computer_dn,
     840             :                                            struct GUID *ntds_guid,
     841             :                                            struct ldb_request *parent)
     842             : {
     843           0 :         int ret;
     844           0 :         struct ldb_dn *dn;
     845             : 
     846         397 :         *ntds_guid = GUID_zero();
     847             : 
     848         397 :         ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
     849             :                                        "serverReferenceBL", &dn, parent);
     850         397 :         if (ret != LDB_SUCCESS) {
     851           0 :                 return ret;
     852             :         }
     853             : 
     854         397 :         if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
     855           0 :                 talloc_free(dn);
     856           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     857             :         }
     858             : 
     859         397 :         ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
     860         397 :         talloc_free(dn);
     861         397 :         return ret;
     862             : }
     863             : 
     864             : /*
     865             :   find a 'reference' DN that points at another object
     866             :   (eg. serverReference, rIDManagerReference etc)
     867             :  */
     868        1344 : int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
     869             :                              const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
     870             : {
     871           0 :         const char *attrs[2];
     872           0 :         struct ldb_result *res;
     873           0 :         int ret;
     874             : 
     875        1344 :         attrs[0] = attribute;
     876        1344 :         attrs[1] = NULL;
     877             : 
     878        1344 :         ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
     879             :                                     DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
     880        1344 :         if (ret != LDB_SUCCESS) {
     881           0 :                 return ret;
     882             :         }
     883             : 
     884        1344 :         *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
     885        1344 :                                       mem_ctx, res->msgs[0], attribute);
     886        1344 :         if (!*dn) {
     887          34 :                 ldb_reset_err_string(ldb_module_get_ctx(module));
     888          34 :                 talloc_free(res);
     889          34 :                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
     890             :         }
     891             : 
     892        1310 :         talloc_free(res);
     893        1310 :         return LDB_SUCCESS;
     894             : }
     895             : 
     896             : /*
     897             :   find the RID Manager$ DN via the rIDManagerReference attribute in the
     898             :   base DN
     899             :  */
     900         412 : int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
     901             :                                struct ldb_request *parent)
     902             : {
     903         412 :         return dsdb_module_reference_dn(module, mem_ctx,
     904             :                                         ldb_get_default_basedn(ldb_module_get_ctx(module)),
     905             :                                         "rIDManagerReference", dn, parent);
     906             : }
     907             : 
     908             : /*
     909             :   used to chain to the callers callback
     910             :  */
     911   157852803 : int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
     912             : {
     913   157852803 :         struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
     914             : 
     915   157852803 :         if (!ares) {
     916           0 :                 return ldb_module_done(up_req, NULL, NULL,
     917             :                                        LDB_ERR_OPERATIONS_ERROR);
     918             :         }
     919             : 
     920   157852803 :         if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
     921    55301447 :                 return ldb_module_done(up_req, ares->controls,
     922             :                                        ares->response, ares->error);
     923             :         }
     924             : 
     925             :         /* Otherwise pass on the callback */
     926   102551356 :         switch (ares->type) {
     927    98381334 :         case LDB_REPLY_ENTRY:
     928    98381334 :                 return ldb_module_send_entry(up_req, ares->message,
     929             :                                              ares->controls);
     930             : 
     931     4170022 :         case LDB_REPLY_REFERRAL:
     932     4170022 :                 return ldb_module_send_referral(up_req,
     933             :                                                 ares->referral);
     934           0 :         default:
     935             :                 /* Can't happen */
     936           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     937             :         }
     938             : }
     939             : 
     940             : /*
     941             :   load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
     942             :   object for a partition
     943             :  */
     944           0 : int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
     945             :                                    uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
     946             : {
     947           0 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     948           0 :         struct ldb_request *req;
     949           0 :         int ret;
     950           0 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     951           0 :         struct dsdb_control_current_partition *p_ctrl;
     952           0 :         struct ldb_result *res;
     953             : 
     954           0 :         res = talloc_zero(tmp_ctx, struct ldb_result);
     955           0 :         if (!res) {
     956           0 :                 talloc_free(tmp_ctx);
     957           0 :                 return ldb_module_oom(module);
     958             :         }
     959             : 
     960           0 :         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
     961             :                                    ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
     962             :                                    LDB_SCOPE_BASE,
     963             :                                    NULL, NULL,
     964             :                                    NULL,
     965             :                                    res, ldb_search_default_callback,
     966             :                                    parent);
     967           0 :         LDB_REQ_SET_LOCATION(req);
     968           0 :         if (ret != LDB_SUCCESS) {
     969           0 :                 talloc_free(tmp_ctx);
     970           0 :                 return ret;
     971             :         }
     972             : 
     973           0 :         p_ctrl = talloc(req, struct dsdb_control_current_partition);
     974           0 :         if (p_ctrl == NULL) {
     975           0 :                 talloc_free(tmp_ctx);
     976           0 :                 return ldb_module_oom(module);
     977             :         }
     978           0 :         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
     979           0 :         p_ctrl->dn = dn;
     980             : 
     981             : 
     982           0 :         ret = ldb_request_add_control(req,
     983             :                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
     984             :                                       false, p_ctrl);
     985           0 :         if (ret != LDB_SUCCESS) {
     986           0 :                 talloc_free(tmp_ctx);
     987           0 :                 return ret;
     988             :         }
     989             : 
     990             :         /* Run the new request */
     991           0 :         ret = ldb_next_request(module, req);
     992             : 
     993           0 :         if (ret == LDB_SUCCESS) {
     994           0 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     995             :         }
     996             : 
     997           0 :         if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
     998             :                 /* it hasn't been created yet, which means
     999             :                    an implicit value of zero */
    1000           0 :                 *uSN = 0;
    1001           0 :                 talloc_free(tmp_ctx);
    1002           0 :                 ldb_reset_err_string(ldb);
    1003           0 :                 return LDB_SUCCESS;
    1004             :         }
    1005             : 
    1006           0 :         if (ret != LDB_SUCCESS) {
    1007           0 :                 talloc_free(tmp_ctx);
    1008           0 :                 return ret;
    1009             :         }
    1010             : 
    1011           0 :         if (res->count != 1) {
    1012           0 :                 *uSN = 0;
    1013           0 :                 if (urgent_uSN) {
    1014           0 :                         *urgent_uSN = 0;
    1015             :                 }
    1016             :         } else {
    1017           0 :                 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
    1018           0 :                 if (urgent_uSN) {
    1019           0 :                         *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
    1020             :                 }
    1021             :         }
    1022             : 
    1023           0 :         talloc_free(tmp_ctx);
    1024             : 
    1025           0 :         return LDB_SUCCESS;
    1026             : }
    1027             : 
    1028             : /*
    1029             :   save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
    1030             :   partition
    1031             :  */
    1032      225821 : int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
    1033             :                                    uint64_t uSN, uint64_t urgent_uSN,
    1034             :                                    struct ldb_request *parent)
    1035             : {
    1036      225821 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1037        1084 :         struct ldb_request *req;
    1038        1084 :         struct ldb_message *msg;
    1039        1084 :         struct dsdb_control_current_partition *p_ctrl;
    1040        1084 :         int ret;
    1041        1084 :         struct ldb_result *res;
    1042             : 
    1043      225821 :         msg = ldb_msg_new(module);
    1044      225821 :         if (msg == NULL) {
    1045           0 :                 return ldb_module_oom(module);
    1046             :         }
    1047             : 
    1048      225821 :         msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
    1049      225821 :         if (msg->dn == NULL) {
    1050           0 :                 talloc_free(msg);
    1051           0 :                 return ldb_operr(ldb_module_get_ctx(module));
    1052             :         }
    1053             : 
    1054      225821 :         res = talloc_zero(msg, struct ldb_result);
    1055      225821 :         if (!res) {
    1056           0 :                 talloc_free(msg);
    1057           0 :                 return ldb_module_oom(module);
    1058             :         }
    1059             : 
    1060      225821 :         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
    1061      225821 :         if (ret != LDB_SUCCESS) {
    1062           0 :                 talloc_free(msg);
    1063           0 :                 return ret;
    1064             :         }
    1065      225821 :         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
    1066             : 
    1067             :         /* urgent_uSN is optional so may not be stored */
    1068      225821 :         if (urgent_uSN) {
    1069       33454 :                 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
    1070             :                                            urgent_uSN);
    1071       33454 :                 if (ret != LDB_SUCCESS) {
    1072           0 :                         talloc_free(msg);
    1073           0 :                         return ret;
    1074             :                 }
    1075       33454 :                 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
    1076             :         }
    1077             : 
    1078             : 
    1079      225821 :         p_ctrl = talloc(msg, struct dsdb_control_current_partition);
    1080      225821 :         if (p_ctrl == NULL) {
    1081           0 :                 talloc_free(msg);
    1082           0 :                 return ldb_oom(ldb);
    1083             :         }
    1084      225821 :         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
    1085      225821 :         p_ctrl->dn = dn;
    1086      225821 :         ret = ldb_build_mod_req(&req, ldb, msg,
    1087             :                                 msg,
    1088             :                                 NULL,
    1089             :                                 res,
    1090             :                                 ldb_modify_default_callback,
    1091             :                                 parent);
    1092      225821 :         LDB_REQ_SET_LOCATION(req);
    1093      226800 : again:
    1094      226800 :         if (ret != LDB_SUCCESS) {
    1095           0 :                 talloc_free(msg);
    1096           0 :                 return ret;
    1097             :         }
    1098             : 
    1099      226800 :         ret = ldb_request_add_control(req,
    1100             :                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
    1101             :                                       false, p_ctrl);
    1102      226800 :         if (ret != LDB_SUCCESS) {
    1103           0 :                 talloc_free(msg);
    1104           0 :                 return ret;
    1105             :         }
    1106             : 
    1107             :         /* Run the new request */
    1108      226800 :         ret = ldb_next_request(module, req);
    1109             : 
    1110      226800 :         if (ret == LDB_SUCCESS) {
    1111      226800 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    1112             :         }
    1113      226800 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
    1114         979 :                 ret = ldb_build_add_req(&req, ldb, msg,
    1115             :                                         msg,
    1116             :                                         NULL,
    1117             :                                         res,
    1118             :                                         ldb_modify_default_callback,
    1119             :                                         parent);
    1120         979 :                 LDB_REQ_SET_LOCATION(req);
    1121         979 :                 goto again;
    1122             :         }
    1123             : 
    1124      225821 :         talloc_free(msg);
    1125             : 
    1126      225821 :         return ret;
    1127             : }
    1128             : 
    1129    52451732 : bool dsdb_module_am_system(struct ldb_module *module)
    1130             : {
    1131    52451732 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1132     3068171 :         struct auth_session_info *session_info
    1133    52451732 :                 = talloc_get_type(
    1134             :                         ldb_get_opaque(ldb, DSDB_SESSION_INFO),
    1135             :                         struct auth_session_info);
    1136    52451732 :         return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
    1137             : }
    1138             : 
    1139    32447146 : bool dsdb_module_am_administrator(struct ldb_module *module)
    1140             : {
    1141    32447146 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1142     1750631 :         struct auth_session_info *session_info
    1143    32447146 :                 = talloc_get_type(
    1144             :                         ldb_get_opaque(ldb, DSDB_SESSION_INFO),
    1145             :                         struct auth_session_info);
    1146    32447146 :         return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
    1147             : }
    1148             : 
    1149             : /*
    1150             :   check if the recyclebin is enabled
    1151             :  */
    1152      118518 : int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
    1153             : {
    1154      118518 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1155        2172 :         struct GUID recyclebin_guid;
    1156        2172 :         int ret;
    1157             : 
    1158      118518 :         GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
    1159             : 
    1160      118518 :         ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
    1161      118518 :         if (ret != LDB_SUCCESS) {
    1162        1726 :                 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
    1163        1726 :                 return ret;
    1164             :         }
    1165             : 
    1166      114642 :         return LDB_SUCCESS;
    1167             : }
    1168             : 
    1169       69163 : int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
    1170             :                                        struct ldb_message *msg,
    1171             :                                        const char *attr,
    1172             :                                        const int32_t *old_val,
    1173             :                                        const int32_t *new_val)
    1174             : {
    1175         345 :         struct ldb_message_element *el;
    1176         345 :         int ret;
    1177         345 :         char *vstring;
    1178             : 
    1179       69163 :         if (old_val) {
    1180       34558 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
    1181       34558 :                 if (ret != LDB_SUCCESS) {
    1182           0 :                         return ret;
    1183             :                 }
    1184       34558 :                 el->num_values = 1;
    1185       34558 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1186       34558 :                 if (!el->values) {
    1187           0 :                         return ldb_module_oom(module);
    1188             :                 }
    1189       34558 :                 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
    1190       34558 :                 if (!vstring) {
    1191           0 :                         return ldb_module_oom(module);
    1192             :                 }
    1193       34558 :                 *el->values = data_blob_string_const(vstring);
    1194             :         }
    1195             : 
    1196       69163 :         if (new_val) {
    1197       34712 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
    1198       34712 :                 if (ret != LDB_SUCCESS) {
    1199           0 :                         return ret;
    1200             :                 }
    1201       34712 :                 el->num_values = 1;
    1202       34712 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1203       34712 :                 if (!el->values) {
    1204           0 :                         return ldb_module_oom(module);
    1205             :                 }
    1206       34712 :                 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
    1207       34712 :                 if (!vstring) {
    1208           0 :                         return ldb_module_oom(module);
    1209             :                 }
    1210       34712 :                 *el->values = data_blob_string_const(vstring);
    1211             :         }
    1212             : 
    1213       68818 :         return LDB_SUCCESS;
    1214             : }
    1215             : 
    1216       69162 : int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
    1217             :                                         struct ldb_message *msg,
    1218             :                                         const char *attr,
    1219             :                                         const uint32_t *old_val,
    1220             :                                         const uint32_t *new_val)
    1221             : {
    1222       69162 :         return dsdb_msg_constrainted_update_int32(module, msg, attr,
    1223             :                                                   (const int32_t *)old_val,
    1224             :                                                   (const int32_t *)new_val);
    1225             : }
    1226             : 
    1227       69306 : int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
    1228             :                                        struct ldb_message *msg,
    1229             :                                        const char *attr,
    1230             :                                        const int64_t *old_val,
    1231             :                                        const int64_t *new_val)
    1232             : {
    1233         344 :         struct ldb_message_element *el;
    1234         344 :         int ret;
    1235         344 :         char *vstring;
    1236             : 
    1237       69306 :         if (old_val) {
    1238         276 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
    1239         276 :                 if (ret != LDB_SUCCESS) {
    1240           0 :                         return ret;
    1241             :                 }
    1242         276 :                 el->num_values = 1;
    1243         276 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1244         276 :                 if (!el->values) {
    1245           0 :                         return ldb_module_oom(module);
    1246             :                 }
    1247         276 :                 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
    1248         276 :                 if (!vstring) {
    1249           0 :                         return ldb_module_oom(module);
    1250             :                 }
    1251         276 :                 *el->values = data_blob_string_const(vstring);
    1252             :         }
    1253             : 
    1254       69306 :         if (new_val) {
    1255         429 :                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
    1256         429 :                 if (ret != LDB_SUCCESS) {
    1257           0 :                         return ret;
    1258             :                 }
    1259         429 :                 el->num_values = 1;
    1260         429 :                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
    1261         429 :                 if (!el->values) {
    1262           0 :                         return ldb_module_oom(module);
    1263             :                 }
    1264         429 :                 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
    1265         429 :                 if (!vstring) {
    1266           0 :                         return ldb_module_oom(module);
    1267             :                 }
    1268         429 :                 *el->values = data_blob_string_const(vstring);
    1269             :         }
    1270             : 
    1271       68962 :         return LDB_SUCCESS;
    1272             : }
    1273             : 
    1274       69162 : int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
    1275             :                                         struct ldb_message *msg,
    1276             :                                         const char *attr,
    1277             :                                         const uint64_t *old_val,
    1278             :                                         const uint64_t *new_val)
    1279             : {
    1280       69162 :         return dsdb_msg_constrainted_update_int64(module, msg, attr,
    1281             :                                                   (const int64_t *)old_val,
    1282             :                                                   (const int64_t *)new_val);
    1283             : }
    1284             : 
    1285             : /*
    1286             :   update an int32 attribute safely via a constrained delete/add
    1287             :  */
    1288           1 : int dsdb_module_constrainted_update_int32(struct ldb_module *module,
    1289             :                                           struct ldb_dn *dn,
    1290             :                                           const char *attr,
    1291             :                                           const int32_t *old_val,
    1292             :                                           const int32_t *new_val,
    1293             :                                           struct ldb_request *parent)
    1294             : {
    1295           1 :         struct ldb_message *msg;
    1296           1 :         int ret;
    1297             : 
    1298           1 :         msg = ldb_msg_new(module);
    1299           1 :         if (msg == NULL) {
    1300           0 :                 return ldb_module_oom(module);
    1301             :         }
    1302           1 :         msg->dn = dn;
    1303             : 
    1304           1 :         ret = dsdb_msg_constrainted_update_int32(module,
    1305             :                                                  msg, attr,
    1306             :                                                  old_val,
    1307             :                                                  new_val);
    1308           1 :         if (ret != LDB_SUCCESS) {
    1309           0 :                 talloc_free(msg);
    1310           0 :                 return ret;
    1311             :         }
    1312             : 
    1313           1 :         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
    1314           1 :         talloc_free(msg);
    1315           1 :         return ret;
    1316             : }
    1317             : 
    1318           1 : int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
    1319             :                                            struct ldb_dn *dn,
    1320             :                                            const char *attr,
    1321             :                                            const uint32_t *old_val,
    1322             :                                            const uint32_t *new_val,
    1323             :                                            struct ldb_request *parent)
    1324             : {
    1325           1 :         return dsdb_module_constrainted_update_int32(module, dn, attr,
    1326             :                                                      (const int32_t *)old_val,
    1327             :                                                      (const int32_t *)new_val, parent);
    1328             : }
    1329             : 
    1330             : /*
    1331             :   update an int64 attribute safely via a constrained delete/add
    1332             :  */
    1333         144 : int dsdb_module_constrainted_update_int64(struct ldb_module *module,
    1334             :                                           struct ldb_dn *dn,
    1335             :                                           const char *attr,
    1336             :                                           const int64_t *old_val,
    1337             :                                           const int64_t *new_val,
    1338             :                                           struct ldb_request *parent)
    1339             : {
    1340           0 :         struct ldb_message *msg;
    1341           0 :         int ret;
    1342             : 
    1343         144 :         msg = ldb_msg_new(module);
    1344         144 :         if (msg == NULL) {
    1345           0 :                 return ldb_module_oom(module);
    1346             :         }
    1347         144 :         msg->dn = dn;
    1348             : 
    1349         144 :         ret = dsdb_msg_constrainted_update_int64(module,
    1350             :                                                  msg, attr,
    1351             :                                                  old_val,
    1352             :                                                  new_val);
    1353         144 :         if (ret != LDB_SUCCESS) {
    1354           0 :                 talloc_free(msg);
    1355           0 :                 return ret;
    1356             :         }
    1357             : 
    1358         144 :         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
    1359         144 :         talloc_free(msg);
    1360         144 :         return ret;
    1361             : }
    1362             : 
    1363         144 : int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
    1364             :                                            struct ldb_dn *dn,
    1365             :                                            const char *attr,
    1366             :                                            const uint64_t *old_val,
    1367             :                                            const uint64_t *new_val,
    1368             :                                            struct ldb_request *parent)
    1369             : {
    1370         144 :         return dsdb_module_constrainted_update_int64(module, dn, attr,
    1371             :                                                      (const int64_t *)old_val,
    1372             :                                                      (const int64_t *)new_val,
    1373             :                                                      parent);
    1374             : }
    1375             : 
    1376             : 
    1377     2223764 : const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
    1378             :                                                     TALLOC_CTX *mem_ctx, struct ldb_request *parent)
    1379             : {
    1380      209991 :         int ret;
    1381      209991 :         struct ldb_dn *new_dn;
    1382     2223764 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
    1383      209991 :         static const char * const attrs[] = { "dSHeuristics", NULL };
    1384      209991 :         struct ldb_result *res;
    1385             : 
    1386     2223764 :         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
    1387     2223764 :         if (!ldb_dn_add_child_fmt(new_dn,
    1388             :                                    "CN=Directory Service,CN=Windows NT,CN=Services")) {
    1389           0 :                 talloc_free(new_dn);
    1390           0 :                 return NULL;
    1391             :         }
    1392     2223764 :         ret = dsdb_module_search_dn(module, mem_ctx, &res,
    1393             :                                     new_dn,
    1394             :                                     attrs,
    1395             :                                     DSDB_FLAG_NEXT_MODULE,
    1396             :                                     parent);
    1397     2223764 :         if (ret == LDB_SUCCESS && res->count == 1) {
    1398     1731113 :                 talloc_free(new_dn);
    1399     1731113 :                 return ldb_msg_find_ldb_val(res->msgs[0],
    1400             :                                             "dSHeuristics");
    1401             :         }
    1402      492651 :         talloc_free(new_dn);
    1403      492651 :         return NULL;
    1404             : }
    1405             : 
    1406      180872 : bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
    1407             : {
    1408      180872 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
    1409        6006 :         bool result;
    1410      180872 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1411             :                                                                      tmp_ctx, parent);
    1412      180872 :         if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
    1413      141826 :                 result = true;
    1414       33040 :         } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
    1415          17 :                 result = false;
    1416             :         } else {
    1417       33023 :                 result = true;
    1418             :         }
    1419             : 
    1420      180872 :         talloc_free(tmp_ctx);
    1421      180872 :         return result;
    1422             : }
    1423             : 
    1424     1488174 : bool dsdb_user_password_support(struct ldb_module *module,
    1425             :                                 TALLOC_CTX *mem_ctx,
    1426             :                                 struct ldb_request *parent)
    1427             : {
    1428     1488174 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1429      120461 :         bool result;
    1430     1488174 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1431             :                                                                      tmp_ctx,
    1432             :                                                                      parent);
    1433     1488174 :         if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
    1434     1233661 :                 result = false;
    1435      134052 :         } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
    1436      134016 :                    (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
    1437      108149 :                 result = false;
    1438             :         } else {
    1439       25903 :                 result = true;
    1440             :         }
    1441             : 
    1442     1488174 :         talloc_free(tmp_ctx);
    1443     1488174 :         return result;
    1444             : }
    1445             : 
    1446       16280 : bool dsdb_do_list_object(struct ldb_module *module,
    1447             :                          TALLOC_CTX *mem_ctx,
    1448             :                          struct ldb_request *parent)
    1449             : {
    1450       16280 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1451           0 :         bool result;
    1452       16280 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1453             :                                                                      tmp_ctx,
    1454             :                                                                      parent);
    1455       16280 :         if (hr_val == NULL || hr_val->length < DS_HR_DOLISTOBJECT) {
    1456          26 :                 result = false;
    1457       16254 :         } else if (hr_val->data[DS_HR_DOLISTOBJECT -1] == '1') {
    1458        8064 :                 result = true;
    1459             :         } else {
    1460        8190 :                 result = false;
    1461             :         }
    1462             : 
    1463       16280 :         talloc_free(tmp_ctx);
    1464       16280 :         return result;
    1465             : }
    1466             : 
    1467      538132 : bool dsdb_attribute_authz_on_ldap_add(struct ldb_module *module,
    1468             :                                       TALLOC_CTX *mem_ctx,
    1469             :                                       struct ldb_request *parent)
    1470             : {
    1471      538132 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1472      538132 :         bool result = false;
    1473      538132 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1474             :                                                                      tmp_ctx,
    1475             :                                                                      parent);
    1476      538132 :         if (hr_val != NULL && hr_val->length >= DS_HR_ATTR_AUTHZ_ON_LDAP_ADD) {
    1477       15750 :                 uint8_t val = hr_val->data[DS_HR_ATTR_AUTHZ_ON_LDAP_ADD - 1];
    1478       15750 :                 if (val != '0' && val != '2') {
    1479       15732 :                         result = true;
    1480             :                 }
    1481             :         }
    1482             : 
    1483      538132 :         talloc_free(tmp_ctx);
    1484      538132 :         return result;
    1485             : }
    1486             : 
    1487         306 : bool dsdb_block_owner_implicit_rights(struct ldb_module *module,
    1488             :                                       TALLOC_CTX *mem_ctx,
    1489             :                                       struct ldb_request *parent)
    1490             : {
    1491         306 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    1492         306 :         bool result = false;
    1493         306 :         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
    1494             :                                                                      tmp_ctx,
    1495             :                                                                      parent);
    1496         306 :         if (hr_val != NULL && hr_val->length >= DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS) {
    1497         306 :                 uint8_t val = hr_val->data[DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS - 1];
    1498         306 :                 if (val != '0' && val != '2') {
    1499         270 :                         result = true;
    1500             :                 }
    1501             :         }
    1502             : 
    1503         306 :         talloc_free(tmp_ctx);
    1504         306 :         return result;
    1505             : }
    1506             : 
    1507             : /*
    1508             :   show the chain of requests, useful for debugging async requests
    1509             :  */
    1510           0 : void dsdb_req_chain_debug(struct ldb_request *req, int level)
    1511             : {
    1512           0 :         char *s = ldb_module_call_chain(req, req);
    1513           0 :         DEBUG(level, ("%s\n", s));
    1514           0 :         talloc_free(s);
    1515           0 : }
    1516             : 
    1517             : /*
    1518             :  * Get all the values that *might* be added by an ldb message, as a composite
    1519             :  * ldb element.
    1520             :  *
    1521             :  * This is useful when we need to check all the possible values against some
    1522             :  * criteria.
    1523             :  *
    1524             :  * In cases where a modify message mixes multiple ADDs, DELETEs, and REPLACES,
    1525             :  * the returned element might contain more values than would actually end up
    1526             :  * in the database if the message was run to its conclusion.
    1527             :  *
    1528             :  * If the operation is not LDB_ADD or LDB_MODIFY, an operations error is
    1529             :  * returned.
    1530             :  *
    1531             :  * The returned element might not be new, and should not be modified or freed
    1532             :  * before the message is finished.
    1533             :  */
    1534             : 
    1535      402639 : int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
    1536             :                                  const struct ldb_message *msg,
    1537             :                                  const char *attr_name,
    1538             :                                  struct ldb_message_element **el,
    1539             :                                  enum ldb_request_type operation)
    1540             : {
    1541       43717 :         unsigned int i;
    1542      402639 :         unsigned int el_count = 0;
    1543      402639 :         unsigned int val_count = 0;
    1544      402639 :         struct ldb_val *v = NULL;
    1545      402639 :         struct ldb_message_element *_el = NULL;
    1546      402639 :         *el = NULL;
    1547             : 
    1548      402639 :         if (operation != LDB_ADD && operation != LDB_MODIFY) {
    1549           0 :                 DBG_ERR("inapplicable operation type: %d\n", operation);
    1550           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1551             :         }
    1552             : 
    1553             :         /* count the adding or replacing elements */
    1554     7283910 :         for (i = 0; i < msg->num_elements; i++) {
    1555     6881271 :                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
    1556       42608 :                         unsigned int tmp;
    1557      386490 :                         if ((operation == LDB_MODIFY) &&
    1558       37275 :                             (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
    1559             :                                                 == LDB_FLAG_MOD_DELETE)) {
    1560       14306 :                                 continue;
    1561             :                         }
    1562      372184 :                         el_count++;
    1563      372184 :                         tmp = val_count + msg->elements[i].num_values;
    1564      372184 :                         if (unlikely(tmp < val_count)) {
    1565           0 :                                 DBG_ERR("too many values for one element!\n");
    1566           0 :                                 return LDB_ERR_OPERATIONS_ERROR;
    1567             :                         }
    1568      329612 :                         val_count = tmp;
    1569             :                 }
    1570             :         }
    1571      402639 :         if (el_count == 0) {
    1572             :                 /* nothing to see here */
    1573       29319 :                 return LDB_SUCCESS;
    1574             :         }
    1575             : 
    1576      372175 :         if (el_count == 1 || val_count == 0) {
    1577             :                 /*
    1578             :                  * There is one effective element, which we can return as-is,
    1579             :                  * OR there are only elements with zero values -- any of which
    1580             :                  * will do.
    1581             :                  */
    1582     2411465 :                 for (i = 0; i < msg->num_elements; i++) {
    1583     2411465 :                         if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
    1584      386448 :                                 if ((operation == LDB_MODIFY) &&
    1585       37233 :                                     (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
    1586             :                                      == LDB_FLAG_MOD_DELETE)) {
    1587       14282 :                                         continue;
    1588             :                                 }
    1589      372166 :                                 *el = &msg->elements[i];
    1590      372166 :                                 return LDB_SUCCESS;
    1591             :                         }
    1592             :                 }
    1593             :         }
    1594             : 
    1595           9 :         _el = talloc_zero(mem_ctx, struct ldb_message_element);
    1596           9 :         if (_el == NULL) {
    1597           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1598             :         }
    1599           9 :         _el->name = attr_name;
    1600             : 
    1601           9 :         if (val_count == 0) {
    1602             :                 /*
    1603             :                  * Seems unlikely, but sometimes we might be adding zero
    1604             :                  * values in multiple separate elements. The talloc zero has
    1605             :                  * already set the expected values = NULL, num_values = 0.
    1606             :                  */
    1607           0 :                 *el = _el;
    1608           0 :                 return LDB_SUCCESS;
    1609             :         }
    1610             : 
    1611           9 :         _el->values = talloc_array(_el, struct ldb_val, val_count);
    1612           9 :         if (_el->values == NULL) {
    1613           0 :                 talloc_free(_el);
    1614           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1615             :         }
    1616           9 :         _el->num_values = val_count;
    1617             : 
    1618           9 :         v = _el->values;
    1619             : 
    1620          36 :         for (i = 0; i < msg->num_elements; i++) {
    1621          27 :                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
    1622          18 :                         const struct ldb_message_element *tmp_el = &msg->elements[i];
    1623          18 :                         if ((operation == LDB_MODIFY) &&
    1624          18 :                             (LDB_FLAG_MOD_TYPE(tmp_el->flags)
    1625             :                                                 == LDB_FLAG_MOD_DELETE)) {
    1626           0 :                                 continue;
    1627             :                         }
    1628          18 :                         if (tmp_el->values == NULL || tmp_el->num_values == 0) {
    1629           0 :                                 continue;
    1630             :                         }
    1631          18 :                         memcpy(v,
    1632          18 :                                tmp_el->values,
    1633          18 :                                tmp_el->num_values * sizeof(*v));
    1634          18 :                         v += tmp_el->num_values;
    1635             :                 }
    1636             :         }
    1637             : 
    1638           9 :         *el = _el;
    1639           9 :         return LDB_SUCCESS;
    1640             : }
    1641             : 
    1642             : 
    1643             : /*
    1644             :  * Get the value of a single-valued attribute from an ADDed message. 'val' will only live as
    1645             :  * long as 'msg' and 'original_val' do, and must not be freed.
    1646             :  */
    1647          36 : int dsdb_msg_add_get_single_value(const struct ldb_message *msg,
    1648             :                                   const char *attr_name,
    1649             :                                   const struct ldb_val **val)
    1650             : {
    1651          36 :         const struct ldb_message_element *el = NULL;
    1652             : 
    1653             :         /*
    1654             :          * The ldb_msg_normalize() call in ldb_request() ensures that
    1655             :          * there is at most one message element for each
    1656             :          * attribute. Thus, we don't need a loop to deal with an
    1657             :          * LDB_ADD.
    1658             :          */
    1659          36 :         el = ldb_msg_find_element(msg, attr_name);
    1660          36 :         if (el == NULL) {
    1661          18 :                 *val = NULL;
    1662          18 :                 return LDB_SUCCESS;
    1663             :         }
    1664          18 :         if (el->num_values != 1) {
    1665           0 :                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1666             :         }
    1667             : 
    1668          18 :         *val = &el->values[0];
    1669          18 :         return LDB_SUCCESS;
    1670             : }
    1671             : 
    1672             : /*
    1673             :  * Get the value of a single-valued attribute after processing a
    1674             :  * message. 'operation' is either LDB_ADD or LDB_MODIFY. 'val' will only live as
    1675             :  * long as 'msg' and 'original_val' do, and must not be freed.
    1676             :  */
    1677        1292 : int dsdb_msg_get_single_value(const struct ldb_message *msg,
    1678             :                               const char *attr_name,
    1679             :                               const struct ldb_val *original_val,
    1680             :                               const struct ldb_val **val,
    1681             :                               enum ldb_request_type operation)
    1682             : {
    1683           3 :         unsigned idx;
    1684             : 
    1685        1292 :         *val = NULL;
    1686             : 
    1687        1292 :         if (operation == LDB_ADD) {
    1688          36 :                 if (original_val != NULL) {
    1689             :                         /* This is an error on the caller's part. */
    1690           0 :                         return LDB_ERR_CONSTRAINT_VIOLATION;
    1691             :                 }
    1692          36 :                 return dsdb_msg_add_get_single_value(msg, attr_name, val);
    1693             :         }
    1694             : 
    1695        1256 :         SMB_ASSERT(operation == LDB_MODIFY);
    1696             : 
    1697        1256 :         *val = original_val;
    1698             : 
    1699        2875 :         for (idx = 0; idx < msg->num_elements; ++idx) {
    1700        1619 :                 const struct ldb_message_element *el = &msg->elements[idx];
    1701             : 
    1702        1619 :                 if (ldb_attr_cmp(el->name, attr_name) != 0) {
    1703        1541 :                         continue;
    1704             :                 }
    1705             : 
    1706          78 :                 switch (el->flags & LDB_FLAG_MOD_MASK) {
    1707           0 :                 case LDB_FLAG_MOD_ADD:
    1708           0 :                         if (el->num_values != 1) {
    1709           0 :                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1710             :                         }
    1711           0 :                         if (*val != NULL) {
    1712           0 :                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1713             :                         }
    1714             : 
    1715           0 :                         *val = &el->values[0];
    1716             : 
    1717           0 :                         break;
    1718             : 
    1719          78 :                 case LDB_FLAG_MOD_REPLACE:
    1720          78 :                         if (el->num_values > 1) {
    1721           0 :                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1722             :                         }
    1723             : 
    1724          78 :                         *val = el->num_values ? &el->values[0] : NULL;
    1725             : 
    1726          78 :                         break;
    1727             : 
    1728           0 :                 case LDB_FLAG_MOD_DELETE:
    1729           0 :                         if (el->num_values > 1) {
    1730           0 :                                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1731             :                         }
    1732             : 
    1733             :                         /*
    1734             :                          * If a value was specified for the delete, we don't
    1735             :                          * bother checking it matches the value we currently
    1736             :                          * have. Any mismatch will be caught later (e.g. in
    1737             :                          * ldb_kv_modify_internal).
    1738             :                          */
    1739             : 
    1740           0 :                         *val = NULL;
    1741             : 
    1742           0 :                         break;
    1743             :                 }
    1744             :         }
    1745             : 
    1746        1253 :         return LDB_SUCCESS;
    1747             : }
    1748             : 
    1749             : /*
    1750             :  * This function determines the (last) structural or 88 object class of a passed
    1751             :  * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
    1752             :  * Without schema this does not work and hence NULL is returned.
    1753             :  */
    1754     6583488 : const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
    1755             :                                                         const struct ldb_message_element *element)
    1756             : {
    1757      297872 :         const struct dsdb_class *last_class;
    1758             : 
    1759     6583488 :         if (schema == NULL) {
    1760           0 :                 return NULL;
    1761             :         }
    1762             : 
    1763     6583488 :         if (element->num_values == 0) {
    1764           0 :                 return NULL;
    1765             :         }
    1766             : 
    1767     6881360 :         last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
    1768     6583488 :                                                            &element->values[element->num_values-1]);
    1769     6583488 :         if (last_class == NULL) {
    1770           0 :                 return NULL;
    1771             :         }
    1772     6583488 :         if (last_class->objectClassCategory > 1) {
    1773           3 :                 return NULL;
    1774             :         }
    1775             : 
    1776     6285613 :         return last_class;
    1777             : }
    1778             : 
    1779     3861429 : const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
    1780             :                                                          const struct ldb_message *msg)
    1781             : {
    1782        5380 :         struct ldb_message_element *oc_el;
    1783             : 
    1784     3861429 :         oc_el = ldb_msg_find_element(msg, "objectClass");
    1785     3861429 :         if (!oc_el) {
    1786           0 :                 return NULL;
    1787             :         }
    1788             : 
    1789     3861429 :         return dsdb_get_last_structural_class(schema, oc_el);
    1790             : }
    1791             : 
    1792             : /*
    1793             :   Get the parent class of an objectclass, or NULL if none exists.
    1794             :  */
    1795       42183 : const struct dsdb_class *dsdb_get_parent_class(const struct dsdb_schema *schema,
    1796             :                                                const struct dsdb_class *objectclass)
    1797             : {
    1798       42183 :         if (ldb_attr_cmp(objectclass->lDAPDisplayName, "top") == 0) {
    1799       14958 :                 return NULL;
    1800             :         }
    1801             : 
    1802       27225 :         if (objectclass->subClassOf == NULL) {
    1803           0 :                 return NULL;
    1804             :         }
    1805             : 
    1806       27225 :         return dsdb_class_by_lDAPDisplayName(schema, objectclass->subClassOf);
    1807             : }
    1808             : 
    1809             : /*
    1810             :   Return true if 'struct_objectclass' is a subclass of 'other_objectclass'. The
    1811             :   two objectclasses must originate from the same schema, to allow for
    1812             :   pointer-based identity comparison.
    1813             :  */
    1814       15894 : bool dsdb_is_subclass_of(const struct dsdb_schema *schema,
    1815             :                          const struct dsdb_class *struct_objectclass,
    1816             :                          const struct dsdb_class *other_objectclass)
    1817             : {
    1818       58077 :         while (struct_objectclass != NULL) {
    1819             :                 /* Pointer comparison can be used due to the same schema str. */
    1820       43119 :                 if (struct_objectclass == other_objectclass) {
    1821         933 :                         return true;
    1822             :                 }
    1823             : 
    1824       42183 :                 struct_objectclass = dsdb_get_parent_class(schema, struct_objectclass);
    1825             :         }
    1826             : 
    1827       14958 :         return false;
    1828             : }
    1829             : 
    1830             : /* Fix the DN so that the relative attribute names are in upper case so that the DN:
    1831             :    cn=Administrator,cn=users,dc=samba,dc=example,dc=com becomes
    1832             :    CN=Administrator,CN=users,DC=samba,DC=example,DC=com
    1833             : */
    1834           0 : int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
    1835             : {
    1836           0 :         int i, ret;
    1837           0 :         char *upper_rdn_attr;
    1838             : 
    1839           0 :         for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
    1840             :                 /* We need the attribute name in upper case */
    1841           0 :                 upper_rdn_attr = strupper_talloc(dn,
    1842             :                                                  ldb_dn_get_component_name(dn, i));
    1843           0 :                 if (!upper_rdn_attr) {
    1844           0 :                         return ldb_oom(ldb);
    1845             :                 }
    1846           0 :                 ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
    1847           0 :                                            *ldb_dn_get_component_val(dn, i));
    1848           0 :                 talloc_free(upper_rdn_attr);
    1849           0 :                 if (ret != LDB_SUCCESS) {
    1850           0 :                         return ret;
    1851             :                 }
    1852             :         }
    1853           0 :         return LDB_SUCCESS;
    1854             : }
    1855             : 
    1856             : /**
    1857             :  * Make most specific objectCategory for the objectClass of passed object
    1858             :  * NOTE: In this implementation we count that it is called on already
    1859             :  * verified objectClass attribute value. See objectclass.c thorough
    1860             :  * implementation for all the magic that involves
    1861             :  *
    1862             :  * @param ldb   ldb context
    1863             :  * @param schema cached schema for ldb. We may get it, but it is very time consuming.
    1864             :  *                      Hence leave the responsibility to the caller.
    1865             :  * @param obj   AD object to determint objectCategory for
    1866             :  * @param mem_ctx Memory context - usually it is obj actually
    1867             :  * @param pobjectcategory location to store found objectCategory
    1868             :  *
    1869             :  * @return LDB_SUCCESS or error including out of memory error
    1870             :  */
    1871         274 : int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
    1872             :                               const struct ldb_message *obj,
    1873             :                               TALLOC_CTX *mem_ctx, const char **pobjectcategory)
    1874             : {
    1875           0 :         const struct dsdb_class                 *objectclass;
    1876           0 :         struct ldb_message_element              *objectclass_element;
    1877           0 :         struct dsdb_extended_dn_store_format    *dn_format;
    1878             : 
    1879         274 :         objectclass_element = ldb_msg_find_element(obj, "objectClass");
    1880         274 :         if (!objectclass_element) {
    1881           0 :                 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
    1882           0 :                                        ldb_dn_get_linearized(obj->dn));
    1883           0 :                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
    1884             :         }
    1885         274 :         if (objectclass_element->num_values == 0) {
    1886           0 :                 ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
    1887           0 :                                        ldb_dn_get_linearized(obj->dn));
    1888           0 :                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1889             :         }
    1890             : 
    1891             :         /*
    1892             :          * Get the new top-most structural object class and check for
    1893             :          * unrelated structural classes
    1894             :          */
    1895         274 :         objectclass = dsdb_get_last_structural_class(schema,
    1896             :                                                      objectclass_element);
    1897         274 :         if (objectclass == NULL) {
    1898           0 :                 ldb_asprintf_errstring(ldb,
    1899             :                                        "Failed to find a structural class for %s",
    1900           0 :                                        ldb_dn_get_linearized(obj->dn));
    1901           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
    1902             :         }
    1903             : 
    1904         274 :         dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
    1905             :                                     struct dsdb_extended_dn_store_format);
    1906         274 :         if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
    1907             :                 /* Strip off extended components */
    1908           0 :                 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
    1909           0 :                                                objectclass->defaultObjectCategory);
    1910           0 :                 *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
    1911           0 :                 talloc_free(dn);
    1912             :         } else {
    1913         274 :                 *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
    1914             :         }
    1915             : 
    1916         274 :         if (*pobjectcategory == NULL) {
    1917           0 :                 return ldb_oom(ldb);
    1918             :         }
    1919             : 
    1920         274 :         return LDB_SUCCESS;
    1921             : }

Generated by: LCOV version 1.14