LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules - schema_data.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 200 316 63.3 %
Date: 2024-04-21 15:09:00 Functions: 10 13 76.9 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS Implementation.
       3             : 
       4             :    The module that handles the Schema checkings and dynamic attributes
       5             :    
       6             :    Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
       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             : 
      24             : #include "includes.h"
      25             : #include "ldb_module.h"
      26             : #include "dsdb/samdb/samdb.h"
      27             : #include "librpc/gen_ndr/ndr_misc.h"
      28             : #include "librpc/gen_ndr/ndr_drsuapi.h"
      29             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      30             : #include "param/param.h"
      31             : #include "dsdb/samdb/ldb_modules/util.h"
      32             : 
      33             : #undef strcasecmp
      34             : 
      35             : static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
      36             :                                   const struct dsdb_schema *schema);
      37             : static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
      38             :                                    const struct dsdb_schema *schema);
      39             : static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
      40             :                                     const struct dsdb_schema *schema);
      41             : static int generate_extendedAttributeInfo(struct ldb_context *ldb, struct ldb_message *msg,
      42             :                                           const struct dsdb_schema *schema);
      43             : static int generate_extendedClassInfo(struct ldb_context *ldb, struct ldb_message *msg,
      44             :                                       const struct dsdb_schema *schema);
      45             : static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_message *msg,
      46             :                                       const struct dsdb_schema *schema);
      47             : 
      48             : static const struct {
      49             :         const char *attr;
      50             :         int (*fn)(struct ldb_context *, struct ldb_message *, const struct dsdb_schema *);
      51             :         bool aggregate;
      52             : } generated_attrs[] = {
      53             :         {
      54             :                 .attr = "objectClasses",
      55             :                 .fn = generate_objectClasses,
      56             :                 .aggregate = true,
      57             :         },
      58             :         {
      59             :                 .attr = "attributeTypes",
      60             :                 .fn = generate_attributeTypes,
      61             :                 .aggregate = true,
      62             :         },
      63             :         {
      64             :                 .attr = "dITContentRules",
      65             :                 .fn = generate_dITContentRules,
      66             :                 .aggregate = true,
      67             :         },
      68             :         {
      69             :                 .attr = "extendedAttributeInfo",
      70             :                 .fn = generate_extendedAttributeInfo,
      71             :                 .aggregate = true,
      72             :         },
      73             :         {
      74             :                 .attr = "extendedClassInfo",
      75             :                 .fn = generate_extendedClassInfo,
      76             :                 .aggregate = true,
      77             :         },
      78             :         {
      79             :                 .attr = "possibleInferiors",
      80             :                 .fn = generate_possibleInferiors,
      81             :                 .aggregate = false,
      82             :         }
      83             : };
      84             : 
      85             : struct schema_data_private_data {
      86             :         struct ldb_dn *aggregate_dn;
      87             :         struct ldb_dn *schema_dn;
      88             : };
      89             : 
      90             : struct schema_data_search_data {
      91             :         struct ldb_module *module;
      92             :         struct ldb_request *req;
      93             : 
      94             :         const struct dsdb_schema *schema;
      95             : };
      96             : 
      97      182002 : static int schema_data_init(struct ldb_module *module)
      98             : {
      99        6015 :         struct ldb_context *ldb;
     100        6015 :         struct ldb_dn *schema_dn;
     101        6015 :         int ret;
     102        6015 :         struct schema_data_private_data *data;
     103             : 
     104      182002 :         ret = ldb_next_init(module);
     105      182002 :         if (ret != LDB_SUCCESS) {
     106           0 :                 return ret;
     107             :         }
     108             : 
     109      182002 :         ldb = ldb_module_get_ctx(module);
     110      182002 :         schema_dn = ldb_get_schema_basedn(ldb);
     111      182002 :         if (!schema_dn) {
     112           0 :                 ldb_reset_err_string(ldb);
     113           0 :                 ldb_debug(ldb, LDB_DEBUG_WARNING,
     114             :                           "schema_data_init: no schema dn present: (skip schema loading)\n");
     115           0 :                 return LDB_SUCCESS;
     116             :         }
     117             : 
     118      182002 :         data = talloc(module, struct schema_data_private_data);
     119      182002 :         if (data == NULL) {
     120           0 :                 return ldb_oom(ldb);
     121             :         }
     122             : 
     123      182002 :         data->schema_dn = schema_dn;
     124             : 
     125             :         /* Used to check to see if this is a result on the CN=Aggregate schema */
     126      182002 :         data->aggregate_dn = samdb_aggregate_schema_dn(ldb, data);
     127      182002 :         if (!data->aggregate_dn) {
     128           0 :                 ldb_asprintf_errstring(ldb, "schema_data_init: Could not build aggregate schema DN for schema in %s", ldb_dn_get_linearized(schema_dn));
     129           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     130             :         }
     131             : 
     132      182002 :         ldb_module_set_private(module, data);
     133      182002 :         return LDB_SUCCESS;
     134             : }
     135             : 
     136      350703 : static int schema_data_add(struct ldb_module *module, struct ldb_request *req)
     137             : {
     138       39060 :         struct ldb_context *ldb;
     139       39060 :         struct dsdb_schema *schema;
     140      350703 :         const struct ldb_val *attributeID = NULL;
     141      350703 :         const struct ldb_val *governsID = NULL;
     142      350703 :         const char *oid_attr = NULL;
     143      350703 :         const char *oid = NULL;
     144      350703 :         struct ldb_dn *parent_dn = NULL;
     145       39060 :         int cmp;
     146       39060 :         WERROR status;
     147      350703 :         bool rodc = false;
     148       39060 :         int ret;
     149       39060 :         struct schema_data_private_data *mc;
     150      350703 :         mc = talloc_get_type(ldb_module_get_private(module), struct schema_data_private_data);
     151             : 
     152      350703 :         ldb = ldb_module_get_ctx(module);
     153             : 
     154             :         /* special objects should always go through */
     155      350703 :         if (ldb_dn_is_special(req->op.add.message->dn)) {
     156        1084 :                 return ldb_next_request(module, req);
     157             :         }
     158             : 
     159             :         /* replicated update should always go through */
     160      349619 :         if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
     161      131383 :                 return ldb_next_request(module, req);
     162             :         }
     163             : 
     164      218236 :         schema = dsdb_get_schema(ldb, req);
     165      218236 :         if (!schema) {
     166           0 :                 return ldb_next_request(module, req);
     167             :         }
     168             : 
     169      218236 :         ret = samdb_rodc(ldb, &rodc);
     170      218236 :         if (ret != LDB_SUCCESS) {
     171           0 :                 DEBUG(4, (__location__ ": unable to tell if we are an RODC \n"));
     172             :         }
     173             : 
     174      218236 :         if (!schema->fsmo.we_are_master && !rodc) {
     175           0 :                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     176             :                           "schema_data_add: we are not master: reject add request\n");
     177           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     178             :         }
     179             : 
     180      218236 :         if (!schema->fsmo.update_allowed && !rodc) {
     181           0 :                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     182             :                           "schema_data_add: updates are not allowed: reject add request\n");
     183           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     184             :         }
     185             : 
     186      218236 :         if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
     187             :                 /*
     188             :                  * the provision code needs to create
     189             :                  * the schema root object.
     190             :                  */
     191      217291 :                 cmp = ldb_dn_compare(req->op.add.message->dn, mc->schema_dn);
     192      217291 :                 if (cmp == 0) {
     193         127 :                         return ldb_next_request(module, req);
     194             :                 }
     195             :         }
     196             : 
     197      218109 :         parent_dn = ldb_dn_get_parent(req, req->op.add.message->dn);
     198      218109 :         if (!parent_dn) {
     199           0 :                 return ldb_oom(ldb);
     200             :         }
     201             : 
     202      218109 :         cmp = ldb_dn_compare(parent_dn, mc->schema_dn);
     203      218109 :         if (cmp != 0) {
     204           0 :                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     205             :                           "schema_data_add: no direct child :%s\n",
     206           0 :                           ldb_dn_get_linearized(req->op.add.message->dn));
     207           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     208             :         }
     209             : 
     210      218109 :         attributeID = ldb_msg_find_ldb_val(req->op.add.message, "attributeID");
     211      218109 :         governsID = ldb_msg_find_ldb_val(req->op.add.message, "governsID");
     212             : 
     213      218109 :         if (attributeID) {
     214      184310 :                 oid_attr = "attributeID";
     215      184310 :                 oid = talloc_strndup(req, (const char *)attributeID->data, attributeID->length);
     216       33799 :         } else if (governsID) {
     217       33672 :                 oid_attr = "governsID";
     218       33672 :                 oid = talloc_strndup(req, (const char *)governsID->data, governsID->length);
     219             :         } else {
     220         127 :                 return ldb_next_request(module, req);
     221             :         }
     222             : 
     223      217982 :         if (!oid) {
     224           0 :                 return ldb_oom(ldb);
     225             :         }
     226             : 
     227      217982 :         status = dsdb_schema_pfm_find_oid(schema->prefixmap, oid, NULL);
     228      217982 :         if (!W_ERROR_IS_OK(status)) {
     229             :                 /* check for internal errors */
     230         686 :                 if (!W_ERROR_EQUAL(status, WERR_NOT_FOUND)) {
     231           0 :                         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     232             :                                       "schema_data_add: failed to map %s[%s]: %s\n",
     233             :                                       oid_attr, oid, win_errstr(status));
     234           0 :                         return LDB_ERR_UNWILLING_TO_PERFORM;
     235             :                 }
     236             : 
     237             :                 /* Update prefixMap and save it */
     238         686 :                 status = dsdb_create_prefix_mapping(ldb, schema, oid);
     239         686 :                 if (!W_ERROR_IS_OK(status)) {
     240           0 :                         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     241             :                                   "schema_data_add: failed to create prefix mapping for %s[%s]: %s\n",
     242             :                                   oid_attr, oid, win_errstr(status));
     243           0 :                         return LDB_ERR_UNWILLING_TO_PERFORM;
     244             :                 }
     245             :         }
     246             : 
     247      217982 :         return ldb_next_request(module, req);
     248             : }
     249             : 
     250      333948 : static int schema_data_modify(struct ldb_module *module, struct ldb_request *req)
     251             : {
     252       12558 :         struct ldb_context *ldb;
     253       12558 :         struct dsdb_schema *schema;
     254       12558 :         int cmp;
     255      333948 :         bool rodc = false;
     256       12558 :         int ret;
     257       12558 :         struct ldb_control *sd_propagation_control;
     258       12558 :         struct schema_data_private_data *mc;
     259      333948 :         mc = talloc_get_type(ldb_module_get_private(module), struct schema_data_private_data);
     260             : 
     261      333948 :         ldb = ldb_module_get_ctx(module);
     262             : 
     263             :         /* special objects should always go through */
     264      333948 :         if (ldb_dn_is_special(req->op.mod.message->dn)) {
     265        2256 :                 return ldb_next_request(module, req);
     266             :         }
     267             : 
     268             :         /* replicated update should always go through */
     269      331692 :         if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
     270         275 :                 return ldb_next_request(module, req);
     271             :         }
     272             : 
     273             :         /* dbcheck should be able to fix things */
     274      331417 :         if (ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
     275       48382 :                 return ldb_next_request(module, req);
     276             :         }
     277             : 
     278      283035 :         sd_propagation_control = ldb_request_get_control(req,
     279             :                                         DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
     280      283035 :         if (sd_propagation_control != NULL) {
     281      241922 :                 if (req->op.mod.message->num_elements != 1) {
     282           0 :                         return ldb_module_operr(module);
     283             :                 }
     284      241922 :                 ret = strcmp(req->op.mod.message->elements[0].name,
     285             :                              "nTSecurityDescriptor");
     286      241922 :                 if (ret != 0) {
     287           0 :                         return ldb_module_operr(module);
     288             :                 }
     289             : 
     290      241922 :                 return ldb_next_request(module, req);
     291             :         }
     292             : 
     293       41113 :         schema = dsdb_get_schema(ldb, req);
     294       41113 :         if (!schema) {
     295           0 :                 return ldb_next_request(module, req);
     296             :         }
     297             : 
     298       41113 :         cmp = ldb_dn_compare(req->op.mod.message->dn, mc->schema_dn);
     299       41113 :         if (cmp == 0) {
     300         127 :                 static const char * const constrained_attrs[] = {
     301             :                         "schemaInfo",
     302             :                         "prefixMap",
     303             :                         "msDs-Schema-Extensions",
     304             :                         "msDS-IntId",
     305             :                         NULL
     306             :                 };
     307         127 :                 size_t i;
     308         127 :                 struct ldb_message_element *el;
     309             : 
     310        6729 :                 if (ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID)) {
     311        2762 :                         return ldb_next_request(module, req);
     312             :                 }
     313             : 
     314       19835 :                 for (i=0; constrained_attrs[i]; i++) {
     315       15868 :                         el = ldb_msg_find_element(req->op.mod.message,
     316       15448 :                                                   constrained_attrs[i]);
     317       15868 :                         if (el == NULL) {
     318       15868 :                                 continue;
     319             :                         }
     320             : 
     321           0 :                         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     322             :                                       "schema_data_modify: reject update "
     323             :                                       "of attribute[%s]\n",
     324           0 :                                       constrained_attrs[i]);
     325           0 :                         return LDB_ERR_CONSTRAINT_VIOLATION;
     326             :                 }
     327             : 
     328        3967 :                 return ldb_next_request(module, req);
     329             :         }
     330             : 
     331       34384 :         ret = samdb_rodc(ldb, &rodc);
     332       34384 :         if (ret != LDB_SUCCESS) {
     333           0 :                 DEBUG(4, (__location__ ": unable to tell if we are an RODC \n"));
     334             :         }
     335             : 
     336       34384 :         if (!schema->fsmo.we_are_master && !rodc) {
     337           0 :                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     338             :                           "schema_data_modify: we are not master: reject modify request\n");
     339           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     340             :         }
     341             : 
     342       34384 :         if (!schema->fsmo.update_allowed && !rodc) {
     343           0 :                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     344             :                           "schema_data_modify: updates are not allowed: reject modify request\n");
     345           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     346             :         }
     347             : 
     348       34384 :         return ldb_next_request(module, req);
     349             : }
     350             : 
     351           0 : static int schema_data_del(struct ldb_module *module, struct ldb_request *req)
     352             : {
     353           0 :         struct ldb_context *ldb;
     354           0 :         struct dsdb_schema *schema;
     355           0 :         bool rodc = false;
     356           0 :         int ret;
     357             : 
     358           0 :         ldb = ldb_module_get_ctx(module);
     359             : 
     360             :         /* special objects should always go through */
     361           0 :         if (ldb_dn_is_special(req->op.del.dn)) {
     362           0 :                 return ldb_next_request(module, req);
     363             :         }
     364             : 
     365             :         /* replicated update should always go through */
     366           0 :         if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
     367           0 :                 return ldb_next_request(module, req);
     368             :         }
     369             : 
     370             :         /* dbcheck should be able to fix things */
     371           0 :         if (ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
     372           0 :                 return ldb_next_request(module, req);
     373             :         }
     374             : 
     375           0 :         schema = dsdb_get_schema(ldb, req);
     376           0 :         if (!schema) {
     377           0 :                 return ldb_next_request(module, req);
     378             :         }
     379             : 
     380           0 :         ret = samdb_rodc(ldb, &rodc);
     381           0 :         if (ret != LDB_SUCCESS) {
     382           0 :                 DEBUG(4, (__location__ ": unable to tell if we are an RODC \n"));
     383             :         }
     384             : 
     385           0 :         if (!schema->fsmo.we_are_master && !rodc) {
     386           0 :                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     387             :                           "schema_data_modify: we are not master: reject request\n");
     388           0 :                 return LDB_ERR_UNWILLING_TO_PERFORM;
     389             :         }
     390             : 
     391             :         /*
     392             :          * normally the DACL will prevent delete
     393             :          * with LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
     394             :          * above us.
     395             :          */
     396           0 :         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
     397             :                       "schema_data_del: delete is not allowed in the schema\n");
     398           0 :         return LDB_ERR_UNWILLING_TO_PERFORM;
     399             : }
     400             : 
     401           9 : static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
     402             :                                   const struct dsdb_schema *schema) 
     403             : {
     404           0 :         const struct dsdb_class *sclass;
     405           0 :         int ret;
     406             : 
     407        2170 :         for (sclass = schema->classes; sclass; sclass = sclass->next) {
     408        2161 :                 char *v = schema_class_to_description(msg, sclass);
     409        2161 :                 if (v == NULL) {
     410           0 :                         return ldb_oom(ldb);
     411             :                 }
     412        2161 :                 ret = ldb_msg_add_steal_string(msg, "objectClasses", v);
     413        2161 :                 if (ret != LDB_SUCCESS) {
     414           0 :                         return ret;
     415             :                 }
     416             :         }
     417           9 :         return LDB_SUCCESS;
     418             : }
     419           9 : static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
     420             :                                   const struct dsdb_schema *schema) 
     421             : {
     422           0 :         const struct dsdb_attribute *attribute;
     423           0 :         int ret;
     424             : 
     425       12178 :         for (attribute = schema->attributes; attribute; attribute = attribute->next) {
     426       12169 :                 char *v = schema_attribute_to_description(msg, attribute);
     427       12169 :                 if (v == NULL) {
     428           0 :                         return ldb_oom(ldb);
     429             :                 }
     430       12169 :                 ret = ldb_msg_add_steal_string(msg, "attributeTypes", v);
     431       12169 :                 if (ret != LDB_SUCCESS) {
     432           0 :                         return ret;
     433             :                 }
     434             :         }
     435           9 :         return LDB_SUCCESS;
     436             : }
     437             : 
     438           9 : static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
     439             :                                     const struct dsdb_schema *schema) 
     440             : {
     441           0 :         const struct dsdb_class *sclass;
     442           0 :         int ret;
     443             : 
     444        2170 :         for (sclass = schema->classes; sclass; sclass = sclass->next) {
     445        2161 :                 if (sclass->auxiliaryClass || sclass->systemAuxiliaryClass) {
     446          81 :                         char *ditcontentrule = schema_class_to_dITContentRule(msg, sclass, schema);
     447          81 :                         if (!ditcontentrule) {
     448           0 :                                 return ldb_oom(ldb);
     449             :                         }
     450          81 :                         ret = ldb_msg_add_steal_string(msg, "dITContentRules", ditcontentrule);
     451          81 :                         if (ret != LDB_SUCCESS) {
     452           0 :                                 return ret;
     453             :                         }
     454             :                 }
     455             :         }
     456           9 :         return LDB_SUCCESS;
     457             : }
     458             : 
     459           0 : static int generate_extendedAttributeInfo(struct ldb_context *ldb,
     460             :                                           struct ldb_message *msg,
     461             :                                           const struct dsdb_schema *schema)
     462             : {
     463           0 :         const struct dsdb_attribute *attribute;
     464           0 :         int ret;
     465             : 
     466           0 :         for (attribute = schema->attributes; attribute; attribute = attribute->next) {
     467           0 :                 char *val = schema_attribute_to_extendedInfo(msg, attribute);
     468           0 :                 if (!val) {
     469           0 :                         return ldb_oom(ldb);
     470             :                 }
     471             : 
     472           0 :                 ret = ldb_msg_add_steal_string(msg, "extendedAttributeInfo", val);
     473           0 :                 if (ret != LDB_SUCCESS) {
     474           0 :                         return ret;
     475             :                 }
     476             :         }
     477             : 
     478           0 :         return LDB_SUCCESS;
     479             : }
     480             : 
     481           0 : static int generate_extendedClassInfo(struct ldb_context *ldb,
     482             :                                       struct ldb_message *msg,
     483             :                                       const struct dsdb_schema *schema)
     484             : {
     485           0 :         const struct dsdb_class *sclass;
     486           0 :         int ret;
     487             : 
     488           0 :         for (sclass = schema->classes; sclass; sclass = sclass->next) {
     489           0 :                 char *val = schema_class_to_extendedInfo(msg, sclass);
     490           0 :                 if (!val) {
     491           0 :                         return ldb_oom(ldb);
     492             :                 }
     493             : 
     494           0 :                 ret = ldb_msg_add_steal_string(msg, "extendedClassInfo", val);
     495           0 :                 if (ret != LDB_SUCCESS) {
     496           0 :                         return ret;
     497             :                 }
     498             :         }
     499             : 
     500           0 :         return LDB_SUCCESS;
     501             : }
     502             : 
     503             : 
     504        2215 : static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_message *msg,
     505             :                                       const struct dsdb_schema *schema) 
     506             : {
     507        2215 :         struct ldb_dn *dn = msg->dn;
     508           0 :         unsigned int i;
     509           0 :         int ret;
     510        2215 :         const char *first_component_name = ldb_dn_get_component_name(dn, 0);
     511           0 :         const struct ldb_val *first_component_val;
     512           0 :         const struct dsdb_class *schema_class;
     513           0 :         const char **possibleInferiors;
     514             : 
     515        2215 :         if (strcasecmp(first_component_name, "cn") != 0) {
     516           0 :                 return LDB_SUCCESS;
     517             :         }
     518             : 
     519        2215 :         first_component_val = ldb_dn_get_component_val(dn, 0);
     520             : 
     521        2215 :         schema_class = dsdb_class_by_cn_ldb_val(schema, first_component_val);
     522        2215 :         if (schema_class == NULL) {
     523           0 :                 return LDB_SUCCESS;
     524             :         }
     525             :         
     526        2215 :         possibleInferiors = schema_class->possibleInferiors;
     527        2215 :         if (possibleInferiors == NULL) {
     528        1361 :                 return LDB_SUCCESS;
     529             :         }
     530             : 
     531       13528 :         for (i=0;possibleInferiors[i];i++) {
     532       12674 :                 char *v = talloc_strdup(msg, possibleInferiors[i]);
     533       12674 :                 if (v == NULL) {
     534           0 :                         return ldb_oom(ldb);
     535             :                 }
     536       12674 :                 ret = ldb_msg_add_steal_string(msg, "possibleInferiors", v);
     537       12674 :                 if (ret != LDB_SUCCESS) {
     538           0 :                         return ret;
     539             :                 }
     540             :         }
     541             : 
     542         854 :         return LDB_SUCCESS;
     543             : }
     544             : 
     545             : 
     546             : /* Add objectClasses, attributeTypes and dITContentRules from the
     547             :    schema object (they are not stored in the database)
     548             :  */
     549        4448 : static int schema_data_search_callback(struct ldb_request *req, struct ldb_reply *ares)
     550             : {
     551           0 :         struct ldb_context *ldb;
     552           0 :         struct schema_data_search_data *ac;
     553           0 :         struct schema_data_private_data *mc;
     554           0 :         unsigned int i;
     555           0 :         int ret;
     556             : 
     557        4448 :         ac = talloc_get_type(req->context, struct schema_data_search_data);
     558        4448 :         mc = talloc_get_type(ldb_module_get_private(ac->module), struct schema_data_private_data);
     559        4448 :         ldb = ldb_module_get_ctx(ac->module);
     560             : 
     561        4448 :         if (!ares) {
     562           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     563             :                                         LDB_ERR_OPERATIONS_ERROR);
     564             :         }
     565        4448 :         if (ares->error != LDB_SUCCESS) {
     566           0 :                 return ldb_module_done(ac->req, ares->controls,
     567             :                                         ares->response, ares->error);
     568             :         }
     569             :         /* Only entries are interesting, and we handle the case of the parent separately */
     570             : 
     571        4448 :         switch (ares->type) {
     572        2224 :         case LDB_REPLY_ENTRY:
     573             : 
     574        2224 :                 if (ldb_dn_compare(ares->message->dn, mc->aggregate_dn) == 0) {
     575          63 :                         for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
     576          99 :                                 if (generated_attrs[i].aggregate &&
     577          45 :                                     ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
     578          27 :                                         ret = generated_attrs[i].fn(ldb, ares->message, ac->schema);
     579          27 :                                         if (ret != LDB_SUCCESS) {
     580           0 :                                                 return ret;
     581             :                                         }
     582             :                                 }
     583             :                         }
     584        2215 :                 } else if ((ldb_dn_compare_base(mc->schema_dn, ares->message->dn) == 0)
     585        2215 :                            && (ldb_dn_compare(mc->schema_dn, ares->message->dn) != 0)) {
     586       15505 :                         for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
     587       15505 :                                 if (!generated_attrs[i].aggregate &&
     588        2215 :                                     ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
     589        2215 :                                         ret = generated_attrs[i].fn(ldb, ares->message, ac->schema);
     590        2215 :                                         if (ret != LDB_SUCCESS) {
     591           0 :                                                 return ret;
     592             :                                         }
     593             :                                 }
     594             :                         }
     595             :                 }
     596             : 
     597             : 
     598        2224 :                 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
     599             : 
     600           0 :         case LDB_REPLY_REFERRAL:
     601             : 
     602           0 :                 return ldb_module_send_referral(ac->req, ares->referral);
     603             : 
     604        2224 :         case LDB_REPLY_DONE:
     605             : 
     606        2224 :                 return ldb_module_done(ac->req, ares->controls,
     607             :                                         ares->response, ares->error);
     608             :         }
     609             : 
     610           0 :         return LDB_SUCCESS;
     611             : }
     612             : 
     613             : /* search */
     614    27658683 : static int schema_data_search(struct ldb_module *module, struct ldb_request *req)
     615             : {
     616    27658683 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     617     1203884 :         unsigned int i;
     618     1203884 :         int ret;
     619     1203884 :         struct schema_data_search_data *search_context;
     620     1203884 :         struct ldb_request *down_req;
     621     1203884 :         const struct dsdb_schema *schema;
     622    27658683 :         if (!ldb_module_get_private(module)) {
     623             :                 /* If there is no module data, there is little we can do */
     624           0 :                 return ldb_next_request(module, req);
     625             :         }
     626             : 
     627             :         /* The schema manipulation does not apply to special DNs */
     628    27658683 :         if (ldb_dn_is_special(req->op.search.base)) {
     629       10551 :                 return ldb_next_request(module, req);
     630             :         }
     631             : 
     632   193534655 :         for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
     633   165888747 :                 if (ldb_attr_in_list(req->op.search.attrs, generated_attrs[i].attr)) {
     634        2224 :                         break;
     635             :                 }
     636             :         }
     637    27648132 :         if (i == ARRAY_SIZE(generated_attrs)) {
     638             :                 /* No request for a generated attr found, nothing to
     639             :                  * see here, move along... */
     640    27645908 :                 return ldb_next_request(module, req);
     641             :         }
     642             : 
     643        2224 :         schema = dsdb_get_schema(ldb, NULL);
     644        2224 :         if (!schema || !ldb_module_get_private(module)) {
     645             :                 /* If there is no schema, there is little we can do */
     646           0 :                 return ldb_next_request(module, req);
     647             :         }
     648             : 
     649        2224 :         search_context = talloc(req, struct schema_data_search_data);
     650        2224 :         if (!search_context) {
     651           0 :                 return ldb_oom(ldb);
     652             :         }
     653             : 
     654        2224 :         search_context->module = module;
     655        2224 :         search_context->req = req;
     656        2224 :         search_context->schema = talloc_reference(search_context, schema);
     657        2224 :         if (!search_context->schema) {
     658           0 :                 return ldb_oom(ldb);
     659             :         }
     660             : 
     661        2224 :         ret = ldb_build_search_req_ex(&down_req, ldb, search_context,
     662             :                                         req->op.search.base,
     663             :                                         req->op.search.scope,
     664             :                                         req->op.search.tree,
     665             :                                         req->op.search.attrs,
     666             :                                         req->controls,
     667             :                                         search_context, schema_data_search_callback,
     668             :                                         req);
     669        2224 :         LDB_REQ_SET_LOCATION(down_req);
     670        2224 :         if (ret != LDB_SUCCESS) {
     671           0 :                 return ldb_operr(ldb);
     672             :         }
     673             : 
     674        2224 :         return ldb_next_request(module, down_req);
     675             : }
     676             : 
     677             : 
     678             : static const struct ldb_module_ops ldb_schema_data_module_ops = {
     679             :         .name           = "schema_data",
     680             :         .init_context   = schema_data_init,
     681             :         .add            = schema_data_add,
     682             :         .modify         = schema_data_modify,
     683             :         .del            = schema_data_del,
     684             :         .search         = schema_data_search
     685             : };
     686             : 
     687        6040 : int ldb_schema_data_module_init(const char *version)
     688             : {
     689        6040 :         LDB_MODULE_CHECK_VERSION(version);
     690        6040 :         return ldb_register_module(&ldb_schema_data_module_ops);
     691             : }

Generated by: LCOV version 1.14