Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : DRS::prefixMap implementation
5 :
6 : Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009
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 : #include "includes.h"
23 : #include "dsdb/samdb/samdb.h"
24 : #include "librpc/gen_ndr/ndr_drsuapi.h"
25 : #include "librpc/gen_ndr/ndr_drsblobs.h"
26 : #include "../lib/util/asn1.h"
27 : #include "lib/util/smb_strtox.h"
28 :
29 :
30 : /**
31 : * Determine range type for supplied ATTID
32 : */
33 53526436 : enum dsdb_attid_type dsdb_pfm_get_attid_type(uint32_t attid)
34 : {
35 53526436 : if (attid <= 0x7FFFFFFF) {
36 53524439 : return DSDB_ATTID_TYPE_PFM;
37 : }
38 1997 : else if (attid <= 0xBFFFFFFF) {
39 1997 : return DSDB_ATTID_TYPE_INTID;
40 : }
41 0 : else if (attid <= 0xFFFEFFFF) {
42 0 : return DSDB_ATTID_TYPE_RESERVED;
43 : }
44 : else {
45 0 : return DSDB_ATTID_TYPE_INTERNAL;
46 : }
47 : }
48 :
49 : /**
50 : * Allocates schema_prefixMap object in supplied memory context
51 : */
52 25727 : static struct dsdb_schema_prefixmap *_dsdb_schema_prefixmap_talloc(TALLOC_CTX *mem_ctx,
53 : uint32_t length)
54 : {
55 : struct dsdb_schema_prefixmap *pfm;
56 :
57 25727 : pfm = talloc_zero(mem_ctx, struct dsdb_schema_prefixmap);
58 25727 : if (!pfm) {
59 0 : return NULL;
60 : }
61 :
62 25727 : pfm->length = length;
63 25727 : pfm->prefixes = talloc_zero_array(pfm, struct dsdb_schema_prefixmap_oid,
64 : pfm->length);
65 25727 : if (!pfm->prefixes) {
66 0 : talloc_free(pfm);
67 0 : return NULL;
68 : }
69 :
70 25727 : return pfm;
71 : }
72 :
73 : /**
74 : * Initial prefixMap creation according to:
75 : * [MS-DRSR] section 5.12.2
76 : */
77 0 : WERROR dsdb_schema_pfm_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
78 : {
79 : uint32_t i;
80 : struct dsdb_schema_prefixmap *pfm;
81 : const struct {
82 : uint32_t id;
83 : const char *oid_prefix;
84 0 : } pfm_init_data[] = {
85 : {.id=0x00000000, .oid_prefix="2.5.4"},
86 : {.id=0x00000001, .oid_prefix="2.5.6"},
87 : {.id=0x00000002, .oid_prefix="1.2.840.113556.1.2"},
88 : {.id=0x00000003, .oid_prefix="1.2.840.113556.1.3"},
89 : {.id=0x00000004, .oid_prefix="2.16.840.1.101.2.2.1"},
90 : {.id=0x00000005, .oid_prefix="2.16.840.1.101.2.2.3"},
91 : {.id=0x00000006, .oid_prefix="2.16.840.1.101.2.1.5"},
92 : {.id=0x00000007, .oid_prefix="2.16.840.1.101.2.1.4"},
93 : {.id=0x00000008, .oid_prefix="2.5.5"},
94 : {.id=0x00000009, .oid_prefix="1.2.840.113556.1.4"},
95 : {.id=0x0000000A, .oid_prefix="1.2.840.113556.1.5"},
96 : {.id=0x00000013, .oid_prefix="0.9.2342.19200300.100"},
97 : {.id=0x00000014, .oid_prefix="2.16.840.1.113730.3"},
98 : {.id=0x00000015, .oid_prefix="0.9.2342.19200300.100.1"},
99 : {.id=0x00000016, .oid_prefix="2.16.840.1.113730.3.1"},
100 : {.id=0x00000017, .oid_prefix="1.2.840.113556.1.5.7000"},
101 : {.id=0x00000018, .oid_prefix="2.5.21"},
102 : {.id=0x00000019, .oid_prefix="2.5.18"},
103 : {.id=0x0000001A, .oid_prefix="2.5.20"},
104 : };
105 :
106 : /* allocate mem for prefix map */
107 0 : pfm = _dsdb_schema_prefixmap_talloc(mem_ctx, ARRAY_SIZE(pfm_init_data));
108 0 : W_ERROR_HAVE_NO_MEMORY(pfm);
109 :
110 : /* build prefixes */
111 0 : for (i = 0; i < pfm->length; i++) {
112 0 : if (!ber_write_partial_OID_String(pfm, &pfm->prefixes[i].bin_oid, pfm_init_data[i].oid_prefix)) {
113 0 : talloc_free(pfm);
114 0 : return WERR_INTERNAL_ERROR;
115 : }
116 0 : pfm->prefixes[i].id = pfm_init_data[i].id;
117 : }
118 :
119 0 : *_pfm = pfm;
120 :
121 0 : return WERR_OK;
122 : }
123 :
124 :
125 62 : struct dsdb_schema_prefixmap *dsdb_schema_pfm_copy_shallow(TALLOC_CTX *mem_ctx,
126 : const struct dsdb_schema_prefixmap *pfm)
127 : {
128 : uint32_t i;
129 : struct dsdb_schema_prefixmap *pfm_copy;
130 :
131 62 : pfm_copy = _dsdb_schema_prefixmap_talloc(mem_ctx, pfm->length);
132 62 : if (!pfm_copy) {
133 0 : return NULL;
134 : }
135 3687 : for (i = 0; i < pfm_copy->length; i++) {
136 3625 : pfm_copy->prefixes[i] = pfm->prefixes[i];
137 : }
138 :
139 62 : return pfm_copy;
140 : }
141 :
142 : /**
143 : * Adds oid to prefix map.
144 : * On success returns ID for newly added index
145 : * or ID of existing entry that matches oid
146 : * Reference: [MS-DRSR] section 5.12.2
147 : *
148 : * \param pfm prefixMap
149 : * \param bin_oid OID prefix to be added to prefixMap
150 : * \param pfm_id Location where to store prefixMap entry ID
151 : */
152 550 : WERROR dsdb_schema_pfm_add_entry(struct dsdb_schema_prefixmap *pfm,
153 : DATA_BLOB bin_oid,
154 : const uint32_t *remote_id,
155 : uint32_t *_idx)
156 : {
157 : uint32_t i;
158 : struct dsdb_schema_prefixmap_oid * pfm_entry;
159 : struct dsdb_schema_prefixmap_oid * prefixes_new;
160 :
161 : /* dup memory for bin-oid prefix to be added */
162 550 : bin_oid = data_blob_dup_talloc(pfm, bin_oid);
163 550 : W_ERROR_HAVE_NO_MEMORY(bin_oid.data);
164 :
165 : /* make room for new entry */
166 550 : prefixes_new = talloc_realloc(pfm, pfm->prefixes, struct dsdb_schema_prefixmap_oid, pfm->length + 1);
167 550 : if (!prefixes_new) {
168 0 : talloc_free(bin_oid.data);
169 0 : return WERR_NOT_ENOUGH_MEMORY;
170 : }
171 550 : pfm->prefixes = prefixes_new;
172 :
173 : /* make new unique ID in prefixMap */
174 550 : pfm_entry = &pfm->prefixes[pfm->length];
175 550 : pfm_entry->id = 0;
176 31924 : for (i = 0; i < pfm->length; i++) {
177 31374 : if (pfm_entry->id < pfm->prefixes[i].id) {
178 26424 : pfm_entry->id = pfm->prefixes[i].id;
179 : }
180 :
181 31374 : if (remote_id == NULL) {
182 23384 : continue;
183 : }
184 :
185 7990 : if (pfm->prefixes[i].id == *remote_id) {
186 : /*
187 : * We can't use the remote id.
188 : * it's already in use.
189 : */
190 0 : remote_id = NULL;
191 : }
192 : }
193 :
194 : /* add new bin-oid prefix */
195 550 : if (remote_id != NULL) {
196 140 : pfm_entry->id = *remote_id;
197 : } else {
198 410 : pfm_entry->id++;
199 : }
200 550 : pfm_entry->bin_oid = bin_oid;
201 :
202 550 : if (_idx != NULL) {
203 410 : *_idx = pfm->length;
204 : }
205 550 : pfm->length++;
206 :
207 550 : return WERR_OK;
208 : }
209 :
210 :
211 : /**
212 : * Make partial binary OID for supplied OID.
213 : * Reference: [MS-DRSR] section 5.12.2
214 : */
215 71443955 : static WERROR _dsdb_pfm_make_binary_oid(const char *full_oid, TALLOC_CTX *mem_ctx,
216 : DATA_BLOB *_bin_oid, uint32_t *_last_subid)
217 : {
218 : uint32_t last_subid;
219 : const char *oid_subid;
220 71443955 : int error = 0;
221 :
222 : /* make last sub-identifier value */
223 71443955 : oid_subid = strrchr(full_oid, '.');
224 71443955 : if (!oid_subid) {
225 0 : return WERR_INVALID_PARAMETER;
226 : }
227 71443955 : oid_subid++;
228 71443955 : last_subid = smb_strtoul(oid_subid, NULL, 10, &error, SMB_STR_STANDARD);
229 71443955 : if (error != 0) {
230 0 : return WERR_INVALID_PARAMETER;
231 : }
232 :
233 : /* encode oid in BER format */
234 71443955 : if (!ber_write_OID_String(mem_ctx, _bin_oid, full_oid)) {
235 0 : DEBUG(0,("ber_write_OID_String() failed for %s\n", full_oid));
236 0 : return WERR_INTERNAL_ERROR;
237 : }
238 :
239 : /* get the prefix of the OID */
240 71443955 : if (last_subid < 128) {
241 41376604 : _bin_oid->length -= 1;
242 : } else {
243 30067351 : _bin_oid->length -= 2;
244 : }
245 :
246 : /* return last_value if requested */
247 71443955 : if (_last_subid) {
248 71315774 : *_last_subid = last_subid;
249 : }
250 :
251 71443955 : return WERR_OK;
252 : }
253 :
254 : /**
255 : * Lookup partial-binary-oid in prefixMap
256 : */
257 71457125 : WERROR dsdb_schema_pfm_find_binary_oid(const struct dsdb_schema_prefixmap *pfm,
258 : DATA_BLOB bin_oid,
259 : uint32_t *_idx)
260 : {
261 : uint32_t i;
262 :
263 726888777 : for (i = 0; i < pfm->length; i++) {
264 726887547 : if (pfm->prefixes[i].bin_oid.length != bin_oid.length) {
265 394840771 : continue;
266 : }
267 :
268 332046776 : if (memcmp(pfm->prefixes[i].bin_oid.data, bin_oid.data, bin_oid.length) == 0) {
269 71455895 : if (_idx) {
270 71328534 : *_idx = i;
271 : }
272 71455895 : return WERR_OK;
273 : }
274 : }
275 :
276 1230 : return WERR_NOT_FOUND;
277 : }
278 :
279 : /**
280 : * Lookup full-oid in prefixMap
281 : * Note: this may be slow.
282 : */
283 128181 : WERROR dsdb_schema_pfm_find_oid(const struct dsdb_schema_prefixmap *pfm,
284 : const char *full_oid,
285 : uint32_t *_idx)
286 : {
287 : WERROR werr;
288 : DATA_BLOB bin_oid;
289 :
290 128181 : ZERO_STRUCT(bin_oid);
291 :
292 : /* make partial-binary-oid to look for */
293 128181 : werr = _dsdb_pfm_make_binary_oid(full_oid, NULL, &bin_oid, NULL);
294 128181 : W_ERROR_NOT_OK_RETURN(werr);
295 :
296 : /* lookup the partial-oid */
297 128181 : werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, _idx);
298 :
299 128181 : data_blob_free(&bin_oid);
300 :
301 128181 : return werr;
302 : }
303 :
304 : /**
305 : * Make ATTID for given OID
306 : * If OID is not in prefixMap, new prefix
307 : * may be added depending on 'can_change_pfm' flag
308 : * Reference: [MS-DRSR] section 5.12.2
309 : */
310 71315774 : static WERROR dsdb_schema_pfm_make_attid_impl(struct dsdb_schema_prefixmap *pfm,
311 : const char *oid,
312 : bool can_change_pfm,
313 : uint32_t *attid)
314 : {
315 : WERROR werr;
316 : uint32_t idx;
317 : uint32_t lo_word, hi_word;
318 : uint32_t last_subid;
319 : DATA_BLOB bin_oid;
320 :
321 71315774 : if (!pfm) {
322 0 : return WERR_INVALID_PARAMETER;
323 : }
324 71315774 : if (!oid) {
325 0 : return WERR_INVALID_PARAMETER;
326 : }
327 :
328 71315774 : werr = _dsdb_pfm_make_binary_oid(oid, pfm, &bin_oid, &last_subid);
329 71315774 : W_ERROR_NOT_OK_RETURN(werr);
330 :
331 : /* search the prefix in the prefix table, if none found, add
332 : * one entry for new prefix.
333 : */
334 71315774 : werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx);
335 71315774 : if (W_ERROR_IS_OK(werr)) {
336 : /* free memory allocated for bin_oid */
337 71315364 : data_blob_free(&bin_oid);
338 : } else {
339 : /* return error in read-only mode */
340 410 : if (!can_change_pfm) {
341 0 : DEBUG(0, ("Unable to convert %s to an attid, and can_change_pfm=false!\n", oid));
342 0 : return werr;
343 : }
344 :
345 : /* entry does not exists, add it */
346 410 : werr = dsdb_schema_pfm_add_entry(pfm, bin_oid, NULL, &idx);
347 410 : W_ERROR_NOT_OK_RETURN(werr);
348 : }
349 :
350 : /* compose the attid */
351 71315774 : lo_word = last_subid % 16384; /* actually get lower 14 bits: lo_word & 0x3FFF */
352 71315774 : if (last_subid >= 16384) {
353 : /* mark it so that it is known to not be the whole lastValue
354 : * This will raise 16-th bit*/
355 331205 : lo_word += 32768;
356 : }
357 71315774 : hi_word = pfm->prefixes[idx].id;
358 :
359 : /* make ATTID:
360 : * HIWORD is prefixMap id
361 : * LOWORD is truncated binary-oid */
362 71315774 : *attid = (hi_word * 65536) + lo_word;
363 :
364 71315774 : return WERR_OK;
365 : }
366 :
367 : /**
368 : * Make ATTID for given OID
369 : * Reference: [MS-DRSR] section 5.12.2
370 : *
371 : * Note: This function may change prefixMap if prefix
372 : * for supplied 'oid' doesn't exists yet.
373 : * It is recommended to be used mostly when caller
374 : * want to add new prefixes.
375 : * Otherwise dsdb_schema_pfm_attid_from_oid() should be used.
376 : */
377 410 : WERROR dsdb_schema_pfm_make_attid(struct dsdb_schema_prefixmap *pfm,
378 : const char *oid,
379 : uint32_t *attid)
380 : {
381 410 : return dsdb_schema_pfm_make_attid_impl(pfm, oid, true, attid);
382 : }
383 :
384 : /**
385 : * Make ATTID for given OID
386 : * Reference: [MS-DRSR] section 5.12.2
387 : */
388 71315364 : WERROR dsdb_schema_pfm_attid_from_oid(struct dsdb_schema_prefixmap *pfm,
389 : const char *oid,
390 : uint32_t *attid)
391 : {
392 71315364 : return dsdb_schema_pfm_make_attid_impl(pfm, oid, false, attid);
393 : }
394 :
395 : /**
396 : * Make OID for given ATTID.
397 : * Reference: [MS-DRSR] section 5.12.2
398 : */
399 11405917 : WERROR dsdb_schema_pfm_oid_from_attid(const struct dsdb_schema_prefixmap *pfm,
400 : uint32_t attid,
401 : TALLOC_CTX *mem_ctx, const char **_oid)
402 : {
403 : uint32_t i;
404 : uint32_t hi_word, lo_word;
405 11405917 : DATA_BLOB bin_oid = {NULL, 0};
406 : char *oid;
407 : struct dsdb_schema_prefixmap_oid *pfm_entry;
408 11405917 : WERROR werr = WERR_OK;
409 :
410 : /* sanity check for attid requested */
411 11405917 : if (dsdb_pfm_get_attid_type(attid) != DSDB_ATTID_TYPE_PFM) {
412 0 : return WERR_INVALID_PARAMETER;
413 : }
414 :
415 : /* crack attid value */
416 11405917 : hi_word = attid >> 16;
417 11405917 : lo_word = attid & 0xFFFF;
418 :
419 : /* locate corRespoNding prefixMap entry */
420 11405917 : pfm_entry = NULL;
421 73536195 : for (i = 0; i < pfm->length; i++) {
422 73536195 : if (hi_word == pfm->prefixes[i].id) {
423 11405917 : pfm_entry = &pfm->prefixes[i];
424 11405917 : break;
425 : }
426 : }
427 :
428 11405917 : if (!pfm_entry) {
429 0 : DEBUG(1,("Failed to find prefixMap entry for ATTID = 0x%08X (%d)\n",
430 : attid, attid));
431 0 : return WERR_DS_NO_ATTRIBUTE_OR_VALUE;
432 : }
433 :
434 : /* copy oid prefix making enough room */
435 11405917 : bin_oid.length = pfm_entry->bin_oid.length + 2;
436 11405917 : bin_oid.data = talloc_array(mem_ctx, uint8_t, bin_oid.length);
437 11405917 : W_ERROR_HAVE_NO_MEMORY(bin_oid.data);
438 11405917 : memcpy(bin_oid.data, pfm_entry->bin_oid.data, pfm_entry->bin_oid.length);
439 :
440 11405917 : if (lo_word < 128) {
441 5431533 : bin_oid.length = bin_oid.length - 1;
442 5431533 : bin_oid.data[bin_oid.length-1] = lo_word;
443 : }
444 : else {
445 5974384 : if (lo_word >= 32768) {
446 656 : lo_word -= 32768;
447 : }
448 5974384 : bin_oid.data[bin_oid.length-2] = (0x80 | ((lo_word>>7) & 0x7f));
449 5974384 : bin_oid.data[bin_oid.length-1] = lo_word & 0x7f;
450 : }
451 :
452 11405917 : if (!ber_read_OID_String(mem_ctx, bin_oid, &oid)) {
453 0 : DEBUG(0,("ber_read_OID_String() failed for %s\n",
454 : hex_encode_talloc(bin_oid.data, bin_oid.data, bin_oid.length)));
455 0 : werr = WERR_INTERNAL_ERROR;
456 : }
457 :
458 : /* free locally allocated memory */
459 11405917 : talloc_free(bin_oid.data);
460 :
461 11405917 : *_oid = oid;
462 :
463 11405917 : return werr;
464 : }
465 :
466 :
467 : /**
468 : * Verifies drsuapi mappings.
469 : */
470 30515 : static WERROR _dsdb_drsuapi_pfm_verify(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
471 : bool have_schema_info)
472 : {
473 : uint32_t i;
474 : uint32_t num_mappings;
475 : struct drsuapi_DsReplicaOIDMapping *mapping;
476 :
477 : /* check input params */
478 30515 : if (!ctr) {
479 0 : return WERR_INVALID_PARAMETER;
480 : }
481 30515 : if (!ctr->mappings) {
482 4544 : return WERR_INVALID_PARAMETER;
483 : }
484 25971 : num_mappings = ctr->num_mappings;
485 :
486 25971 : if (have_schema_info) {
487 : DATA_BLOB blob;
488 :
489 5949 : if (ctr->num_mappings < 2) {
490 0 : return WERR_INVALID_PARAMETER;
491 : }
492 :
493 : /* check last entry for being special */
494 5949 : mapping = &ctr->mappings[ctr->num_mappings - 1];
495 5949 : if (mapping->id_prefix != 0) {
496 0 : return WERR_INVALID_PARAMETER;
497 : }
498 :
499 : /* verify schemaInfo blob is valid one */
500 5949 : blob = data_blob_const(mapping->oid.binary_oid, mapping->oid.length);
501 5949 : if (!dsdb_schema_info_blob_is_valid(&blob)) {
502 0 : return WERR_INVALID_PARAMETER;
503 : }
504 :
505 : /* get number of read mappings in the map */
506 5949 : num_mappings--;
507 : }
508 :
509 : /* now, verify rest of entries for being at least not null */
510 1482865 : for (i = 0; i < num_mappings; i++) {
511 1456894 : mapping = &ctr->mappings[i];
512 1456894 : if (!mapping->oid.length) {
513 0 : return WERR_INVALID_PARAMETER;
514 : }
515 1456894 : if (!mapping->oid.binary_oid) {
516 0 : return WERR_INVALID_PARAMETER;
517 : }
518 : /* check it is not the special entry */
519 1456894 : if (*mapping->oid.binary_oid == 0xFF) {
520 0 : return WERR_INVALID_PARAMETER;
521 : }
522 : }
523 :
524 25971 : return WERR_OK;
525 : }
526 :
527 : /**
528 : * Convert drsuapi_ prefix map to prefixMap internal presentation.
529 : *
530 : * \param ctr Pointer to drsuapi_DsReplicaOIDMapping_Ctr which represents drsuapi_ prefixMap
531 : * \param have_schema_info if drsuapi_prefixMap have schem_info in it or not
532 : * \param mem_ctx TALLOC_CTX to make allocations in
533 : * \param _pfm Out pointer to hold newly created prefixMap
534 : * \param _schema_info Out param to store schema_info to. If NULL, schema_info is not decoded
535 : */
536 30209 : WERROR dsdb_schema_pfm_from_drsuapi_pfm(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
537 : bool have_schema_info,
538 : TALLOC_CTX *mem_ctx,
539 : struct dsdb_schema_prefixmap **_pfm,
540 : struct dsdb_schema_info **_schema_info)
541 : {
542 : WERROR werr;
543 : uint32_t i;
544 : DATA_BLOB blob;
545 : uint32_t num_mappings;
546 : struct dsdb_schema_prefixmap *pfm;
547 :
548 30209 : if (!_pfm) {
549 0 : return WERR_INVALID_PARAMETER;
550 : }
551 :
552 : /*
553 : * error out if schema_info is requested
554 : * but it is not in the drsuapi_prefixMap
555 : */
556 30209 : if (_schema_info && !have_schema_info) {
557 0 : return WERR_INVALID_PARAMETER;
558 : }
559 :
560 : /* verify drsuapi_pefixMap */
561 30209 : werr =_dsdb_drsuapi_pfm_verify(ctr, have_schema_info);
562 30209 : W_ERROR_NOT_OK_RETURN(werr);
563 :
564 : /* allocate mem for prefix map */
565 25665 : num_mappings = ctr->num_mappings;
566 25665 : if (have_schema_info) {
567 5643 : num_mappings--;
568 : }
569 25665 : pfm = _dsdb_schema_prefixmap_talloc(mem_ctx, num_mappings);
570 25665 : W_ERROR_HAVE_NO_MEMORY(pfm);
571 :
572 : /* copy entries from drsuapi_prefixMap */
573 1469389 : for (i = 0; i < pfm->length; i++) {
574 1443724 : blob = data_blob_talloc(pfm,
575 : ctr->mappings[i].oid.binary_oid,
576 : ctr->mappings[i].oid.length);
577 1443724 : if (!blob.data) {
578 0 : talloc_free(pfm);
579 0 : return WERR_NOT_ENOUGH_MEMORY;
580 : }
581 1443724 : pfm->prefixes[i].id = ctr->mappings[i].id_prefix;
582 1443724 : pfm->prefixes[i].bin_oid = blob;
583 : }
584 :
585 : /* fetch schema_info if requested */
586 25665 : if (_schema_info) {
587 : /* by this time, i should have this value,
588 : * but set it here for clarity */
589 76 : i = ctr->num_mappings - 1;
590 :
591 76 : blob = data_blob_const(ctr->mappings[i].oid.binary_oid,
592 76 : ctr->mappings[i].oid.length);
593 76 : werr = dsdb_schema_info_from_blob(&blob, mem_ctx, _schema_info);
594 76 : if (!W_ERROR_IS_OK(werr)) {
595 0 : talloc_free(pfm);
596 0 : return werr;
597 : }
598 : }
599 :
600 : /* schema_prefixMap created successfully */
601 25665 : *_pfm = pfm;
602 :
603 25665 : return WERR_OK;
604 : }
605 :
606 : /**
607 : * Convert drsuapi_ prefix map to prefixMap internal presentation.
608 : *
609 : * \param pfm Schema prefixMap to be converted
610 : * \param schema_info schema_info string - if NULL, we don't need it
611 : * \param mem_ctx TALLOC_CTX to make allocations in
612 : * \param _ctr Out pointer to drsuapi_DsReplicaOIDMapping_Ctr prefix map structure
613 : */
614 8061 : WERROR dsdb_drsuapi_pfm_from_schema_pfm(const struct dsdb_schema_prefixmap *pfm,
615 : const struct dsdb_schema_info *schema_info,
616 : TALLOC_CTX *mem_ctx,
617 : struct drsuapi_DsReplicaOIDMapping_Ctr **_ctr)
618 : {
619 : uint32_t i;
620 : DATA_BLOB blob;
621 : struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
622 :
623 8061 : if (!_ctr) {
624 0 : return WERR_INVALID_PARAMETER;
625 : }
626 8061 : if (!pfm) {
627 0 : return WERR_INVALID_PARAMETER;
628 : }
629 8061 : if (pfm->length == 0) {
630 0 : return WERR_INVALID_PARAMETER;
631 : }
632 :
633 : /* allocate memory for the structure */
634 8061 : ctr = talloc_zero(mem_ctx, struct drsuapi_DsReplicaOIDMapping_Ctr);
635 8061 : W_ERROR_HAVE_NO_MEMORY(ctr);
636 :
637 8061 : ctr->num_mappings = (schema_info ? pfm->length + 1 : pfm->length);
638 8061 : ctr->mappings = talloc_array(ctr, struct drsuapi_DsReplicaOIDMapping, ctr->num_mappings);
639 8061 : if (!ctr->mappings) {
640 0 : talloc_free(ctr);
641 0 : return WERR_NOT_ENOUGH_MEMORY;
642 : }
643 :
644 : /* copy entries from schema_prefixMap */
645 400292 : for (i = 0; i < pfm->length; i++) {
646 392231 : blob = data_blob_dup_talloc(ctr, pfm->prefixes[i].bin_oid);
647 392231 : if (!blob.data) {
648 0 : talloc_free(ctr);
649 0 : return WERR_NOT_ENOUGH_MEMORY;
650 : }
651 392231 : ctr->mappings[i].id_prefix = pfm->prefixes[i].id;
652 392231 : ctr->mappings[i].oid.length = blob.length;
653 392231 : ctr->mappings[i].oid.binary_oid = blob.data;
654 : }
655 :
656 : /* make schema_info entry if needed */
657 8061 : if (schema_info) {
658 : WERROR werr;
659 :
660 : /* by this time, i should have this value,
661 : * but set it here for clarity */
662 7513 : i = ctr->num_mappings - 1;
663 :
664 7513 : werr = dsdb_blob_from_schema_info(schema_info, ctr, &blob);
665 7513 : if (!W_ERROR_IS_OK(werr)) {
666 0 : talloc_free(ctr);
667 0 : return werr;
668 : }
669 :
670 7513 : ctr->mappings[i].id_prefix = 0;
671 7513 : ctr->mappings[i].oid.length = blob.length;
672 7513 : ctr->mappings[i].oid.binary_oid = blob.data;
673 : }
674 :
675 : /* drsuapi_prefixMap constructed successfully */
676 8061 : *_ctr = ctr;
677 :
678 8061 : return WERR_OK;
679 : }
680 :
681 : /**
682 : * Verifies schema prefixMap and drsuapi prefixMap are same.
683 : * Note that we just need to verify pfm contains prefixes
684 : * from ctr, not that those prefixes has same id_prefix.
685 : */
686 306 : WERROR dsdb_schema_pfm_contains_drsuapi_pfm(const struct dsdb_schema_prefixmap *pfm,
687 : const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
688 : {
689 : WERROR werr;
690 : uint32_t i;
691 : uint32_t idx;
692 : DATA_BLOB bin_oid;
693 :
694 : /* verify drsuapi_pefixMap */
695 306 : werr = _dsdb_drsuapi_pfm_verify(ctr, true);
696 306 : W_ERROR_NOT_OK_RETURN(werr);
697 :
698 : /* check pfm contains every entry from ctr, except the last one */
699 13476 : for (i = 0; i < ctr->num_mappings - 1; i++) {
700 13170 : bin_oid.length = ctr->mappings[i].oid.length;
701 13170 : bin_oid.data = ctr->mappings[i].oid.binary_oid;
702 :
703 13170 : werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx);
704 13170 : if (!W_ERROR_IS_OK(werr)) {
705 0 : return WERR_DS_DRA_SCHEMA_MISMATCH;
706 : }
707 : }
708 :
709 306 : return WERR_OK;
710 : }
|