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 66057143 : enum dsdb_attid_type dsdb_pfm_get_attid_type(uint32_t attid)
34 : {
35 66057143 : if (attid <= 0x7FFFFFFF) {
36 64494914 : return DSDB_ATTID_TYPE_PFM;
37 : }
38 1899 : else if (attid <= 0xBFFFFFFF) {
39 1893 : return DSDB_ATTID_TYPE_INTID;
40 : }
41 4 : else if (attid <= 0xFFFEFFFF) {
42 0 : return DSDB_ATTID_TYPE_RESERVED;
43 : }
44 : else {
45 2 : return DSDB_ATTID_TYPE_INTERNAL;
46 : }
47 : }
48 :
49 : /**
50 : * Allocates schema_prefixMap object in supplied memory context
51 : */
52 34630 : static struct dsdb_schema_prefixmap *_dsdb_schema_prefixmap_talloc(TALLOC_CTX *mem_ctx,
53 : uint32_t length)
54 : {
55 378 : struct dsdb_schema_prefixmap *pfm;
56 :
57 34630 : pfm = talloc_zero(mem_ctx, struct dsdb_schema_prefixmap);
58 34630 : if (!pfm) {
59 0 : return NULL;
60 : }
61 :
62 34630 : pfm->length = length;
63 34630 : pfm->prefixes = talloc_zero_array(pfm, struct dsdb_schema_prefixmap_oid,
64 : pfm->length);
65 34630 : if (!pfm->prefixes) {
66 0 : talloc_free(pfm);
67 0 : return NULL;
68 : }
69 :
70 34252 : return pfm;
71 : }
72 :
73 : /**
74 : * Initial prefixMap creation according to:
75 : * [MS-DRSR] section 5.12.2
76 : */
77 3 : WERROR dsdb_schema_pfm_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
78 : {
79 3 : uint32_t i;
80 3 : struct dsdb_schema_prefixmap *pfm;
81 3 : const struct {
82 : uint32_t id;
83 : const char *oid_prefix;
84 3 : } 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 3 : pfm = _dsdb_schema_prefixmap_talloc(mem_ctx, ARRAY_SIZE(pfm_init_data));
108 3 : W_ERROR_HAVE_NO_MEMORY(pfm);
109 :
110 : /* build prefixes */
111 60 : for (i = 0; i < pfm->length; i++) {
112 57 : 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 57 : pfm->prefixes[i].id = pfm_init_data[i].id;
117 : }
118 :
119 3 : *_pfm = pfm;
120 :
121 3 : return WERR_OK;
122 : }
123 :
124 :
125 68 : struct dsdb_schema_prefixmap *dsdb_schema_pfm_copy_shallow(TALLOC_CTX *mem_ctx,
126 : const struct dsdb_schema_prefixmap *pfm)
127 : {
128 10 : uint32_t i;
129 10 : struct dsdb_schema_prefixmap *pfm_copy;
130 :
131 68 : pfm_copy = _dsdb_schema_prefixmap_talloc(mem_ctx, pfm->length);
132 68 : if (!pfm_copy) {
133 0 : return NULL;
134 : }
135 3747 : for (i = 0; i < pfm_copy->length; i++) {
136 3679 : pfm_copy->prefixes[i] = pfm->prefixes[i];
137 : }
138 :
139 58 : 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 837 : 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 9 : uint32_t i;
158 9 : struct dsdb_schema_prefixmap_oid * pfm_entry;
159 9 : struct dsdb_schema_prefixmap_oid * prefixes_new;
160 :
161 : /* dup memory for bin-oid prefix to be added */
162 837 : bin_oid = data_blob_dup_talloc(pfm, bin_oid);
163 837 : W_ERROR_HAVE_NO_MEMORY(bin_oid.data);
164 :
165 : /* make room for new entry */
166 837 : prefixes_new = talloc_realloc(pfm, pfm->prefixes, struct dsdb_schema_prefixmap_oid, pfm->length + 1);
167 837 : if (!prefixes_new) {
168 0 : talloc_free(bin_oid.data);
169 0 : return WERR_NOT_ENOUGH_MEMORY;
170 : }
171 837 : pfm->prefixes = prefixes_new;
172 :
173 : /* make new unique ID in prefixMap */
174 837 : pfm_entry = &pfm->prefixes[pfm->length];
175 837 : pfm_entry->id = 0;
176 62659 : for (i = 0; i < pfm->length; i++) {
177 61822 : if (pfm_entry->id < pfm->prefixes[i].id) {
178 54361 : pfm_entry->id = pfm->prefixes[i].id;
179 : }
180 :
181 61822 : if (remote_id == NULL) {
182 53645 : continue;
183 : }
184 :
185 8177 : 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 837 : if (remote_id != NULL) {
196 142 : pfm_entry->id = *remote_id;
197 : } else {
198 695 : pfm_entry->id++;
199 : }
200 837 : pfm_entry->bin_oid = bin_oid;
201 :
202 837 : if (_idx != NULL) {
203 695 : *_idx = pfm->length;
204 : }
205 837 : pfm->length++;
206 :
207 837 : 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 99192865 : 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 1200895 : uint32_t last_subid;
219 1200895 : const char *oid_subid;
220 99192865 : int error = 0;
221 :
222 : /* make last sub-identifier value */
223 99192865 : oid_subid = strrchr(full_oid, '.');
224 99192865 : if (!oid_subid) {
225 0 : return WERR_INVALID_PARAMETER;
226 : }
227 99192865 : oid_subid++;
228 99192865 : last_subid = smb_strtoul(oid_subid, NULL, 10, &error, SMB_STR_STANDARD);
229 99192865 : if (error != 0) {
230 0 : return WERR_INVALID_PARAMETER;
231 : }
232 :
233 : /* encode oid in BER format */
234 99192865 : 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 99192865 : if (last_subid < 128) {
241 57913783 : _bin_oid->length -= 1;
242 : } else {
243 41279082 : _bin_oid->length -= 2;
244 : }
245 :
246 : /* return last_value if requested */
247 99192865 : if (_last_subid) {
248 98974187 : *_last_subid = last_subid;
249 : }
250 :
251 99192865 : return WERR_OK;
252 : }
253 :
254 : /**
255 : * Lookup partial-binary-oid in prefixMap
256 : */
257 99208639 : WERROR dsdb_schema_pfm_find_binary_oid(const struct dsdb_schema_prefixmap *pfm,
258 : DATA_BLOB bin_oid,
259 : uint32_t *_idx)
260 : {
261 1200945 : uint32_t i;
262 :
263 1027483270 : for (i = 0; i < pfm->length; i++) {
264 1027481197 : if (pfm->prefixes[i].bin_oid.length != bin_oid.length) {
265 560711012 : continue;
266 : }
267 :
268 466770185 : if (memcmp(pfm->prefixes[i].bin_oid.data, bin_oid.data, bin_oid.length) == 0) {
269 99206566 : if (_idx) {
270 98989263 : *_idx = i;
271 : }
272 99206566 : return WERR_OK;
273 : }
274 : }
275 :
276 2073 : return WERR_NOT_FOUND;
277 : }
278 :
279 : /**
280 : * Lookup full-oid in prefixMap
281 : * Note: this may be slow.
282 : */
283 218678 : WERROR dsdb_schema_pfm_find_oid(const struct dsdb_schema_prefixmap *pfm,
284 : const char *full_oid,
285 : uint32_t *_idx)
286 : {
287 38906 : WERROR werr;
288 38906 : DATA_BLOB bin_oid;
289 :
290 218678 : ZERO_STRUCT(bin_oid);
291 :
292 : /* make partial-binary-oid to look for */
293 218678 : werr = _dsdb_pfm_make_binary_oid(full_oid, NULL, &bin_oid, NULL);
294 218678 : W_ERROR_NOT_OK_RETURN(werr);
295 :
296 : /* lookup the partial-oid */
297 218678 : werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, _idx);
298 :
299 218678 : data_blob_free(&bin_oid);
300 :
301 218678 : 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 98974187 : 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 1161989 : WERROR werr;
316 1161989 : uint32_t idx;
317 1161989 : uint32_t lo_word, hi_word;
318 1161989 : uint32_t last_subid;
319 1161989 : DATA_BLOB bin_oid;
320 :
321 98974187 : if (!pfm) {
322 0 : return WERR_INVALID_PARAMETER;
323 : }
324 98974187 : if (!oid) {
325 0 : return WERR_INVALID_PARAMETER;
326 : }
327 :
328 98974187 : werr = _dsdb_pfm_make_binary_oid(oid, pfm, &bin_oid, &last_subid);
329 98974187 : 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 98974187 : werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx);
335 98974187 : if (W_ERROR_IS_OK(werr)) {
336 : /* free memory allocated for bin_oid */
337 98973489 : data_blob_free(&bin_oid);
338 : } else {
339 : /* return error in read-only mode */
340 698 : if (!can_change_pfm) {
341 3 : DEBUG(0, ("Unable to convert %s to an attid, and can_change_pfm=false!\n", oid));
342 3 : return werr;
343 : }
344 :
345 : /* entry does not exists, add it */
346 695 : werr = dsdb_schema_pfm_add_entry(pfm, bin_oid, NULL, &idx);
347 695 : W_ERROR_NOT_OK_RETURN(werr);
348 : }
349 :
350 : /* compose the attid */
351 98974184 : lo_word = last_subid % 16384; /* actually get lower 14 bits: lo_word & 0x3FFF */
352 98974184 : 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 446706 : lo_word += 32768;
356 : }
357 98974184 : hi_word = pfm->prefixes[idx].id;
358 :
359 : /* make ATTID:
360 : * HIWORD is prefixMap id
361 : * LOWORD is truncated binary-oid */
362 98974184 : *attid = (hi_word * 65536) + lo_word;
363 :
364 98974184 : 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 722 : WERROR dsdb_schema_pfm_make_attid(struct dsdb_schema_prefixmap *pfm,
378 : const char *oid,
379 : uint32_t *attid)
380 : {
381 722 : 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 98973465 : WERROR dsdb_schema_pfm_attid_from_oid(struct dsdb_schema_prefixmap *pfm,
389 : const char *oid,
390 : uint32_t *attid)
391 : {
392 98973465 : 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 13123724 : 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 99421 : uint32_t i;
404 99421 : uint32_t hi_word, lo_word;
405 13123724 : DATA_BLOB bin_oid = {NULL, 0};
406 99421 : char *oid;
407 99421 : struct dsdb_schema_prefixmap_oid *pfm_entry;
408 13123724 : WERROR werr = WERR_OK;
409 :
410 : /* sanity check for attid requested */
411 13123724 : if (dsdb_pfm_get_attid_type(attid) != DSDB_ATTID_TYPE_PFM) {
412 6 : return WERR_INVALID_PARAMETER;
413 : }
414 :
415 : /* crack attid value */
416 13123718 : hi_word = attid >> 16;
417 13123718 : lo_word = attid & 0xFFFF;
418 :
419 : /* locate corRespoNding prefixMap entry */
420 13123718 : pfm_entry = NULL;
421 84389743 : for (i = 0; i < pfm->length; i++) {
422 84389742 : if (hi_word == pfm->prefixes[i].id) {
423 13024303 : pfm_entry = &pfm->prefixes[i];
424 13024303 : break;
425 : }
426 : }
427 :
428 13123718 : if (!pfm_entry) {
429 1 : DEBUG(1,("Failed to find prefixMap entry for ATTID = 0x%08X (%d)\n",
430 : attid, attid));
431 1 : return WERR_DS_NO_ATTRIBUTE_OR_VALUE;
432 : }
433 :
434 : /* copy oid prefix making enough room */
435 13123717 : bin_oid.length = pfm_entry->bin_oid.length + 2;
436 13123717 : bin_oid.data = talloc_array(mem_ctx, uint8_t, bin_oid.length);
437 13123717 : W_ERROR_HAVE_NO_MEMORY(bin_oid.data);
438 13123717 : memcpy(bin_oid.data, pfm_entry->bin_oid.data, pfm_entry->bin_oid.length);
439 :
440 13123717 : if (lo_word < 128) {
441 6438845 : bin_oid.length = bin_oid.length - 1;
442 6438845 : bin_oid.data[bin_oid.length-1] = lo_word;
443 : }
444 : else {
445 6684872 : if (lo_word >= 32768) {
446 1287 : lo_word -= 32768;
447 : }
448 6684872 : bin_oid.data[bin_oid.length-2] = (0x80 | ((lo_word>>7) & 0x7f));
449 6684872 : bin_oid.data[bin_oid.length-1] = lo_word & 0x7f;
450 : }
451 :
452 13123717 : 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 13123717 : talloc_free(bin_oid.data);
460 :
461 13123717 : *_oid = oid;
462 :
463 13123717 : return werr;
464 : }
465 :
466 :
467 : /**
468 : * Verifies drsuapi mappings.
469 : */
470 42390 : static WERROR _dsdb_drsuapi_pfm_verify(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
471 : bool have_schema_info)
472 : {
473 366 : uint32_t i;
474 366 : uint32_t num_mappings;
475 366 : struct drsuapi_DsReplicaOIDMapping *mapping;
476 :
477 : /* check input params */
478 42390 : if (!ctr) {
479 0 : return WERR_INVALID_PARAMETER;
480 : }
481 42390 : if (!ctr->mappings) {
482 7514 : return WERR_INVALID_PARAMETER;
483 : }
484 34876 : num_mappings = ctr->num_mappings;
485 :
486 34876 : if (have_schema_info) {
487 2 : DATA_BLOB blob;
488 :
489 6060 : if (ctr->num_mappings < 2) {
490 0 : return WERR_INVALID_PARAMETER;
491 : }
492 :
493 : /* check last entry for being special */
494 6060 : mapping = &ctr->mappings[ctr->num_mappings - 1];
495 6060 : if (mapping->id_prefix != 0) {
496 0 : return WERR_INVALID_PARAMETER;
497 : }
498 :
499 : /* verify schemaInfo blob is valid one */
500 6060 : blob = data_blob_const(mapping->oid.binary_oid, mapping->oid.length);
501 6060 : 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 6060 : num_mappings--;
507 : }
508 :
509 : /* now, verify rest of entries for being at least not null */
510 2103012 : for (i = 0; i < num_mappings; i++) {
511 2068136 : mapping = &ctr->mappings[i];
512 2068136 : if (!mapping->oid.length) {
513 0 : return WERR_INVALID_PARAMETER;
514 : }
515 2068136 : if (!mapping->oid.binary_oid) {
516 0 : return WERR_INVALID_PARAMETER;
517 : }
518 : /* check it is not the special entry */
519 2068136 : if (*mapping->oid.binary_oid == 0xFF) {
520 0 : return WERR_INVALID_PARAMETER;
521 : }
522 : }
523 :
524 34876 : 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 42073 : 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 365 : WERROR werr;
543 365 : uint32_t i;
544 365 : DATA_BLOB blob;
545 365 : uint32_t num_mappings;
546 365 : struct dsdb_schema_prefixmap *pfm;
547 :
548 42073 : 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 42073 : if (_schema_info && !have_schema_info) {
557 0 : return WERR_INVALID_PARAMETER;
558 : }
559 :
560 : /* verify drsuapi_pefixMap */
561 42073 : werr =_dsdb_drsuapi_pfm_verify(ctr, have_schema_info);
562 42073 : W_ERROR_NOT_OK_RETURN(werr);
563 :
564 : /* allocate mem for prefix map */
565 34559 : num_mappings = ctr->num_mappings;
566 34559 : if (have_schema_info) {
567 5743 : num_mappings--;
568 : }
569 34559 : pfm = _dsdb_schema_prefixmap_talloc(mem_ctx, num_mappings);
570 34559 : W_ERROR_HAVE_NO_MEMORY(pfm);
571 :
572 : /* copy entries from drsuapi_prefixMap */
573 2086921 : for (i = 0; i < pfm->length; i++) {
574 2052362 : blob = data_blob_talloc(pfm,
575 : ctr->mappings[i].oid.binary_oid,
576 : ctr->mappings[i].oid.length);
577 2052362 : if (!blob.data) {
578 0 : talloc_free(pfm);
579 0 : return WERR_NOT_ENOUGH_MEMORY;
580 : }
581 2052362 : pfm->prefixes[i].id = ctr->mappings[i].id_prefix;
582 2052362 : pfm->prefixes[i].bin_oid = blob;
583 : }
584 :
585 : /* fetch schema_info if requested */
586 34559 : if (_schema_info) {
587 : /* by this time, i should have this value,
588 : * but set it here for clarity */
589 83 : i = ctr->num_mappings - 1;
590 :
591 83 : blob = data_blob_const(ctr->mappings[i].oid.binary_oid,
592 83 : ctr->mappings[i].oid.length);
593 83 : werr = dsdb_schema_info_from_blob(&blob, mem_ctx, _schema_info);
594 83 : if (!W_ERROR_IS_OK(werr)) {
595 0 : talloc_free(pfm);
596 0 : return werr;
597 : }
598 : }
599 :
600 : /* schema_prefixMap created successfully */
601 34559 : *_pfm = pfm;
602 :
603 34559 : 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 11187 : 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 29 : uint32_t i;
620 29 : DATA_BLOB blob;
621 29 : struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
622 :
623 11187 : if (!_ctr) {
624 0 : return WERR_INVALID_PARAMETER;
625 : }
626 11187 : if (!pfm) {
627 0 : return WERR_INVALID_PARAMETER;
628 : }
629 11187 : if (pfm->length == 0) {
630 0 : return WERR_INVALID_PARAMETER;
631 : }
632 :
633 : /* allocate memory for the structure */
634 11187 : ctr = talloc_zero(mem_ctx, struct drsuapi_DsReplicaOIDMapping_Ctr);
635 11187 : W_ERROR_HAVE_NO_MEMORY(ctr);
636 :
637 11187 : ctr->num_mappings = (schema_info ? pfm->length + 1 : pfm->length);
638 11187 : ctr->mappings = talloc_array(ctr, struct drsuapi_DsReplicaOIDMapping, ctr->num_mappings);
639 11187 : if (!ctr->mappings) {
640 0 : talloc_free(ctr);
641 0 : return WERR_NOT_ENOUGH_MEMORY;
642 : }
643 :
644 : /* copy entries from schema_prefixMap */
645 916551 : for (i = 0; i < pfm->length; i++) {
646 905364 : blob = data_blob_dup_talloc(ctr, pfm->prefixes[i].bin_oid);
647 905364 : if (!blob.data) {
648 0 : talloc_free(ctr);
649 0 : return WERR_NOT_ENOUGH_MEMORY;
650 : }
651 905364 : ctr->mappings[i].id_prefix = pfm->prefixes[i].id;
652 905364 : ctr->mappings[i].oid.length = blob.length;
653 905364 : ctr->mappings[i].oid.binary_oid = blob.data;
654 : }
655 :
656 : /* make schema_info entry if needed */
657 11187 : if (schema_info) {
658 1 : WERROR werr;
659 :
660 : /* by this time, i should have this value,
661 : * but set it here for clarity */
662 10310 : i = ctr->num_mappings - 1;
663 :
664 10310 : werr = dsdb_blob_from_schema_info(schema_info, ctr, &blob);
665 10310 : if (!W_ERROR_IS_OK(werr)) {
666 0 : talloc_free(ctr);
667 0 : return werr;
668 : }
669 :
670 10310 : ctr->mappings[i].id_prefix = 0;
671 10310 : ctr->mappings[i].oid.length = blob.length;
672 10310 : ctr->mappings[i].oid.binary_oid = blob.data;
673 : }
674 :
675 : /* drsuapi_prefixMap constructed successfully */
676 11187 : *_ctr = ctr;
677 :
678 11187 : 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 317 : WERROR dsdb_schema_pfm_contains_drsuapi_pfm(const struct dsdb_schema_prefixmap *pfm,
687 : const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
688 : {
689 1 : WERROR werr;
690 1 : uint32_t i;
691 1 : uint32_t idx;
692 1 : DATA_BLOB bin_oid;
693 :
694 : /* verify drsuapi_pefixMap */
695 317 : werr = _dsdb_drsuapi_pfm_verify(ctr, true);
696 317 : W_ERROR_NOT_OK_RETURN(werr);
697 :
698 : /* check pfm contains every entry from ctr, except the last one */
699 16091 : for (i = 0; i < ctr->num_mappings - 1; i++) {
700 15774 : bin_oid.length = ctr->mappings[i].oid.length;
701 15774 : bin_oid.data = ctr->mappings[i].oid.binary_oid;
702 :
703 15774 : werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx);
704 15774 : if (!W_ERROR_IS_OK(werr)) {
705 0 : return WERR_DS_DRA_SCHEMA_MISMATCH;
706 : }
707 : }
708 :
709 317 : return WERR_OK;
710 : }
|