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 "lib/ldb/include/ldb_errors.h"
|
---|
26 | #include "../lib/util/dlinklist.h"
|
---|
27 | #include "librpc/gen_ndr/ndr_misc.h"
|
---|
28 | #include "librpc/gen_ndr/ndr_drsuapi.h"
|
---|
29 | #include "librpc/gen_ndr/ndr_drsblobs.h"
|
---|
30 | #include "param/param.h"
|
---|
31 | #include "lib/ldb/include/ldb_module.h"
|
---|
32 |
|
---|
33 | struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience)
|
---|
34 | {
|
---|
35 | struct dsdb_schema *schema = talloc_zero(mem_ctx, struct dsdb_schema);
|
---|
36 | if (!schema) {
|
---|
37 | return NULL;
|
---|
38 | }
|
---|
39 |
|
---|
40 | schema->iconv_convenience = iconv_convenience;
|
---|
41 | return schema;
|
---|
42 | }
|
---|
43 |
|
---|
44 |
|
---|
45 | WERROR dsdb_load_oid_mappings_drsuapi(struct dsdb_schema *schema, const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
|
---|
46 | {
|
---|
47 | uint32_t i,j;
|
---|
48 |
|
---|
49 | schema->prefixes = talloc_array(schema, struct dsdb_schema_oid_prefix, ctr->num_mappings);
|
---|
50 | W_ERROR_HAVE_NO_MEMORY(schema->prefixes);
|
---|
51 |
|
---|
52 | for (i=0, j=0; i < ctr->num_mappings; i++) {
|
---|
53 | if (ctr->mappings[i].oid.oid == NULL) {
|
---|
54 | return WERR_INVALID_PARAM;
|
---|
55 | }
|
---|
56 |
|
---|
57 | if (strncasecmp(ctr->mappings[i].oid.oid, "ff", 2) == 0) {
|
---|
58 | if (ctr->mappings[i].id_prefix != 0) {
|
---|
59 | return WERR_INVALID_PARAM;
|
---|
60 | }
|
---|
61 |
|
---|
62 | /* the magic value should be in the last array member */
|
---|
63 | if (i != (ctr->num_mappings - 1)) {
|
---|
64 | return WERR_INVALID_PARAM;
|
---|
65 | }
|
---|
66 |
|
---|
67 | if (ctr->mappings[i].oid.__ndr_size != 21) {
|
---|
68 | return WERR_INVALID_PARAM;
|
---|
69 | }
|
---|
70 |
|
---|
71 | schema->schema_info = talloc_strdup(schema, ctr->mappings[i].oid.oid);
|
---|
72 | W_ERROR_HAVE_NO_MEMORY(schema->schema_info);
|
---|
73 | } else {
|
---|
74 | /* the last array member should contain the magic value not a oid */
|
---|
75 | if (i == (ctr->num_mappings - 1)) {
|
---|
76 | return WERR_INVALID_PARAM;
|
---|
77 | }
|
---|
78 |
|
---|
79 | schema->prefixes[j].id = ctr->mappings[i].id_prefix<<16;
|
---|
80 | schema->prefixes[j].oid = talloc_asprintf(schema->prefixes, "%s.",
|
---|
81 | ctr->mappings[i].oid.oid);
|
---|
82 | W_ERROR_HAVE_NO_MEMORY(schema->prefixes[j].oid);
|
---|
83 | schema->prefixes[j].oid_len = strlen(schema->prefixes[j].oid);
|
---|
84 | j++;
|
---|
85 | }
|
---|
86 | }
|
---|
87 |
|
---|
88 | schema->num_prefixes = j;
|
---|
89 | return WERR_OK;
|
---|
90 | }
|
---|
91 |
|
---|
92 | WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema,
|
---|
93 | const struct ldb_val *prefixMap,
|
---|
94 | const struct ldb_val *schemaInfo)
|
---|
95 | {
|
---|
96 | WERROR status;
|
---|
97 | enum ndr_err_code ndr_err;
|
---|
98 | struct prefixMapBlob pfm;
|
---|
99 | char *schema_info;
|
---|
100 |
|
---|
101 | TALLOC_CTX *mem_ctx = talloc_new(schema);
|
---|
102 | W_ERROR_HAVE_NO_MEMORY(mem_ctx);
|
---|
103 |
|
---|
104 | ndr_err = ndr_pull_struct_blob(prefixMap, mem_ctx, schema->iconv_convenience, &pfm, (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
|
---|
105 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
106 | NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
|
---|
107 | talloc_free(mem_ctx);
|
---|
108 | return ntstatus_to_werror(nt_status);
|
---|
109 | }
|
---|
110 |
|
---|
111 | if (pfm.version != PREFIX_MAP_VERSION_DSDB) {
|
---|
112 | talloc_free(mem_ctx);
|
---|
113 | return WERR_FOOBAR;
|
---|
114 | }
|
---|
115 |
|
---|
116 | if (schemaInfo->length != 21 && schemaInfo->data[0] == 0xFF) {
|
---|
117 | talloc_free(mem_ctx);
|
---|
118 | return WERR_FOOBAR;
|
---|
119 | }
|
---|
120 |
|
---|
121 | /* append the schema info as last element */
|
---|
122 | pfm.ctr.dsdb.num_mappings++;
|
---|
123 | pfm.ctr.dsdb.mappings = talloc_realloc(mem_ctx, pfm.ctr.dsdb.mappings,
|
---|
124 | struct drsuapi_DsReplicaOIDMapping,
|
---|
125 | pfm.ctr.dsdb.num_mappings);
|
---|
126 | W_ERROR_HAVE_NO_MEMORY(pfm.ctr.dsdb.mappings);
|
---|
127 |
|
---|
128 | schema_info = data_blob_hex_string(pfm.ctr.dsdb.mappings, schemaInfo);
|
---|
129 | W_ERROR_HAVE_NO_MEMORY(schema_info);
|
---|
130 |
|
---|
131 | pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].id_prefix = 0;
|
---|
132 | pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.__ndr_size = schemaInfo->length;
|
---|
133 | pfm.ctr.dsdb.mappings[pfm.ctr.dsdb.num_mappings - 1].oid.oid = schema_info;
|
---|
134 |
|
---|
135 | /* call the drsuapi version */
|
---|
136 | status = dsdb_load_oid_mappings_drsuapi(schema, &pfm.ctr.dsdb);
|
---|
137 | talloc_free(mem_ctx);
|
---|
138 |
|
---|
139 | W_ERROR_NOT_OK_RETURN(status);
|
---|
140 |
|
---|
141 | return WERR_OK;
|
---|
142 | }
|
---|
143 |
|
---|
144 | WERROR dsdb_get_oid_mappings_drsuapi(const struct dsdb_schema *schema,
|
---|
145 | bool include_schema_info,
|
---|
146 | TALLOC_CTX *mem_ctx,
|
---|
147 | struct drsuapi_DsReplicaOIDMapping_Ctr **_ctr)
|
---|
148 | {
|
---|
149 | struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
|
---|
150 | uint32_t i;
|
---|
151 |
|
---|
152 | ctr = talloc(mem_ctx, struct drsuapi_DsReplicaOIDMapping_Ctr);
|
---|
153 | W_ERROR_HAVE_NO_MEMORY(ctr);
|
---|
154 |
|
---|
155 | ctr->num_mappings = schema->num_prefixes;
|
---|
156 | if (include_schema_info) ctr->num_mappings++;
|
---|
157 | ctr->mappings = talloc_array(schema, struct drsuapi_DsReplicaOIDMapping, ctr->num_mappings);
|
---|
158 | W_ERROR_HAVE_NO_MEMORY(ctr->mappings);
|
---|
159 |
|
---|
160 | for (i=0; i < schema->num_prefixes; i++) {
|
---|
161 | ctr->mappings[i].id_prefix = schema->prefixes[i].id>>16;
|
---|
162 | ctr->mappings[i].oid.oid = talloc_strndup(ctr->mappings,
|
---|
163 | schema->prefixes[i].oid,
|
---|
164 | schema->prefixes[i].oid_len - 1);
|
---|
165 | W_ERROR_HAVE_NO_MEMORY(ctr->mappings[i].oid.oid);
|
---|
166 | }
|
---|
167 |
|
---|
168 | if (include_schema_info) {
|
---|
169 | ctr->mappings[i].id_prefix = 0;
|
---|
170 | ctr->mappings[i].oid.oid = talloc_strdup(ctr->mappings,
|
---|
171 | schema->schema_info);
|
---|
172 | W_ERROR_HAVE_NO_MEMORY(ctr->mappings[i].oid.oid);
|
---|
173 | }
|
---|
174 |
|
---|
175 | *_ctr = ctr;
|
---|
176 | return WERR_OK;
|
---|
177 | }
|
---|
178 |
|
---|
179 | WERROR dsdb_get_oid_mappings_ldb(const struct dsdb_schema *schema,
|
---|
180 | TALLOC_CTX *mem_ctx,
|
---|
181 | struct ldb_val *prefixMap,
|
---|
182 | struct ldb_val *schemaInfo)
|
---|
183 | {
|
---|
184 | WERROR status;
|
---|
185 | enum ndr_err_code ndr_err;
|
---|
186 | struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
|
---|
187 | struct prefixMapBlob pfm;
|
---|
188 |
|
---|
189 | status = dsdb_get_oid_mappings_drsuapi(schema, false, mem_ctx, &ctr);
|
---|
190 | W_ERROR_NOT_OK_RETURN(status);
|
---|
191 |
|
---|
192 | pfm.version = PREFIX_MAP_VERSION_DSDB;
|
---|
193 | pfm.reserved = 0;
|
---|
194 | pfm.ctr.dsdb = *ctr;
|
---|
195 |
|
---|
196 | ndr_err = ndr_push_struct_blob(prefixMap, mem_ctx, schema->iconv_convenience, &pfm, (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
|
---|
197 | talloc_free(ctr);
|
---|
198 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
199 | NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
|
---|
200 | return ntstatus_to_werror(nt_status);
|
---|
201 | }
|
---|
202 |
|
---|
203 | *schemaInfo = strhex_to_data_blob(mem_ctx, schema->schema_info);
|
---|
204 | W_ERROR_HAVE_NO_MEMORY(schemaInfo->data);
|
---|
205 |
|
---|
206 | return WERR_OK;
|
---|
207 | }
|
---|
208 |
|
---|
209 | WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
|
---|
210 | {
|
---|
211 | uint32_t i,j;
|
---|
212 |
|
---|
213 | for (i=0; i < ctr->num_mappings; i++) {
|
---|
214 | if (ctr->mappings[i].oid.oid == NULL) {
|
---|
215 | return WERR_INVALID_PARAM;
|
---|
216 | }
|
---|
217 |
|
---|
218 | if (strncasecmp(ctr->mappings[i].oid.oid, "ff", 2) == 0) {
|
---|
219 | if (ctr->mappings[i].id_prefix != 0) {
|
---|
220 | return WERR_INVALID_PARAM;
|
---|
221 | }
|
---|
222 |
|
---|
223 | /* the magic value should be in the last array member */
|
---|
224 | if (i != (ctr->num_mappings - 1)) {
|
---|
225 | return WERR_INVALID_PARAM;
|
---|
226 | }
|
---|
227 |
|
---|
228 | if (ctr->mappings[i].oid.__ndr_size != 21) {
|
---|
229 | return WERR_INVALID_PARAM;
|
---|
230 | }
|
---|
231 |
|
---|
232 | if (strcasecmp(schema->schema_info, ctr->mappings[i].oid.oid) != 0) {
|
---|
233 | return WERR_DS_DRA_SCHEMA_MISMATCH;
|
---|
234 | }
|
---|
235 | } else {
|
---|
236 | /* the last array member should contain the magic value not a oid */
|
---|
237 | if (i == (ctr->num_mappings - 1)) {
|
---|
238 | return WERR_INVALID_PARAM;
|
---|
239 | }
|
---|
240 |
|
---|
241 | for (j=0; j < schema->num_prefixes; j++) {
|
---|
242 | size_t oid_len;
|
---|
243 | if (schema->prefixes[j].id != (ctr->mappings[i].id_prefix<<16)) {
|
---|
244 | continue;
|
---|
245 | }
|
---|
246 |
|
---|
247 | oid_len = strlen(ctr->mappings[i].oid.oid);
|
---|
248 |
|
---|
249 | if (oid_len != (schema->prefixes[j].oid_len - 1)) {
|
---|
250 | return WERR_DS_DRA_SCHEMA_MISMATCH;
|
---|
251 | }
|
---|
252 |
|
---|
253 | if (strncmp(ctr->mappings[i].oid.oid, schema->prefixes[j].oid, oid_len) != 0) {
|
---|
254 | return WERR_DS_DRA_SCHEMA_MISMATCH;
|
---|
255 | }
|
---|
256 |
|
---|
257 | break;
|
---|
258 | }
|
---|
259 |
|
---|
260 | if (j == schema->num_prefixes) {
|
---|
261 | return WERR_DS_DRA_SCHEMA_MISMATCH;
|
---|
262 | }
|
---|
263 | }
|
---|
264 | }
|
---|
265 |
|
---|
266 | return WERR_OK;
|
---|
267 | }
|
---|
268 |
|
---|
269 | WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, uint32_t *out)
|
---|
270 | {
|
---|
271 | return dsdb_find_prefix_for_oid(schema->num_prefixes, schema->prefixes, in, out);
|
---|
272 | }
|
---|
273 |
|
---|
274 |
|
---|
275 | WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CTX *mem_ctx, const char **out)
|
---|
276 | {
|
---|
277 | uint32_t i;
|
---|
278 |
|
---|
279 | for (i=0; i < schema->num_prefixes; i++) {
|
---|
280 | const char *val;
|
---|
281 | if (schema->prefixes[i].id != (in & 0xFFFF0000)) {
|
---|
282 | continue;
|
---|
283 | }
|
---|
284 |
|
---|
285 | val = talloc_asprintf(mem_ctx, "%s%u",
|
---|
286 | schema->prefixes[i].oid,
|
---|
287 | in & 0xFFFF);
|
---|
288 | W_ERROR_HAVE_NO_MEMORY(val);
|
---|
289 |
|
---|
290 | *out = val;
|
---|
291 | return WERR_OK;
|
---|
292 | }
|
---|
293 |
|
---|
294 | return WERR_DS_NO_MSDS_INTID;
|
---|
295 | }
|
---|
296 |
|
---|
297 | /*
|
---|
298 | * this function is called from within a ldb transaction from the schema_fsmo module
|
---|
299 | */
|
---|
300 | WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
|
---|
301 | {
|
---|
302 | WERROR status;
|
---|
303 | uint32_t num_prefixes;
|
---|
304 | struct dsdb_schema_oid_prefix *prefixes;
|
---|
305 | TALLOC_CTX *mem_ctx;
|
---|
306 | uint32_t out;
|
---|
307 |
|
---|
308 | mem_ctx = talloc_new(ldb);
|
---|
309 | W_ERROR_HAVE_NO_MEMORY(mem_ctx);
|
---|
310 |
|
---|
311 | /* Read prefixes from disk*/
|
---|
312 | status = dsdb_read_prefixes_from_ldb( mem_ctx, ldb, &num_prefixes, &prefixes );
|
---|
313 | if (!W_ERROR_IS_OK(status)) {
|
---|
314 | DEBUG(0,("dsdb_create_prefix_mapping: dsdb_read_prefixes_from_ldb: %s\n",
|
---|
315 | win_errstr(status)));
|
---|
316 | talloc_free(mem_ctx);
|
---|
317 | return status;
|
---|
318 | }
|
---|
319 |
|
---|
320 | /* Check if there is a prefix for the oid in the prefixes array*/
|
---|
321 | status = dsdb_find_prefix_for_oid( num_prefixes, prefixes, full_oid, &out );
|
---|
322 | if (W_ERROR_IS_OK(status)) {
|
---|
323 | /* prefix found*/
|
---|
324 | talloc_free(mem_ctx);
|
---|
325 | return status;
|
---|
326 | } else if (!W_ERROR_EQUAL(WERR_DS_NO_MSDS_INTID, status)) {
|
---|
327 | /* error */
|
---|
328 | DEBUG(0,("dsdb_create_prefix_mapping: dsdb_find_prefix_for_oid: %s\n",
|
---|
329 | win_errstr(status)));
|
---|
330 | talloc_free(mem_ctx);
|
---|
331 | return status;
|
---|
332 | }
|
---|
333 |
|
---|
334 | /* Create the new mapping for the prefix of full_oid */
|
---|
335 | status = dsdb_prefix_map_update(mem_ctx, &num_prefixes, &prefixes, full_oid);
|
---|
336 | if (!W_ERROR_IS_OK(status)) {
|
---|
337 | DEBUG(0,("dsdb_create_prefix_mapping: dsdb_prefix_map_update: %s\n",
|
---|
338 | win_errstr(status)));
|
---|
339 | talloc_free(mem_ctx);
|
---|
340 | return status;
|
---|
341 | }
|
---|
342 |
|
---|
343 | talloc_free(schema->prefixes);
|
---|
344 | schema->prefixes = talloc_steal(schema, prefixes);
|
---|
345 | schema->num_prefixes = num_prefixes;
|
---|
346 |
|
---|
347 | /* Update prefixMap in ldb*/
|
---|
348 | status = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, ldb, schema);
|
---|
349 | if (!W_ERROR_IS_OK(status)) {
|
---|
350 | DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ldb: %s\n",
|
---|
351 | win_errstr(status)));
|
---|
352 | talloc_free(mem_ctx);
|
---|
353 | return status;
|
---|
354 | }
|
---|
355 |
|
---|
356 | DEBUG(2,(__location__ " Added prefixMap %s - now have %u prefixes\n",
|
---|
357 | full_oid, num_prefixes));
|
---|
358 |
|
---|
359 | talloc_free(mem_ctx);
|
---|
360 | return status;
|
---|
361 | }
|
---|
362 |
|
---|
363 | WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, struct dsdb_schema_oid_prefix **prefixes, const char *oid)
|
---|
364 | {
|
---|
365 | uint32_t new_num_prefixes, index_new_prefix, new_entry_id;
|
---|
366 | const char* lastDotOffset;
|
---|
367 | size_t size;
|
---|
368 |
|
---|
369 | new_num_prefixes = *num_prefixes + 1;
|
---|
370 | index_new_prefix = *num_prefixes;
|
---|
371 |
|
---|
372 | /*
|
---|
373 | * this is the algorithm we use to create new mappings for now
|
---|
374 | *
|
---|
375 | * TODO: find what algorithm windows use
|
---|
376 | */
|
---|
377 | new_entry_id = (*num_prefixes)<<16;
|
---|
378 |
|
---|
379 | /* Extract the prefix from the oid*/
|
---|
380 | lastDotOffset = strrchr(oid, '.');
|
---|
381 | if (lastDotOffset == NULL) {
|
---|
382 | DEBUG(0,("dsdb_prefix_map_update: failed to find the last dot\n"));
|
---|
383 | return WERR_NOT_FOUND;
|
---|
384 | }
|
---|
385 |
|
---|
386 | /* Calculate the size of the remainig string that should be the prefix of it */
|
---|
387 | size = strlen(oid) - strlen(lastDotOffset);
|
---|
388 | if (size <= 0) {
|
---|
389 | DEBUG(0,("dsdb_prefix_map_update: size of the remaining string invalid\n"));
|
---|
390 | return WERR_FOOBAR;
|
---|
391 | }
|
---|
392 | /* Add one because we need to copy the dot */
|
---|
393 | size += 1;
|
---|
394 |
|
---|
395 | /* Create a spot in the prefixMap for one more prefix*/
|
---|
396 | (*prefixes) = talloc_realloc(mem_ctx, *prefixes, struct dsdb_schema_oid_prefix, new_num_prefixes);
|
---|
397 | W_ERROR_HAVE_NO_MEMORY(*prefixes);
|
---|
398 |
|
---|
399 | /* Add the new prefix entry*/
|
---|
400 | (*prefixes)[index_new_prefix].id = new_entry_id;
|
---|
401 | (*prefixes)[index_new_prefix].oid = talloc_strndup(mem_ctx, oid, size);
|
---|
402 | (*prefixes)[index_new_prefix].oid_len = strlen((*prefixes)[index_new_prefix].oid);
|
---|
403 |
|
---|
404 | /* Increase num_prefixes because new prefix has been added */
|
---|
405 | ++(*num_prefixes);
|
---|
406 |
|
---|
407 | return WERR_OK;
|
---|
408 | }
|
---|
409 |
|
---|
410 | WERROR dsdb_find_prefix_for_oid(uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, const char *in, uint32_t *out)
|
---|
411 | {
|
---|
412 | uint32_t i;
|
---|
413 |
|
---|
414 | for (i=0; i < num_prefixes; i++) {
|
---|
415 | const char *val_str;
|
---|
416 | char *end_str;
|
---|
417 | unsigned val;
|
---|
418 |
|
---|
419 | if (strncmp(prefixes[i].oid, in, prefixes[i].oid_len) != 0) {
|
---|
420 | continue;
|
---|
421 | }
|
---|
422 |
|
---|
423 | val_str = in + prefixes[i].oid_len;
|
---|
424 | end_str = NULL;
|
---|
425 | errno = 0;
|
---|
426 |
|
---|
427 | if (val_str[0] == '\0') {
|
---|
428 | return WERR_INVALID_PARAM;
|
---|
429 | }
|
---|
430 |
|
---|
431 | /* two '.' chars are invalid */
|
---|
432 | if (val_str[0] == '.') {
|
---|
433 | return WERR_INVALID_PARAM;
|
---|
434 | }
|
---|
435 |
|
---|
436 | val = strtoul(val_str, &end_str, 10);
|
---|
437 | if (end_str[0] == '.' && end_str[1] != '\0') {
|
---|
438 | /*
|
---|
439 | * if it's a '.' and not the last char
|
---|
440 | * then maybe an other mapping apply
|
---|
441 | */
|
---|
442 | continue;
|
---|
443 | } else if (end_str[0] != '\0') {
|
---|
444 | return WERR_INVALID_PARAM;
|
---|
445 | } else if (val > 0xFFFF) {
|
---|
446 | return WERR_INVALID_PARAM;
|
---|
447 | }
|
---|
448 |
|
---|
449 | *out = prefixes[i].id | val;
|
---|
450 | return WERR_OK;
|
---|
451 | }
|
---|
452 |
|
---|
453 | DEBUG(5,(__location__ " Failed to find oid %s - have %u prefixes\n", in, num_prefixes));
|
---|
454 |
|
---|
455 | return WERR_DS_NO_MSDS_INTID;
|
---|
456 | }
|
---|
457 |
|
---|
458 | WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
|
---|
459 | const struct dsdb_schema *schema)
|
---|
460 | {
|
---|
461 | struct ldb_message *msg = ldb_msg_new(mem_ctx);
|
---|
462 | struct ldb_dn *schema_dn;
|
---|
463 | struct prefixMapBlob pm;
|
---|
464 | struct ldb_val ndr_blob;
|
---|
465 | enum ndr_err_code ndr_err;
|
---|
466 | uint32_t i;
|
---|
467 | int ret;
|
---|
468 |
|
---|
469 | if (!msg) {
|
---|
470 | return WERR_NOMEM;
|
---|
471 | }
|
---|
472 |
|
---|
473 | schema_dn = samdb_schema_dn(ldb);
|
---|
474 | if (!schema_dn) {
|
---|
475 | DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: no schema dn present\n"));
|
---|
476 | return WERR_FOOBAR;
|
---|
477 | }
|
---|
478 |
|
---|
479 | pm.version = PREFIX_MAP_VERSION_DSDB;
|
---|
480 | pm.ctr.dsdb.num_mappings = schema->num_prefixes;
|
---|
481 | pm.ctr.dsdb.mappings = talloc_array(msg,
|
---|
482 | struct drsuapi_DsReplicaOIDMapping,
|
---|
483 | pm.ctr.dsdb.num_mappings);
|
---|
484 | if (!pm.ctr.dsdb.mappings) {
|
---|
485 | talloc_free(msg);
|
---|
486 | return WERR_NOMEM;
|
---|
487 | }
|
---|
488 |
|
---|
489 | for (i=0; i < schema->num_prefixes; i++) {
|
---|
490 | pm.ctr.dsdb.mappings[i].id_prefix = schema->prefixes[i].id>>16;
|
---|
491 | pm.ctr.dsdb.mappings[i].oid.oid = talloc_strdup(pm.ctr.dsdb.mappings, schema->prefixes[i].oid);
|
---|
492 | }
|
---|
493 |
|
---|
494 | ndr_err = ndr_push_struct_blob(&ndr_blob, msg,
|
---|
495 | lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
|
---|
496 | &pm,
|
---|
497 | (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
|
---|
498 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
499 | talloc_free(msg);
|
---|
500 | return WERR_FOOBAR;
|
---|
501 | }
|
---|
502 |
|
---|
503 | msg->dn = schema_dn;
|
---|
504 | ret = ldb_msg_add_value(msg, "prefixMap", &ndr_blob, NULL);
|
---|
505 | if (ret != 0) {
|
---|
506 | talloc_free(msg);
|
---|
507 | DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: ldb_msg_add_value failed\n"));
|
---|
508 | return WERR_NOMEM;
|
---|
509 | }
|
---|
510 |
|
---|
511 | ret = samdb_replace( ldb, msg, msg );
|
---|
512 | talloc_free(msg);
|
---|
513 |
|
---|
514 | if (ret != 0) {
|
---|
515 | DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: samdb_replace failed\n"));
|
---|
516 | return WERR_FOOBAR;
|
---|
517 | }
|
---|
518 |
|
---|
519 | return WERR_OK;
|
---|
520 | }
|
---|
521 |
|
---|
522 | WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes)
|
---|
523 | {
|
---|
524 | struct prefixMapBlob *blob;
|
---|
525 | enum ndr_err_code ndr_err;
|
---|
526 | uint32_t i;
|
---|
527 | const struct ldb_val *prefix_val;
|
---|
528 | struct ldb_dn *schema_dn;
|
---|
529 | struct ldb_result *schema_res;
|
---|
530 | int ret;
|
---|
531 | static const char *schema_attrs[] = {
|
---|
532 | "prefixMap",
|
---|
533 | NULL
|
---|
534 | };
|
---|
535 |
|
---|
536 | schema_dn = samdb_schema_dn(ldb);
|
---|
537 | if (!schema_dn) {
|
---|
538 | DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n"));
|
---|
539 | return WERR_FOOBAR;
|
---|
540 | }
|
---|
541 |
|
---|
542 | ret = ldb_search(ldb, mem_ctx, &schema_res, schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL);
|
---|
543 | if (ret == LDB_ERR_NO_SUCH_OBJECT) {
|
---|
544 | DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n"));
|
---|
545 | talloc_free(schema_res);
|
---|
546 | return WERR_FOOBAR;
|
---|
547 | } else if (ret != LDB_SUCCESS) {
|
---|
548 | DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n"));
|
---|
549 | talloc_free(schema_res);
|
---|
550 | return WERR_FOOBAR;
|
---|
551 | }
|
---|
552 |
|
---|
553 | prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
|
---|
554 | if (!prefix_val) {
|
---|
555 | DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n"));
|
---|
556 | talloc_free(schema_res);
|
---|
557 | return WERR_FOOBAR;
|
---|
558 | }
|
---|
559 |
|
---|
560 | blob = talloc(mem_ctx, struct prefixMapBlob);
|
---|
561 | W_ERROR_HAVE_NO_MEMORY(blob);
|
---|
562 |
|
---|
563 | ndr_err = ndr_pull_struct_blob(prefix_val, blob,
|
---|
564 | lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
|
---|
565 | blob,
|
---|
566 | (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
|
---|
567 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
568 | DEBUG(0,("dsdb_read_prefixes_from_ldb: ndr_pull_struct_blob failed\n"));
|
---|
569 | talloc_free(blob);
|
---|
570 | talloc_free(schema_res);
|
---|
571 | return WERR_FOOBAR;
|
---|
572 | }
|
---|
573 |
|
---|
574 | talloc_free(schema_res);
|
---|
575 |
|
---|
576 | if (blob->version != PREFIX_MAP_VERSION_DSDB) {
|
---|
577 | DEBUG(0,("dsdb_read_prefixes_from_ldb: blob->version incorect\n"));
|
---|
578 | talloc_free(blob);
|
---|
579 | return WERR_FOOBAR;
|
---|
580 | }
|
---|
581 |
|
---|
582 | *num_prefixes = blob->ctr.dsdb.num_mappings;
|
---|
583 | *prefixes = talloc_array(mem_ctx, struct dsdb_schema_oid_prefix, *num_prefixes);
|
---|
584 | if(!(*prefixes)) {
|
---|
585 | talloc_free(blob);
|
---|
586 | return WERR_NOMEM;
|
---|
587 | }
|
---|
588 | for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
|
---|
589 | char *oid;
|
---|
590 | (*prefixes)[i].id = blob->ctr.dsdb.mappings[i].id_prefix<<16;
|
---|
591 | oid = talloc_strdup(mem_ctx, blob->ctr.dsdb.mappings[i].oid.oid);
|
---|
592 | (*prefixes)[i].oid = talloc_asprintf_append(oid, ".");
|
---|
593 | (*prefixes)[i].oid_len = strlen((*prefixes)[i].oid);
|
---|
594 | }
|
---|
595 |
|
---|
596 | talloc_free(blob);
|
---|
597 | return WERR_OK;
|
---|
598 | }
|
---|
599 |
|
---|
600 | /*
|
---|
601 | this will be replaced with something that looks at the right part of
|
---|
602 | the schema once we know where unique indexing information is hidden
|
---|
603 | */
|
---|
604 | static bool dsdb_schema_unique_attribute(const char *attr)
|
---|
605 | {
|
---|
606 | const char *attrs[] = { "objectGUID", "objectSID" , NULL };
|
---|
607 | int i;
|
---|
608 | for (i=0;attrs[i];i++) {
|
---|
609 | if (strcasecmp(attr, attrs[i]) == 0) {
|
---|
610 | return true;
|
---|
611 | }
|
---|
612 | }
|
---|
613 | return false;
|
---|
614 | }
|
---|
615 |
|
---|
616 |
|
---|
617 | /*
|
---|
618 | setup the ldb_schema_attribute field for a dsdb_attribute
|
---|
619 | */
|
---|
620 | static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb,
|
---|
621 | struct dsdb_attribute *attr)
|
---|
622 | {
|
---|
623 | const char *syntax = attr->syntax->ldb_syntax;
|
---|
624 | const struct ldb_schema_syntax *s;
|
---|
625 | struct ldb_schema_attribute *a;
|
---|
626 |
|
---|
627 | if (!syntax) {
|
---|
628 | syntax = attr->syntax->ldap_oid;
|
---|
629 | }
|
---|
630 |
|
---|
631 | s = ldb_samba_syntax_by_lDAPDisplayName(ldb, attr->lDAPDisplayName);
|
---|
632 | if (s == NULL) {
|
---|
633 | s = ldb_samba_syntax_by_name(ldb, syntax);
|
---|
634 | }
|
---|
635 | if (s == NULL) {
|
---|
636 | s = ldb_standard_syntax_by_name(ldb, syntax);
|
---|
637 | }
|
---|
638 |
|
---|
639 | if (s == NULL) {
|
---|
640 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
641 | }
|
---|
642 |
|
---|
643 | attr->ldb_schema_attribute = a = talloc(attr, struct ldb_schema_attribute);
|
---|
644 | if (attr->ldb_schema_attribute == NULL) {
|
---|
645 | ldb_oom(ldb);
|
---|
646 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
647 | }
|
---|
648 |
|
---|
649 | a->name = attr->lDAPDisplayName;
|
---|
650 | a->flags = 0;
|
---|
651 | a->syntax = s;
|
---|
652 |
|
---|
653 | if (dsdb_schema_unique_attribute(a->name)) {
|
---|
654 | a->flags |= LDB_ATTR_FLAG_UNIQUE_INDEX;
|
---|
655 | }
|
---|
656 | if (attr->isSingleValued) {
|
---|
657 | a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE;
|
---|
658 | }
|
---|
659 |
|
---|
660 |
|
---|
661 | return LDB_SUCCESS;
|
---|
662 | }
|
---|
663 |
|
---|
664 |
|
---|
665 | #define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
|
---|
666 | const struct ldb_val *get_string_val = ldb_msg_find_ldb_val(msg, attr); \
|
---|
667 | if (get_string_val == NULL) { \
|
---|
668 | if (strict) { \
|
---|
669 | d_printf("%s: %s == NULL\n", __location__, attr); \
|
---|
670 | return WERR_INVALID_PARAM; \
|
---|
671 | } else { \
|
---|
672 | (p)->elem = NULL; \
|
---|
673 | } \
|
---|
674 | } else { \
|
---|
675 | (p)->elem = talloc_strndup(mem_ctx, \
|
---|
676 | (const char *)get_string_val->data, \
|
---|
677 | get_string_val->length); \
|
---|
678 | if (!(p)->elem) { \
|
---|
679 | d_printf("%s: talloc_strndup failed for %s\n", __location__, attr); \
|
---|
680 | return WERR_NOMEM; \
|
---|
681 | } \
|
---|
682 | } \
|
---|
683 | } while (0)
|
---|
684 |
|
---|
685 | #define GET_STRING_LIST_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
|
---|
686 | int get_string_list_counter; \
|
---|
687 | struct ldb_message_element *get_string_list_el = ldb_msg_find_element(msg, attr); \
|
---|
688 | if (get_string_list_el == NULL) { \
|
---|
689 | if (strict) { \
|
---|
690 | d_printf("%s: %s == NULL\n", __location__, attr); \
|
---|
691 | return WERR_INVALID_PARAM; \
|
---|
692 | } else { \
|
---|
693 | (p)->elem = NULL; \
|
---|
694 | break; \
|
---|
695 | } \
|
---|
696 | } \
|
---|
697 | (p)->elem = talloc_array(mem_ctx, const char *, get_string_list_el->num_values + 1); \
|
---|
698 | for (get_string_list_counter=0; \
|
---|
699 | get_string_list_counter < get_string_list_el->num_values; \
|
---|
700 | get_string_list_counter++) { \
|
---|
701 | (p)->elem[get_string_list_counter] = talloc_strndup((p)->elem, \
|
---|
702 | (const char *)get_string_list_el->values[get_string_list_counter].data, \
|
---|
703 | get_string_list_el->values[get_string_list_counter].length); \
|
---|
704 | if (!(p)->elem[get_string_list_counter]) { \
|
---|
705 | d_printf("%s: talloc_strndup failed for %s\n", __location__, attr); \
|
---|
706 | return WERR_NOMEM; \
|
---|
707 | } \
|
---|
708 | (p)->elem[get_string_list_counter+1] = NULL; \
|
---|
709 | } \
|
---|
710 | talloc_steal(mem_ctx, (p)->elem); \
|
---|
711 | } while (0)
|
---|
712 |
|
---|
713 | #define GET_BOOL_LDB(msg, attr, p, elem, strict) do { \
|
---|
714 | const char *str; \
|
---|
715 | str = samdb_result_string(msg, attr, NULL);\
|
---|
716 | if (str == NULL) { \
|
---|
717 | if (strict) { \
|
---|
718 | d_printf("%s: %s == NULL\n", __location__, attr); \
|
---|
719 | return WERR_INVALID_PARAM; \
|
---|
720 | } else { \
|
---|
721 | (p)->elem = false; \
|
---|
722 | } \
|
---|
723 | } else if (strcasecmp("TRUE", str) == 0) { \
|
---|
724 | (p)->elem = true; \
|
---|
725 | } else if (strcasecmp("FALSE", str) == 0) { \
|
---|
726 | (p)->elem = false; \
|
---|
727 | } else { \
|
---|
728 | d_printf("%s: %s == %s\n", __location__, attr, str); \
|
---|
729 | return WERR_INVALID_PARAM; \
|
---|
730 | } \
|
---|
731 | } while (0)
|
---|
732 |
|
---|
733 | #define GET_UINT32_LDB(msg, attr, p, elem) do { \
|
---|
734 | (p)->elem = samdb_result_uint(msg, attr, 0);\
|
---|
735 | } while (0)
|
---|
736 |
|
---|
737 | #define GET_UINT32_PTR_LDB(msg, attr, p, elem) do { \
|
---|
738 | uint64_t _v = samdb_result_uint64(msg, attr, UINT64_MAX);\
|
---|
739 | if (_v == UINT64_MAX) { \
|
---|
740 | (p)->elem = NULL; \
|
---|
741 | } else if (_v > UINT32_MAX) { \
|
---|
742 | d_printf("%s: %s == 0x%llX\n", __location__, \
|
---|
743 | attr, (unsigned long long)_v); \
|
---|
744 | return WERR_INVALID_PARAM; \
|
---|
745 | } else { \
|
---|
746 | (p)->elem = talloc(mem_ctx, uint32_t); \
|
---|
747 | if (!(p)->elem) { \
|
---|
748 | d_printf("%s: talloc failed for %s\n", __location__, attr); \
|
---|
749 | return WERR_NOMEM; \
|
---|
750 | } \
|
---|
751 | *(p)->elem = (uint32_t)_v; \
|
---|
752 | } \
|
---|
753 | } while (0)
|
---|
754 |
|
---|
755 | #define GET_GUID_LDB(msg, attr, p, elem) do { \
|
---|
756 | (p)->elem = samdb_result_guid(msg, attr);\
|
---|
757 | } while (0)
|
---|
758 |
|
---|
759 | #define GET_BLOB_LDB(msg, attr, mem_ctx, p, elem) do { \
|
---|
760 | const struct ldb_val *_val;\
|
---|
761 | _val = ldb_msg_find_ldb_val(msg, attr);\
|
---|
762 | if (_val) {\
|
---|
763 | (p)->elem = *_val;\
|
---|
764 | talloc_steal(mem_ctx, (p)->elem.data);\
|
---|
765 | } else {\
|
---|
766 | ZERO_STRUCT((p)->elem);\
|
---|
767 | }\
|
---|
768 | } while (0)
|
---|
769 |
|
---|
770 | WERROR dsdb_attribute_from_ldb(struct ldb_context *ldb,
|
---|
771 | const struct dsdb_schema *schema,
|
---|
772 | struct ldb_message *msg,
|
---|
773 | TALLOC_CTX *mem_ctx,
|
---|
774 | struct dsdb_attribute *attr)
|
---|
775 | {
|
---|
776 | WERROR status;
|
---|
777 |
|
---|
778 | GET_STRING_LDB(msg, "cn", mem_ctx, attr, cn, false);
|
---|
779 | GET_STRING_LDB(msg, "lDAPDisplayName", mem_ctx, attr, lDAPDisplayName, true);
|
---|
780 | GET_STRING_LDB(msg, "attributeID", mem_ctx, attr, attributeID_oid, true);
|
---|
781 | if (schema->num_prefixes == 0) {
|
---|
782 | /* set an invalid value */
|
---|
783 | attr->attributeID_id = 0xFFFFFFFF;
|
---|
784 | } else {
|
---|
785 | status = dsdb_map_oid2int(schema, attr->attributeID_oid, &attr->attributeID_id);
|
---|
786 | if (!W_ERROR_IS_OK(status)) {
|
---|
787 | DEBUG(0,("%s: '%s': unable to map attributeID %s: %s\n",
|
---|
788 | __location__, attr->lDAPDisplayName, attr->attributeID_oid,
|
---|
789 | win_errstr(status)));
|
---|
790 | return status;
|
---|
791 | }
|
---|
792 | }
|
---|
793 | GET_GUID_LDB(msg, "schemaIDGUID", attr, schemaIDGUID);
|
---|
794 | GET_UINT32_LDB(msg, "mAPIID", attr, mAPIID);
|
---|
795 |
|
---|
796 | GET_GUID_LDB(msg, "attributeSecurityGUID", attr, attributeSecurityGUID);
|
---|
797 |
|
---|
798 | GET_UINT32_LDB(msg, "searchFlags", attr, searchFlags);
|
---|
799 | GET_UINT32_LDB(msg, "systemFlags", attr, systemFlags);
|
---|
800 | GET_BOOL_LDB(msg, "isMemberOfPartialAttributeSet", attr, isMemberOfPartialAttributeSet, false);
|
---|
801 | GET_UINT32_LDB(msg, "linkID", attr, linkID);
|
---|
802 |
|
---|
803 | GET_STRING_LDB(msg, "attributeSyntax", mem_ctx, attr, attributeSyntax_oid, true);
|
---|
804 | if (schema->num_prefixes == 0) {
|
---|
805 | /* set an invalid value */
|
---|
806 | attr->attributeSyntax_id = 0xFFFFFFFF;
|
---|
807 | } else {
|
---|
808 | status = dsdb_map_oid2int(schema, attr->attributeSyntax_oid, &attr->attributeSyntax_id);
|
---|
809 | if (!W_ERROR_IS_OK(status)) {
|
---|
810 | DEBUG(0,("%s: '%s': unable to map attributeSyntax_ %s: %s\n",
|
---|
811 | __location__, attr->lDAPDisplayName, attr->attributeSyntax_oid,
|
---|
812 | win_errstr(status)));
|
---|
813 | return status;
|
---|
814 | }
|
---|
815 | }
|
---|
816 | GET_UINT32_LDB(msg, "oMSyntax", attr, oMSyntax);
|
---|
817 | GET_BLOB_LDB(msg, "oMObjectClass", mem_ctx, attr, oMObjectClass);
|
---|
818 |
|
---|
819 | GET_BOOL_LDB(msg, "isSingleValued", attr, isSingleValued, true);
|
---|
820 | GET_UINT32_PTR_LDB(msg, "rangeLower", attr, rangeLower);
|
---|
821 | GET_UINT32_PTR_LDB(msg, "rangeUpper", attr, rangeUpper);
|
---|
822 | GET_BOOL_LDB(msg, "extendedCharsAllowed", attr, extendedCharsAllowed, false);
|
---|
823 |
|
---|
824 | GET_UINT32_LDB(msg, "schemaFlagsEx", attr, schemaFlagsEx);
|
---|
825 | GET_BLOB_LDB(msg, "msDs-Schema-Extensions", mem_ctx, attr, msDs_Schema_Extensions);
|
---|
826 |
|
---|
827 | GET_BOOL_LDB(msg, "showInAdvancedViewOnly", attr, showInAdvancedViewOnly, false);
|
---|
828 | GET_STRING_LDB(msg, "adminDisplayName", mem_ctx, attr, adminDisplayName, false);
|
---|
829 | GET_STRING_LDB(msg, "adminDescription", mem_ctx, attr, adminDescription, false);
|
---|
830 | GET_STRING_LDB(msg, "classDisplayName", mem_ctx, attr, classDisplayName, false);
|
---|
831 | GET_BOOL_LDB(msg, "isEphemeral", attr, isEphemeral, false);
|
---|
832 | GET_BOOL_LDB(msg, "isDefunct", attr, isDefunct, false);
|
---|
833 | GET_BOOL_LDB(msg, "systemOnly", attr, systemOnly, false);
|
---|
834 |
|
---|
835 | attr->syntax = dsdb_syntax_for_attribute(attr);
|
---|
836 | if (!attr->syntax) {
|
---|
837 | return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
|
---|
838 | }
|
---|
839 |
|
---|
840 | if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
|
---|
841 | return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
|
---|
842 | }
|
---|
843 |
|
---|
844 | return WERR_OK;
|
---|
845 | }
|
---|
846 |
|
---|
847 | WERROR dsdb_class_from_ldb(const struct dsdb_schema *schema,
|
---|
848 | struct ldb_message *msg,
|
---|
849 | TALLOC_CTX *mem_ctx,
|
---|
850 | struct dsdb_class *obj)
|
---|
851 | {
|
---|
852 | WERROR status;
|
---|
853 |
|
---|
854 | GET_STRING_LDB(msg, "cn", mem_ctx, obj, cn, false);
|
---|
855 | GET_STRING_LDB(msg, "lDAPDisplayName", mem_ctx, obj, lDAPDisplayName, true);
|
---|
856 | GET_STRING_LDB(msg, "governsID", mem_ctx, obj, governsID_oid, true);
|
---|
857 | if (schema->num_prefixes == 0) {
|
---|
858 | /* set an invalid value */
|
---|
859 | obj->governsID_id = 0xFFFFFFFF;
|
---|
860 | } else {
|
---|
861 | status = dsdb_map_oid2int(schema, obj->governsID_oid, &obj->governsID_id);
|
---|
862 | if (!W_ERROR_IS_OK(status)) {
|
---|
863 | DEBUG(0,("%s: '%s': unable to map governsID %s: %s\n",
|
---|
864 | __location__, obj->lDAPDisplayName, obj->governsID_oid,
|
---|
865 | win_errstr(status)));
|
---|
866 | return status;
|
---|
867 | }
|
---|
868 | }
|
---|
869 | GET_GUID_LDB(msg, "schemaIDGUID", obj, schemaIDGUID);
|
---|
870 |
|
---|
871 | GET_UINT32_LDB(msg, "objectClassCategory", obj, objectClassCategory);
|
---|
872 | GET_STRING_LDB(msg, "rDNAttID", mem_ctx, obj, rDNAttID, false);
|
---|
873 | GET_STRING_LDB(msg, "defaultObjectCategory", mem_ctx, obj, defaultObjectCategory, true);
|
---|
874 |
|
---|
875 | GET_STRING_LDB(msg, "subClassOf", mem_ctx, obj, subClassOf, true);
|
---|
876 |
|
---|
877 | GET_STRING_LIST_LDB(msg, "systemAuxiliaryClass", mem_ctx, obj, systemAuxiliaryClass, false);
|
---|
878 | GET_STRING_LIST_LDB(msg, "auxiliaryClass", mem_ctx, obj, auxiliaryClass, false);
|
---|
879 |
|
---|
880 | GET_STRING_LIST_LDB(msg, "systemMustContain", mem_ctx, obj, systemMustContain, false);
|
---|
881 | GET_STRING_LIST_LDB(msg, "systemMayContain", mem_ctx, obj, systemMayContain, false);
|
---|
882 | GET_STRING_LIST_LDB(msg, "mustContain", mem_ctx, obj, mustContain, false);
|
---|
883 | GET_STRING_LIST_LDB(msg, "mayContain", mem_ctx, obj, mayContain, false);
|
---|
884 |
|
---|
885 | GET_STRING_LIST_LDB(msg, "systemPossSuperiors", mem_ctx, obj, systemPossSuperiors, false);
|
---|
886 | GET_STRING_LIST_LDB(msg, "possSuperiors", mem_ctx, obj, possSuperiors, false);
|
---|
887 |
|
---|
888 | GET_STRING_LDB(msg, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, false);
|
---|
889 |
|
---|
890 | GET_UINT32_LDB(msg, "schemaFlagsEx", obj, schemaFlagsEx);
|
---|
891 | GET_BLOB_LDB(msg, "msDs-Schema-Extensions", mem_ctx, obj, msDs_Schema_Extensions);
|
---|
892 |
|
---|
893 | GET_BOOL_LDB(msg, "showInAdvancedViewOnly", obj, showInAdvancedViewOnly, false);
|
---|
894 | GET_STRING_LDB(msg, "adminDisplayName", mem_ctx, obj, adminDisplayName, false);
|
---|
895 | GET_STRING_LDB(msg, "adminDescription", mem_ctx, obj, adminDescription, false);
|
---|
896 | GET_STRING_LDB(msg, "classDisplayName", mem_ctx, obj, classDisplayName, false);
|
---|
897 | GET_BOOL_LDB(msg, "defaultHidingValue", obj, defaultHidingValue, false);
|
---|
898 | GET_BOOL_LDB(msg, "isDefunct", obj, isDefunct, false);
|
---|
899 | GET_BOOL_LDB(msg, "systemOnly", obj, systemOnly, false);
|
---|
900 |
|
---|
901 | return WERR_OK;
|
---|
902 | }
|
---|
903 |
|
---|
904 | #define dsdb_oom(error_string, mem_ctx) *error_string = talloc_asprintf(mem_ctx, "dsdb out of memory at %s:%d\n", __FILE__, __LINE__)
|
---|
905 |
|
---|
906 | /*
|
---|
907 | Create a DSDB schema from the ldb results provided. This is called
|
---|
908 | directly when the schema is provisioned from an on-disk LDIF file, or
|
---|
909 | from dsdb_schema_from_schema_dn below
|
---|
910 | */
|
---|
911 |
|
---|
912 | int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
|
---|
913 | struct smb_iconv_convenience *iconv_convenience,
|
---|
914 | struct ldb_result *schema_res,
|
---|
915 | struct ldb_result *attrs_res, struct ldb_result *objectclass_res,
|
---|
916 | struct dsdb_schema **schema_out,
|
---|
917 | char **error_string)
|
---|
918 | {
|
---|
919 | WERROR status;
|
---|
920 | uint32_t i;
|
---|
921 | const struct ldb_val *prefix_val;
|
---|
922 | const struct ldb_val *info_val;
|
---|
923 | struct ldb_val info_val_default;
|
---|
924 | struct dsdb_schema *schema;
|
---|
925 |
|
---|
926 | schema = dsdb_new_schema(mem_ctx, iconv_convenience);
|
---|
927 | if (!schema) {
|
---|
928 | dsdb_oom(error_string, mem_ctx);
|
---|
929 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
930 | }
|
---|
931 |
|
---|
932 | prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
|
---|
933 | if (!prefix_val) {
|
---|
934 | *error_string = talloc_asprintf(mem_ctx,
|
---|
935 | "schema_fsmo_init: no prefixMap attribute found");
|
---|
936 | DEBUG(0,(__location__ ": %s\n", *error_string));
|
---|
937 | return LDB_ERR_CONSTRAINT_VIOLATION;
|
---|
938 | }
|
---|
939 | info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
|
---|
940 | if (!info_val) {
|
---|
941 | info_val_default = strhex_to_data_blob(mem_ctx, "FF0000000000000000000000000000000000000000");
|
---|
942 | if (!info_val_default.data) {
|
---|
943 | dsdb_oom(error_string, mem_ctx);
|
---|
944 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
945 | }
|
---|
946 | info_val = &info_val_default;
|
---|
947 | }
|
---|
948 |
|
---|
949 | status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
|
---|
950 | if (!W_ERROR_IS_OK(status)) {
|
---|
951 | *error_string = talloc_asprintf(mem_ctx,
|
---|
952 | "schema_fsmo_init: failed to load oid mappings: %s",
|
---|
953 | win_errstr(status));
|
---|
954 | DEBUG(0,(__location__ ": %s\n", *error_string));
|
---|
955 | return LDB_ERR_CONSTRAINT_VIOLATION;
|
---|
956 | }
|
---|
957 |
|
---|
958 | for (i=0; i < attrs_res->count; i++) {
|
---|
959 | struct dsdb_attribute *sa;
|
---|
960 |
|
---|
961 | sa = talloc_zero(schema, struct dsdb_attribute);
|
---|
962 | if (!sa) {
|
---|
963 | dsdb_oom(error_string, mem_ctx);
|
---|
964 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
965 | }
|
---|
966 |
|
---|
967 | status = dsdb_attribute_from_ldb(ldb, schema, attrs_res->msgs[i], sa, sa);
|
---|
968 | if (!W_ERROR_IS_OK(status)) {
|
---|
969 | *error_string = talloc_asprintf(mem_ctx,
|
---|
970 | "schema_fsmo_init: failed to load attribute definition: %s:%s",
|
---|
971 | ldb_dn_get_linearized(attrs_res->msgs[i]->dn),
|
---|
972 | win_errstr(status));
|
---|
973 | DEBUG(0,(__location__ ": %s\n", *error_string));
|
---|
974 | return LDB_ERR_CONSTRAINT_VIOLATION;
|
---|
975 | }
|
---|
976 |
|
---|
977 | DLIST_ADD(schema->attributes, sa);
|
---|
978 | }
|
---|
979 |
|
---|
980 | for (i=0; i < objectclass_res->count; i++) {
|
---|
981 | struct dsdb_class *sc;
|
---|
982 |
|
---|
983 | sc = talloc_zero(schema, struct dsdb_class);
|
---|
984 | if (!sc) {
|
---|
985 | dsdb_oom(error_string, mem_ctx);
|
---|
986 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
987 | }
|
---|
988 |
|
---|
989 | status = dsdb_class_from_ldb(schema, objectclass_res->msgs[i], sc, sc);
|
---|
990 | if (!W_ERROR_IS_OK(status)) {
|
---|
991 | *error_string = talloc_asprintf(mem_ctx,
|
---|
992 | "schema_fsmo_init: failed to load class definition: %s:%s",
|
---|
993 | ldb_dn_get_linearized(objectclass_res->msgs[i]->dn),
|
---|
994 | win_errstr(status));
|
---|
995 | DEBUG(0,(__location__ ": %s\n", *error_string));
|
---|
996 | return LDB_ERR_CONSTRAINT_VIOLATION;
|
---|
997 | }
|
---|
998 |
|
---|
999 | DLIST_ADD(schema->classes, sc);
|
---|
1000 | }
|
---|
1001 |
|
---|
1002 | schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_res->msgs[0], "fSMORoleOwner");
|
---|
1003 | if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), schema->fsmo.master_dn) == 0) {
|
---|
1004 | schema->fsmo.we_are_master = true;
|
---|
1005 | } else {
|
---|
1006 | schema->fsmo.we_are_master = false;
|
---|
1007 | }
|
---|
1008 |
|
---|
1009 | DEBUG(5, ("schema_fsmo_init: we are master: %s\n",
|
---|
1010 | (schema->fsmo.we_are_master?"yes":"no")));
|
---|
1011 |
|
---|
1012 | *schema_out = schema;
|
---|
1013 | return LDB_SUCCESS;
|
---|
1014 | }
|
---|
1015 |
|
---|
1016 | /*
|
---|
1017 | Given an LDB, and the DN, return a populated schema
|
---|
1018 | */
|
---|
1019 |
|
---|
1020 | int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
|
---|
1021 | struct smb_iconv_convenience *iconv_convenience,
|
---|
1022 | struct ldb_dn *schema_dn,
|
---|
1023 | struct dsdb_schema **schema,
|
---|
1024 | char **error_string_out)
|
---|
1025 | {
|
---|
1026 | TALLOC_CTX *tmp_ctx;
|
---|
1027 | char *error_string;
|
---|
1028 | int ret;
|
---|
1029 |
|
---|
1030 | struct ldb_result *schema_res;
|
---|
1031 | struct ldb_result *a_res;
|
---|
1032 | struct ldb_result *c_res;
|
---|
1033 | static const char *schema_attrs[] = {
|
---|
1034 | "prefixMap",
|
---|
1035 | "schemaInfo",
|
---|
1036 | "fSMORoleOwner",
|
---|
1037 | NULL
|
---|
1038 | };
|
---|
1039 | unsigned flags;
|
---|
1040 |
|
---|
1041 | tmp_ctx = talloc_new(mem_ctx);
|
---|
1042 | if (!tmp_ctx) {
|
---|
1043 | dsdb_oom(error_string_out, mem_ctx);
|
---|
1044 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
1045 | }
|
---|
1046 |
|
---|
1047 | /* we don't want to trace the schema load */
|
---|
1048 | flags = ldb_get_flags(ldb);
|
---|
1049 | ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
|
---|
1050 |
|
---|
1051 | /*
|
---|
1052 | * setup the prefix mappings and schema info
|
---|
1053 | */
|
---|
1054 | ret = ldb_search(ldb, tmp_ctx, &schema_res,
|
---|
1055 | schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL);
|
---|
1056 | if (ret == LDB_ERR_NO_SUCH_OBJECT) {
|
---|
1057 | goto failed;
|
---|
1058 | } else if (ret != LDB_SUCCESS) {
|
---|
1059 | *error_string_out = talloc_asprintf(mem_ctx,
|
---|
1060 | "dsdb_schema: failed to search the schema head: %s",
|
---|
1061 | ldb_errstring(ldb));
|
---|
1062 | goto failed;
|
---|
1063 | }
|
---|
1064 | if (schema_res->count != 1) {
|
---|
1065 | *error_string_out = talloc_asprintf(mem_ctx,
|
---|
1066 | "dsdb_schema: [%u] schema heads found on a base search",
|
---|
1067 | schema_res->count);
|
---|
1068 | goto failed;
|
---|
1069 | }
|
---|
1070 |
|
---|
1071 | /*
|
---|
1072 | * load the attribute definitions
|
---|
1073 | */
|
---|
1074 | ret = ldb_search(ldb, tmp_ctx, &a_res,
|
---|
1075 | schema_dn, LDB_SCOPE_ONELEVEL, NULL,
|
---|
1076 | "(objectClass=attributeSchema)");
|
---|
1077 | if (ret != LDB_SUCCESS) {
|
---|
1078 | *error_string_out = talloc_asprintf(mem_ctx,
|
---|
1079 | "dsdb_schema: failed to search attributeSchema objects: %s",
|
---|
1080 | ldb_errstring(ldb));
|
---|
1081 | goto failed;
|
---|
1082 | }
|
---|
1083 |
|
---|
1084 | /*
|
---|
1085 | * load the objectClass definitions
|
---|
1086 | */
|
---|
1087 | ret = ldb_search(ldb, tmp_ctx, &c_res,
|
---|
1088 | schema_dn, LDB_SCOPE_ONELEVEL, NULL,
|
---|
1089 | "(objectClass=classSchema)");
|
---|
1090 | if (ret != LDB_SUCCESS) {
|
---|
1091 | *error_string_out = talloc_asprintf(mem_ctx,
|
---|
1092 | "dsdb_schema: failed to search attributeSchema objects: %s",
|
---|
1093 | ldb_errstring(ldb));
|
---|
1094 | goto failed;
|
---|
1095 | }
|
---|
1096 |
|
---|
1097 | ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
|
---|
1098 | lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
|
---|
1099 | schema_res, a_res, c_res, schema, &error_string);
|
---|
1100 | if (ret != LDB_SUCCESS) {
|
---|
1101 | *error_string_out = talloc_asprintf(mem_ctx,
|
---|
1102 | "dsdb_schema load failed: %s",
|
---|
1103 | error_string);
|
---|
1104 | goto failed;
|
---|
1105 | }
|
---|
1106 | talloc_steal(mem_ctx, *schema);
|
---|
1107 | talloc_free(tmp_ctx);
|
---|
1108 |
|
---|
1109 | if (flags & LDB_FLG_ENABLE_TRACING) {
|
---|
1110 | flags = ldb_get_flags(ldb);
|
---|
1111 | ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
|
---|
1112 | }
|
---|
1113 |
|
---|
1114 | return LDB_SUCCESS;
|
---|
1115 |
|
---|
1116 | failed:
|
---|
1117 | if (flags & LDB_FLG_ENABLE_TRACING) {
|
---|
1118 | flags = ldb_get_flags(ldb);
|
---|
1119 | ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
|
---|
1120 | }
|
---|
1121 | talloc_free(tmp_ctx);
|
---|
1122 | return ret;
|
---|
1123 | }
|
---|
1124 |
|
---|
1125 |
|
---|
1126 | static const struct {
|
---|
1127 | const char *name;
|
---|
1128 | const char *oid;
|
---|
1129 | } name_mappings[] = {
|
---|
1130 | { "cn", "2.5.4.3" },
|
---|
1131 | { "name", "1.2.840.113556.1.4.1" },
|
---|
1132 | { "lDAPDisplayName", "1.2.840.113556.1.2.460" },
|
---|
1133 | { "attributeID", "1.2.840.113556.1.2.30" },
|
---|
1134 | { "schemaIDGUID", "1.2.840.113556.1.4.148" },
|
---|
1135 | { "mAPIID", "1.2.840.113556.1.2.49" },
|
---|
1136 | { "attributeSecurityGUID", "1.2.840.113556.1.4.149" },
|
---|
1137 | { "searchFlags", "1.2.840.113556.1.2.334" },
|
---|
1138 | { "systemFlags", "1.2.840.113556.1.4.375" },
|
---|
1139 | { "isMemberOfPartialAttributeSet", "1.2.840.113556.1.4.639" },
|
---|
1140 | { "linkID", "1.2.840.113556.1.2.50" },
|
---|
1141 | { "attributeSyntax", "1.2.840.113556.1.2.32" },
|
---|
1142 | { "oMSyntax", "1.2.840.113556.1.2.231" },
|
---|
1143 | { "oMObjectClass", "1.2.840.113556.1.2.218" },
|
---|
1144 | { "isSingleValued", "1.2.840.113556.1.2.33" },
|
---|
1145 | { "rangeLower", "1.2.840.113556.1.2.34" },
|
---|
1146 | { "rangeUpper", "1.2.840.113556.1.2.35" },
|
---|
1147 | { "extendedCharsAllowed", "1.2.840.113556.1.2.380" },
|
---|
1148 | { "schemaFlagsEx", "1.2.840.113556.1.4.120" },
|
---|
1149 | { "msDs-Schema-Extensions", "1.2.840.113556.1.4.1440" },
|
---|
1150 | { "showInAdvancedViewOnly", "1.2.840.113556.1.2.169" },
|
---|
1151 | { "adminDisplayName", "1.2.840.113556.1.2.194" },
|
---|
1152 | { "adminDescription", "1.2.840.113556.1.2.226" },
|
---|
1153 | { "classDisplayName", "1.2.840.113556.1.4.610" },
|
---|
1154 | { "isEphemeral", "1.2.840.113556.1.4.1212" },
|
---|
1155 | { "isDefunct", "1.2.840.113556.1.4.661" },
|
---|
1156 | { "systemOnly", "1.2.840.113556.1.4.170" },
|
---|
1157 | { "governsID", "1.2.840.113556.1.2.22" },
|
---|
1158 | { "objectClassCategory", "1.2.840.113556.1.2.370" },
|
---|
1159 | { "rDNAttID", "1.2.840.113556.1.2.26" },
|
---|
1160 | { "defaultObjectCategory", "1.2.840.113556.1.4.783" },
|
---|
1161 | { "subClassOf", "1.2.840.113556.1.2.21" },
|
---|
1162 | { "systemAuxiliaryClass", "1.2.840.113556.1.4.198" },
|
---|
1163 | { "systemPossSuperiors", "1.2.840.113556.1.4.195" },
|
---|
1164 | { "systemMustContain", "1.2.840.113556.1.4.197" },
|
---|
1165 | { "systemMayContain", "1.2.840.113556.1.4.196" },
|
---|
1166 | { "auxiliaryClass", "1.2.840.113556.1.2.351" },
|
---|
1167 | { "possSuperiors", "1.2.840.113556.1.2.8" },
|
---|
1168 | { "mustContain", "1.2.840.113556.1.2.24" },
|
---|
1169 | { "mayContain", "1.2.840.113556.1.2.25" },
|
---|
1170 | { "defaultSecurityDescriptor", "1.2.840.113556.1.4.224" },
|
---|
1171 | { "defaultHidingValue", "1.2.840.113556.1.4.518" },
|
---|
1172 | };
|
---|
1173 |
|
---|
1174 | static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb_schema *schema,
|
---|
1175 | struct drsuapi_DsReplicaObject *obj,
|
---|
1176 | const char *name,
|
---|
1177 | uint32_t *idx)
|
---|
1178 | {
|
---|
1179 | WERROR status;
|
---|
1180 | uint32_t i, id;
|
---|
1181 | const char *oid = NULL;
|
---|
1182 |
|
---|
1183 | for(i=0; i < ARRAY_SIZE(name_mappings); i++) {
|
---|
1184 | if (strcmp(name_mappings[i].name, name) != 0) continue;
|
---|
1185 |
|
---|
1186 | oid = name_mappings[i].oid;
|
---|
1187 | break;
|
---|
1188 | }
|
---|
1189 |
|
---|
1190 | if (!oid) {
|
---|
1191 | return NULL;
|
---|
1192 | }
|
---|
1193 |
|
---|
1194 | status = dsdb_map_oid2int(schema, oid, &id);
|
---|
1195 | if (!W_ERROR_IS_OK(status)) {
|
---|
1196 | return NULL;
|
---|
1197 | }
|
---|
1198 |
|
---|
1199 | for (i=0; i < obj->attribute_ctr.num_attributes; i++) {
|
---|
1200 | if (obj->attribute_ctr.attributes[i].attid != id) continue;
|
---|
1201 |
|
---|
1202 | if (idx) *idx = i;
|
---|
1203 | return &obj->attribute_ctr.attributes[i];
|
---|
1204 | }
|
---|
1205 |
|
---|
1206 | return NULL;
|
---|
1207 | }
|
---|
1208 |
|
---|
1209 | #define GET_STRING_DS(s, r, attr, mem_ctx, p, elem, strict) do { \
|
---|
1210 | struct drsuapi_DsReplicaAttribute *_a; \
|
---|
1211 | _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
|
---|
1212 | if (strict && !_a) { \
|
---|
1213 | d_printf("%s: %s == NULL\n", __location__, attr); \
|
---|
1214 | return WERR_INVALID_PARAM; \
|
---|
1215 | } \
|
---|
1216 | if (strict && _a->value_ctr.num_values != 1) { \
|
---|
1217 | d_printf("%s: %s num_values == %u\n", __location__, attr, \
|
---|
1218 | _a->value_ctr.num_values); \
|
---|
1219 | return WERR_INVALID_PARAM; \
|
---|
1220 | } \
|
---|
1221 | if (_a && _a->value_ctr.num_values >= 1) { \
|
---|
1222 | size_t _ret; \
|
---|
1223 | if (!convert_string_talloc_convenience(mem_ctx, s->iconv_convenience, CH_UTF16, CH_UNIX, \
|
---|
1224 | _a->value_ctr.values[0].blob->data, \
|
---|
1225 | _a->value_ctr.values[0].blob->length, \
|
---|
1226 | (void **)discard_const(&(p)->elem), &_ret, false)) { \
|
---|
1227 | DEBUG(0,("%s: invalid data!\n", attr)); \
|
---|
1228 | dump_data(0, \
|
---|
1229 | _a->value_ctr.values[0].blob->data, \
|
---|
1230 | _a->value_ctr.values[0].blob->length); \
|
---|
1231 | return WERR_FOOBAR; \
|
---|
1232 | } \
|
---|
1233 | } else { \
|
---|
1234 | (p)->elem = NULL; \
|
---|
1235 | } \
|
---|
1236 | } while (0)
|
---|
1237 |
|
---|
1238 | #define GET_UINT32_LIST_DS(s, r, attr, mem_ctx, p, elem) do { \
|
---|
1239 | int list_counter; \
|
---|
1240 | struct drsuapi_DsReplicaAttribute *_a; \
|
---|
1241 | _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
|
---|
1242 | (p)->elem = _a ? talloc_array(mem_ctx, uint32_t, _a->value_ctr.num_values + 1) : NULL; \
|
---|
1243 | for (list_counter=0; \
|
---|
1244 | _a && list_counter < _a->value_ctr.num_values; \
|
---|
1245 | list_counter++) { \
|
---|
1246 | if (_a->value_ctr.values[list_counter].blob->length != 4) { \
|
---|
1247 | return WERR_INVALID_PARAM; \
|
---|
1248 | } \
|
---|
1249 | (p)->elem[list_counter] = IVAL(_a->value_ctr.values[list_counter].blob->data, 0); \
|
---|
1250 | } \
|
---|
1251 | if (_a) (p)->elem[list_counter] = 0; \
|
---|
1252 | } while (0)
|
---|
1253 |
|
---|
1254 | #define GET_DN_DS(s, r, attr, mem_ctx, p, elem, strict) do { \
|
---|
1255 | struct drsuapi_DsReplicaAttribute *_a; \
|
---|
1256 | _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
|
---|
1257 | if (strict && !_a) { \
|
---|
1258 | d_printf("%s: %s == NULL\n", __location__, attr); \
|
---|
1259 | return WERR_INVALID_PARAM; \
|
---|
1260 | } \
|
---|
1261 | if (strict && _a->value_ctr.num_values != 1) { \
|
---|
1262 | d_printf("%s: %s num_values == %u\n", __location__, attr, \
|
---|
1263 | _a->value_ctr.num_values); \
|
---|
1264 | return WERR_INVALID_PARAM; \
|
---|
1265 | } \
|
---|
1266 | if (strict && !_a->value_ctr.values[0].blob) { \
|
---|
1267 | d_printf("%s: %s data == NULL\n", __location__, attr); \
|
---|
1268 | return WERR_INVALID_PARAM; \
|
---|
1269 | } \
|
---|
1270 | if (_a && _a->value_ctr.num_values >= 1 \
|
---|
1271 | && _a->value_ctr.values[0].blob) { \
|
---|
1272 | struct drsuapi_DsReplicaObjectIdentifier3 _id3; \
|
---|
1273 | enum ndr_err_code _ndr_err; \
|
---|
1274 | _ndr_err = ndr_pull_struct_blob_all(_a->value_ctr.values[0].blob, \
|
---|
1275 | mem_ctx, s->iconv_convenience, &_id3,\
|
---|
1276 | (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);\
|
---|
1277 | if (!NDR_ERR_CODE_IS_SUCCESS(_ndr_err)) { \
|
---|
1278 | NTSTATUS _nt_status = ndr_map_error2ntstatus(_ndr_err); \
|
---|
1279 | return ntstatus_to_werror(_nt_status); \
|
---|
1280 | } \
|
---|
1281 | (p)->elem = _id3.dn; \
|
---|
1282 | } else { \
|
---|
1283 | (p)->elem = NULL; \
|
---|
1284 | } \
|
---|
1285 | } while (0)
|
---|
1286 |
|
---|
1287 | #define GET_BOOL_DS(s, r, attr, p, elem, strict) do { \
|
---|
1288 | struct drsuapi_DsReplicaAttribute *_a; \
|
---|
1289 | _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
|
---|
1290 | if (strict && !_a) { \
|
---|
1291 | d_printf("%s: %s == NULL\n", __location__, attr); \
|
---|
1292 | return WERR_INVALID_PARAM; \
|
---|
1293 | } \
|
---|
1294 | if (strict && _a->value_ctr.num_values != 1) { \
|
---|
1295 | d_printf("%s: %s num_values == %u\n", __location__, attr, \
|
---|
1296 | (unsigned int)_a->value_ctr.num_values); \
|
---|
1297 | return WERR_INVALID_PARAM; \
|
---|
1298 | } \
|
---|
1299 | if (strict && !_a->value_ctr.values[0].blob) { \
|
---|
1300 | d_printf("%s: %s data == NULL\n", __location__, attr); \
|
---|
1301 | return WERR_INVALID_PARAM; \
|
---|
1302 | } \
|
---|
1303 | if (strict && _a->value_ctr.values[0].blob->length != 4) { \
|
---|
1304 | d_printf("%s: %s length == %u\n", __location__, attr, \
|
---|
1305 | (unsigned int)_a->value_ctr.values[0].blob->length); \
|
---|
1306 | return WERR_INVALID_PARAM; \
|
---|
1307 | } \
|
---|
1308 | if (_a && _a->value_ctr.num_values >= 1 \
|
---|
1309 | && _a->value_ctr.values[0].blob \
|
---|
1310 | && _a->value_ctr.values[0].blob->length == 4) { \
|
---|
1311 | (p)->elem = (IVAL(_a->value_ctr.values[0].blob->data,0)?true:false);\
|
---|
1312 | } else { \
|
---|
1313 | (p)->elem = false; \
|
---|
1314 | } \
|
---|
1315 | } while (0)
|
---|
1316 |
|
---|
1317 | #define GET_UINT32_DS(s, r, attr, p, elem) do { \
|
---|
1318 | struct drsuapi_DsReplicaAttribute *_a; \
|
---|
1319 | _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
|
---|
1320 | if (_a && _a->value_ctr.num_values >= 1 \
|
---|
1321 | && _a->value_ctr.values[0].blob \
|
---|
1322 | && _a->value_ctr.values[0].blob->length == 4) { \
|
---|
1323 | (p)->elem = IVAL(_a->value_ctr.values[0].blob->data,0);\
|
---|
1324 | } else { \
|
---|
1325 | (p)->elem = 0; \
|
---|
1326 | } \
|
---|
1327 | } while (0)
|
---|
1328 |
|
---|
1329 | #define GET_UINT32_PTR_DS(s, r, attr, p, elem) do { \
|
---|
1330 | struct drsuapi_DsReplicaAttribute *_a; \
|
---|
1331 | _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
|
---|
1332 | if (_a && _a->value_ctr.num_values >= 1 \
|
---|
1333 | && _a->value_ctr.values[0].blob \
|
---|
1334 | && _a->value_ctr.values[0].blob->length == 4) { \
|
---|
1335 | (p)->elem = talloc(mem_ctx, uint32_t); \
|
---|
1336 | if (!(p)->elem) { \
|
---|
1337 | d_printf("%s: talloc failed for %s\n", __location__, attr); \
|
---|
1338 | return WERR_NOMEM; \
|
---|
1339 | } \
|
---|
1340 | *(p)->elem = IVAL(_a->value_ctr.values[0].blob->data,0);\
|
---|
1341 | } else { \
|
---|
1342 | (p)->elem = NULL; \
|
---|
1343 | } \
|
---|
1344 | } while (0)
|
---|
1345 |
|
---|
1346 | #define GET_GUID_DS(s, r, attr, mem_ctx, p, elem) do { \
|
---|
1347 | struct drsuapi_DsReplicaAttribute *_a; \
|
---|
1348 | _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
|
---|
1349 | if (_a && _a->value_ctr.num_values >= 1 \
|
---|
1350 | && _a->value_ctr.values[0].blob \
|
---|
1351 | && _a->value_ctr.values[0].blob->length == 16) { \
|
---|
1352 | enum ndr_err_code _ndr_err; \
|
---|
1353 | _ndr_err = ndr_pull_struct_blob_all(_a->value_ctr.values[0].blob, \
|
---|
1354 | mem_ctx, s->iconv_convenience, &(p)->elem, \
|
---|
1355 | (ndr_pull_flags_fn_t)ndr_pull_GUID); \
|
---|
1356 | if (!NDR_ERR_CODE_IS_SUCCESS(_ndr_err)) { \
|
---|
1357 | NTSTATUS _nt_status = ndr_map_error2ntstatus(_ndr_err); \
|
---|
1358 | return ntstatus_to_werror(_nt_status); \
|
---|
1359 | } \
|
---|
1360 | } else { \
|
---|
1361 | ZERO_STRUCT((p)->elem);\
|
---|
1362 | } \
|
---|
1363 | } while (0)
|
---|
1364 |
|
---|
1365 | #define GET_BLOB_DS(s, r, attr, mem_ctx, p, elem) do { \
|
---|
1366 | struct drsuapi_DsReplicaAttribute *_a; \
|
---|
1367 | _a = dsdb_find_object_attr_name(s, r, attr, NULL); \
|
---|
1368 | if (_a && _a->value_ctr.num_values >= 1 \
|
---|
1369 | && _a->value_ctr.values[0].blob) { \
|
---|
1370 | (p)->elem = *_a->value_ctr.values[0].blob;\
|
---|
1371 | talloc_steal(mem_ctx, (p)->elem.data); \
|
---|
1372 | } else { \
|
---|
1373 | ZERO_STRUCT((p)->elem);\
|
---|
1374 | }\
|
---|
1375 | } while (0)
|
---|
1376 |
|
---|
1377 | WERROR dsdb_attribute_from_drsuapi(struct ldb_context *ldb,
|
---|
1378 | struct dsdb_schema *schema,
|
---|
1379 | struct drsuapi_DsReplicaObject *r,
|
---|
1380 | TALLOC_CTX *mem_ctx,
|
---|
1381 | struct dsdb_attribute *attr)
|
---|
1382 | {
|
---|
1383 | WERROR status;
|
---|
1384 |
|
---|
1385 | GET_STRING_DS(schema, r, "name", mem_ctx, attr, cn, true);
|
---|
1386 | GET_STRING_DS(schema, r, "lDAPDisplayName", mem_ctx, attr, lDAPDisplayName, true);
|
---|
1387 | GET_UINT32_DS(schema, r, "attributeID", attr, attributeID_id);
|
---|
1388 | status = dsdb_map_int2oid(schema, attr->attributeID_id, mem_ctx, &attr->attributeID_oid);
|
---|
1389 | if (!W_ERROR_IS_OK(status)) {
|
---|
1390 | DEBUG(0,("%s: '%s': unable to map attributeID 0x%08X: %s\n",
|
---|
1391 | __location__, attr->lDAPDisplayName, attr->attributeID_id,
|
---|
1392 | win_errstr(status)));
|
---|
1393 | return status;
|
---|
1394 | }
|
---|
1395 | GET_GUID_DS(schema, r, "schemaIDGUID", mem_ctx, attr, schemaIDGUID);
|
---|
1396 | GET_UINT32_DS(schema, r, "mAPIID", attr, mAPIID);
|
---|
1397 |
|
---|
1398 | GET_GUID_DS(schema, r, "attributeSecurityGUID", mem_ctx, attr, attributeSecurityGUID);
|
---|
1399 |
|
---|
1400 | GET_UINT32_DS(schema, r, "searchFlags", attr, searchFlags);
|
---|
1401 | GET_UINT32_DS(schema, r, "systemFlags", attr, systemFlags);
|
---|
1402 | GET_BOOL_DS(schema, r, "isMemberOfPartialAttributeSet", attr, isMemberOfPartialAttributeSet, false);
|
---|
1403 | GET_UINT32_DS(schema, r, "linkID", attr, linkID);
|
---|
1404 |
|
---|
1405 | GET_UINT32_DS(schema, r, "attributeSyntax", attr, attributeSyntax_id);
|
---|
1406 | status = dsdb_map_int2oid(schema, attr->attributeSyntax_id, mem_ctx, &attr->attributeSyntax_oid);
|
---|
1407 | if (!W_ERROR_IS_OK(status)) {
|
---|
1408 | DEBUG(0,("%s: '%s': unable to map attributeSyntax 0x%08X: %s\n",
|
---|
1409 | __location__, attr->lDAPDisplayName, attr->attributeSyntax_id,
|
---|
1410 | win_errstr(status)));
|
---|
1411 | return status;
|
---|
1412 | }
|
---|
1413 | GET_UINT32_DS(schema, r, "oMSyntax", attr, oMSyntax);
|
---|
1414 | GET_BLOB_DS(schema, r, "oMObjectClass", mem_ctx, attr, oMObjectClass);
|
---|
1415 |
|
---|
1416 | GET_BOOL_DS(schema, r, "isSingleValued", attr, isSingleValued, true);
|
---|
1417 | GET_UINT32_PTR_DS(schema, r, "rangeLower", attr, rangeLower);
|
---|
1418 | GET_UINT32_PTR_DS(schema, r, "rangeUpper", attr, rangeUpper);
|
---|
1419 | GET_BOOL_DS(schema, r, "extendedCharsAllowed", attr, extendedCharsAllowed, false);
|
---|
1420 |
|
---|
1421 | GET_UINT32_DS(schema, r, "schemaFlagsEx", attr, schemaFlagsEx);
|
---|
1422 | GET_BLOB_DS(schema, r, "msDs-Schema-Extensions", mem_ctx, attr, msDs_Schema_Extensions);
|
---|
1423 |
|
---|
1424 | GET_BOOL_DS(schema, r, "showInAdvancedViewOnly", attr, showInAdvancedViewOnly, false);
|
---|
1425 | GET_STRING_DS(schema, r, "adminDisplayName", mem_ctx, attr, adminDisplayName, false);
|
---|
1426 | GET_STRING_DS(schema, r, "adminDescription", mem_ctx, attr, adminDescription, false);
|
---|
1427 | GET_STRING_DS(schema, r, "classDisplayName", mem_ctx, attr, classDisplayName, false);
|
---|
1428 | GET_BOOL_DS(schema, r, "isEphemeral", attr, isEphemeral, false);
|
---|
1429 | GET_BOOL_DS(schema, r, "isDefunct", attr, isDefunct, false);
|
---|
1430 | GET_BOOL_DS(schema, r, "systemOnly", attr, systemOnly, false);
|
---|
1431 |
|
---|
1432 | attr->syntax = dsdb_syntax_for_attribute(attr);
|
---|
1433 | if (!attr->syntax) {
|
---|
1434 | return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
|
---|
1435 | }
|
---|
1436 |
|
---|
1437 | if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
|
---|
1438 | return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
|
---|
1439 | }
|
---|
1440 |
|
---|
1441 | return WERR_OK;
|
---|
1442 | }
|
---|
1443 |
|
---|
1444 | WERROR dsdb_class_from_drsuapi(struct dsdb_schema *schema,
|
---|
1445 | struct drsuapi_DsReplicaObject *r,
|
---|
1446 | TALLOC_CTX *mem_ctx,
|
---|
1447 | struct dsdb_class *obj)
|
---|
1448 | {
|
---|
1449 | WERROR status;
|
---|
1450 |
|
---|
1451 | GET_STRING_DS(schema, r, "name", mem_ctx, obj, cn, true);
|
---|
1452 | GET_STRING_DS(schema, r, "lDAPDisplayName", mem_ctx, obj, lDAPDisplayName, true);
|
---|
1453 | GET_UINT32_DS(schema, r, "governsID", obj, governsID_id);
|
---|
1454 | status = dsdb_map_int2oid(schema, obj->governsID_id, mem_ctx, &obj->governsID_oid);
|
---|
1455 | if (!W_ERROR_IS_OK(status)) {
|
---|
1456 | DEBUG(0,("%s: '%s': unable to map governsID 0x%08X: %s\n",
|
---|
1457 | __location__, obj->lDAPDisplayName, obj->governsID_id,
|
---|
1458 | win_errstr(status)));
|
---|
1459 | return status;
|
---|
1460 | }
|
---|
1461 | GET_GUID_DS(schema, r, "schemaIDGUID", mem_ctx, obj, schemaIDGUID);
|
---|
1462 |
|
---|
1463 | GET_UINT32_DS(schema, r, "objectClassCategory", obj, objectClassCategory);
|
---|
1464 | GET_STRING_DS(schema, r, "rDNAttID", mem_ctx, obj, rDNAttID, false);
|
---|
1465 | GET_DN_DS(schema, r, "defaultObjectCategory", mem_ctx, obj, defaultObjectCategory, true);
|
---|
1466 |
|
---|
1467 | GET_UINT32_DS(schema, r, "subClassOf", obj, subClassOf_id);
|
---|
1468 |
|
---|
1469 | GET_UINT32_LIST_DS(schema, r, "systemAuxiliaryClass", mem_ctx, obj, systemAuxiliaryClass_ids);
|
---|
1470 | GET_UINT32_LIST_DS(schema, r, "auxiliaryClass", mem_ctx, obj, auxiliaryClass_ids);
|
---|
1471 |
|
---|
1472 | GET_UINT32_LIST_DS(schema, r, "systemMustContain", mem_ctx, obj, systemMustContain_ids);
|
---|
1473 | GET_UINT32_LIST_DS(schema, r, "systemMayContain", mem_ctx, obj, systemMayContain_ids);
|
---|
1474 | GET_UINT32_LIST_DS(schema, r, "mustContain", mem_ctx, obj, mustContain_ids);
|
---|
1475 | GET_UINT32_LIST_DS(schema, r, "mayContain", mem_ctx, obj, mayContain_ids);
|
---|
1476 |
|
---|
1477 | GET_UINT32_LIST_DS(schema, r, "systemPossSuperiors", mem_ctx, obj, systemPossSuperiors_ids);
|
---|
1478 | GET_UINT32_LIST_DS(schema, r, "possSuperiors", mem_ctx, obj, possSuperiors_ids);
|
---|
1479 |
|
---|
1480 | GET_STRING_DS(schema, r, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, false);
|
---|
1481 |
|
---|
1482 | GET_UINT32_DS(schema, r, "schemaFlagsEx", obj, schemaFlagsEx);
|
---|
1483 | GET_BLOB_DS(schema, r, "msDs-Schema-Extensions", mem_ctx, obj, msDs_Schema_Extensions);
|
---|
1484 |
|
---|
1485 | GET_BOOL_DS(schema, r, "showInAdvancedViewOnly", obj, showInAdvancedViewOnly, false);
|
---|
1486 | GET_STRING_DS(schema, r, "adminDisplayName", mem_ctx, obj, adminDisplayName, false);
|
---|
1487 | GET_STRING_DS(schema, r, "adminDescription", mem_ctx, obj, adminDescription, false);
|
---|
1488 | GET_STRING_DS(schema, r, "classDisplayName", mem_ctx, obj, classDisplayName, false);
|
---|
1489 | GET_BOOL_DS(schema, r, "defaultHidingValue", obj, defaultHidingValue, false);
|
---|
1490 | GET_BOOL_DS(schema, r, "isDefunct", obj, isDefunct, false);
|
---|
1491 | GET_BOOL_DS(schema, r, "systemOnly", obj, systemOnly, false);
|
---|
1492 |
|
---|
1493 | return WERR_OK;
|
---|
1494 | }
|
---|
1495 |
|
---|