LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules - util.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 649 916 70.9 %
Date: 2024-02-29 22:57:05 Functions: 45 48 93.8 %

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

Generated by: LCOV version 1.14