LCOV - code coverage report
Current view: top level - source4/dsdb/schema - schema_inferiors.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 131 165 79.4 %
Date: 2024-04-21 15:09:00 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    implement possibleInferiors calculation
       5             :    
       6             :    Copyright (C) Andrew Tridgell 2009
       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             :   This module is a C implementation of the logic in the
      25             :   dsdb/samdb/ldb_modules/tests/possibleInferiors.py code
      26             : 
      27             :   To understand the C code, please see the python code first
      28             :  */
      29             : 
      30             : #include "includes.h"
      31             : #include "dsdb/samdb/samdb.h"
      32             : 
      33             : 
      34             : /*
      35             :   create the SUPCLASSES() list
      36             :  */
      37    14991414 : static const char **schema_supclasses(const struct dsdb_schema *schema,
      38             :                                       struct dsdb_class *schema_class)
      39             : {
      40      174767 :         const char **list;
      41             : 
      42    14991414 :         if (schema_class->tmp.supclasses) {
      43     7394250 :                 return schema_class->tmp.supclasses;
      44             :         }
      45             : 
      46     7509951 :         list = const_str_list(str_list_make_empty(schema_class));
      47     7509951 :         if (list == NULL) {
      48           0 :                 DEBUG(0,(__location__ " out of memory\n"));
      49           0 :                 return NULL;
      50             :         }
      51             : 
      52             :         /* Cope with 'top SUP top', i.e. top is subClassOf top */
      53     7509951 :         if (schema_class->subClassOf &&
      54     7509951 :             strcmp(schema_class->lDAPDisplayName, schema_class->subClassOf) == 0) {
      55       28488 :                 schema_class->tmp.supclasses = list;
      56       28488 :                 return list;
      57             :         }
      58             : 
      59     7481463 :         if (schema_class->subClassOf) {
      60     7481463 :                 const struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf);
      61       87213 :                 const char **list2;
      62     7481463 :                 list = str_list_add_const(list, schema_class->subClassOf);
      63             : 
      64     7481463 :                 list2 = schema_supclasses(schema, discard_const_p(struct dsdb_class, schema_class2));
      65     7481463 :                 list = str_list_append_const(list, list2);
      66             :         }
      67             : 
      68     7481463 :         schema_class->tmp.supclasses = str_list_unique(list);
      69             : 
      70     7481463 :         return schema_class->tmp.supclasses;
      71             : }
      72             : 
      73             : /*
      74             :   this one is used internally
      75             :   matches SUBCLASSES() python function
      76             :  */
      77     7509951 : static const char **schema_subclasses(const struct dsdb_schema *schema,
      78             :                                       TALLOC_CTX *mem_ctx,
      79             :                                       const char **oclist)
      80             : {
      81     7509951 :         const char **list = const_str_list(str_list_make_empty(mem_ctx));
      82       87554 :         unsigned int i;
      83             : 
      84    50735179 :         for (i=0; oclist && oclist[i]; i++) {
      85    43137674 :                 const struct dsdb_class *schema_class = dsdb_class_by_lDAPDisplayName(schema, oclist[i]);
      86    43137674 :                 if (!schema_class) {
      87           0 :                         DEBUG(0, ("ERROR: Unable to locate subClass: '%s'\n", oclist[i]));
      88           0 :                         continue;
      89             :                 }
      90    43137674 :                 list = str_list_append_const(list, schema_class->tmp.subclasses);
      91             :         }
      92     7509951 :         return list;
      93             : }
      94             : 
      95             : 
      96             : /* 
      97             :    equivalent of the POSSSUPERIORS() python function
      98             :  */
      99  2023107650 : static const char **schema_posssuperiors(const struct dsdb_schema *schema,
     100             :                                          struct dsdb_class *schema_class)
     101             : {
     102  2023107650 :         if (schema_class->tmp.posssuperiors == NULL) {
     103     7509951 :                 const char **list2 = const_str_list(str_list_make_empty(schema_class));
     104       87554 :                 const char **list3;
     105       87554 :                 unsigned int i;
     106             : 
     107     7509951 :                 list2 = str_list_append_const(list2, schema_class->systemPossSuperiors);
     108     7509951 :                 list2 = str_list_append_const(list2, schema_class->possSuperiors);
     109     7509951 :                 list3 = schema_supclasses(schema, schema_class);
     110    19024864 :                 for (i=0; list3 && list3[i]; i++) {
     111    11427359 :                         const struct dsdb_class *class2 = dsdb_class_by_lDAPDisplayName(schema, list3[i]);
     112    11427359 :                         if (!class2) {
     113           0 :                                 DEBUG(0, ("ERROR: Unable to locate supClass: '%s'\n", list3[i]));
     114           0 :                                 continue;
     115             :                         }
     116    11427359 :                         list2 = str_list_append_const(list2, schema_posssuperiors(schema,
     117             :                                 discard_const_p(struct dsdb_class, class2)));
     118             :                 }
     119     7509951 :                 list2 = str_list_append_const(list2, schema_subclasses(schema, list2, list2));
     120             : 
     121     7509951 :                 schema_class->tmp.posssuperiors = str_list_unique(list2);
     122             :         }
     123             : 
     124  2023107650 :         return schema_class->tmp.posssuperiors;
     125             : }
     126             : 
     127    36294334 : static const char **schema_subclasses_recurse(const struct dsdb_schema *schema,
     128             :                                               struct dsdb_class *schema_class)
     129             : {
     130    36294334 :         const char **list = str_list_copy_const(schema_class, schema_class->tmp.subclasses_direct);
     131      412413 :         unsigned int i;
     132    65491130 :         for (i=0;list && list[i]; i++) {
     133    28784383 :                 const struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, list[i]);
     134    28784383 :                 if (schema_class != schema_class2) {
     135    28784383 :                         list = str_list_append_const(list, schema_subclasses_recurse(schema,
     136             :                                 discard_const_p(struct dsdb_class, schema_class2)));
     137             :                 }
     138             :         }
     139    36294334 :         return list;
     140             : }
     141             : 
     142             : /* Walk down the subClass tree, setting a higher index as we go down
     143             :  * each level.  top is 1, subclasses of top are 2, etc */
     144     7509951 : static void schema_subclasses_order_recurse(const struct dsdb_schema *schema,
     145             :                                             struct dsdb_class *schema_class,
     146             :                                             const int order)
     147             : {
     148     7509951 :         const char **list = schema_class->tmp.subclasses_direct;
     149       87554 :         unsigned int i;
     150     7509951 :         schema_class->subClass_order = order;
     151    14991414 :         for (i=0;list && list[i]; i++) {
     152     7481463 :                 const struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, list[i]);
     153     7481463 :                 schema_subclasses_order_recurse(schema, discard_const_p(struct dsdb_class, schema_class2), order+1);
     154             :         }
     155     7509951 :         return;
     156             : }
     157             : 
     158       28488 : static int schema_create_subclasses(const struct dsdb_schema *schema)
     159             : {
     160         341 :         struct dsdb_class *schema_class, *top;
     161             : 
     162     7538439 :         for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
     163     7509951 :                 struct dsdb_class *schema_class2 = discard_const_p(struct dsdb_class,
     164             :                         dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf));
     165     7509951 :                 if (schema_class2 == NULL) {
     166           0 :                         DEBUG(0,("ERROR: no subClassOf '%s' for '%s'\n",
     167             :                                  schema_class->subClassOf,
     168             :                                  schema_class->lDAPDisplayName));
     169           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     170             :                 }
     171     7509951 :                 if (schema_class2 && schema_class != schema_class2) {
     172     7481463 :                         if (schema_class2->tmp.subclasses_direct == NULL) {
     173      710792 :                                 schema_class2->tmp.subclasses_direct = const_str_list(str_list_make_empty(schema_class2));
     174      710792 :                                 if (!schema_class2->tmp.subclasses_direct) {
     175           0 :                                         return LDB_ERR_OPERATIONS_ERROR;
     176             :                                 }
     177             :                         }
     178     7481463 :                         schema_class2->tmp.subclasses_direct = str_list_add_const(schema_class2->tmp.subclasses_direct,
     179             :                                                 schema_class->lDAPDisplayName);
     180             :                 }
     181             :         }
     182             : 
     183     7538439 :         for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
     184     7509951 :                 schema_class->tmp.subclasses = str_list_unique(schema_subclasses_recurse(schema, schema_class));
     185             : 
     186             :                 /* Initialize the subClass order, to ensure we can't have uninitialized sort on the subClass hierarchy */
     187     7509951 :                 schema_class->subClass_order = 0;
     188             :         }
     189             : 
     190       28488 :         top = discard_const_p(struct dsdb_class, dsdb_class_by_lDAPDisplayName(schema, "top"));
     191       28488 :         if (!top) {
     192           0 :                 DEBUG(0,("ERROR: no 'top' class in loaded schema\n"));
     193           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     194             :         }
     195             : 
     196       28488 :         schema_subclasses_order_recurse(schema, top, 1);
     197       28488 :         return LDB_SUCCESS;
     198             : }
     199             : 
     200     7509951 : static void schema_fill_possible_inferiors(const struct dsdb_schema *schema,
     201             :                                            struct dsdb_class *schema_class)
     202             : {
     203       87554 :         struct dsdb_class *c2;
     204     7509951 :         const char **poss_inf = NULL;
     205     7509951 :         const char **sys_poss_inf = NULL;
     206             : 
     207  2019190242 :         for (c2 = schema->classes; c2; c2 = c2->next) {
     208  2011680291 :                 const char **superiors = schema_posssuperiors(schema, c2);
     209  2011680291 :                 if (c2->objectClassCategory != 2 &&
     210  3758412799 :                     c2->objectClassCategory != 3 &&
     211  1839297450 :                     str_list_check(superiors, schema_class->lDAPDisplayName))
     212             :                 {
     213    43696310 :                         if (c2->systemOnly == false) {
     214    42143953 :                                 if (poss_inf == NULL) {
     215     2913275 :                                         poss_inf = const_str_list(str_list_make_empty(schema_class));
     216             :                                 }
     217    42143953 :                                 poss_inf = str_list_add_const(poss_inf,
     218             :                                                               c2->lDAPDisplayName);
     219             :                         }
     220    43696310 :                         if (sys_poss_inf == NULL) {
     221     2941452 :                                 sys_poss_inf = const_str_list(str_list_make_empty(schema_class));
     222             :                         }
     223    43696310 :                         sys_poss_inf = str_list_add_const(sys_poss_inf,
     224             :                                                           c2->lDAPDisplayName);
     225             :                 }
     226             :         }
     227     7509951 :         schema_class->systemPossibleInferiors = str_list_unique(sys_poss_inf);
     228     7509951 :         schema_class->possibleInferiors = str_list_unique(poss_inf);
     229     7509951 : }
     230             : 
     231             : /*
     232             :   fill in a string class name from a governs_ID
     233             :  */
     234     7509951 : static void schema_fill_from_class_one(const struct dsdb_schema *schema,
     235             :                                        const struct dsdb_class *c,
     236             :                                        const char **s,
     237             :                                        const uint32_t id)
     238             : {
     239     7422397 :         if (*s == NULL && id != 0) {
     240           0 :                 const struct dsdb_class *c2 =
     241           0 :                                         dsdb_class_by_governsID_id(schema, id);
     242           0 :                 if (c2) {
     243           0 :                         *s = c2->lDAPDisplayName;
     244             :                 }
     245             :         }
     246     7422397 : }
     247             : 
     248             : /*
     249             :   fill in a list of string class names from a governs_ID list
     250             :  */
     251    30039804 : static void schema_fill_from_class_list(const struct dsdb_schema *schema,
     252             :                                         const struct dsdb_class *c,
     253             :                                         const char ***s,
     254             :                                         const uint32_t *ids)
     255             : {
     256    30039804 :         if (*s == NULL && ids != NULL) {
     257             :                 unsigned int i;
     258           0 :                 for (i=0;ids[i];i++) ;
     259           0 :                 *s = talloc_array(c, const char *, i+1);
     260           0 :                 for (i=0;ids[i];i++) {
     261           0 :                         const struct dsdb_class *c2 =
     262           0 :                                 dsdb_class_by_governsID_id(schema, ids[i]);
     263           0 :                         if (c2) {
     264           0 :                                 (*s)[i] = c2->lDAPDisplayName;
     265             :                         } else {
     266           0 :                                 (*s)[i] = NULL;                         
     267             :                         }
     268             :                 }
     269           0 :                 (*s)[i] = NULL;                         
     270             :         }
     271    30039804 : }
     272             : 
     273             : /*
     274             :   fill in a list of string attribute names from a attributeID list
     275             :  */
     276    30039804 : static void schema_fill_from_attribute_list(const struct dsdb_schema *schema,
     277             :                                             const struct dsdb_class *c,
     278             :                                             const char ***s,
     279             :                                             const uint32_t *ids)
     280             : {
     281    30039804 :         if (*s == NULL && ids != NULL) {
     282             :                 unsigned int i;
     283           0 :                 for (i=0;ids[i];i++) ;
     284           0 :                 *s = talloc_array(c, const char *, i+1);
     285           0 :                 for (i=0;ids[i];i++) {
     286           0 :                         const struct dsdb_attribute *a =
     287           0 :                                 dsdb_attribute_by_attributeID_id(schema, ids[i]);
     288           0 :                         if (a) {
     289           0 :                                 (*s)[i] = a->lDAPDisplayName;
     290             :                         } else {
     291           0 :                                 (*s)[i] = NULL;                         
     292             :                         }
     293             :                 }
     294           0 :                 (*s)[i] = NULL;                         
     295             :         }
     296    30039804 : }
     297             : 
     298             : /*
     299             :   if the schema came from DRS then some attributes will be setup as IDs
     300             :  */
     301       28488 : static void schema_fill_from_ids(const struct dsdb_schema *schema)
     302             : {
     303         341 :         struct dsdb_class *c;
     304     7538439 :         for (c=schema->classes; c; c=c->next) {
     305     7509951 :                 schema_fill_from_class_one(schema, c, &c->subClassOf, c->subClassOf_id);
     306     7509951 :                 schema_fill_from_attribute_list(schema, c, &c->systemMayContain, c->systemMayContain_ids);
     307     7509951 :                 schema_fill_from_attribute_list(schema, c, &c->systemMustContain, c->systemMustContain_ids);
     308     7509951 :                 schema_fill_from_attribute_list(schema, c, &c->mustContain, c->mustContain_ids);
     309     7509951 :                 schema_fill_from_attribute_list(schema, c, &c->mayContain, c->mayContain_ids);
     310     7509951 :                 schema_fill_from_class_list(schema, c, &c->possSuperiors, c->possSuperiors_ids);
     311     7509951 :                 schema_fill_from_class_list(schema, c, &c->systemPossSuperiors, c->systemPossSuperiors_ids);
     312     7509951 :                 schema_fill_from_class_list(schema, c, &c->systemAuxiliaryClass, c->systemAuxiliaryClass_ids);
     313     7509951 :                 schema_fill_from_class_list(schema, c, &c->auxiliaryClass, c->auxiliaryClass_ids);
     314             :         }
     315       28488 : }
     316             : 
     317       28488 : int schema_fill_constructed(const struct dsdb_schema *schema)
     318             : {
     319         341 :         int ret;
     320         341 :         struct dsdb_class *schema_class;
     321             : 
     322             :         /* make sure we start with a clean cache */
     323     7538439 :         for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
     324     7509951 :                 ZERO_STRUCT(schema_class->tmp);
     325             :         }
     326             : 
     327       28488 :         schema_fill_from_ids(schema);
     328             : 
     329       28488 :         ret = schema_create_subclasses(schema);
     330       28488 :         if (ret != LDB_SUCCESS) {
     331           0 :                 return ret;
     332             :         }
     333             : 
     334     7538439 :         for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
     335     7509951 :                 schema_fill_possible_inferiors(schema, schema_class);
     336             :         }
     337             : 
     338             :         /* free up our internal cache elements */
     339     7538439 :         for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
     340     7509951 :                 TALLOC_FREE(schema_class->tmp.supclasses);
     341     7509951 :                 TALLOC_FREE(schema_class->tmp.subclasses_direct);
     342     7509951 :                 TALLOC_FREE(schema_class->tmp.subclasses);
     343     7509951 :                 TALLOC_FREE(schema_class->tmp.posssuperiors);
     344             :         }
     345             : 
     346       28147 :         return LDB_SUCCESS;
     347             : }

Generated by: LCOV version 1.14