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 master 2f515e9b Lines: 216 269 80.3 %
Date: 2024-04-21 15:09:00 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      182010 : 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        6016 :         int ret;
      48        6016 :         static const char *rootdse_attrs[] = { "defaultNamingContext", "configurationNamingContext", "schemaNamingContext", NULL };
      49        6016 :         struct ldb_result *rootdse_res;
      50        6016 :         struct ldb_dn *rootdse_dn;
      51      182010 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
      52      182010 :         if (!tmp_ctx) {
      53           0 :                 return ldb_oom(ldb);
      54             :         }
      55             : 
      56      182010 :         rootdse_dn = ldb_dn_new(tmp_ctx, ldb, "@ROOTDSE");
      57      182010 :         if (!rootdse_dn) {
      58           0 :                 talloc_free(tmp_ctx);
      59           0 :                 return ldb_oom(ldb);
      60             :         }
      61             : 
      62      182010 :         ret = dsdb_module_search_dn(module, tmp_ctx, &rootdse_res, rootdse_dn,
      63             :                                     rootdse_attrs, DSDB_FLAG_NEXT_MODULE, parent);
      64      182010 :         if (ret != LDB_SUCCESS) {
      65           6 :                 talloc_free(tmp_ctx);
      66           6 :                 return ret;
      67             :         }
      68             : 
      69      182004 :         talloc_steal(mem_ctx, rootdse_res->msgs);
      70      182004 :         *msg = rootdse_res->msgs[0];
      71             : 
      72      182004 :         talloc_free(tmp_ctx);
      73             : 
      74      182004 :         return ret;
      75             : }
      76             : 
      77      364008 : 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       12032 :         int ret;
      84       12032 :         const char **backend_full_list;
      85       12032 :         const char *backend_dn;
      86       12032 :         char *mod_list_string;
      87       12032 :         char *full_string;
      88      364008 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
      89      364008 :         if (!tmp_ctx) {
      90           0 :                 return ldb_oom(ldb);
      91             :         }
      92             : 
      93      364008 :         if (backend_attr) {
      94      182004 :                 backend_dn = ldb_msg_find_attr_as_string(rootdse_msg, backend_attr, NULL);
      95      182004 :                 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      175988 :                 backend_dn = "*";
     105             :         }
     106             : 
     107      364008 :         if (backend_mod) {
     108      182004 :                 char **b = str_list_make_single(tmp_ctx, backend_mod);
     109      182004 :                 backend_full_list = discard_const_p(const char *, b);
     110             :         } else {
     111      182004 :                 char **b = str_list_make_empty(tmp_ctx);
     112      182004 :                 backend_full_list = discard_const_p(const char *, b);
     113             :         }
     114      364008 :         if (!backend_full_list) {
     115           0 :                 talloc_free(tmp_ctx);
     116           0 :                 return ldb_oom(ldb);
     117             :         }
     118             : 
     119      364008 :         backend_full_list = str_list_append_const(backend_full_list, backend_mod_list);
     120      364008 :         if (!backend_full_list) {
     121           0 :                 talloc_free(tmp_ctx);
     122           0 :                 return ldb_oom(ldb);
     123             :         }
     124             : 
     125      364008 :         mod_list_string = str_list_join(tmp_ctx, backend_full_list, ',');
     126             : 
     127             :         /* str_list_append allocates on NULL */
     128      364008 :         talloc_free(backend_full_list);
     129             : 
     130      364008 :         if (!mod_list_string) {
     131           0 :                 talloc_free(tmp_ctx);
     132           0 :                 return ldb_oom(ldb);
     133             :         }
     134             : 
     135      364008 :         full_string = talloc_asprintf(tmp_ctx, "%s:%s", backend_dn, mod_list_string);
     136      364008 :         ret = ldb_msg_add_steal_string(msg, "modules", full_string);
     137      364008 :         talloc_free(tmp_ctx);
     138      364008 :         return ret;
     139             : }
     140             : 
     141      182005 : static bool check_required_features(struct ldb_message_element *el)
     142             : {
     143      182005 :         if (el != NULL) {
     144        5938 :                 int k;
     145      167150 :                 DATA_BLOB esf = data_blob_string_const(
     146             :                         SAMBA_ENCRYPTED_SECRETS_FEATURE);
     147      167150 :                 DATA_BLOB lmdbl1 = data_blob_string_const(
     148             :                         SAMBA_LMDB_LEVEL_ONE_FEATURE);
     149      434170 :                 for (k = 0; k < el->num_values; k++) {
     150      355016 :                         if ((data_blob_cmp(&esf, &el->values[k]) != 0) &&
     151       93933 :                             (data_blob_cmp(&lmdbl1, &el->values[k]) != 0)) {
     152           1 :                                 return false;
     153             :                         }
     154             :                 }
     155             :         }
     156      175988 :         return true;
     157             : }
     158             : 
     159      182011 : static int samba_dsdb_init(struct ldb_module *module)
     160             : {
     161      182011 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     162        6017 :         int ret, lock_ret, len, i, j;
     163      182011 :         TALLOC_CTX *tmp_ctx = talloc_new(module);
     164        6017 :         struct ldb_result *res;
     165      182011 :         struct ldb_message *rootdse_msg = NULL, *partition_msg;
     166        6017 :         struct ldb_dn *samba_dsdb_dn, *partition_dn, *indexlist_dn;
     167        6017 :         struct ldb_module *backend_module, *module_chain;
     168        6017 :         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        6017 :         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        6017 :         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        6017 :         const char **link_modules;
     218        6017 :         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        6017 :         const char *extended_dn_module;
     231      182011 :         const char *extended_dn_module_ldb = "extended_dn_out_ldb";
     232      182011 :         const char *extended_dn_in_module = "extended_dn_in";
     233             : 
     234        6017 :         static const char *modules_list2[] = {"dns_notify",
     235             :                                               "show_deleted",
     236             :                                               "new_partition",
     237             :                                               "partition",
     238             :                                               NULL };
     239             : 
     240        6017 :         const char **backend_modules;
     241        6017 :         static const char *samba_dsdb_attrs[] = { SAMBA_COMPATIBLE_FEATURES_ATTR,
     242             :                                                   SAMBA_REQUIRED_FEATURES_ATTR, NULL };
     243        6017 :         static const char *indexlist_attrs[] = { SAMBA_FEATURES_SUPPORTED_FLAG, NULL };
     244             : 
     245      182011 :         const char *current_supportedFeatures[] = {SAMBA_SORTED_LINKS_FEATURE};
     246             : 
     247      182011 :         if (!tmp_ctx) {
     248           0 :                 return ldb_oom(ldb);
     249             :         }
     250             : 
     251      182011 :         ret = ldb_register_samba_handlers(ldb);
     252      182011 :         if (ret != LDB_SUCCESS) {
     253           0 :                 talloc_free(tmp_ctx);
     254           0 :                 return ret;
     255             :         }
     256             : 
     257      182011 :         samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
     258      182011 :         if (!samba_dsdb_dn) {
     259           0 :                 talloc_free(tmp_ctx);
     260           0 :                 return ldb_oom(ldb);
     261             :         }
     262             : 
     263      182011 :         indexlist_dn = ldb_dn_new(tmp_ctx, ldb, "@INDEXLIST");
     264      182011 :         if (!samba_dsdb_dn) {
     265           0 :                 talloc_free(tmp_ctx);
     266           0 :                 return ldb_oom(ldb);
     267             :         }
     268             : 
     269      182011 :         partition_dn = ldb_dn_new(tmp_ctx, ldb, DSDB_PARTITION_DN);
     270      182011 :         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      182011 :         ret = dsdb_module_search_dn(module, tmp_ctx, &res, samba_dsdb_dn,
     284             :                                     samba_dsdb_attrs, DSDB_FLAG_NEXT_MODULE, NULL);
     285      182011 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     286             :                 /* do nothing, a very old db being upgraded */
     287      182005 :         } else if (ret == LDB_SUCCESS) {
     288        6017 :                 struct ldb_message_element *requiredFeatures;
     289        6017 :                 struct ldb_message_element *old_compatibleFeatures;
     290             : 
     291      182005 :                 requiredFeatures = ldb_msg_find_element(res->msgs[0], SAMBA_REQUIRED_FEATURES_ATTR);
     292      182005 :                 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      182004 :                 old_compatibleFeatures = ldb_msg_find_element(res->msgs[0],
     304             :                                                               SAMBA_COMPATIBLE_FEATURES_ATTR);
     305             : 
     306      182004 :                 if (old_compatibleFeatures) {
     307        5937 :                         struct ldb_message *features_msg;
     308        5937 :                         struct ldb_message_element *features_el;
     309      181696 :                         int samba_options_supported = 0;
     310      181696 :                         ret = dsdb_module_search_dn(module, tmp_ctx, &res,
     311             :                                                     indexlist_dn,
     312             :                                                     indexlist_attrs,
     313             :                                                     DSDB_FLAG_NEXT_MODULE, NULL);
     314      181696 :                         if (ret == LDB_SUCCESS) {
     315        5914 :                                 samba_options_supported
     316      181491 :                                         = ldb_msg_find_attr_as_int(res->msgs[0],
     317             :                                                                    SAMBA_FEATURES_SUPPORTED_FLAG,
     318             :                                                                    0);
     319             : 
     320         205 :                         } 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         205 :                                 samba_options_supported = 1;
     328             :                         }
     329             : 
     330      181696 :                         features_msg = ldb_msg_new(res);
     331      181696 :                         if (features_msg == NULL) {
     332           0 :                                 return ldb_module_operr(module);
     333             :                         }
     334      181696 :                         features_msg->dn = samba_dsdb_dn;
     335             : 
     336      181696 :                         ret = ldb_msg_add_empty(features_msg, SAMBA_COMPATIBLE_FEATURES_ATTR,
     337             :                                                 LDB_FLAG_MOD_DELETE, &features_el);
     338      181696 :                         if (ret != LDB_SUCCESS) {
     339           0 :                                 return ret;
     340             :                         }
     341             : 
     342      181696 :                         if (samba_options_supported == 1) {
     343      175759 :                                 for (i = 0;
     344      363393 :                                      old_compatibleFeatures && i < old_compatibleFeatures->num_values;
     345      181697 :                                      i++) {
     346      175759 :                                         for (j = 0;
     347      181698 :                                              j < ARRAY_SIZE(current_supportedFeatures); j++) {
     348      181697 :                                                 if (strcmp((char *)old_compatibleFeatures->values[i].data,
     349             :                                                            current_supportedFeatures[j]) == 0) {
     350      175759 :                                                         break;
     351             :                                                 }
     352             :                                         }
     353      181697 :                                         if (j == ARRAY_SIZE(current_supportedFeatures)) {
     354             :                                                 /*
     355             :                                                  * Add to list of features to remove
     356             :                                                  * (rather than all features)
     357             :                                                  */
     358           2 :                                                 ret = ldb_msg_add_value(features_msg, SAMBA_COMPATIBLE_FEATURES_ATTR,
     359           1 :                                                                         &old_compatibleFeatures->values[i],
     360             :                                                                         NULL);
     361           1 :                                                 if (ret != LDB_SUCCESS) {
     362           0 :                                                         return ret;
     363             :                                                 }
     364             :                                         }
     365             :                                 }
     366             : 
     367      181696 :                                 if (features_el->num_values > 0) {
     368             :                                         /* Delete by list */
     369           1 :                                         ret = ldb_next_start_trans(module);
     370           1 :                                         if (ret != LDB_SUCCESS) {
     371           0 :                                                 return ret;
     372             :                                         }
     373           1 :                                         ret = dsdb_module_modify(module, features_msg, DSDB_FLAG_NEXT_MODULE, NULL);
     374           1 :                                         if (ret != LDB_SUCCESS) {
     375           0 :                                                 ldb_next_del_trans(module);
     376           0 :                                                 return ret;
     377             :                                         }
     378           1 :                                         ret = ldb_next_end_trans(module);
     379           1 :                                         if (ret != LDB_SUCCESS) {
     380           0 :                                                 return ret;
     381             :                                         }
     382             :                                 }
     383             :                         } else {
     384             :                                 /* Delete all */
     385           0 :                                 ret = ldb_next_start_trans(module);
     386           0 :                                 if (ret != LDB_SUCCESS) {
     387           0 :                                         return ret;
     388             :                                 }
     389           0 :                                 ret = dsdb_module_modify(module, features_msg, DSDB_FLAG_NEXT_MODULE, NULL);
     390           0 :                                 if (ret != LDB_SUCCESS) {
     391           0 :                                         ldb_next_del_trans(module);
     392           0 :                                         return ret;
     393             :                                 }
     394           0 :                                 ret = ldb_next_end_trans(module);
     395           0 :                                 if (ret != LDB_SUCCESS) {
     396           0 :                                         return ret;
     397             :                                 }
     398             :                         }
     399             :                 }
     400             : 
     401             :         } else {
     402           0 :                 talloc_free(tmp_ctx);
     403           0 :                 return ret;
     404             :         }
     405             : 
     406      182010 :         backend_modules = NULL;
     407      182010 :         extended_dn_module = extended_dn_module_ldb;
     408      182010 :         link_modules = tdb_modules_list;
     409             : 
     410             : #define CHECK_MODULE_LIST \
     411             :         do {                                                    \
     412             :                 if (!final_module_list) {                       \
     413             :                         talloc_free(tmp_ctx);                   \
     414             :                         return ldb_oom(ldb);                    \
     415             :                 }                                               \
     416             :         } while (0)
     417             : 
     418      182010 :         final_module_list = str_list_copy_const(tmp_ctx, modules_list1);
     419      182010 :         CHECK_MODULE_LIST;
     420             : 
     421      182010 :         final_module_list = str_list_add_const(final_module_list, extended_dn_in_module);
     422      182010 :         CHECK_MODULE_LIST;
     423             : 
     424      182010 :         final_module_list = str_list_append_const(final_module_list, modules_list1a);
     425      182010 :         CHECK_MODULE_LIST;
     426             : 
     427      182010 :         final_module_list = str_list_append_const(final_module_list, link_modules);
     428      182010 :         CHECK_MODULE_LIST;
     429             : 
     430      182010 :         final_module_list = str_list_add_const(final_module_list, extended_dn_module);
     431      182010 :         CHECK_MODULE_LIST;
     432             : 
     433      182010 :         final_module_list = str_list_append_const(final_module_list, modules_list2);
     434      182010 :         CHECK_MODULE_LIST;
     435             : 
     436             : 
     437      182010 :         ret = read_at_rootdse_record(ldb, module, tmp_ctx, &rootdse_msg, NULL);
     438      182010 :         CHECK_LDB_RET(ret);
     439             : 
     440      182004 :         partition_msg = ldb_msg_new(tmp_ctx);
     441      182004 :         partition_msg->dn = ldb_dn_new(partition_msg, ldb, "@" DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME);
     442             : 
     443      182004 :         ret = prepare_modules_line(ldb, tmp_ctx,
     444             :                                    rootdse_msg,
     445             :                                    partition_msg, "schemaNamingContext",
     446             :                                    "schema_data", backend_modules);
     447      182004 :         CHECK_LDB_RET(ret);
     448             : 
     449      182004 :         ret = prepare_modules_line(ldb, tmp_ctx,
     450             :                                    rootdse_msg,
     451             :                                    partition_msg, NULL,
     452             :                                    NULL, backend_modules);
     453      182004 :         CHECK_LDB_RET(ret);
     454             : 
     455      182004 :         ret = ldb_set_opaque(ldb, DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME, partition_msg);
     456      182004 :         CHECK_LDB_RET(ret);
     457             : 
     458      182004 :         talloc_steal(ldb, partition_msg);
     459             : 
     460             :         /* Now prepare the module chain. Oddly, we must give it to
     461             :          * ldb_module_load_list in REVERSE */
     462     7104172 :         for (len = 0; final_module_list[len]; len++) { /* noop */};
     463             : 
     464      182004 :         reverse_module_list = talloc_array(tmp_ctx, const char *, len+1);
     465      182004 :         if (!reverse_module_list) {
     466           0 :                 talloc_free(tmp_ctx);
     467           0 :                 return ldb_oom(ldb);
     468             :         }
     469     7098156 :         for (i=0; i < len; i++) {
     470     6916152 :                 reverse_module_list[i] = final_module_list[(len - 1) - i];
     471             :         }
     472      182004 :         reverse_module_list[i] = NULL;
     473             : 
     474             :         /* The backend (at least until the partitions module
     475             :          * reconfigures things) is the next module in the currently
     476             :          * loaded chain */
     477      182004 :         backend_module = ldb_module_next(module);
     478      182004 :         ret = ldb_module_load_list(ldb, reverse_module_list, backend_module, &module_chain);
     479      182004 :         CHECK_LDB_RET(ret);
     480             : 
     481      182004 :         talloc_free(tmp_ctx);
     482             :         /* Set this as the 'next' module, so that we effectively append it to
     483             :          * module chain */
     484      182004 :         ldb_module_set_next(module, module_chain);
     485             : 
     486      182004 :         ret = ldb_next_read_lock(module);
     487      182004 :         if (ret != LDB_SUCCESS) {
     488           0 :                 return ret;
     489             :         }
     490             : 
     491      182004 :         ret = ldb_next_init(module);
     492             : 
     493      182004 :         lock_ret = ldb_next_read_unlock(module);
     494             : 
     495      182004 :         if (lock_ret != LDB_SUCCESS) {
     496           0 :                 return lock_ret;
     497             :         }
     498             : 
     499      175988 :         return ret;
     500             : }
     501             : 
     502             : static const struct ldb_module_ops ldb_samba_dsdb_module_ops = {
     503             :         .name              = "samba_dsdb",
     504             :         .init_context      = samba_dsdb_init,
     505             : };
     506             : 
     507          35 : static struct ldb_message *dsdb_flags_ignore_fixup(TALLOC_CTX *mem_ctx,
     508             :                                                 const struct ldb_message *_msg)
     509             : {
     510          35 :         struct ldb_message *msg = NULL;
     511          35 :         unsigned int i;
     512             : 
     513             :         /* we have to copy the message as the caller might have it as a const */
     514          35 :         msg = ldb_msg_copy_shallow(mem_ctx, _msg);
     515          35 :         if (msg == NULL) {
     516           0 :                 return NULL;
     517             :         }
     518             : 
     519         212 :         for (i=0; i < msg->num_elements;) {
     520         177 :                 struct ldb_message_element *e = &msg->elements[i];
     521             : 
     522         177 :                 if (!(e->flags & DSDB_FLAG_INTERNAL_FORCE_META_DATA)) {
     523         165 :                         i++;
     524         165 :                         continue;
     525             :                 }
     526             : 
     527          12 :                 e->flags &= ~DSDB_FLAG_INTERNAL_FORCE_META_DATA;
     528             : 
     529          12 :                 if (e->num_values != 0) {
     530           2 :                         i++;
     531           2 :                         continue;
     532             :                 }
     533             : 
     534          10 :                 ldb_msg_remove_element(msg, e);
     535             :         }
     536             : 
     537           0 :         return msg;
     538             : }
     539             : 
     540          16 : static int dsdb_flags_ignore_add(struct ldb_module *module, struct ldb_request *req)
     541             : {
     542          16 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     543          16 :         struct ldb_request *down_req = NULL;
     544          16 :         struct ldb_message *msg = NULL;
     545          16 :         int ret;
     546             : 
     547          16 :         msg = dsdb_flags_ignore_fixup(req, req->op.add.message);
     548          16 :         if (msg == NULL) {
     549           0 :                 return ldb_module_oom(module);
     550             :         }
     551             : 
     552          16 :         ret = ldb_build_add_req(&down_req, ldb, req,
     553             :                                 msg,
     554             :                                 req->controls,
     555             :                                 req, dsdb_next_callback,
     556             :                                 req);
     557          16 :         LDB_REQ_SET_LOCATION(down_req);
     558          16 :         if (ret != LDB_SUCCESS) {
     559           0 :                 return ret;
     560             :         }
     561             : 
     562             :         /* go on with the call chain */
     563          16 :         return ldb_next_request(module, down_req);
     564             : }
     565             : 
     566          19 : static int dsdb_flags_ignore_modify(struct ldb_module *module, struct ldb_request *req)
     567             : {
     568          19 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     569          19 :         struct ldb_request *down_req = NULL;
     570          19 :         struct ldb_message *msg = NULL;
     571          19 :         int ret;
     572             : 
     573          19 :         msg = dsdb_flags_ignore_fixup(req, req->op.mod.message);
     574          19 :         if (msg == NULL) {
     575           0 :                 return ldb_module_oom(module);
     576             :         }
     577             : 
     578          19 :         ret = ldb_build_mod_req(&down_req, ldb, req,
     579             :                                 msg,
     580             :                                 req->controls,
     581             :                                 req, dsdb_next_callback,
     582             :                                 req);
     583          19 :         LDB_REQ_SET_LOCATION(down_req);
     584          19 :         if (ret != LDB_SUCCESS) {
     585           0 :                 return ret;
     586             :         }
     587             : 
     588             :         /* go on with the call chain */
     589          19 :         return ldb_next_request(module, down_req);
     590             : }
     591             : 
     592             : static const struct ldb_module_ops ldb_dsdb_flags_ignore_module_ops = {
     593             :         .name   = "dsdb_flags_ignore",
     594             :         .add    = dsdb_flags_ignore_add,
     595             :         .modify = dsdb_flags_ignore_modify,
     596             : };
     597             : 
     598        6040 : int ldb_samba_dsdb_module_init(const char *version)
     599             : {
     600         444 :         int ret;
     601        6040 :         LDB_MODULE_CHECK_VERSION(version);
     602        6040 :         ret = ldb_register_module(&ldb_samba_dsdb_module_ops);
     603        6040 :         if (ret != LDB_SUCCESS) {
     604           0 :                 return ret;
     605             :         }
     606        6040 :         ret = ldb_register_module(&ldb_dsdb_flags_ignore_module_ops);
     607        6040 :         if (ret != LDB_SUCCESS) {
     608           0 :                 return ret;
     609             :         }
     610        5596 :         return LDB_SUCCESS;
     611             : }

Generated by: LCOV version 1.14