1 | /*
|
---|
2 | Unix SMB/CIFS mplementation.
|
---|
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 |
|
---|
36 | struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx)
|
---|
37 | {
|
---|
38 | struct dsdb_schema *schema = talloc_zero(mem_ctx, struct dsdb_schema);
|
---|
39 | if (!schema) {
|
---|
40 | return NULL;
|
---|
41 | }
|
---|
42 |
|
---|
43 | return schema;
|
---|
44 | }
|
---|
45 |
|
---|
46 | struct dsdb_schema *dsdb_schema_copy_shallow(TALLOC_CTX *mem_ctx,
|
---|
47 | struct ldb_context *ldb,
|
---|
48 | const struct dsdb_schema *schema)
|
---|
49 | {
|
---|
50 | int ret;
|
---|
51 | struct dsdb_class *cls;
|
---|
52 | struct dsdb_attribute *attr;
|
---|
53 | struct dsdb_schema *schema_copy;
|
---|
54 |
|
---|
55 | schema_copy = dsdb_new_schema(mem_ctx);
|
---|
56 | if (!schema_copy) {
|
---|
57 | return NULL;
|
---|
58 | }
|
---|
59 |
|
---|
60 | /* schema base_dn */
|
---|
61 | schema_copy->base_dn = ldb_dn_copy(schema_copy, schema->base_dn);
|
---|
62 | if (!schema_copy->base_dn) {
|
---|
63 | goto failed;
|
---|
64 | }
|
---|
65 |
|
---|
66 | /* copy prexiMap & schemaInfo */
|
---|
67 | schema_copy->prefixmap = dsdb_schema_pfm_copy_shallow(schema_copy,
|
---|
68 | schema->prefixmap);
|
---|
69 | if (!schema_copy->prefixmap) {
|
---|
70 | goto failed;
|
---|
71 | }
|
---|
72 |
|
---|
73 | schema_copy->schema_info = talloc_strdup(schema_copy, schema->schema_info);
|
---|
74 |
|
---|
75 | /* copy classes and attributes*/
|
---|
76 | for (cls = schema->classes; cls; cls = cls->next) {
|
---|
77 | struct dsdb_class *class_copy = talloc_memdup(schema_copy,
|
---|
78 | cls, sizeof(*cls));
|
---|
79 | if (!class_copy) {
|
---|
80 | goto failed;
|
---|
81 | }
|
---|
82 | DLIST_ADD(schema_copy->classes, class_copy);
|
---|
83 | }
|
---|
84 | schema_copy->num_classes = schema->num_classes;
|
---|
85 |
|
---|
86 | for (attr = schema->attributes; attr; attr = attr->next) {
|
---|
87 | struct dsdb_attribute *a_copy = talloc_memdup(schema_copy,
|
---|
88 | attr, sizeof(*attr));
|
---|
89 | if (!a_copy) {
|
---|
90 | goto failed;
|
---|
91 | }
|
---|
92 | DLIST_ADD(schema_copy->attributes, a_copy);
|
---|
93 | }
|
---|
94 | schema_copy->num_attributes = schema->num_attributes;
|
---|
95 |
|
---|
96 | /* rebuild indexes */
|
---|
97 | ret = dsdb_setup_sorted_accessors(ldb, schema_copy);
|
---|
98 | if (ret != LDB_SUCCESS) {
|
---|
99 | goto failed;
|
---|
100 | }
|
---|
101 |
|
---|
102 | /* leave reload_seq_number = 0 so it will be refresh ASAP */
|
---|
103 | schema_copy->refresh_fn = schema->refresh_fn;
|
---|
104 | schema_copy->loaded_from_module = schema->loaded_from_module;
|
---|
105 |
|
---|
106 | return schema_copy;
|
---|
107 |
|
---|
108 | failed:
|
---|
109 | talloc_free(schema_copy);
|
---|
110 | return NULL;
|
---|
111 | }
|
---|
112 |
|
---|
113 |
|
---|
114 | WERROR dsdb_load_prefixmap_from_drsuapi(struct dsdb_schema *schema,
|
---|
115 | const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
|
---|
116 | {
|
---|
117 | WERROR werr;
|
---|
118 | const char *schema_info;
|
---|
119 | struct dsdb_schema_prefixmap *pfm;
|
---|
120 |
|
---|
121 | werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, true, schema, &pfm, &schema_info);
|
---|
122 | W_ERROR_NOT_OK_RETURN(werr);
|
---|
123 |
|
---|
124 | /* set loaded prefixMap */
|
---|
125 | talloc_free(schema->prefixmap);
|
---|
126 | schema->prefixmap = pfm;
|
---|
127 |
|
---|
128 | talloc_free(discard_const(schema->schema_info));
|
---|
129 | schema->schema_info = schema_info;
|
---|
130 |
|
---|
131 | return WERR_OK;
|
---|
132 | }
|
---|
133 |
|
---|
134 | static WERROR _dsdb_prefixmap_from_ldb_val(const struct ldb_val *pfm_ldb_val,
|
---|
135 | TALLOC_CTX *mem_ctx,
|
---|
136 | struct dsdb_schema_prefixmap **_pfm)
|
---|
137 | {
|
---|
138 | WERROR werr;
|
---|
139 | enum ndr_err_code ndr_err;
|
---|
140 | struct prefixMapBlob pfm_blob;
|
---|
141 |
|
---|
142 | TALLOC_CTX *temp_ctx = talloc_new(mem_ctx);
|
---|
143 | W_ERROR_HAVE_NO_MEMORY(temp_ctx);
|
---|
144 |
|
---|
145 | ndr_err = ndr_pull_struct_blob(pfm_ldb_val, temp_ctx,
|
---|
146 | &pfm_blob,
|
---|
147 | (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
|
---|
148 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
149 | NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
|
---|
150 | DEBUG(0,("_dsdb_prefixmap_from_ldb_val: Failed to parse prefixmap of length %u: %s\n",
|
---|
151 | (unsigned int)pfm_ldb_val->length, ndr_map_error2string(ndr_err)));
|
---|
152 | talloc_free(temp_ctx);
|
---|
153 | return ntstatus_to_werror(nt_status);
|
---|
154 | }
|
---|
155 |
|
---|
156 | if (pfm_blob.version != PREFIX_MAP_VERSION_DSDB) {
|
---|
157 | DEBUG(0,("_dsdb_prefixmap_from_ldb_val: pfm_blob->version %u incorrect\n", (unsigned int)pfm_blob.version));
|
---|
158 | talloc_free(temp_ctx);
|
---|
159 | return WERR_VERSION_PARSE_ERROR;
|
---|
160 | }
|
---|
161 |
|
---|
162 | /* call the drsuapi version */
|
---|
163 | werr = dsdb_schema_pfm_from_drsuapi_pfm(&pfm_blob.ctr.dsdb, false, mem_ctx, _pfm, NULL);
|
---|
164 | if (!W_ERROR_IS_OK(werr)) {
|
---|
165 | DEBUG(0, (__location__ " dsdb_schema_pfm_from_drsuapi_pfm failed: %s\n", win_errstr(werr)));
|
---|
166 | talloc_free(temp_ctx);
|
---|
167 | return werr;
|
---|
168 | }
|
---|
169 |
|
---|
170 | talloc_free(temp_ctx);
|
---|
171 |
|
---|
172 | return werr;
|
---|
173 | }
|
---|
174 |
|
---|
175 | WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema,
|
---|
176 | const struct ldb_val *prefixMap,
|
---|
177 | const struct ldb_val *schemaInfo)
|
---|
178 | {
|
---|
179 | WERROR werr;
|
---|
180 | const char *schema_info;
|
---|
181 | struct dsdb_schema_prefixmap *pfm;
|
---|
182 | TALLOC_CTX *mem_ctx;
|
---|
183 |
|
---|
184 | /* verify schemaInfo blob is valid one */
|
---|
185 | if (!dsdb_schema_info_blob_is_valid(schemaInfo)) {
|
---|
186 | DEBUG(0,(__location__": dsdb_schema_info_blob_is_valid() failed.\n"));
|
---|
187 | return WERR_INVALID_PARAMETER;
|
---|
188 | }
|
---|
189 |
|
---|
190 | mem_ctx = talloc_new(schema);
|
---|
191 | W_ERROR_HAVE_NO_MEMORY(mem_ctx);
|
---|
192 |
|
---|
193 | /* fetch prefixMap */
|
---|
194 | werr = _dsdb_prefixmap_from_ldb_val(prefixMap,
|
---|
195 | mem_ctx, &pfm);
|
---|
196 | if (!W_ERROR_IS_OK(werr)) {
|
---|
197 | DEBUG(0, (__location__ " _dsdb_prefixmap_from_ldb_val failed: %s\n", win_errstr(werr)));
|
---|
198 | talloc_free(mem_ctx);
|
---|
199 | return werr;
|
---|
200 | }
|
---|
201 |
|
---|
202 | /* decode schema_info */
|
---|
203 | schema_info = hex_encode_talloc(mem_ctx,
|
---|
204 | schemaInfo->data,
|
---|
205 | schemaInfo->length);
|
---|
206 | if (!schema_info) {
|
---|
207 | talloc_free(mem_ctx);
|
---|
208 | return WERR_NOMEM;
|
---|
209 | }
|
---|
210 |
|
---|
211 | /* store prefixMap and schema_info into cached Schema */
|
---|
212 | talloc_free(schema->prefixmap);
|
---|
213 | schema->prefixmap = talloc_steal(schema, pfm);
|
---|
214 |
|
---|
215 | talloc_free(discard_const(schema->schema_info));
|
---|
216 | schema->schema_info = talloc_steal(schema, schema_info);
|
---|
217 |
|
---|
218 | /* clean up locally allocated mem */
|
---|
219 | talloc_free(mem_ctx);
|
---|
220 |
|
---|
221 | return WERR_OK;
|
---|
222 | }
|
---|
223 |
|
---|
224 | WERROR dsdb_get_oid_mappings_drsuapi(const struct dsdb_schema *schema,
|
---|
225 | bool include_schema_info,
|
---|
226 | TALLOC_CTX *mem_ctx,
|
---|
227 | struct drsuapi_DsReplicaOIDMapping_Ctr **_ctr)
|
---|
228 | {
|
---|
229 | return dsdb_drsuapi_pfm_from_schema_pfm(schema->prefixmap,
|
---|
230 | include_schema_info ? schema->schema_info : NULL,
|
---|
231 | mem_ctx, _ctr);
|
---|
232 | }
|
---|
233 |
|
---|
234 | WERROR dsdb_get_drsuapi_prefixmap_as_blob(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
|
---|
235 | TALLOC_CTX *mem_ctx,
|
---|
236 | struct ldb_val *prefixMap)
|
---|
237 | {
|
---|
238 | struct prefixMapBlob pfm;
|
---|
239 | enum ndr_err_code ndr_err;
|
---|
240 | pfm.version = PREFIX_MAP_VERSION_DSDB;
|
---|
241 | pfm.reserved = 0;
|
---|
242 | pfm.ctr.dsdb = *ctr;
|
---|
243 |
|
---|
244 | ndr_err = ndr_push_struct_blob(prefixMap, mem_ctx, &pfm,
|
---|
245 | (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
|
---|
246 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
247 | NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
|
---|
248 | return ntstatus_to_werror(nt_status);
|
---|
249 | }
|
---|
250 | return WERR_OK;
|
---|
251 | }
|
---|
252 |
|
---|
253 | WERROR dsdb_get_oid_mappings_ldb(const struct dsdb_schema *schema,
|
---|
254 | TALLOC_CTX *mem_ctx,
|
---|
255 | struct ldb_val *prefixMap,
|
---|
256 | struct ldb_val *schemaInfo)
|
---|
257 | {
|
---|
258 | WERROR status;
|
---|
259 | struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
|
---|
260 |
|
---|
261 | status = dsdb_get_oid_mappings_drsuapi(schema, false, mem_ctx, &ctr);
|
---|
262 | W_ERROR_NOT_OK_RETURN(status);
|
---|
263 |
|
---|
264 | status = dsdb_get_drsuapi_prefixmap_as_blob(ctr, mem_ctx, prefixMap);
|
---|
265 | talloc_free(ctr);
|
---|
266 | W_ERROR_NOT_OK_RETURN(status);
|
---|
267 |
|
---|
268 | *schemaInfo = strhex_to_data_blob(mem_ctx, schema->schema_info);
|
---|
269 | W_ERROR_HAVE_NO_MEMORY(schemaInfo->data);
|
---|
270 |
|
---|
271 | return WERR_OK;
|
---|
272 | }
|
---|
273 |
|
---|
274 |
|
---|
275 | /*
|
---|
276 | * this function is called from within a ldb transaction from the schema_fsmo module
|
---|
277 | */
|
---|
278 | WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
|
---|
279 | {
|
---|
280 | WERROR status;
|
---|
281 | uint32_t attid;
|
---|
282 | TALLOC_CTX *mem_ctx;
|
---|
283 | struct dsdb_schema_prefixmap *pfm;
|
---|
284 |
|
---|
285 | mem_ctx = talloc_new(ldb);
|
---|
286 | W_ERROR_HAVE_NO_MEMORY(mem_ctx);
|
---|
287 |
|
---|
288 | /* Read prefixes from disk*/
|
---|
289 | status = dsdb_read_prefixes_from_ldb(ldb, mem_ctx, &pfm);
|
---|
290 | if (!W_ERROR_IS_OK(status)) {
|
---|
291 | DEBUG(0,("dsdb_create_prefix_mapping: dsdb_read_prefixes_from_ldb: %s\n",
|
---|
292 | win_errstr(status)));
|
---|
293 | talloc_free(mem_ctx);
|
---|
294 | return status;
|
---|
295 | }
|
---|
296 |
|
---|
297 | /* Check if there is a prefix for the oid in the prefixes array*/
|
---|
298 | status = dsdb_schema_pfm_find_oid(pfm, full_oid, NULL);
|
---|
299 | if (W_ERROR_IS_OK(status)) {
|
---|
300 | /* prefix found*/
|
---|
301 | talloc_free(mem_ctx);
|
---|
302 | return status;
|
---|
303 | } else if (!W_ERROR_EQUAL(status, WERR_NOT_FOUND)) {
|
---|
304 | /* error */
|
---|
305 | DEBUG(0,("dsdb_create_prefix_mapping: dsdb_find_prefix_for_oid: %s\n",
|
---|
306 | win_errstr(status)));
|
---|
307 | talloc_free(mem_ctx);
|
---|
308 | return status;
|
---|
309 | }
|
---|
310 |
|
---|
311 | /* Create the new mapping for the prefix of full_oid */
|
---|
312 | status = dsdb_schema_pfm_make_attid(pfm, full_oid, &attid);
|
---|
313 | if (!W_ERROR_IS_OK(status)) {
|
---|
314 | DEBUG(0,("dsdb_create_prefix_mapping: dsdb_schema_pfm_make_attid: %s\n",
|
---|
315 | win_errstr(status)));
|
---|
316 | talloc_free(mem_ctx);
|
---|
317 | return status;
|
---|
318 | }
|
---|
319 |
|
---|
320 | talloc_unlink(schema, schema->prefixmap);
|
---|
321 | schema->prefixmap = talloc_steal(schema, pfm);
|
---|
322 |
|
---|
323 | /* Update prefixMap in ldb*/
|
---|
324 | status = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, ldb, schema);
|
---|
325 | if (!W_ERROR_IS_OK(status)) {
|
---|
326 | DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ldb: %s\n",
|
---|
327 | win_errstr(status)));
|
---|
328 | talloc_free(mem_ctx);
|
---|
329 | return status;
|
---|
330 | }
|
---|
331 |
|
---|
332 | DEBUG(2,(__location__ " Added prefixMap %s - now have %u prefixes\n",
|
---|
333 | full_oid, schema->prefixmap->length));
|
---|
334 |
|
---|
335 | talloc_free(mem_ctx);
|
---|
336 | return status;
|
---|
337 | }
|
---|
338 |
|
---|
339 |
|
---|
340 | WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
|
---|
341 | const struct dsdb_schema *schema)
|
---|
342 | {
|
---|
343 | WERROR status;
|
---|
344 | int ldb_ret;
|
---|
345 | struct ldb_message *msg;
|
---|
346 | struct ldb_dn *schema_dn;
|
---|
347 | struct prefixMapBlob pfm_blob;
|
---|
348 | struct ldb_val ndr_blob;
|
---|
349 | enum ndr_err_code ndr_err;
|
---|
350 | TALLOC_CTX *temp_ctx;
|
---|
351 | struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
|
---|
352 |
|
---|
353 | schema_dn = ldb_get_schema_basedn(ldb);
|
---|
354 | if (!schema_dn) {
|
---|
355 | DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: no schema dn present\n"));
|
---|
356 | return WERR_FOOBAR;
|
---|
357 | }
|
---|
358 |
|
---|
359 | temp_ctx = talloc_new(mem_ctx);
|
---|
360 | W_ERROR_HAVE_NO_MEMORY(temp_ctx);
|
---|
361 |
|
---|
362 | /* convert schema_prefixMap to prefixMap blob */
|
---|
363 | status = dsdb_get_oid_mappings_drsuapi(schema, false, temp_ctx, &ctr);
|
---|
364 | if (!W_ERROR_IS_OK(status)) {
|
---|
365 | talloc_free(temp_ctx);
|
---|
366 | return status;
|
---|
367 | }
|
---|
368 |
|
---|
369 | pfm_blob.version = PREFIX_MAP_VERSION_DSDB;
|
---|
370 | pfm_blob.ctr.dsdb = *ctr;
|
---|
371 |
|
---|
372 | ndr_err = ndr_push_struct_blob(&ndr_blob, temp_ctx,
|
---|
373 | &pfm_blob,
|
---|
374 | (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
|
---|
375 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
376 | talloc_free(temp_ctx);
|
---|
377 | return WERR_FOOBAR;
|
---|
378 | }
|
---|
379 |
|
---|
380 | /* write serialized prefixMap into LDB */
|
---|
381 | msg = ldb_msg_new(temp_ctx);
|
---|
382 | if (!msg) {
|
---|
383 | talloc_free(temp_ctx);
|
---|
384 | return WERR_NOMEM;
|
---|
385 | }
|
---|
386 |
|
---|
387 | msg->dn = schema_dn;
|
---|
388 | ldb_ret = ldb_msg_add_value(msg, "prefixMap", &ndr_blob, NULL);
|
---|
389 | if (ldb_ret != 0) {
|
---|
390 | talloc_free(temp_ctx);
|
---|
391 | DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: ldb_msg_add_value failed\n"));
|
---|
392 | return WERR_NOMEM;
|
---|
393 | }
|
---|
394 |
|
---|
395 | ldb_ret = dsdb_replace(ldb, msg, DSDB_FLAG_AS_SYSTEM);
|
---|
396 |
|
---|
397 | talloc_free(temp_ctx);
|
---|
398 |
|
---|
399 | if (ldb_ret != 0) {
|
---|
400 | DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: dsdb_replace failed\n"));
|
---|
401 | return WERR_FOOBAR;
|
---|
402 | }
|
---|
403 |
|
---|
404 | return WERR_OK;
|
---|
405 | }
|
---|
406 |
|
---|
407 | WERROR dsdb_read_prefixes_from_ldb(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
|
---|
408 | {
|
---|
409 | WERROR werr;
|
---|
410 | int ldb_ret;
|
---|
411 | const struct ldb_val *prefix_val;
|
---|
412 | struct ldb_dn *schema_dn;
|
---|
413 | struct ldb_result *schema_res = NULL;
|
---|
414 | static const char *schema_attrs[] = {
|
---|
415 | "prefixMap",
|
---|
416 | NULL
|
---|
417 | };
|
---|
418 |
|
---|
419 | schema_dn = ldb_get_schema_basedn(ldb);
|
---|
420 | if (!schema_dn) {
|
---|
421 | DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n"));
|
---|
422 | return WERR_FOOBAR;
|
---|
423 | }
|
---|
424 |
|
---|
425 | ldb_ret = ldb_search(ldb, mem_ctx, &schema_res, schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL);
|
---|
426 | if (ldb_ret == LDB_ERR_NO_SUCH_OBJECT) {
|
---|
427 | DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n"));
|
---|
428 | talloc_free(schema_res);
|
---|
429 | return WERR_FOOBAR;
|
---|
430 | } else if (ldb_ret != LDB_SUCCESS) {
|
---|
431 | DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n"));
|
---|
432 | talloc_free(schema_res);
|
---|
433 | return WERR_FOOBAR;
|
---|
434 | }
|
---|
435 |
|
---|
436 | prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
|
---|
437 | if (!prefix_val) {
|
---|
438 | DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n"));
|
---|
439 | talloc_free(schema_res);
|
---|
440 | return WERR_FOOBAR;
|
---|
441 | }
|
---|
442 |
|
---|
443 | werr = _dsdb_prefixmap_from_ldb_val(prefix_val,
|
---|
444 | mem_ctx,
|
---|
445 | _pfm);
|
---|
446 | talloc_free(schema_res);
|
---|
447 | W_ERROR_NOT_OK_RETURN(werr);
|
---|
448 |
|
---|
449 | return WERR_OK;
|
---|
450 | }
|
---|
451 |
|
---|
452 | /*
|
---|
453 | this will be replaced with something that looks at the right part of
|
---|
454 | the schema once we know where unique indexing information is hidden
|
---|
455 | */
|
---|
456 | static bool dsdb_schema_unique_attribute(const char *attr)
|
---|
457 | {
|
---|
458 | const char *attrs[] = { "objectGUID", "objectSid" , NULL };
|
---|
459 | unsigned int i;
|
---|
460 | for (i=0;attrs[i];i++) {
|
---|
461 | if (strcasecmp(attr, attrs[i]) == 0) {
|
---|
462 | return true;
|
---|
463 | }
|
---|
464 | }
|
---|
465 | return false;
|
---|
466 | }
|
---|
467 |
|
---|
468 |
|
---|
469 | /*
|
---|
470 | setup the ldb_schema_attribute field for a dsdb_attribute
|
---|
471 | */
|
---|
472 | static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb,
|
---|
473 | struct dsdb_attribute *attr)
|
---|
474 | {
|
---|
475 | const char *syntax = attr->syntax->ldb_syntax;
|
---|
476 | const struct ldb_schema_syntax *s;
|
---|
477 | struct ldb_schema_attribute *a;
|
---|
478 |
|
---|
479 | if (!syntax) {
|
---|
480 | syntax = attr->syntax->ldap_oid;
|
---|
481 | }
|
---|
482 |
|
---|
483 | s = ldb_samba_syntax_by_lDAPDisplayName(ldb, attr->lDAPDisplayName);
|
---|
484 | if (s == NULL) {
|
---|
485 | s = ldb_samba_syntax_by_name(ldb, syntax);
|
---|
486 | }
|
---|
487 | if (s == NULL) {
|
---|
488 | s = ldb_standard_syntax_by_name(ldb, syntax);
|
---|
489 | }
|
---|
490 |
|
---|
491 | if (s == NULL) {
|
---|
492 | return ldb_operr(ldb);
|
---|
493 | }
|
---|
494 |
|
---|
495 | attr->ldb_schema_attribute = a = talloc(attr, struct ldb_schema_attribute);
|
---|
496 | if (attr->ldb_schema_attribute == NULL) {
|
---|
497 | return ldb_oom(ldb);
|
---|
498 | }
|
---|
499 |
|
---|
500 | a->name = attr->lDAPDisplayName;
|
---|
501 | a->flags = 0;
|
---|
502 | a->syntax = s;
|
---|
503 |
|
---|
504 | if (dsdb_schema_unique_attribute(a->name)) {
|
---|
505 | a->flags |= LDB_ATTR_FLAG_UNIQUE_INDEX;
|
---|
506 | }
|
---|
507 | if (attr->isSingleValued) {
|
---|
508 | a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE;
|
---|
509 | }
|
---|
510 |
|
---|
511 |
|
---|
512 | return LDB_SUCCESS;
|
---|
513 | }
|
---|
514 |
|
---|
515 |
|
---|
516 | #define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
|
---|
517 | const struct ldb_val *get_string_val = ldb_msg_find_ldb_val(msg, attr); \
|
---|
518 | if (get_string_val == NULL) { \
|
---|
519 | if (strict) { \
|
---|
520 | d_printf("%s: %s == NULL in %s\n", __location__, attr, ldb_dn_get_linearized(msg->dn)); \
|
---|
521 | return WERR_INVALID_PARAM; \
|
---|
522 | } else { \
|
---|
523 | (p)->elem = NULL; \
|
---|
524 | } \
|
---|
525 | } else { \
|
---|
526 | (p)->elem = talloc_strndup(mem_ctx, \
|
---|
527 | (const char *)get_string_val->data, \
|
---|
528 | get_string_val->length); \
|
---|
529 | if (!(p)->elem) { \
|
---|
530 | d_printf("%s: talloc_strndup failed for %s\n", __location__, attr); \
|
---|
531 | return WERR_NOMEM; \
|
---|
532 | } \
|
---|
533 | } \
|
---|
534 | } while (0)
|
---|
535 |
|
---|
536 | #define GET_STRING_LIST_LDB(msg, attr, mem_ctx, p, elem) do { \
|
---|
537 | int get_string_list_counter; \
|
---|
538 | struct ldb_message_element *get_string_list_el = ldb_msg_find_element(msg, attr); \
|
---|
539 | /* We may get empty attributes over the replication channel */ \
|
---|
540 | if (get_string_list_el == NULL || get_string_list_el->num_values == 0) { \
|
---|
541 | (p)->elem = NULL; \
|
---|
542 | break; \
|
---|
543 | } \
|
---|
544 | (p)->elem = talloc_array(mem_ctx, const char *, get_string_list_el->num_values + 1); \
|
---|
545 | for (get_string_list_counter=0; \
|
---|
546 | get_string_list_counter < get_string_list_el->num_values; \
|
---|
547 | get_string_list_counter++) { \
|
---|
548 | (p)->elem[get_string_list_counter] = talloc_strndup((p)->elem, \
|
---|
549 | (const char *)get_string_list_el->values[get_string_list_counter].data, \
|
---|
550 | get_string_list_el->values[get_string_list_counter].length); \
|
---|
551 | if (!(p)->elem[get_string_list_counter]) { \
|
---|
552 | d_printf("%s: talloc_strndup failed for %s\n", __location__, attr); \
|
---|
553 | return WERR_NOMEM; \
|
---|
554 | } \
|
---|
555 | (p)->elem[get_string_list_counter+1] = NULL; \
|
---|
556 | } \
|
---|
557 | talloc_steal(mem_ctx, (p)->elem); \
|
---|
558 | } while (0)
|
---|
559 |
|
---|
560 | #define GET_BOOL_LDB(msg, attr, p, elem, strict) do { \
|
---|
561 | const char *str; \
|
---|
562 | str = ldb_msg_find_attr_as_string(msg, attr, NULL);\
|
---|
563 | if (str == NULL) { \
|
---|
564 | if (strict) { \
|
---|
565 | d_printf("%s: %s == NULL\n", __location__, attr); \
|
---|
566 | return WERR_INVALID_PARAM; \
|
---|
567 | } else { \
|
---|
568 | (p)->elem = false; \
|
---|
569 | } \
|
---|
570 | } else if (strcasecmp("TRUE", str) == 0) { \
|
---|
571 | (p)->elem = true; \
|
---|
572 | } else if (strcasecmp("FALSE", str) == 0) { \
|
---|
573 | (p)->elem = false; \
|
---|
574 | } else { \
|
---|
575 | d_printf("%s: %s == %s\n", __location__, attr, str); \
|
---|
576 | return WERR_INVALID_PARAM; \
|
---|
577 | } \
|
---|
578 | } while (0)
|
---|
579 |
|
---|
580 | #define GET_UINT32_LDB(msg, attr, p, elem) do { \
|
---|
581 | (p)->elem = ldb_msg_find_attr_as_uint(msg, attr, 0);\
|
---|
582 | } while (0)
|
---|
583 |
|
---|
584 | #define GET_UINT32_PTR_LDB(msg, attr, mem_ctx, p, elem) do { \
|
---|
585 | uint64_t _v = ldb_msg_find_attr_as_uint64(msg, attr, UINT64_MAX);\
|
---|
586 | if (_v == UINT64_MAX) { \
|
---|
587 | (p)->elem = NULL; \
|
---|
588 | } else if (_v > UINT32_MAX) { \
|
---|
589 | d_printf("%s: %s == 0x%llX\n", __location__, \
|
---|
590 | attr, (unsigned long long)_v); \
|
---|
591 | return WERR_INVALID_PARAM; \
|
---|
592 | } else { \
|
---|
593 | (p)->elem = talloc(mem_ctx, uint32_t); \
|
---|
594 | if (!(p)->elem) { \
|
---|
595 | d_printf("%s: talloc failed for %s\n", __location__, attr); \
|
---|
596 | return WERR_NOMEM; \
|
---|
597 | } \
|
---|
598 | *(p)->elem = (uint32_t)_v; \
|
---|
599 | } \
|
---|
600 | } while (0)
|
---|
601 |
|
---|
602 | #define GET_GUID_LDB(msg, attr, p, elem) do { \
|
---|
603 | (p)->elem = samdb_result_guid(msg, attr);\
|
---|
604 | } while (0)
|
---|
605 |
|
---|
606 | #define GET_BLOB_LDB(msg, attr, mem_ctx, p, elem) do { \
|
---|
607 | const struct ldb_val *_val;\
|
---|
608 | _val = ldb_msg_find_ldb_val(msg, attr);\
|
---|
609 | if (_val) {\
|
---|
610 | (p)->elem = *_val;\
|
---|
611 | talloc_steal(mem_ctx, (p)->elem.data);\
|
---|
612 | } else {\
|
---|
613 | ZERO_STRUCT((p)->elem);\
|
---|
614 | }\
|
---|
615 | } while (0)
|
---|
616 |
|
---|
617 | WERROR dsdb_attribute_from_ldb(struct ldb_context *ldb,
|
---|
618 | struct dsdb_schema *schema,
|
---|
619 | struct ldb_message *msg)
|
---|
620 | {
|
---|
621 | WERROR status;
|
---|
622 | struct dsdb_attribute *attr = talloc_zero(schema, struct dsdb_attribute);
|
---|
623 | if (!attr) {
|
---|
624 | return WERR_NOMEM;
|
---|
625 | }
|
---|
626 |
|
---|
627 | GET_STRING_LDB(msg, "cn", attr, attr, cn, false);
|
---|
628 | GET_STRING_LDB(msg, "lDAPDisplayName", attr, attr, lDAPDisplayName, true);
|
---|
629 | GET_STRING_LDB(msg, "attributeID", attr, attr, attributeID_oid, true);
|
---|
630 | if (!schema->prefixmap || schema->prefixmap->length == 0) {
|
---|
631 | /* set an invalid value */
|
---|
632 | attr->attributeID_id = DRSUAPI_ATTID_INVALID;
|
---|
633 | } else {
|
---|
634 | status = dsdb_schema_pfm_make_attid(schema->prefixmap,
|
---|
635 | attr->attributeID_oid,
|
---|
636 | &attr->attributeID_id);
|
---|
637 | if (!W_ERROR_IS_OK(status)) {
|
---|
638 | DEBUG(0,("%s: '%s': unable to map attributeID %s: %s\n",
|
---|
639 | __location__, attr->lDAPDisplayName, attr->attributeID_oid,
|
---|
640 | win_errstr(status)));
|
---|
641 | return status;
|
---|
642 | }
|
---|
643 | }
|
---|
644 | /* fetch msDS-IntId to be used in resolving ATTRTYP values */
|
---|
645 | GET_UINT32_LDB(msg, "msDS-IntId", attr, msDS_IntId);
|
---|
646 |
|
---|
647 | GET_GUID_LDB(msg, "schemaIDGUID", attr, schemaIDGUID);
|
---|
648 | GET_UINT32_LDB(msg, "mAPIID", attr, mAPIID);
|
---|
649 |
|
---|
650 | GET_GUID_LDB(msg, "attributeSecurityGUID", attr, attributeSecurityGUID);
|
---|
651 |
|
---|
652 | GET_GUID_LDB(msg, "objectGUID", attr, objectGUID);
|
---|
653 |
|
---|
654 | GET_UINT32_LDB(msg, "searchFlags", attr, searchFlags);
|
---|
655 | GET_UINT32_LDB(msg, "systemFlags", attr, systemFlags);
|
---|
656 | GET_BOOL_LDB(msg, "isMemberOfPartialAttributeSet", attr, isMemberOfPartialAttributeSet, false);
|
---|
657 | GET_UINT32_LDB(msg, "linkID", attr, linkID);
|
---|
658 |
|
---|
659 | GET_STRING_LDB(msg, "attributeSyntax", attr, attr, attributeSyntax_oid, true);
|
---|
660 | if (!schema->prefixmap || schema->prefixmap->length == 0) {
|
---|
661 | /* set an invalid value */
|
---|
662 | attr->attributeSyntax_id = DRSUAPI_ATTID_INVALID;
|
---|
663 | } else {
|
---|
664 | status = dsdb_schema_pfm_attid_from_oid(schema->prefixmap,
|
---|
665 | attr->attributeSyntax_oid,
|
---|
666 | &attr->attributeSyntax_id);
|
---|
667 | if (!W_ERROR_IS_OK(status)) {
|
---|
668 | DEBUG(0,("%s: '%s': unable to map attributeSyntax_ %s: %s\n",
|
---|
669 | __location__, attr->lDAPDisplayName, attr->attributeSyntax_oid,
|
---|
670 | win_errstr(status)));
|
---|
671 | return status;
|
---|
672 | }
|
---|
673 | }
|
---|
674 | GET_UINT32_LDB(msg, "oMSyntax", attr, oMSyntax);
|
---|
675 | GET_BLOB_LDB(msg, "oMObjectClass", attr, attr, oMObjectClass);
|
---|
676 |
|
---|
677 | GET_BOOL_LDB(msg, "isSingleValued", attr, isSingleValued, true);
|
---|
678 | GET_UINT32_PTR_LDB(msg, "rangeLower", attr, attr, rangeLower);
|
---|
679 | GET_UINT32_PTR_LDB(msg, "rangeUpper", attr, attr, rangeUpper);
|
---|
680 | GET_BOOL_LDB(msg, "extendedCharsAllowed", attr, extendedCharsAllowed, false);
|
---|
681 |
|
---|
682 | GET_UINT32_LDB(msg, "schemaFlagsEx", attr, schemaFlagsEx);
|
---|
683 | GET_BLOB_LDB(msg, "msDs-Schema-Extensions", attr, attr, msDs_Schema_Extensions);
|
---|
684 |
|
---|
685 | GET_BOOL_LDB(msg, "showInAdvancedViewOnly", attr, showInAdvancedViewOnly, false);
|
---|
686 | GET_STRING_LDB(msg, "adminDisplayName", attr, attr, adminDisplayName, false);
|
---|
687 | GET_STRING_LDB(msg, "adminDescription", attr, attr, adminDescription, false);
|
---|
688 | GET_STRING_LDB(msg, "classDisplayName", attr, attr, classDisplayName, false);
|
---|
689 | GET_BOOL_LDB(msg, "isEphemeral", attr, isEphemeral, false);
|
---|
690 | GET_BOOL_LDB(msg, "isDefunct", attr, isDefunct, false);
|
---|
691 | GET_BOOL_LDB(msg, "systemOnly", attr, systemOnly, false);
|
---|
692 |
|
---|
693 | attr->syntax = dsdb_syntax_for_attribute(attr);
|
---|
694 | if (!attr->syntax) {
|
---|
695 | DEBUG(0,(__location__ ": Unknown schema syntax for %s\n",
|
---|
696 | attr->lDAPDisplayName));
|
---|
697 | return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
|
---|
698 | }
|
---|
699 |
|
---|
700 | if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
|
---|
701 | DEBUG(0,(__location__ ": Unknown schema syntax for %s - ldb_syntax: %s, ldap_oid: %s\n",
|
---|
702 | attr->lDAPDisplayName,
|
---|
703 | attr->syntax->ldb_syntax,
|
---|
704 | attr->syntax->ldap_oid));
|
---|
705 | return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
|
---|
706 | }
|
---|
707 |
|
---|
708 | DLIST_ADD(schema->attributes, attr);
|
---|
709 | return WERR_OK;
|
---|
710 | }
|
---|
711 |
|
---|
712 | WERROR dsdb_class_from_ldb(struct dsdb_schema *schema,
|
---|
713 | struct ldb_message *msg)
|
---|
714 | {
|
---|
715 | WERROR status;
|
---|
716 | struct dsdb_class *obj = talloc_zero(schema, struct dsdb_class);
|
---|
717 | if (!obj) {
|
---|
718 | return WERR_NOMEM;
|
---|
719 | }
|
---|
720 | GET_STRING_LDB(msg, "cn", obj, obj, cn, false);
|
---|
721 | GET_STRING_LDB(msg, "lDAPDisplayName", obj, obj, lDAPDisplayName, true);
|
---|
722 | GET_STRING_LDB(msg, "governsID", obj, obj, governsID_oid, true);
|
---|
723 | if (!schema->prefixmap || schema->prefixmap->length == 0) {
|
---|
724 | /* set an invalid value */
|
---|
725 | obj->governsID_id = DRSUAPI_ATTID_INVALID;
|
---|
726 | } else {
|
---|
727 | status = dsdb_schema_pfm_make_attid(schema->prefixmap,
|
---|
728 | obj->governsID_oid,
|
---|
729 | &obj->governsID_id);
|
---|
730 | if (!W_ERROR_IS_OK(status)) {
|
---|
731 | DEBUG(0,("%s: '%s': unable to map governsID %s: %s\n",
|
---|
732 | __location__, obj->lDAPDisplayName, obj->governsID_oid,
|
---|
733 | win_errstr(status)));
|
---|
734 | return status;
|
---|
735 | }
|
---|
736 | }
|
---|
737 | GET_GUID_LDB(msg, "schemaIDGUID", obj, schemaIDGUID);
|
---|
738 | GET_GUID_LDB(msg, "objectGUID", obj, objectGUID);
|
---|
739 |
|
---|
740 | GET_UINT32_LDB(msg, "objectClassCategory", obj, objectClassCategory);
|
---|
741 | GET_STRING_LDB(msg, "rDNAttID", obj, obj, rDNAttID, false);
|
---|
742 | GET_STRING_LDB(msg, "defaultObjectCategory", obj, obj, defaultObjectCategory, true);
|
---|
743 |
|
---|
744 | GET_STRING_LDB(msg, "subClassOf", obj, obj, subClassOf, true);
|
---|
745 |
|
---|
746 | GET_STRING_LIST_LDB(msg, "systemAuxiliaryClass", obj, obj, systemAuxiliaryClass);
|
---|
747 | GET_STRING_LIST_LDB(msg, "auxiliaryClass", obj, obj, auxiliaryClass);
|
---|
748 |
|
---|
749 | GET_STRING_LIST_LDB(msg, "systemMustContain", obj, obj, systemMustContain);
|
---|
750 | GET_STRING_LIST_LDB(msg, "systemMayContain", obj, obj, systemMayContain);
|
---|
751 | GET_STRING_LIST_LDB(msg, "mustContain", obj, obj, mustContain);
|
---|
752 | GET_STRING_LIST_LDB(msg, "mayContain", obj, obj, mayContain);
|
---|
753 |
|
---|
754 | GET_STRING_LIST_LDB(msg, "systemPossSuperiors", obj, obj, systemPossSuperiors);
|
---|
755 | GET_STRING_LIST_LDB(msg, "possSuperiors", obj, obj, possSuperiors);
|
---|
756 |
|
---|
757 | GET_STRING_LDB(msg, "defaultSecurityDescriptor", obj, obj, defaultSecurityDescriptor, false);
|
---|
758 |
|
---|
759 | GET_UINT32_LDB(msg, "schemaFlagsEx", obj, schemaFlagsEx);
|
---|
760 | GET_BLOB_LDB(msg, "msDs-Schema-Extensions", obj, obj, msDs_Schema_Extensions);
|
---|
761 |
|
---|
762 | GET_BOOL_LDB(msg, "showInAdvancedViewOnly", obj, showInAdvancedViewOnly, false);
|
---|
763 | GET_STRING_LDB(msg, "adminDisplayName", obj, obj, adminDisplayName, false);
|
---|
764 | GET_STRING_LDB(msg, "adminDescription", obj, obj, adminDescription, false);
|
---|
765 | GET_STRING_LDB(msg, "classDisplayName", obj, obj, classDisplayName, false);
|
---|
766 | GET_BOOL_LDB(msg, "defaultHidingValue", obj, defaultHidingValue, false);
|
---|
767 | GET_BOOL_LDB(msg, "isDefunct", obj, isDefunct, false);
|
---|
768 | GET_BOOL_LDB(msg, "systemOnly", obj, systemOnly, false);
|
---|
769 |
|
---|
770 | DLIST_ADD(schema->classes, obj);
|
---|
771 | return WERR_OK;
|
---|
772 | }
|
---|
773 |
|
---|
774 | #define dsdb_oom(error_string, mem_ctx) *error_string = talloc_asprintf(mem_ctx, "dsdb out of memory at %s:%d\n", __FILE__, __LINE__)
|
---|
775 |
|
---|
776 | /*
|
---|
777 | Create a DSDB schema from the ldb results provided. This is called
|
---|
778 | directly when the schema is provisioned from an on-disk LDIF file, or
|
---|
779 | from dsdb_schema_from_schema_dn in schema_fsmo
|
---|
780 | */
|
---|
781 |
|
---|
782 | int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
|
---|
783 | struct ldb_result *schema_res,
|
---|
784 | struct ldb_result *attrs_res, struct ldb_result *objectclass_res,
|
---|
785 | struct dsdb_schema **schema_out,
|
---|
786 | char **error_string)
|
---|
787 | {
|
---|
788 | WERROR status;
|
---|
789 | unsigned int i;
|
---|
790 | const struct ldb_val *prefix_val;
|
---|
791 | const struct ldb_val *info_val;
|
---|
792 | struct ldb_val info_val_default;
|
---|
793 | struct dsdb_schema *schema;
|
---|
794 |
|
---|
795 | schema = dsdb_new_schema(mem_ctx);
|
---|
796 | if (!schema) {
|
---|
797 | dsdb_oom(error_string, mem_ctx);
|
---|
798 | return ldb_operr(ldb);
|
---|
799 | }
|
---|
800 |
|
---|
801 | schema->base_dn = talloc_steal(schema, schema_res->msgs[0]->dn);
|
---|
802 |
|
---|
803 | prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
|
---|
804 | if (!prefix_val) {
|
---|
805 | *error_string = talloc_asprintf(mem_ctx,
|
---|
806 | "schema_fsmo_init: no prefixMap attribute found");
|
---|
807 | DEBUG(0,(__location__ ": %s\n", *error_string));
|
---|
808 | return LDB_ERR_CONSTRAINT_VIOLATION;
|
---|
809 | }
|
---|
810 | info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
|
---|
811 | if (!info_val) {
|
---|
812 | status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default);
|
---|
813 | if (!W_ERROR_IS_OK(status)) {
|
---|
814 | *error_string = talloc_asprintf(mem_ctx,
|
---|
815 | "schema_fsmo_init: dsdb_schema_info_blob_new() failed - %s",
|
---|
816 | win_errstr(status));
|
---|
817 | DEBUG(0,(__location__ ": %s\n", *error_string));
|
---|
818 | return ldb_operr(ldb);
|
---|
819 | }
|
---|
820 | info_val = &info_val_default;
|
---|
821 | }
|
---|
822 |
|
---|
823 | status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
|
---|
824 | if (!W_ERROR_IS_OK(status)) {
|
---|
825 | *error_string = talloc_asprintf(mem_ctx,
|
---|
826 | "schema_fsmo_init: failed to load oid mappings: %s",
|
---|
827 | win_errstr(status));
|
---|
828 | DEBUG(0,(__location__ ": %s\n", *error_string));
|
---|
829 | return LDB_ERR_CONSTRAINT_VIOLATION;
|
---|
830 | }
|
---|
831 |
|
---|
832 | for (i=0; i < attrs_res->count; i++) {
|
---|
833 | status = dsdb_attribute_from_ldb(ldb, schema, attrs_res->msgs[i]);
|
---|
834 | if (!W_ERROR_IS_OK(status)) {
|
---|
835 | *error_string = talloc_asprintf(mem_ctx,
|
---|
836 | "schema_fsmo_init: failed to load attribute definition: %s:%s",
|
---|
837 | ldb_dn_get_linearized(attrs_res->msgs[i]->dn),
|
---|
838 | win_errstr(status));
|
---|
839 | DEBUG(0,(__location__ ": %s\n", *error_string));
|
---|
840 | return LDB_ERR_CONSTRAINT_VIOLATION;
|
---|
841 | }
|
---|
842 | }
|
---|
843 |
|
---|
844 | for (i=0; i < objectclass_res->count; i++) {
|
---|
845 | status = dsdb_class_from_ldb(schema, objectclass_res->msgs[i]);
|
---|
846 | if (!W_ERROR_IS_OK(status)) {
|
---|
847 | *error_string = talloc_asprintf(mem_ctx,
|
---|
848 | "schema_fsmo_init: failed to load class definition: %s:%s",
|
---|
849 | ldb_dn_get_linearized(objectclass_res->msgs[i]->dn),
|
---|
850 | win_errstr(status));
|
---|
851 | DEBUG(0,(__location__ ": %s\n", *error_string));
|
---|
852 | return LDB_ERR_CONSTRAINT_VIOLATION;
|
---|
853 | }
|
---|
854 | }
|
---|
855 |
|
---|
856 | schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_res->msgs[0], "fSMORoleOwner");
|
---|
857 | if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), schema->fsmo.master_dn) == 0) {
|
---|
858 | schema->fsmo.we_are_master = true;
|
---|
859 | } else {
|
---|
860 | schema->fsmo.we_are_master = false;
|
---|
861 | }
|
---|
862 |
|
---|
863 | DEBUG(5, ("schema_fsmo_init: we are master: %s\n",
|
---|
864 | (schema->fsmo.we_are_master?"yes":"no")));
|
---|
865 |
|
---|
866 | *schema_out = schema;
|
---|
867 | return LDB_SUCCESS;
|
---|
868 | }
|
---|