LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules - samba_dsdb.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 182 234 77.8 %
Date: 2021-09-23 10:06:22 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :    Samba4 module loading module
       3             : 
       4             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : /*
      21             :  *  Name: ldb
      22             :  *
      23             :  *  Component: Samba4 module loading module
      24             :  *
      25             :  *  Description: Implement a single 'module' in the ldb database,
      26             :  *  which loads the remaining modules based on 'choice of configuration' attributes
      27             :  *
      28             :  *  This is to avoid forcing a reprovision of the ldb databases when we change the internal structure of the code
      29             :  *
      30             :  *  Author: Andrew Bartlett
      31             :  */
      32             : 
      33             : #include "includes.h"
      34             : #include <ldb.h>
      35             : #include <ldb_errors.h>
      36             : #include <ldb_module.h>
      37             : #include "dsdb/samdb/ldb_modules/util.h"
      38             : #include "dsdb/samdb/samdb.h"
      39             : #include "librpc/ndr/libndr.h"
      40             : #include "auth/credentials/credentials.h"
      41             : #include "param/secrets.h"
      42             : #include "lib/ldb-samba/ldb_wrap.h"
      43             : 
      44      132459 : static int read_at_rootdse_record(struct ldb_context *ldb, struct ldb_module *module, TALLOC_CTX *mem_ctx,
      45             :                                   struct ldb_message **msg, struct ldb_request *parent)
      46             : {
      47             :         int ret;
      48             :         static const char *rootdse_attrs[] = { "defaultNamingContext", "configurationNamingContext", "schemaNamingContext", NULL };
      49             :         struct ldb_result *rootdse_res;
      50             :         struct ldb_dn *rootdse_dn;
      51      132459 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
      52      132459 :         if (!tmp_ctx) {
      53           0 :                 return ldb_oom(ldb);
      54             :         }
      55             : 
      56      132459 :         rootdse_dn = ldb_dn_new(tmp_ctx, ldb, "@ROOTDSE");
      57      132459 :         if (!rootdse_dn) {
      58           0 :                 talloc_free(tmp_ctx);
      59           0 :                 return ldb_oom(ldb);
      60             :         }
      61             : 
      62      132459 :         ret = dsdb_module_search_dn(module, tmp_ctx, &rootdse_res, rootdse_dn,
      63             :                                     rootdse_attrs, DSDB_FLAG_NEXT_MODULE, parent);
      64      132459 :         if (ret != LDB_SUCCESS) {
      65           6 :                 talloc_free(tmp_ctx);
      66           6 :                 return ret;
      67             :         }
      68             : 
      69      132453 :         talloc_steal(mem_ctx, rootdse_res->msgs);
      70      132453 :         *msg = rootdse_res->msgs[0];
      71             : 
      72      132453 :         talloc_free(tmp_ctx);
      73             : 
      74      132453 :         return ret;
      75             : }
      76             : 
      77      264906 : static int prepare_modules_line(struct ldb_context *ldb,
      78             :                                 TALLOC_CTX *mem_ctx,
      79             :                                 const struct ldb_message *rootdse_msg,
      80             :                                 struct ldb_message *msg, const char *backend_attr,
      81             :                                 const char *backend_mod, const char **backend_mod_list)
      82             : {
      83             :         int ret;
      84             :         const char **backend_full_list;
      85             :         const char *backend_dn;
      86             :         char *mod_list_string;
      87             :         char *full_string;
      88      264906 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
      89      264906 :         if (!tmp_ctx) {
      90           0 :                 return ldb_oom(ldb);
      91             :         }
      92             : 
      93      264906 :         if (backend_attr) {
      94      132453 :                 backend_dn = ldb_msg_find_attr_as_string(rootdse_msg, backend_attr, NULL);
      95      132453 :                 if (!backend_dn) {
      96           0 :                         ldb_asprintf_errstring(ldb,
      97             :                                                "samba_dsdb_init: "
      98             :                                                "unable to read %s from %s:%s",
      99           0 :                                                backend_attr, ldb_dn_get_linearized(rootdse_msg->dn),
     100             :                                                ldb_errstring(ldb));
     101           0 :                         return LDB_ERR_CONSTRAINT_VIOLATION;
     102             :                 }
     103             :         } else {
     104      127712 :                 backend_dn = "*";
     105             :         }
     106             : 
     107      264906 :         if (backend_mod) {
     108      132453 :                 char **b = str_list_make_single(tmp_ctx, backend_mod);
     109      132453 :                 backend_full_list = discard_const_p(const char *, b);
     110             :         } else {
     111      132453 :                 char **b = str_list_make_empty(tmp_ctx);
     112      132453 :                 backend_full_list = discard_const_p(const char *, b);
     113             :         }
     114      264906 :         if (!backend_full_list) {
     115           0 :                 talloc_free(tmp_ctx);
     116           0 :                 return ldb_oom(ldb);
     117             :         }
     118             : 
     119      264906 :         backend_full_list = str_list_append_const(backend_full_list, backend_mod_list);
     120      264906 :         if (!backend_full_list) {
     121           0 :                 talloc_free(tmp_ctx);
     122           0 :                 return ldb_oom(ldb);
     123             :         }
     124             : 
     125      264906 :         mod_list_string = str_list_join(tmp_ctx, backend_full_list, ',');
     126             : 
     127             :         /* str_list_append allocates on NULL */
     128      264906 :         talloc_free(backend_full_list);
     129             : 
     130      264906 :         if (!mod_list_string) {
     131           0 :                 talloc_free(tmp_ctx);
     132           0 :                 return ldb_oom(ldb);
     133             :         }
     134             : 
     135      264906 :         full_string = talloc_asprintf(tmp_ctx, "%s:%s", backend_dn, mod_list_string);
     136      264906 :         ret = ldb_msg_add_steal_string(msg, "modules", full_string);
     137      264906 :         talloc_free(tmp_ctx);
     138      264906 :         return ret;
     139             : }
     140             : 
     141      132454 : static bool check_required_features(struct ldb_message_element *el)
     142             : {
     143      132454 :         if (el != NULL) {
     144             :                 int k;
     145      120755 :                 DATA_BLOB esf = data_blob_string_const(
     146             :                         SAMBA_ENCRYPTED_SECRETS_FEATURE);
     147      120755 :                 DATA_BLOB lmdbl1 = data_blob_string_const(
     148             :                         SAMBA_LMDB_LEVEL_ONE_FEATURE);
     149      302051 :                 for (k = 0; k < el->num_values; k++) {
     150      241839 :                         if ((data_blob_cmp(&esf, &el->values[k]) != 0) &&
     151       60542 :                             (data_blob_cmp(&lmdbl1, &el->values[k]) != 0)) {
     152           1 :                                 return false;
     153             :                         }
     154             :                 }
     155             :         }
     156      127712 :         return true;
     157             : }
     158             : 
     159      132460 : static int samba_dsdb_init(struct ldb_module *module)
     160             : {
     161      132460 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     162             :         int ret, lock_ret, len, i, j;
     163      132460 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     164             :         struct ldb_result *res;
     165      132460 :         struct ldb_message *rootdse_msg = NULL, *partition_msg;
     166             :         struct ldb_dn *samba_dsdb_dn, *partition_dn, *indexlist_dn;
     167             :         struct ldb_module *backend_module, *module_chain;
     168             :         const char **final_module_list, **reverse_module_list;
     169             :         /*
     170             :           Add modules to the list to activate them by default
     171             :           beware often order is important
     172             : 
     173             :           Some Known ordering constraints:
     174             :           - rootdse must be first, as it makes redirects from "" -> cn=rootdse
     175             :           - extended_dn_in must be before objectclass.c, as it resolves the DN
     176             :           - objectclass must be before password_hash and samldb since these LDB
     177             :             modules require the expanded "objectClass" list
     178             :           - objectclass must be before descriptor and acl, as both assume that
     179             :             objectClass values are sorted
     180             :           - objectclass_attrs must be behind operational in order to see all
     181             :             attributes (the operational module protects and therefore
     182             :             suppresses per default some important ones)
     183             :           - partition must be last
     184             :           - each partition has its own module list then
     185             : 
     186             :           The list is presented here as a set of declarations to show the
     187             :           stack visually - the code below then handles the creation of the list
     188             :           based on the parameters loaded from the database.
     189             :         */
     190             :         static const char *modules_list1[] = {"resolve_oids",
     191             :                                              "rootdse",
     192             :                                              "dsdb_notification",
     193             :                                              "schema_load",
     194             :                                              "lazy_commit",
     195             :                                              "dirsync",
     196             :                                              "dsdb_paged_results",
     197             :                                              "vlv",
     198             :                                              "ranged_results",
     199             :                                              "anr",
     200             :                                              "server_sort",
     201             :                                              "asq",
     202             :                                              "extended_dn_store",
     203             :                                              NULL };
     204             :         /* extended_dn_in or extended_dn_in_openldap goes here */
     205             :         static const char *modules_list1a[] = {"audit_log",
     206             :                                              "objectclass",
     207             :                                              "tombstone_reanimate",
     208             :                                              "descriptor",
     209             :                                              "acl",
     210             :                                              "aclread",
     211             :                                              "samldb",
     212             :                                              "password_hash",
     213             :                                              "instancetype",
     214             :                                              "objectclass_attrs",
     215             :                                              NULL };
     216             : 
     217             :         const char **link_modules;
     218             :         static const char *tdb_modules_list[] = {
     219             :                 "rdn_name",
     220             :                 "subtree_delete",
     221             :                 "repl_meta_data",
     222             :                 "group_audit_log",
     223             :                 "encrypted_secrets",
     224             :                 "operational",
     225             :                 "unique_object_sids",
     226             :                 "subtree_rename",
     227             :                 "linked_attributes",
     228             :                 NULL};
     229             : 
     230             :         const char *extended_dn_module;
     231      132460 :         const char *extended_dn_module_ldb = "extended_dn_out_ldb";
     232      132460 :         const char *extended_dn_in_module = "extended_dn_in";
     233             : 
     234             :         static const char *modules_list2[] = {"dns_notify",
     235             :                                               "show_deleted",
     236             :                                               "new_partition",
     237             :                                               "partition",
     238             :                                               NULL };
     239             : 
     240             :         const char **backend_modules;
     241             :         static const char *samba_dsdb_attrs[] = { SAMBA_COMPATIBLE_FEATURES_ATTR,
     242             :                                                   SAMBA_REQUIRED_FEATURES_ATTR, NULL };
     243             :         static const char *indexlist_attrs[] = { SAMBA_FEATURES_SUPPORTED_FLAG, NULL };
     244             : 
     245      132460 :         const char *current_supportedFeatures[] = {SAMBA_SORTED_LINKS_FEATURE};
     246             : 
     247      132460 :         if (!tmp_ctx) {
     248           0 :                 return ldb_oom(ldb);
     249             :         }
     250             : 
     251      132460 :         ret = ldb_register_samba_handlers(ldb);
     252      132460 :         if (ret != LDB_SUCCESS) {
     253           0 :                 talloc_free(tmp_ctx);
     254           0 :                 return ret;
     255             :         }
     256             : 
     257      132460 :         samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
     258      132460 :         if (!samba_dsdb_dn) {
     259           0 :                 talloc_free(tmp_ctx);
     260           0 :                 return ldb_oom(ldb);
     261             :         }
     262             : 
     263      132460 :         indexlist_dn = ldb_dn_new(tmp_ctx, ldb, "@INDEXLIST");
     264      127718 :         if (!samba_dsdb_dn) {
     265           0 :                 talloc_free(tmp_ctx);
     266           0 :                 return ldb_oom(ldb);
     267             :         }
     268             : 
     269      132460 :         partition_dn = ldb_dn_new(tmp_ctx, ldb, DSDB_PARTITION_DN);
     270      132460 :         if (!partition_dn) {
     271           0 :                 talloc_free(tmp_ctx);
     272           0 :                 return ldb_oom(ldb);
     273             :         }
     274             : 
     275             : #define CHECK_LDB_RET(check_ret)                                \
     276             :         do {                                                    \
     277             :                 if (check_ret != LDB_SUCCESS) {                 \
     278             :                         talloc_free(tmp_ctx);                   \
     279             :                         return check_ret;                       \
     280             :                 }                                               \
     281             :         } while (0)
     282             : 
     283      132460 :         ret = dsdb_module_search_dn(module, tmp_ctx, &res, samba_dsdb_dn,
     284             :                                     samba_dsdb_attrs, DSDB_FLAG_NEXT_MODULE, NULL);
     285      132460 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     286             :                 /* do nothing, a very old db being upgraded */
     287      132454 :         } else if (ret == LDB_SUCCESS) {
     288             :                 struct ldb_message_element *requiredFeatures;
     289             :                 struct ldb_message_element *old_compatibleFeatures;
     290             : 
     291      132454 :                 requiredFeatures = ldb_msg_find_element(res->msgs[0], SAMBA_REQUIRED_FEATURES_ATTR);
     292      132454 :                 if (!check_required_features(requiredFeatures)) {
     293           1 :                         ldb_set_errstring(
     294             :                                 ldb,
     295             :                                 "This Samba database was created with "
     296             :                                 "a newer Samba version and is marked "
     297             :                                 "with extra requiredFeatures in "
     298             :                                 "@SAMBA_DSDB. This database can not "
     299             :                                 "safely be read by this Samba version");
     300           1 :                         return LDB_ERR_OPERATIONS_ERROR;
     301             :                 }
     302             : 
     303      132453 :                 old_compatibleFeatures = ldb_msg_find_element(res->msgs[0],
     304             :                                                               SAMBA_COMPATIBLE_FEATURES_ATTR);
     305             : 
     306      132453 :                 if (old_compatibleFeatures) {
     307             :                         struct ldb_message *features_msg;
     308             :                         struct ldb_message_element *features_el;
     309      132157 :                         int samba_options_supported = 0;
     310      132157 :                         ret = dsdb_module_search_dn(module, tmp_ctx, &res,
     311             :                                                     indexlist_dn,
     312             :                                                     indexlist_attrs,
     313             :                                                     DSDB_FLAG_NEXT_MODULE, NULL);
     314      132157 :                         if (ret == LDB_SUCCESS) {
     315             :                                 samba_options_supported
     316      131964 :                                         = ldb_msg_find_attr_as_int(res->msgs[0],
     317             :                                                                    SAMBA_FEATURES_SUPPORTED_FLAG,
     318             :                                                                    0);
     319             : 
     320         193 :                         } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     321             :                                 /*
     322             :                                  * If we don't have @INDEXLIST yet, then we
     323             :                                  * are so early in set-up that we know this is
     324             :                                  * a blank DB, so no need to wripe out old
     325             :                                  * features
     326             :                                  */
     327         193 :                                 samba_options_supported = 1;
     328             :                         }
     329             : 
     330      132157 :                         features_msg = ldb_msg_new(res);
     331      132157 :                         if (features_msg == NULL) {
     332           0 :                                 return ldb_module_operr(module);
     333             :                         }
     334      132157 :                         features_msg->dn = samba_dsdb_dn;
     335             : 
     336      132157 :                         ldb_msg_add_empty(features_msg, SAMBA_COMPATIBLE_FEATURES_ATTR,
     337             :                                           LDB_FLAG_MOD_DELETE, &features_el);
     338             : 
     339      132157 :                         if (samba_options_supported == 1) {
     340      302409 :                                 for (i = 0;
     341      264315 :                                      old_compatibleFeatures && i < old_compatibleFeatures->num_values;
     342      132158 :                                      i++) {
     343      219619 :                                         for (j = 0;
     344       40029 :                                              j < ARRAY_SIZE(current_supportedFeatures); j++) {
     345      132158 :                                                 if (strcmp((char *)old_compatibleFeatures->values[i].data,
     346             :                                                            current_supportedFeatures[j]) == 0) {
     347      127489 :                                                         break;
     348             :                                                 }
     349             :                                         }
     350      132158 :                                         if (j == ARRAY_SIZE(current_supportedFeatures)) {
     351             :                                                 /*
     352             :                                                  * Add to list of features to remove
     353             :                                                  * (rather than all features)
     354             :                                                  */
     355           1 :                                                 ret = ldb_msg_add_value(features_msg, SAMBA_COMPATIBLE_FEATURES_ATTR,
     356           1 :                                                                         &old_compatibleFeatures->values[i],
     357             :                                                                         NULL);
     358           1 :                                                 if (ret != LDB_SUCCESS) {
     359           0 :                                                         return ret;
     360             :                                                 }
     361             :                                         }
     362             :                                 }
     363             : 
     364      132157 :                                 if (features_el->num_values > 0) {
     365             :                                         /* Delete by list */
     366           1 :                                         ret = ldb_next_start_trans(module);
     367           1 :                                         if (ret != LDB_SUCCESS) {
     368           0 :                                                 return ret;
     369             :                                         }
     370           1 :                                         ret = dsdb_module_modify(module, features_msg, DSDB_FLAG_NEXT_MODULE, NULL);
     371           1 :                                         if (ret != LDB_SUCCESS) {
     372           0 :                                                 ldb_next_del_trans(module);
     373           0 :                                                 return ret;
     374             :                                         }
     375           1 :                                         ret = ldb_next_end_trans(module);
     376           1 :                                         if (ret != LDB_SUCCESS) {
     377           0 :                                                 return ret;
     378             :                                         }
     379             :                                 }
     380             :                         } else {
     381             :                                 /* Delete all */
     382           0 :                                 ret = ldb_next_start_trans(module);
     383           0 :                                 if (ret != LDB_SUCCESS) {
     384           0 :                                         return ret;
     385             :                                 }
     386           0 :                                 ret = dsdb_module_modify(module, features_msg, DSDB_FLAG_NEXT_MODULE, NULL);
     387           0 :                                 if (ret != LDB_SUCCESS) {
     388           0 :                                         ldb_next_del_trans(module);
     389           0 :                                         return ret;
     390             :                                 }
     391           0 :                                 ret = ldb_next_end_trans(module);
     392           0 :                                 if (ret != LDB_SUCCESS) {
     393           0 :                                         return ret;
     394             :                                 }
     395             :                         }
     396             :                 }
     397             : 
     398             :         } else {
     399           0 :                 talloc_free(tmp_ctx);
     400           0 :                 return ret;
     401             :         }
     402             : 
     403      132459 :         backend_modules = NULL;
     404      132459 :         extended_dn_module = extended_dn_module_ldb;
     405      132459 :         link_modules = tdb_modules_list;
     406             : 
     407             : #define CHECK_MODULE_LIST \
     408             :         do {                                                    \
     409             :                 if (!final_module_list) {                       \
     410             :                         talloc_free(tmp_ctx);                   \
     411             :                         return ldb_oom(ldb);                    \
     412             :                 }                                               \
     413             :         } while (0)
     414             : 
     415      132459 :         final_module_list = str_list_copy_const(tmp_ctx, modules_list1);
     416      132459 :         CHECK_MODULE_LIST;
     417             : 
     418      132459 :         final_module_list = str_list_add_const(final_module_list, extended_dn_in_module);
     419      132459 :         CHECK_MODULE_LIST;
     420             : 
     421      132459 :         final_module_list = str_list_append_const(final_module_list, modules_list1a);
     422      132459 :         CHECK_MODULE_LIST;
     423             : 
     424      132459 :         final_module_list = str_list_append_const(final_module_list, link_modules);
     425      132459 :         CHECK_MODULE_LIST;
     426             : 
     427      132459 :         final_module_list = str_list_add_const(final_module_list, extended_dn_module);
     428      132459 :         CHECK_MODULE_LIST;
     429             : 
     430      132459 :         final_module_list = str_list_append_const(final_module_list, modules_list2);
     431      132459 :         CHECK_MODULE_LIST;
     432             : 
     433             : 
     434      132459 :         ret = read_at_rootdse_record(ldb, module, tmp_ctx, &rootdse_msg, NULL);
     435      132459 :         CHECK_LDB_RET(ret);
     436             : 
     437      132453 :         partition_msg = ldb_msg_new(tmp_ctx);
     438      132453 :         partition_msg->dn = ldb_dn_new(partition_msg, ldb, "@" DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME);
     439             : 
     440      132453 :         ret = prepare_modules_line(ldb, tmp_ctx,
     441             :                                    rootdse_msg,
     442             :                                    partition_msg, "schemaNamingContext",
     443             :                                    "schema_data", backend_modules);
     444      132453 :         CHECK_LDB_RET(ret);
     445             : 
     446      132453 :         ret = prepare_modules_line(ldb, tmp_ctx,
     447             :                                    rootdse_msg,
     448             :                                    partition_msg, NULL,
     449             :                                    NULL, backend_modules);
     450      132453 :         CHECK_LDB_RET(ret);
     451             : 
     452      132453 :         ret = ldb_set_opaque(ldb, DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME, partition_msg);
     453      132453 :         CHECK_LDB_RET(ret);
     454             : 
     455      132453 :         talloc_steal(ldb, partition_msg);
     456             : 
     457             :         /* Now prepare the module chain. Oddly, we must give it to
     458             :          * ldb_module_load_list in REVERSE */
     459     1653555 :         for (len = 0; final_module_list[len]; len++) { /* noop */};
     460             : 
     461      132453 :         reverse_module_list = talloc_array(tmp_ctx, const char *, len+1);
     462      132453 :         if (!reverse_module_list) {
     463           0 :                 talloc_free(tmp_ctx);
     464           0 :                 return ldb_oom(ldb);
     465             :         }
     466     5160926 :         for (i=0; i < len; i++) {
     467     5033214 :                 reverse_module_list[i] = final_module_list[(len - 1) - i];
     468             :         }
     469      132453 :         reverse_module_list[i] = NULL;
     470             : 
     471             :         /* The backend (at least until the partitions module
     472             :          * reconfigures things) is the next module in the currently
     473             :          * loaded chain */
     474      132453 :         backend_module = ldb_module_next(module);
     475      132453 :         ret = ldb_module_load_list(ldb, reverse_module_list, backend_module, &module_chain);
     476      132453 :         CHECK_LDB_RET(ret);
     477             : 
     478      132453 :         talloc_free(tmp_ctx);
     479             :         /* Set this as the 'next' module, so that we effectively append it to
     480             :          * module chain */
     481      132453 :         ldb_module_set_next(module, module_chain);
     482             : 
     483      132453 :         ret = ldb_next_read_lock(module);
     484      132453 :         if (ret != LDB_SUCCESS) {
     485           0 :                 return ret;
     486             :         }
     487             : 
     488      132453 :         ret = ldb_next_init(module);
     489             : 
     490      132453 :         lock_ret = ldb_next_read_unlock(module);
     491             : 
     492      132453 :         if (lock_ret != LDB_SUCCESS) {
     493           0 :                 return lock_ret;
     494             :         }
     495             : 
     496      132453 :         return ret;
     497             : }
     498             : 
     499             : static const struct ldb_module_ops ldb_samba_dsdb_module_ops = {
     500             :         .name              = "samba_dsdb",
     501             :         .init_context      = samba_dsdb_init,
     502             : };
     503             : 
     504          35 : static struct ldb_message *dsdb_flags_ignore_fixup(TALLOC_CTX *mem_ctx,
     505             :                                                 const struct ldb_message *_msg)
     506             : {
     507          35 :         struct ldb_message *msg = NULL;
     508             :         unsigned int i;
     509             : 
     510             :         /* we have to copy the message as the caller might have it as a const */
     511          35 :         msg = ldb_msg_copy_shallow(mem_ctx, _msg);
     512          35 :         if (msg == NULL) {
     513           0 :                 return NULL;
     514             :         }
     515             : 
     516         212 :         for (i=0; i < msg->num_elements;) {
     517         177 :                 struct ldb_message_element *e = &msg->elements[i];
     518             : 
     519         177 :                 if (!(e->flags & DSDB_FLAG_INTERNAL_FORCE_META_DATA)) {
     520         165 :                         i++;
     521         165 :                         continue;
     522             :                 }
     523             : 
     524          12 :                 e->flags &= ~DSDB_FLAG_INTERNAL_FORCE_META_DATA;
     525             : 
     526          12 :                 if (e->num_values != 0) {
     527           2 :                         i++;
     528           2 :                         continue;
     529             :                 }
     530             : 
     531          10 :                 ldb_msg_remove_element(msg, e);
     532             :         }
     533             : 
     534           0 :         return msg;
     535             : }
     536             : 
     537          16 : static int dsdb_flags_ignore_add(struct ldb_module *module, struct ldb_request *req)
     538             : {
     539          16 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     540          16 :         struct ldb_request *down_req = NULL;
     541          16 :         struct ldb_message *msg = NULL;
     542             :         int ret;
     543             : 
     544          16 :         msg = dsdb_flags_ignore_fixup(req, req->op.add.message);
     545          16 :         if (msg == NULL) {
     546           0 :                 return ldb_module_oom(module);
     547             :         }
     548             : 
     549          16 :         ret = ldb_build_add_req(&down_req, ldb, req,
     550             :                                 msg,
     551             :                                 req->controls,
     552             :                                 req, dsdb_next_callback,
     553             :                                 req);
     554          16 :         LDB_REQ_SET_LOCATION(down_req);
     555          16 :         if (ret != LDB_SUCCESS) {
     556           0 :                 return ret;
     557             :         }
     558             : 
     559             :         /* go on with the call chain */
     560          16 :         return ldb_next_request(module, down_req);
     561             : }
     562             : 
     563          19 : static int dsdb_flags_ignore_modify(struct ldb_module *module, struct ldb_request *req)
     564             : {
     565          19 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     566          19 :         struct ldb_request *down_req = NULL;
     567          19 :         struct ldb_message *msg = NULL;
     568             :         int ret;
     569             : 
     570          19 :         msg = dsdb_flags_ignore_fixup(req, req->op.mod.message);
     571          19 :         if (msg == NULL) {
     572           0 :                 return ldb_module_oom(module);
     573             :         }
     574             : 
     575          19 :         ret = ldb_build_mod_req(&down_req, ldb, req,
     576             :                                 msg,
     577             :                                 req->controls,
     578             :                                 req, dsdb_next_callback,
     579             :                                 req);
     580          19 :         LDB_REQ_SET_LOCATION(down_req);
     581          19 :         if (ret != LDB_SUCCESS) {
     582           0 :                 return ret;
     583             :         }
     584             : 
     585             :         /* go on with the call chain */
     586          19 :         return ldb_next_request(module, down_req);
     587             : }
     588             : 
     589             : static const struct ldb_module_ops ldb_dsdb_flags_ignore_module_ops = {
     590             :         .name   = "dsdb_flags_ignore",
     591             :         .add    = dsdb_flags_ignore_add,
     592             :         .modify = dsdb_flags_ignore_modify,
     593             : };
     594             : 
     595        5536 : int ldb_samba_dsdb_module_init(const char *version)
     596             : {
     597             :         int ret;
     598        5536 :         LDB_MODULE_CHECK_VERSION(version);
     599        5536 :         ret = ldb_register_module(&ldb_samba_dsdb_module_ops);
     600        5536 :         if (ret != LDB_SUCCESS) {
     601           0 :                 return ret;
     602             :         }
     603        5536 :         ret = ldb_register_module(&ldb_dsdb_flags_ignore_module_ops);
     604        5536 :         if (ret != LDB_SUCCESS) {
     605           0 :                 return ret;
     606             :         }
     607        5536 :         return LDB_SUCCESS;
     608             : }

Generated by: LCOV version 1.13