LCOV - code coverage report
Current view: top level - source4/dsdb/schema - schema_init.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 348 479 72.7 %
Date: 2023-11-21 12:31:41 Functions: 20 20 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS Implementation.
       3             :    DSDB schema header
       4             :    
       5             :    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             :    
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "dsdb/samdb/samdb.h"
      25             : #include "dsdb/common/util.h"
      26             : #include <ldb_errors.h>
      27             : #include "../lib/util/dlinklist.h"
      28             : #include "librpc/gen_ndr/ndr_misc.h"
      29             : #include "librpc/gen_ndr/ndr_drsuapi.h"
      30             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      31             : #include "param/param.h"
      32             : #include <ldb_module.h>
      33             : #include "../lib/util/asn1.h"
      34             : 
      35             : #undef strcasecmp
      36             : 
      37       27952 : struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx)
      38             : {
      39       27952 :         struct dsdb_schema *schema = talloc_zero(mem_ctx, struct dsdb_schema);
      40       27952 :         if (!schema) {
      41           0 :                 return NULL;
      42             :         }
      43             : 
      44       27608 :         return schema;
      45             : }
      46             : 
      47          61 : struct dsdb_schema *dsdb_schema_copy_shallow(TALLOC_CTX *mem_ctx,
      48             :                                              struct ldb_context *ldb,
      49             :                                              const struct dsdb_schema *schema)
      50             : {
      51           0 :         int ret;
      52           0 :         struct dsdb_class *cls;
      53           0 :         struct dsdb_attribute *attr;
      54           0 :         struct dsdb_schema *schema_copy;
      55             : 
      56          61 :         schema_copy = dsdb_new_schema(mem_ctx);
      57          61 :         if (!schema_copy) {
      58           0 :                 return NULL;
      59             :         }
      60             : 
      61             :         /* copy prexiMap & schemaInfo */
      62         122 :         schema_copy->prefixmap = dsdb_schema_pfm_copy_shallow(schema_copy,
      63          61 :                                                               schema->prefixmap);
      64          61 :         if (!schema_copy->prefixmap) {
      65           0 :                 goto failed;
      66             :         }
      67             : 
      68          61 :         schema_copy->schema_info = talloc(schema_copy, struct dsdb_schema_info);
      69          61 :         if (!schema_copy->schema_info) {
      70           0 :                 goto failed;
      71             :         }
      72          61 :         *schema_copy->schema_info = *schema->schema_info;
      73             : 
      74             :         /* copy classes and attributes*/
      75       15944 :         for (cls = schema->classes; cls; cls = cls->next) {
      76       15883 :                 struct dsdb_class *class_copy = talloc_memdup(schema_copy,
      77             :                                                               cls, sizeof(*cls));
      78       15883 :                 if (!class_copy) {
      79           0 :                         goto failed;
      80             :                 }
      81       15883 :                 DLIST_ADD(schema_copy->classes, class_copy);
      82             :         }
      83          61 :         schema_copy->num_classes = schema->num_classes;
      84             : 
      85       85517 :         for (attr = schema->attributes; attr; attr = attr->next) {
      86       85456 :                 struct dsdb_attribute *a_copy = talloc_memdup(schema_copy,
      87             :                                                               attr, sizeof(*attr));
      88       85456 :                 if (!a_copy) {
      89           0 :                         goto failed;
      90             :                 }
      91       85456 :                 DLIST_ADD(schema_copy->attributes, a_copy);
      92             :         }
      93          61 :         schema_copy->num_attributes = schema->num_attributes;
      94             : 
      95             :         /* rebuild indexes */
      96          61 :         ret = dsdb_setup_sorted_accessors(ldb, schema_copy);
      97          61 :         if (ret != LDB_SUCCESS) {
      98           0 :                 goto failed;
      99             :         }
     100             : 
     101             :         /* leave reload_seq_number = 0 so it will be refresh ASAP */
     102             : 
     103          61 :         return schema_copy;
     104             : 
     105           0 : failed:
     106           0 :         talloc_free(schema_copy);
     107           0 :         return NULL;
     108             : }
     109             : 
     110             : 
     111          82 : WERROR dsdb_load_prefixmap_from_drsuapi(struct dsdb_schema *schema,
     112             :                                         const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
     113             : {
     114           0 :         WERROR werr;
     115          82 :         struct dsdb_schema_info *schema_info = NULL;
     116          82 :         struct dsdb_schema_prefixmap *pfm = NULL;
     117             : 
     118          82 :         werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, true, schema, &pfm, &schema_info);
     119          82 :         W_ERROR_NOT_OK_RETURN(werr);
     120             : 
     121             :         /* set loaded prefixMap */
     122          82 :         talloc_free(schema->prefixmap);
     123          82 :         schema->prefixmap = pfm;
     124             : 
     125          82 :         talloc_free(schema->schema_info);
     126          82 :         schema->schema_info = schema_info;
     127             : 
     128          82 :         return WERR_OK;
     129             : }
     130             : 
     131       28513 : static WERROR _dsdb_prefixmap_from_ldb_val(const struct ldb_val *pfm_ldb_val,
     132             :                                            TALLOC_CTX *mem_ctx,
     133             :                                            struct dsdb_schema_prefixmap **_pfm)
     134             : {
     135         363 :         WERROR werr;
     136         363 :         enum ndr_err_code ndr_err;
     137         363 :         struct prefixMapBlob pfm_blob;
     138             : 
     139       28513 :         TALLOC_CTX *temp_ctx = talloc_new(mem_ctx);
     140       28513 :         W_ERROR_HAVE_NO_MEMORY(temp_ctx);
     141             : 
     142       28513 :         ndr_err = ndr_pull_struct_blob(pfm_ldb_val, temp_ctx,
     143             :                                 &pfm_blob,
     144             :                                 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
     145       28513 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     146           0 :                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
     147           0 :                 DEBUG(0,("_dsdb_prefixmap_from_ldb_val: Failed to parse prefixmap of length %u: %s\n",
     148             :                          (unsigned int)pfm_ldb_val->length, ndr_map_error2string(ndr_err)));
     149           0 :                 talloc_free(temp_ctx);
     150           0 :                 return ntstatus_to_werror(nt_status);
     151             :         }
     152             : 
     153       28513 :         if (pfm_blob.version != PREFIX_MAP_VERSION_DSDB) {
     154           0 :                 DEBUG(0,("_dsdb_prefixmap_from_ldb_val: pfm_blob->version %u incorrect\n", (unsigned int)pfm_blob.version));
     155           0 :                 talloc_free(temp_ctx);
     156           0 :                 return WERR_VERSION_PARSE_ERROR;
     157             :         }
     158             : 
     159             :         /* call the drsuapi version */
     160       28513 :         werr = dsdb_schema_pfm_from_drsuapi_pfm(&pfm_blob.ctr.dsdb, false, mem_ctx, _pfm, NULL);
     161       28513 :         if (!W_ERROR_IS_OK(werr)) {
     162           0 :                 DEBUG(0, (__location__ " dsdb_schema_pfm_from_drsuapi_pfm failed: %s\n", win_errstr(werr)));
     163           0 :                 talloc_free(temp_ctx);
     164           0 :                 return werr;
     165             :         }
     166             : 
     167       28513 :         talloc_free(temp_ctx);
     168             : 
     169       28513 :         return werr;
     170             : }
     171             : 
     172       27806 : WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema,
     173             :                                   const struct ldb_val *prefixMap,
     174             :                                   const struct ldb_val *schemaInfo)
     175             : {
     176         341 :         WERROR werr;
     177       27806 :         struct dsdb_schema_info *schema_info = NULL;
     178       27806 :         struct dsdb_schema_prefixmap *pfm = NULL;
     179         341 :         TALLOC_CTX *mem_ctx;
     180             : 
     181             :         /* verify schemaInfo blob is valid one */
     182       27806 :         if (!dsdb_schema_info_blob_is_valid(schemaInfo)) {
     183           0 :                 DEBUG(0,(__location__": dsdb_schema_info_blob_is_valid() failed.\n"));
     184           0 :                 return WERR_INVALID_PARAMETER;
     185             :         }
     186             : 
     187       27806 :         mem_ctx = talloc_new(schema);
     188       27806 :         W_ERROR_HAVE_NO_MEMORY(mem_ctx);
     189             : 
     190             :         /* fetch prefixMap */
     191       27806 :         werr = _dsdb_prefixmap_from_ldb_val(prefixMap,
     192             :                                             mem_ctx, &pfm);
     193       27806 :         if (!W_ERROR_IS_OK(werr)) {
     194           0 :                 DEBUG(0, (__location__ " _dsdb_prefixmap_from_ldb_val failed: %s\n", win_errstr(werr)));
     195           0 :                 talloc_free(mem_ctx);
     196           0 :                 return werr;
     197             :         }
     198             : 
     199             :         /* decode schema_info */
     200       27806 :         werr = dsdb_schema_info_from_blob(schemaInfo, mem_ctx, &schema_info);
     201       27806 :         if (!W_ERROR_IS_OK(werr)) {
     202           0 :                 DEBUG(0, (__location__ " dsdb_schema_info_from_blob failed: %s\n", win_errstr(werr)));
     203           0 :                 talloc_free(mem_ctx);
     204           0 :                 return werr;
     205             :         }
     206             : 
     207             :         /* store prefixMap and schema_info into cached Schema */
     208       27806 :         talloc_free(schema->prefixmap);
     209       27806 :         schema->prefixmap = talloc_steal(schema, pfm);
     210             : 
     211       27806 :         talloc_free(schema->schema_info);
     212       27806 :         schema->schema_info = talloc_steal(schema, schema_info);
     213             : 
     214             :         /* clean up locally allocated mem */
     215       27806 :         talloc_free(mem_ctx);
     216             : 
     217       27806 :         return WERR_OK;
     218             : }
     219             : 
     220       11237 : WERROR dsdb_get_oid_mappings_drsuapi(const struct dsdb_schema *schema,
     221             :                                      bool include_schema_info,
     222             :                                      TALLOC_CTX *mem_ctx,
     223             :                                      struct drsuapi_DsReplicaOIDMapping_Ctr **_ctr)
     224             : {
     225       11237 :         return dsdb_drsuapi_pfm_from_schema_pfm(schema->prefixmap,
     226             :                                                 include_schema_info ? schema->schema_info : NULL,
     227             :                                                 mem_ctx, _ctr);
     228             : }
     229             : 
     230          77 : WERROR dsdb_get_drsuapi_prefixmap_as_blob(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
     231             :                                           TALLOC_CTX *mem_ctx,
     232             :                                           struct ldb_val *prefixMap)
     233             : {
     234           1 :         struct prefixMapBlob pfm;
     235           1 :         enum ndr_err_code ndr_err;
     236          77 :         pfm.version     = PREFIX_MAP_VERSION_DSDB;
     237          77 :         pfm.reserved    = 0;
     238          77 :         pfm.ctr.dsdb    = *ctr;
     239             : 
     240          77 :         ndr_err = ndr_push_struct_blob(prefixMap, mem_ctx, &pfm,
     241             :                                         (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
     242          77 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     243           0 :                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
     244           0 :                 return ntstatus_to_werror(nt_status);
     245             :         }
     246          77 :         return WERR_OK;
     247             : }
     248             : 
     249           1 : WERROR dsdb_get_oid_mappings_ldb(const struct dsdb_schema *schema,
     250             :                                  TALLOC_CTX *mem_ctx,
     251             :                                  struct ldb_val *prefixMap,
     252             :                                  struct ldb_val *schemaInfo)
     253             : {
     254           1 :         WERROR status;
     255           1 :         struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
     256             : 
     257           1 :         status = dsdb_get_oid_mappings_drsuapi(schema, false, mem_ctx, &ctr);
     258           1 :         W_ERROR_NOT_OK_RETURN(status);
     259             : 
     260           1 :         status = dsdb_get_drsuapi_prefixmap_as_blob(ctr, mem_ctx, prefixMap);
     261           1 :         talloc_free(ctr);
     262           1 :         W_ERROR_NOT_OK_RETURN(status);
     263             : 
     264           1 :         status = dsdb_blob_from_schema_info(schema->schema_info, mem_ctx, schemaInfo);
     265           1 :         W_ERROR_NOT_OK_RETURN(status);
     266             : 
     267           1 :         return WERR_OK;
     268             : }
     269             : 
     270             : 
     271             : /*
     272             :  * this function is called from within a ldb transaction from the schema_fsmo module
     273             :  */
     274         695 : WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
     275             : {
     276          10 :         WERROR status;
     277          10 :         uint32_t attid;
     278          10 :         TALLOC_CTX *mem_ctx;
     279          10 :         struct dsdb_schema_prefixmap *pfm;
     280         695 :         struct dsdb_schema_prefixmap *orig_pfm = NULL;
     281             : 
     282         695 :         mem_ctx = talloc_new(ldb);
     283         695 :         W_ERROR_HAVE_NO_MEMORY(mem_ctx);
     284             : 
     285             :         /* Read prefixes from disk*/
     286         695 :         status = dsdb_read_prefixes_from_ldb(ldb, mem_ctx, &pfm);
     287         695 :         if (!W_ERROR_IS_OK(status)) {
     288           0 :                 DEBUG(0,("dsdb_create_prefix_mapping: dsdb_read_prefixes_from_ldb: %s\n",
     289             :                         win_errstr(status)));
     290           0 :                 talloc_free(mem_ctx);
     291           0 :                 return status;
     292             :         }
     293             : 
     294             :         /* Check if there is a prefix for the oid in the prefixes array*/
     295         695 :         status = dsdb_schema_pfm_find_oid(pfm, full_oid, NULL);
     296         695 :         if (W_ERROR_IS_OK(status)) {
     297             :                 /* prefix found*/
     298           7 :                 talloc_free(mem_ctx);
     299           7 :                 return status;
     300         688 :         } else if (!W_ERROR_EQUAL(status, WERR_NOT_FOUND)) {
     301             :                 /* error */
     302           0 :                 DEBUG(0,("dsdb_create_prefix_mapping: dsdb_find_prefix_for_oid: %s\n",
     303             :                         win_errstr(status)));
     304           0 :                 talloc_free(mem_ctx);
     305           0 :                 return status;
     306             :         }
     307             : 
     308             :         /* Create the new mapping for the prefix of full_oid */
     309         688 :         status = dsdb_schema_pfm_make_attid(pfm, full_oid, &attid);
     310         688 :         if (!W_ERROR_IS_OK(status)) {
     311           0 :                 DEBUG(0,("dsdb_create_prefix_mapping: dsdb_schema_pfm_make_attid: %s\n",
     312             :                         win_errstr(status)));
     313           0 :                 talloc_free(mem_ctx);
     314           0 :                 return status;
     315             :         }
     316             : 
     317             :         /*
     318             :          * We temporary replcate schema->prefixmap.
     319             :          */
     320         688 :         orig_pfm = schema->prefixmap;
     321         688 :         schema->prefixmap = pfm;
     322             : 
     323             :         /* Update prefixMap in ldb*/
     324         688 :         status = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, ldb, schema);
     325         688 :         if (!W_ERROR_IS_OK(status)) {
     326           0 :                 DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ldb: %s\n",
     327             :                         win_errstr(status)));
     328           0 :                 talloc_free(mem_ctx);
     329           0 :                 return status;
     330             :         }
     331             : 
     332         688 :         DEBUG(2,(__location__ " Added prefixMap %s - now have %u prefixes\n",
     333             :                  full_oid, schema->prefixmap->length));
     334             : 
     335             :         /*
     336             :          * We restore the original prefix map.
     337             :          *
     338             :          * The next schema reload should get an updated prefix map!
     339             :          */
     340         688 :         schema->prefixmap = orig_pfm;
     341             : 
     342         688 :         talloc_free(mem_ctx);
     343         688 :         return status;
     344             : }
     345             : 
     346             : 
     347         878 : WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
     348             :                                               const struct dsdb_schema *schema)
     349             : {
     350          27 :         WERROR status;
     351          27 :         int ldb_ret;
     352          27 :         struct ldb_message *msg;
     353          27 :         struct ldb_dn *schema_dn;
     354          27 :         struct prefixMapBlob pfm_blob;
     355          27 :         struct ldb_val ndr_blob;
     356          27 :         enum ndr_err_code ndr_err;
     357          27 :         TALLOC_CTX *temp_ctx;
     358          27 :         struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
     359             : 
     360         878 :         schema_dn = ldb_get_schema_basedn(ldb);
     361         878 :         if (!schema_dn) {
     362           0 :                 DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: no schema dn present\n"));
     363           0 :                 return WERR_FOOBAR;
     364             :         }
     365             : 
     366         878 :         temp_ctx = talloc_new(mem_ctx);
     367         878 :         W_ERROR_HAVE_NO_MEMORY(temp_ctx);
     368             : 
     369             :         /* convert schema_prefixMap to prefixMap blob */
     370         878 :         status = dsdb_get_oid_mappings_drsuapi(schema, false, temp_ctx, &ctr);
     371         878 :         if (!W_ERROR_IS_OK(status)) {
     372           0 :                 talloc_free(temp_ctx);
     373           0 :                 return status;
     374             :         }
     375             : 
     376         878 :         pfm_blob.version        = PREFIX_MAP_VERSION_DSDB;
     377         878 :         pfm_blob.ctr.dsdb       = *ctr;
     378             : 
     379         878 :         ndr_err = ndr_push_struct_blob(&ndr_blob, temp_ctx,
     380             :                                        &pfm_blob,
     381             :                                        (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
     382         878 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     383           0 :                 talloc_free(temp_ctx);
     384           0 :                 return WERR_FOOBAR;
     385             :         }
     386             :  
     387             :         /* write serialized prefixMap into LDB */
     388         878 :         msg = ldb_msg_new(temp_ctx);
     389         878 :         if (!msg) {
     390           0 :                 talloc_free(temp_ctx);
     391           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     392             :         }
     393             : 
     394         878 :         msg->dn = schema_dn;
     395         878 :         ldb_ret = ldb_msg_add_value(msg, "prefixMap", &ndr_blob, NULL);
     396         878 :         if (ldb_ret != 0) {
     397           0 :                 talloc_free(temp_ctx);
     398           0 :                 DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: ldb_msg_add_value failed\n"));      
     399           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     400             :         }
     401             :  
     402         878 :         ldb_ret = dsdb_replace(ldb, msg, DSDB_FLAG_AS_SYSTEM);
     403             : 
     404         878 :         talloc_free(temp_ctx);
     405             : 
     406         878 :         if (ldb_ret != 0) {
     407           0 :                 DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: dsdb_replace failed\n"));
     408           0 :                 return WERR_FOOBAR;
     409             :         }
     410             :  
     411         878 :         return WERR_OK;
     412             : }
     413             : 
     414         707 : WERROR dsdb_read_prefixes_from_ldb(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
     415             : {
     416          22 :         WERROR werr;
     417          22 :         int ldb_ret;
     418          22 :         const struct ldb_val *prefix_val;
     419          22 :         struct ldb_dn *schema_dn;
     420         707 :         struct ldb_result *schema_res = NULL;
     421          22 :         static const char *schema_attrs[] = {
     422             :                 "prefixMap",
     423             :                 NULL
     424             :         };
     425             : 
     426         707 :         schema_dn = ldb_get_schema_basedn(ldb);
     427         707 :         if (!schema_dn) {
     428           0 :                 DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n"));
     429           0 :                 return WERR_FOOBAR;
     430             :         }
     431             : 
     432         707 :         ldb_ret = ldb_search(ldb, mem_ctx, &schema_res, schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL);
     433         707 :         if (ldb_ret == LDB_ERR_NO_SUCH_OBJECT) {
     434           0 :                 DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n"));
     435           0 :                 talloc_free(schema_res);
     436           0 :                 return WERR_FOOBAR;
     437         707 :         } else if (ldb_ret != LDB_SUCCESS) {
     438           0 :                 DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n"));
     439           0 :                 talloc_free(schema_res);
     440           0 :                 return WERR_FOOBAR;
     441             :         }
     442             : 
     443         707 :         prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
     444         707 :         if (!prefix_val) {
     445           0 :                 DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n"));
     446           0 :                 talloc_free(schema_res);
     447           0 :                 return WERR_FOOBAR;
     448             :         }
     449             : 
     450         707 :         werr = _dsdb_prefixmap_from_ldb_val(prefix_val,
     451             :                                             mem_ctx,
     452             :                                             _pfm);
     453         707 :         talloc_free(schema_res);
     454         707 :         W_ERROR_NOT_OK_RETURN(werr);
     455             : 
     456         707 :         return WERR_OK;
     457             : }
     458             : 
     459             : /*
     460             :   this will be replaced with something that looks at the right part of
     461             :   the schema once we know where unique indexing information is hidden
     462             :  */
     463    38929857 : static bool dsdb_schema_unique_attribute(const char *attr)
     464             : {
     465    38929857 :         const char *attrs[] = { "objectGUID", NULL };
     466      487620 :         unsigned int i;
     467    77831826 :         for (i=0;attrs[i];i++) {
     468    38929857 :                 if (ldb_attr_cmp(attr, attrs[i]) == 0) {
     469       27548 :                         return true;
     470             :                 }
     471             :         }
     472    38414689 :         return false;
     473             : }
     474             : 
     475             : 
     476             : /*
     477             :   setup the ldb_schema_attribute field for a dsdb_attribute
     478             :  */
     479    38929857 : static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb, 
     480             :                                                   struct dsdb_attribute *attr)
     481             : {
     482    38929857 :         const char *syntax = attr->syntax->ldb_syntax;
     483      487620 :         const struct ldb_schema_syntax *s;
     484      487620 :         struct ldb_schema_attribute *a;
     485             : 
     486    38929857 :         if (!syntax) {
     487    21818983 :                 syntax = attr->syntax->ldap_oid;
     488             :         }
     489             : 
     490    38929857 :         s = ldb_samba_syntax_by_lDAPDisplayName(ldb, attr->lDAPDisplayName);
     491    38929857 :         if (s == NULL) {
     492    37335506 :                 s = ldb_samba_syntax_by_name(ldb, syntax);
     493             :         }
     494    38929857 :         if (s == NULL) {
     495    19694959 :                 s = ldb_standard_syntax_by_name(ldb, syntax);
     496             :         }
     497             : 
     498    38929857 :         if (s == NULL) {
     499           0 :                 return ldb_operr(ldb);
     500             :         }
     501             : 
     502    38929857 :         attr->ldb_schema_attribute = a = talloc(attr, struct ldb_schema_attribute);
     503    38929857 :         if (attr->ldb_schema_attribute == NULL) {
     504           0 :                 return ldb_oom(ldb);
     505             :         }
     506             : 
     507    38929857 :         a->name = attr->lDAPDisplayName;
     508    38929857 :         a->flags = 0;
     509    38929857 :         a->syntax = s;
     510             : 
     511    38929857 :         if (dsdb_schema_unique_attribute(a->name)) {
     512       27888 :                 a->flags |= LDB_ATTR_FLAG_UNIQUE_INDEX;
     513             :         }
     514    38929857 :         if (attr->isSingleValued) {
     515    27258877 :                 a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE;
     516             :         }
     517             : 
     518             :         /*
     519             :          * Is the attribute indexed? By treating confidential attributes as
     520             :          * unindexed, we force searches to go through the unindexed search path,
     521             :          * avoiding observable timing differences.
     522             :          */
     523    38929857 :         if (attr->searchFlags & SEARCH_FLAG_ATTINDEX &&
     524     3625756 :             !(attr->searchFlags & SEARCH_FLAG_CONFIDENTIAL))
     525             :         {
     526     3674354 :                 a->flags |= LDB_ATTR_FLAG_INDEXED;
     527             :         }
     528             : 
     529             :         
     530    38442237 :         return LDB_SUCCESS;
     531             : }
     532             : 
     533             : 
     534             : #define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
     535             :         const struct ldb_val *get_string_val = ldb_msg_find_ldb_val(msg, attr); \
     536             :         if (get_string_val == NULL) { \
     537             :                 if (strict) {                                     \
     538             :                         d_printf("%s: %s == NULL in %s\n", __location__, attr, ldb_dn_get_linearized(msg->dn)); \
     539             :                         return WERR_INVALID_PARAMETER;                  \
     540             :                 } else {                                                \
     541             :                         (p)->elem = NULL;                            \
     542             :                 }                                                       \
     543             :         } else {                                                        \
     544             :                 (p)->elem = talloc_strndup(mem_ctx,                  \
     545             :                                            (const char *)get_string_val->data, \
     546             :                                            get_string_val->length); \
     547             :                 if (!(p)->elem) {                                    \
     548             :                         d_printf("%s: talloc_strndup failed for %s\n", __location__, attr); \
     549             :                         return WERR_NOT_ENOUGH_MEMORY;                          \
     550             :                 }                                                       \
     551             :         }                                                               \
     552             : } while (0)
     553             : 
     554             : #define GET_STRING_LIST_LDB(msg, attr, mem_ctx, p, elem) do {   \
     555             :         int get_string_list_counter;                                    \
     556             :         struct ldb_message_element *get_string_list_el = ldb_msg_find_element(msg, attr); \
     557             :         /* We may get empty attributes over the replication channel */  \
     558             :         if (get_string_list_el == NULL || get_string_list_el->num_values == 0) {                             \
     559             :                 (p)->elem = NULL;                                    \
     560             :                 break;                                                  \
     561             :         }                                                               \
     562             :         (p)->elem = talloc_array(mem_ctx, const char *, get_string_list_el->num_values + 1); \
     563             :         for (get_string_list_counter=0;                                 \
     564             :              get_string_list_counter < get_string_list_el->num_values;    \
     565             :              get_string_list_counter++) {                               \
     566             :                 (p)->elem[get_string_list_counter] = talloc_strndup((p)->elem, \
     567             :                                                                     (const char *)get_string_list_el->values[get_string_list_counter].data, \
     568             :                                                                     get_string_list_el->values[get_string_list_counter].length); \
     569             :                 if (!(p)->elem[get_string_list_counter]) {           \
     570             :                         d_printf("%s: talloc_strndup failed for %s\n", __location__, attr); \
     571             :                         return WERR_NOT_ENOUGH_MEMORY;                          \
     572             :                 }                                                       \
     573             :                 (p)->elem[get_string_list_counter+1] = NULL;         \
     574             :         }                                                               \
     575             :         talloc_steal(mem_ctx, (p)->elem);                            \
     576             : } while (0)
     577             : 
     578             : #define GET_BOOL_LDB(msg, attr, p, elem, strict) do { \
     579             :         const char *str; \
     580             :         str = ldb_msg_find_attr_as_string(msg, attr, NULL);\
     581             :         if (str == NULL) { \
     582             :                 if (strict) { \
     583             :                         d_printf("%s: %s == NULL\n", __location__, attr); \
     584             :                         return WERR_INVALID_PARAMETER; \
     585             :                 } else { \
     586             :                         (p)->elem = false; \
     587             :                 } \
     588             :         } else if (strcasecmp("TRUE", str) == 0) { \
     589             :                 (p)->elem = true; \
     590             :         } else if (strcasecmp("FALSE", str) == 0) { \
     591             :                 (p)->elem = false; \
     592             :         } else { \
     593             :                 d_printf("%s: %s == %s\n", __location__, attr, str); \
     594             :                 return WERR_INVALID_PARAMETER; \
     595             :         } \
     596             : } while (0)
     597             : 
     598             : #define GET_UINT32_LDB(msg, attr, p, elem) do { \
     599             :         (p)->elem = ldb_msg_find_attr_as_uint(msg, attr, 0);\
     600             : } while (0)
     601             : 
     602             : #define GET_UINT32_PTR_LDB(msg, attr, mem_ctx, p, elem) do {            \
     603             :         uint64_t _v = ldb_msg_find_attr_as_uint64(msg, attr, UINT64_MAX);\
     604             :         if (_v == UINT64_MAX) { \
     605             :                 (p)->elem = NULL; \
     606             :         } else if (_v > UINT32_MAX) { \
     607             :                 d_printf("%s: %s == 0x%llX\n", __location__, \
     608             :                          attr, (unsigned long long)_v); \
     609             :                 return WERR_INVALID_PARAMETER; \
     610             :         } else { \
     611             :                 (p)->elem = talloc(mem_ctx, uint32_t); \
     612             :                 if (!(p)->elem) { \
     613             :                         d_printf("%s: talloc failed for %s\n", __location__, attr); \
     614             :                         return WERR_NOT_ENOUGH_MEMORY; \
     615             :                 } \
     616             :                 *(p)->elem = (uint32_t)_v; \
     617             :         } \
     618             : } while (0)
     619             : 
     620             : #define GET_GUID_LDB(msg, attr, p, elem) do { \
     621             :         (p)->elem = samdb_result_guid(msg, attr);\
     622             : } while (0)
     623             : 
     624             : #define GET_BLOB_LDB(msg, attr, mem_ctx, p, elem) do { \
     625             :         const struct ldb_val *_val;\
     626             :         _val = ldb_msg_find_ldb_val(msg, attr);\
     627             :         if (_val) {\
     628             :                 (p)->elem = *_val;\
     629             :                 talloc_steal(mem_ctx, (p)->elem.data);\
     630             :         } else {\
     631             :                 ZERO_STRUCT((p)->elem);\
     632             :         }\
     633             : } while (0)
     634             : 
     635             : /** Create an dsdb_attribute out of ldb message, attr must be already talloced
     636             :  *
     637             :  * If supplied the attribute will be checked against the prefixmap to
     638             :  * ensure it can be mapped.  However we can't have this attribute
     639             :  * const as dsdb_schema_pfm_attid_from_oid calls
     640             :  * dsdb_schema_pfm_make_attid_impl() which may modify prefixmap in
     641             :  * other situations.
     642             :  */
     643             : 
     644    39151405 : WERROR dsdb_attribute_from_ldb(struct dsdb_schema_prefixmap *prefixmap,
     645             :                                struct ldb_message *msg,
     646             :                                struct dsdb_attribute *attr)
     647             : {
     648      524540 :         WERROR status;
     649    39151405 :         if (attr == NULL) {
     650           0 :                 DEBUG(0, ("%s: attr is null, it's expected not to be so\n", __location__));
     651           0 :                 return WERR_INVALID_PARAMETER;
     652             :         }
     653             : 
     654    39151405 :         GET_STRING_LDB(msg, "cn", attr, attr, cn, false);
     655             : 
     656             :         /*
     657             :          * This allows for the fact that the CN attribute is not
     658             :          * replicated over DRS, it is only replicated under the alias
     659             :          * 'name'.
     660             :          */
     661    39151405 :         if (attr->cn == NULL) {
     662      110572 :                 GET_STRING_LDB(msg, "name", attr, attr, cn, true);
     663             :         }
     664             : 
     665    39151405 :         GET_STRING_LDB(msg, "lDAPDisplayName", attr, attr, lDAPDisplayName, true);
     666    39151405 :         GET_STRING_LDB(msg, "attributeID", attr, attr, attributeID_oid, true);
     667    39151405 :         if (!prefixmap || prefixmap->length == 0) {
     668             :                 /* set an invalid value */
     669      223047 :                 attr->attributeID_id = DRSUAPI_ATTID_INVALID;
     670             :         } else {
     671    38928358 :                 status = dsdb_schema_pfm_attid_from_oid(prefixmap,
     672             :                                                         attr->attributeID_oid,
     673             :                                                         &attr->attributeID_id);
     674    38928358 :                 if (!W_ERROR_IS_OK(status)) {
     675           0 :                         DEBUG(0,("%s: '%s': unable to map attributeID %s: %s\n",
     676             :                                 __location__, attr->lDAPDisplayName, attr->attributeID_oid,
     677             :                                 win_errstr(status)));
     678           0 :                         return status;
     679             :                 }
     680             :         }
     681             :         /* fetch msDS-IntId to be used in resolving ATTRTYP values */
     682    39151405 :         GET_UINT32_LDB(msg, "msDS-IntId", attr, msDS_IntId);
     683             : 
     684    39151405 :         GET_GUID_LDB(msg, "schemaIDGUID", attr, schemaIDGUID);
     685    39151405 :         GET_UINT32_LDB(msg, "mAPIID", attr, mAPIID);
     686             : 
     687    39151405 :         GET_GUID_LDB(msg, "attributeSecurityGUID", attr, attributeSecurityGUID);
     688             : 
     689    39151405 :         GET_GUID_LDB(msg, "objectGUID", attr, objectGUID);
     690             : 
     691    39151405 :         GET_UINT32_LDB(msg, "searchFlags", attr, searchFlags);
     692    39151405 :         GET_UINT32_LDB(msg, "systemFlags", attr, systemFlags);
     693    39151405 :         GET_BOOL_LDB(msg, "isMemberOfPartialAttributeSet", attr, isMemberOfPartialAttributeSet, false);
     694    39151405 :         GET_UINT32_LDB(msg, "linkID", attr, linkID);
     695             : 
     696    39151405 :         GET_STRING_LDB(msg, "attributeSyntax", attr, attr, attributeSyntax_oid, true);
     697    39151405 :         if (!prefixmap || prefixmap->length == 0) {
     698             :                 /* set an invalid value */
     699      223047 :                 attr->attributeSyntax_id = DRSUAPI_ATTID_INVALID;
     700             :         } else {
     701    38928358 :                 status = dsdb_schema_pfm_attid_from_oid(prefixmap,
     702             :                                                         attr->attributeSyntax_oid,
     703             :                                                         &attr->attributeSyntax_id);
     704    38928358 :                 if (!W_ERROR_IS_OK(status)) {
     705           0 :                         DEBUG(0,("%s: '%s': unable to map attributeSyntax_ %s: %s\n",
     706             :                                 __location__, attr->lDAPDisplayName, attr->attributeSyntax_oid,
     707             :                                 win_errstr(status)));
     708           0 :                         return status;
     709             :                 }
     710             :         }
     711    39151405 :         GET_UINT32_LDB(msg, "oMSyntax", attr, oMSyntax);
     712    39151405 :         GET_BLOB_LDB(msg, "oMObjectClass", attr, attr, oMObjectClass);
     713             : 
     714    39151405 :         GET_BOOL_LDB(msg, "isSingleValued", attr, isSingleValued, true);
     715    39151405 :         GET_UINT32_PTR_LDB(msg, "rangeLower", attr, attr, rangeLower);
     716    39151405 :         GET_UINT32_PTR_LDB(msg, "rangeUpper", attr, attr, rangeUpper);
     717    39151405 :         GET_BOOL_LDB(msg, "extendedCharsAllowed", attr, extendedCharsAllowed, false);
     718             : 
     719    39151405 :         GET_UINT32_LDB(msg, "schemaFlagsEx", attr, schemaFlagsEx);
     720    39151405 :         GET_BLOB_LDB(msg, "msDs-Schema-Extensions", attr, attr, msDs_Schema_Extensions);
     721             : 
     722    39151405 :         GET_BOOL_LDB(msg, "showInAdvancedViewOnly", attr, showInAdvancedViewOnly, false);
     723    39151405 :         GET_STRING_LDB(msg, "adminDisplayName", attr, attr, adminDisplayName, false);
     724    39151405 :         GET_STRING_LDB(msg, "adminDescription", attr, attr, adminDescription, false);
     725    39151405 :         GET_STRING_LDB(msg, "classDisplayName", attr, attr, classDisplayName, false);
     726    39151405 :         GET_BOOL_LDB(msg, "isEphemeral", attr, isEphemeral, false);
     727    39151405 :         GET_BOOL_LDB(msg, "isDefunct", attr, isDefunct, false);
     728    39151405 :         GET_BOOL_LDB(msg, "systemOnly", attr, systemOnly, false);
     729             : 
     730    39151405 :         return WERR_OK;
     731             : }
     732             : 
     733    38929857 : WERROR dsdb_set_attribute_from_ldb_dups(struct ldb_context *ldb,
     734             :                                         struct dsdb_schema *schema,
     735             :                                         struct ldb_message *msg,
     736             :                                         bool checkdups)
     737             : {
     738      487620 :         WERROR status;
     739    38929857 :         struct dsdb_attribute *attr = talloc_zero(schema, struct dsdb_attribute);
     740    38929857 :         if (!attr) {
     741           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     742             :         }
     743             : 
     744    38929857 :         status = dsdb_attribute_from_ldb(schema->prefixmap, msg, attr);
     745    38929857 :         if (!W_ERROR_IS_OK(status)) {
     746           0 :                 return status;
     747             :         }
     748             : 
     749    38929857 :         attr->syntax = dsdb_syntax_for_attribute(attr);
     750    38929857 :         if (!attr->syntax) {
     751           0 :                 DEBUG(0,(__location__ ": Unknown schema syntax for %s\n",
     752             :                          attr->lDAPDisplayName));
     753           0 :                 return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
     754             :         }
     755             : 
     756    38929857 :         if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
     757           0 :                 DEBUG(0,(__location__ ": Unknown schema syntax for %s - ldb_syntax: %s, ldap_oid: %s\n",
     758             :                          attr->lDAPDisplayName,
     759             :                          attr->syntax->ldb_syntax,
     760             :                          attr->syntax->ldap_oid));
     761           0 :                 return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
     762             :         }
     763             : 
     764    38929857 :         if (checkdups) {
     765           0 :                 const struct dsdb_attribute *a2;
     766           0 :                 struct dsdb_attribute **a;
     767           0 :                 uint32_t i;
     768             : 
     769      110572 :                 a2 = dsdb_attribute_by_attributeID_id(schema,
     770             :                                                       attr->attributeID_id);
     771      110572 :                 if (a2 == NULL) {
     772      110572 :                         goto done;
     773             :                 }
     774             : 
     775           0 :                 i = schema->attributes_to_remove_size;
     776           0 :                 a = talloc_realloc(schema, schema->attributes_to_remove,
     777             :                                    struct dsdb_attribute *, i + 1);
     778           0 :                 if (a == NULL) {
     779           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     780             :                 }
     781             :                 /* Mark the old attribute as to be removed */
     782           0 :                 a[i] = discard_const_p(struct dsdb_attribute, a2);
     783           0 :                 schema->attributes_to_remove = a;
     784           0 :                 schema->attributes_to_remove_size++;
     785             :         }
     786             : 
     787    38819285 : done:
     788    38929857 :         DLIST_ADD(schema->attributes, attr);
     789    38929857 :         return WERR_OK;
     790             : }
     791             : 
     792        1500 : WERROR dsdb_set_attribute_from_ldb(struct ldb_context *ldb,
     793             :                                    struct dsdb_schema *schema,
     794             :                                    struct ldb_message *msg)
     795             : {
     796        1500 :         return dsdb_set_attribute_from_ldb_dups(ldb, schema, msg, false);
     797             : }
     798             : 
     799     7348454 : WERROR dsdb_set_class_from_ldb_dups(struct dsdb_schema *schema,
     800             :                                     struct ldb_message *msg,
     801             :                                     bool checkdups)
     802             : {
     803       87290 :         WERROR status;
     804     7348454 :         struct dsdb_class *obj = talloc_zero(schema, struct dsdb_class);
     805     7348454 :         if (!obj) {
     806           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     807             :         }
     808     7348454 :         GET_STRING_LDB(msg, "cn", obj, obj, cn, false);
     809             : 
     810             :         /*
     811             :          * This allows for the fact that the CN attribute is not
     812             :          * replicated over DRS, it is only replicated under the alias
     813             :          * 'name'.
     814             :          */
     815     7348454 :         if (obj->cn == NULL) {
     816       20659 :                 GET_STRING_LDB(msg, "name", obj, obj, cn, true);
     817             :         }
     818             : 
     819     7348454 :         GET_STRING_LDB(msg, "lDAPDisplayName", obj, obj, lDAPDisplayName, true);
     820     7348454 :         GET_STRING_LDB(msg, "governsID", obj, obj, governsID_oid, true);
     821     7348454 :         if (!schema->prefixmap || schema->prefixmap->length == 0) {
     822             :                 /* set an invalid value */
     823         269 :                 obj->governsID_id = DRSUAPI_ATTID_INVALID;
     824             :         } else {
     825     7348185 :                 status = dsdb_schema_pfm_attid_from_oid(schema->prefixmap,
     826             :                                                         obj->governsID_oid,
     827             :                                                         &obj->governsID_id);
     828     7348185 :                 if (!W_ERROR_IS_OK(status)) {
     829           0 :                         DEBUG(0,("%s: '%s': unable to map governsID %s: %s\n",
     830             :                                 __location__, obj->lDAPDisplayName, obj->governsID_oid,
     831             :                                 win_errstr(status)));
     832           0 :                         return status;
     833             :                 }
     834             :         }
     835     7348454 :         GET_GUID_LDB(msg, "schemaIDGUID", obj, schemaIDGUID);
     836     7348454 :         GET_GUID_LDB(msg, "objectGUID", obj, objectGUID);
     837             : 
     838     7348454 :         GET_UINT32_LDB(msg, "objectClassCategory", obj, objectClassCategory);
     839     7348454 :         GET_STRING_LDB(msg, "rDNAttID", obj, obj, rDNAttID, false);
     840     7348454 :         GET_STRING_LDB(msg, "defaultObjectCategory", obj, obj, defaultObjectCategory, true);
     841             :  
     842     7348454 :         GET_STRING_LDB(msg, "subClassOf", obj, obj, subClassOf, true);
     843             : 
     844     7610262 :         GET_STRING_LIST_LDB(msg, "systemAuxiliaryClass", obj, obj, systemAuxiliaryClass);
     845     7543138 :         GET_STRING_LIST_LDB(msg, "auxiliaryClass", obj, obj, auxiliaryClass);
     846             : 
     847    13037016 :         GET_STRING_LIST_LDB(msg, "systemMustContain", obj, obj, systemMustContain);
     848    49927579 :         GET_STRING_LIST_LDB(msg, "systemMayContain", obj, obj, systemMayContain);
     849     8127190 :         GET_STRING_LIST_LDB(msg, "mustContain", obj, obj, mustContain);
     850    17718443 :         GET_STRING_LIST_LDB(msg, "mayContain", obj, obj, mayContain);
     851             : 
     852    16383055 :         GET_STRING_LIST_LDB(msg, "systemPossSuperiors", obj, obj, systemPossSuperiors);
     853     9528564 :         GET_STRING_LIST_LDB(msg, "possSuperiors", obj, obj, possSuperiors);
     854             : 
     855     7348454 :         GET_STRING_LDB(msg, "defaultSecurityDescriptor", obj, obj, defaultSecurityDescriptor, false);
     856             : 
     857     7348454 :         GET_UINT32_LDB(msg, "schemaFlagsEx", obj, schemaFlagsEx);
     858     7348454 :         GET_UINT32_LDB(msg, "systemFlags", obj, systemFlags);
     859     7348454 :         GET_BLOB_LDB(msg, "msDs-Schema-Extensions", obj, obj, msDs_Schema_Extensions);
     860             : 
     861     7348454 :         GET_BOOL_LDB(msg, "showInAdvancedViewOnly", obj, showInAdvancedViewOnly, false);
     862     7348454 :         GET_STRING_LDB(msg, "adminDisplayName", obj, obj, adminDisplayName, false);
     863     7348454 :         GET_STRING_LDB(msg, "adminDescription", obj, obj, adminDescription, false);
     864     7348454 :         GET_STRING_LDB(msg, "classDisplayName", obj, obj, classDisplayName, false);
     865     7348454 :         GET_BOOL_LDB(msg, "defaultHidingValue", obj, defaultHidingValue, false);
     866     7348454 :         GET_BOOL_LDB(msg, "isDefunct", obj, isDefunct, false);
     867     7348454 :         GET_BOOL_LDB(msg, "systemOnly", obj, systemOnly, false);
     868             : 
     869     7348454 :         if (checkdups) {
     870           0 :                 const struct dsdb_class *c2;
     871           0 :                 struct dsdb_class **c;
     872           0 :                 uint32_t i;
     873             : 
     874       20659 :                 c2 = dsdb_class_by_governsID_id(schema, obj->governsID_id);
     875       20659 :                 if (c2 == NULL) {
     876       20659 :                         goto done;
     877             :                 }
     878             : 
     879           0 :                 i = schema->classes_to_remove_size;
     880           0 :                 c = talloc_realloc(schema, schema->classes_to_remove,
     881             :                                    struct dsdb_class *, i + 1);
     882           0 :                 if (c == NULL) {
     883           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     884             :                 }
     885             :                 /* Mark the old class to be removed */
     886           0 :                 c[i] = discard_const_p(struct dsdb_class, c2);
     887           0 :                 schema->classes_to_remove = c;
     888           0 :                 schema->classes_to_remove_size++;
     889             :         }
     890             : 
     891     7327795 : done:
     892     7348454 :         DLIST_ADD(schema->classes, obj);
     893     7348454 :         return WERR_OK;
     894             : }
     895             : 
     896         269 : WERROR dsdb_set_class_from_ldb(struct dsdb_schema *schema,
     897             :                                struct ldb_message *msg)
     898             : {
     899         269 :         return dsdb_set_class_from_ldb_dups(schema, msg, false);
     900             : }
     901             : 
     902             : #define dsdb_oom(error_string, mem_ctx) *error_string = talloc_asprintf(mem_ctx, "dsdb out of memory at %s:%d\n", __FILE__, __LINE__)
     903             : 
     904             : /* 
     905             :  Fill a DSDB schema from the ldb results provided.  This is called
     906             :  directly when a schema must be created with a pre-initialised prefixMap
     907             : */
     908             : 
     909       27421 : int dsdb_load_ldb_results_into_schema(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
     910             :                                       struct dsdb_schema *schema,
     911             :                                       struct ldb_result *attrs_class_res,
     912             :                                       char **error_string)
     913             : {
     914         316 :         unsigned int i;
     915         316 :         WERROR status;
     916             : 
     917       27421 :         schema->ts_last_change = 0;
     918    45525248 :         for (i=0; i < attrs_class_res->count; i++) {
     919    45497827 :                 const char *prefixMap = NULL;
     920             :                 /*
     921             :                  * attrs_class_res also includes the schema object;
     922             :                  * we only want to process classes & attributes
     923             :                  */
     924    46030651 :                 prefixMap = ldb_msg_find_attr_as_string(
     925    45497827 :                                 attrs_class_res->msgs[i],
     926             :                                 "prefixMap", NULL);
     927    45497827 :                 if (prefixMap != NULL) {
     928       27415 :                         continue;
     929             :                 }
     930             : 
     931    45470412 :                 status = dsdb_schema_set_el_from_ldb_msg(ldb, schema,
     932    45470412 :                                                          attrs_class_res->msgs[i]);
     933    45470412 :                 if (!W_ERROR_IS_OK(status)) {
     934           0 :                         *error_string = talloc_asprintf(mem_ctx,
     935             :                                       "dsdb_load_ldb_results_into_schema: failed to load attribute or class definition: %s:%s",
     936           0 :                                       ldb_dn_get_linearized(attrs_class_res->msgs[i]->dn),
     937             :                                       win_errstr(status));
     938           0 :                         DEBUG(0,(__location__ ": %s\n", *error_string));
     939           0 :                         return LDB_ERR_CONSTRAINT_VIOLATION;
     940             :                 }
     941             :         }
     942             : 
     943       27105 :         return LDB_SUCCESS;
     944             : }
     945             : 
     946             : /*
     947             :  Create a DSDB schema from the ldb results provided.  This is called
     948             :  directly when the schema is provisioned from an on-disk LDIF file, or
     949             :  from dsdb_schema_from_schema_dn in schema_fsmo
     950             : */
     951             : 
     952       27415 : int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
     953             :                                  struct ldb_message *schema_msg,
     954             :                                  struct ldb_result *attrs_class_res,
     955             :                                  struct dsdb_schema **schema_out,
     956             :                                  char **error_string)
     957             : {
     958         316 :         WERROR status;
     959         316 :         const struct ldb_val *prefix_val;
     960         316 :         const struct ldb_val *info_val;
     961         316 :         struct ldb_val info_val_default;
     962         316 :         struct dsdb_schema *schema;
     963       27415 :         void *lp_opaque = ldb_get_opaque(ldb, "loadparm");
     964         316 :         int ret;
     965             : 
     966       27415 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     967       27415 :         if (!tmp_ctx) {
     968           0 :                 dsdb_oom(error_string, mem_ctx);
     969           0 :                 return ldb_operr(ldb);
     970             :         }
     971             : 
     972       27415 :         schema = dsdb_new_schema(tmp_ctx);
     973       27415 :         if (!schema) {
     974           0 :                 dsdb_oom(error_string, mem_ctx);
     975           0 :                 talloc_free(tmp_ctx);
     976           0 :                 return ldb_operr(ldb);
     977             :         }
     978             : 
     979       27415 :         if (lp_opaque) {
     980       27415 :                 struct loadparm_context *lp_ctx = talloc_get_type_abort(lp_opaque, struct loadparm_context);
     981       27415 :                 schema->fsmo.update_allowed = lpcfg_parm_bool(lp_ctx, NULL,
     982             :                                                               "dsdb", "schema update allowed",
     983             :                                                               false);
     984             :         }
     985             : 
     986       27415 :         prefix_val = ldb_msg_find_ldb_val(schema_msg, "prefixMap");
     987       27415 :         if (!prefix_val) {
     988           0 :                 *error_string = talloc_asprintf(mem_ctx, 
     989             :                                                 "schema_fsmo_init: no prefixMap attribute found");
     990           0 :                 DEBUG(0,(__location__ ": %s\n", *error_string));
     991           0 :                 talloc_free(tmp_ctx);
     992           0 :                 return LDB_ERR_CONSTRAINT_VIOLATION;
     993             :         }
     994       27415 :         info_val = ldb_msg_find_ldb_val(schema_msg, "schemaInfo");
     995       27415 :         if (!info_val) {
     996       10453 :                 status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default);
     997       10453 :                 if (!W_ERROR_IS_OK(status)) {
     998           0 :                         *error_string = talloc_asprintf(mem_ctx,
     999             :                                                         "schema_fsmo_init: dsdb_schema_info_blob_new() failed - %s",
    1000             :                                                         win_errstr(status));
    1001           0 :                         DEBUG(0,(__location__ ": %s\n", *error_string));
    1002           0 :                         talloc_free(tmp_ctx);
    1003           0 :                         return ldb_operr(ldb);
    1004             :                 }
    1005       10137 :                 info_val = &info_val_default;
    1006             :         }
    1007             : 
    1008       27415 :         status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
    1009       27415 :         if (!W_ERROR_IS_OK(status)) {
    1010           0 :                 *error_string = talloc_asprintf(mem_ctx, 
    1011             :                               "schema_fsmo_init: failed to load oid mappings: %s",
    1012             :                               win_errstr(status));
    1013           0 :                 DEBUG(0,(__location__ ": %s\n", *error_string));
    1014           0 :                 talloc_free(tmp_ctx);
    1015           0 :                 return LDB_ERR_CONSTRAINT_VIOLATION;
    1016             :         }
    1017             : 
    1018       27415 :         ret = dsdb_load_ldb_results_into_schema(mem_ctx, ldb, schema, attrs_class_res, error_string);
    1019       27415 :         if (ret != LDB_SUCCESS) {
    1020           0 :                 talloc_free(tmp_ctx);
    1021           0 :                 return ret;
    1022             :         }
    1023             : 
    1024       27415 :         schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_msg, "fSMORoleOwner");
    1025       27415 :         if (ldb_dn_compare(samdb_ntds_settings_dn(ldb, tmp_ctx), schema->fsmo.master_dn) == 0) {
    1026       26678 :                 schema->fsmo.we_are_master = true;
    1027             :         } else {
    1028         737 :                 schema->fsmo.we_are_master = false;
    1029             :         }
    1030             : 
    1031       27415 :         DEBUG(5, ("schema_fsmo_init: we are master[%s] updates allowed[%s]\n",
    1032             :                   (schema->fsmo.we_are_master?"yes":"no"),
    1033             :                   (schema->fsmo.update_allowed?"yes":"no")));
    1034             : 
    1035       27415 :         *schema_out = talloc_steal(mem_ctx, schema);
    1036       27415 :         talloc_free(tmp_ctx);
    1037       27415 :         return LDB_SUCCESS;
    1038             : }

Generated by: LCOV version 1.14