/src/samba/source4/dsdb/schema/schema_prefixmap.c
Line | Count | Source |
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 | | enum dsdb_attid_type dsdb_pfm_get_attid_type(uint32_t attid) |
34 | 0 | { |
35 | 0 | if (attid <= 0x7FFFFFFF) { |
36 | 0 | return DSDB_ATTID_TYPE_PFM; |
37 | 0 | } |
38 | 0 | else if (attid <= 0xBFFFFFFF) { |
39 | 0 | return DSDB_ATTID_TYPE_INTID; |
40 | 0 | } |
41 | 0 | else if (attid <= 0xFFFEFFFF) { |
42 | 0 | return DSDB_ATTID_TYPE_RESERVED; |
43 | 0 | } |
44 | 0 | else { |
45 | 0 | return DSDB_ATTID_TYPE_INTERNAL; |
46 | 0 | } |
47 | 0 | } |
48 | | |
49 | | /** |
50 | | * Allocates schema_prefixMap object in supplied memory context |
51 | | */ |
52 | | static struct dsdb_schema_prefixmap *_dsdb_schema_prefixmap_talloc(TALLOC_CTX *mem_ctx, |
53 | | uint32_t length) |
54 | 0 | { |
55 | 0 | struct dsdb_schema_prefixmap *pfm; |
56 | |
|
57 | 0 | pfm = talloc_zero(mem_ctx, struct dsdb_schema_prefixmap); |
58 | 0 | if (!pfm) { |
59 | 0 | return NULL; |
60 | 0 | } |
61 | | |
62 | 0 | pfm->length = length; |
63 | 0 | pfm->prefixes = talloc_zero_array(pfm, struct dsdb_schema_prefixmap_oid, |
64 | 0 | pfm->length); |
65 | 0 | if (!pfm->prefixes) { |
66 | 0 | talloc_free(pfm); |
67 | 0 | return NULL; |
68 | 0 | } |
69 | | |
70 | 0 | return pfm; |
71 | 0 | } |
72 | | |
73 | | /** |
74 | | * Initial prefixMap creation according to: |
75 | | * [MS-DRSR] section 5.12.2 |
76 | | */ |
77 | | WERROR dsdb_schema_pfm_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm) |
78 | 0 | { |
79 | 0 | uint32_t i; |
80 | 0 | struct dsdb_schema_prefixmap *pfm; |
81 | 0 | const struct { |
82 | 0 | uint32_t id; |
83 | 0 | const char *oid_prefix; |
84 | 0 | } pfm_init_data[] = { |
85 | 0 | {.id=0x00000000, .oid_prefix="2.5.4"}, |
86 | 0 | {.id=0x00000001, .oid_prefix="2.5.6"}, |
87 | 0 | {.id=0x00000002, .oid_prefix="1.2.840.113556.1.2"}, |
88 | 0 | {.id=0x00000003, .oid_prefix="1.2.840.113556.1.3"}, |
89 | 0 | {.id=0x00000004, .oid_prefix="2.16.840.1.101.2.2.1"}, |
90 | 0 | {.id=0x00000005, .oid_prefix="2.16.840.1.101.2.2.3"}, |
91 | 0 | {.id=0x00000006, .oid_prefix="2.16.840.1.101.2.1.5"}, |
92 | 0 | {.id=0x00000007, .oid_prefix="2.16.840.1.101.2.1.4"}, |
93 | 0 | {.id=0x00000008, .oid_prefix="2.5.5"}, |
94 | 0 | {.id=0x00000009, .oid_prefix="1.2.840.113556.1.4"}, |
95 | 0 | {.id=0x0000000A, .oid_prefix="1.2.840.113556.1.5"}, |
96 | 0 | {.id=0x00000013, .oid_prefix="0.9.2342.19200300.100"}, |
97 | 0 | {.id=0x00000014, .oid_prefix="2.16.840.1.113730.3"}, |
98 | 0 | {.id=0x00000015, .oid_prefix="0.9.2342.19200300.100.1"}, |
99 | 0 | {.id=0x00000016, .oid_prefix="2.16.840.1.113730.3.1"}, |
100 | 0 | {.id=0x00000017, .oid_prefix="1.2.840.113556.1.5.7000"}, |
101 | 0 | {.id=0x00000018, .oid_prefix="2.5.21"}, |
102 | 0 | {.id=0x00000019, .oid_prefix="2.5.18"}, |
103 | 0 | {.id=0x0000001A, .oid_prefix="2.5.20"}, |
104 | 0 | }; |
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 | 0 | } |
116 | 0 | pfm->prefixes[i].id = pfm_init_data[i].id; |
117 | 0 | } |
118 | | |
119 | 0 | *_pfm = pfm; |
120 | |
|
121 | 0 | return WERR_OK; |
122 | 0 | } |
123 | | |
124 | | |
125 | | struct dsdb_schema_prefixmap *dsdb_schema_pfm_copy_shallow(TALLOC_CTX *mem_ctx, |
126 | | const struct dsdb_schema_prefixmap *pfm) |
127 | 0 | { |
128 | 0 | uint32_t i; |
129 | 0 | struct dsdb_schema_prefixmap *pfm_copy; |
130 | |
|
131 | 0 | pfm_copy = _dsdb_schema_prefixmap_talloc(mem_ctx, pfm->length); |
132 | 0 | if (!pfm_copy) { |
133 | 0 | return NULL; |
134 | 0 | } |
135 | 0 | for (i = 0; i < pfm_copy->length; i++) { |
136 | 0 | pfm_copy->prefixes[i] = pfm->prefixes[i]; |
137 | 0 | } |
138 | |
|
139 | 0 | return pfm_copy; |
140 | 0 | } |
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 | | 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 | 0 | { |
157 | 0 | uint32_t i; |
158 | 0 | struct dsdb_schema_prefixmap_oid * pfm_entry; |
159 | 0 | struct dsdb_schema_prefixmap_oid * prefixes_new; |
160 | | |
161 | | /* dup memory for bin-oid prefix to be added */ |
162 | 0 | bin_oid = data_blob_dup_talloc(pfm, bin_oid); |
163 | 0 | W_ERROR_HAVE_NO_MEMORY(bin_oid.data); |
164 | | |
165 | | /* make room for new entry */ |
166 | 0 | prefixes_new = talloc_realloc(pfm, pfm->prefixes, struct dsdb_schema_prefixmap_oid, pfm->length + 1); |
167 | 0 | if (!prefixes_new) { |
168 | 0 | talloc_free(bin_oid.data); |
169 | 0 | return WERR_NOT_ENOUGH_MEMORY; |
170 | 0 | } |
171 | 0 | pfm->prefixes = prefixes_new; |
172 | | |
173 | | /* make new unique ID in prefixMap */ |
174 | 0 | pfm_entry = &pfm->prefixes[pfm->length]; |
175 | 0 | pfm_entry->id = 0; |
176 | 0 | for (i = 0; i < pfm->length; i++) { |
177 | 0 | if (pfm_entry->id < pfm->prefixes[i].id) { |
178 | 0 | pfm_entry->id = pfm->prefixes[i].id; |
179 | 0 | } |
180 | |
|
181 | 0 | if (remote_id == NULL) { |
182 | 0 | continue; |
183 | 0 | } |
184 | | |
185 | 0 | 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 | 0 | } |
192 | 0 | } |
193 | | |
194 | | /* add new bin-oid prefix */ |
195 | 0 | if (remote_id != NULL) { |
196 | 0 | pfm_entry->id = *remote_id; |
197 | 0 | } else { |
198 | 0 | pfm_entry->id++; |
199 | 0 | } |
200 | 0 | pfm_entry->bin_oid = bin_oid; |
201 | |
|
202 | 0 | if (_idx != NULL) { |
203 | 0 | *_idx = pfm->length; |
204 | 0 | } |
205 | 0 | pfm->length++; |
206 | |
|
207 | 0 | return WERR_OK; |
208 | 0 | } |
209 | | |
210 | | |
211 | | /** |
212 | | * Make partial binary OID for supplied OID. |
213 | | * Reference: [MS-DRSR] section 5.12.2 |
214 | | */ |
215 | | 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 | 0 | { |
218 | 0 | uint32_t last_subid; |
219 | 0 | const char *oid_subid; |
220 | 0 | int error = 0; |
221 | | |
222 | | /* make last sub-identifier value */ |
223 | 0 | oid_subid = strrchr(full_oid, '.'); |
224 | 0 | if (!oid_subid) { |
225 | 0 | return WERR_INVALID_PARAMETER; |
226 | 0 | } |
227 | 0 | oid_subid++; |
228 | 0 | last_subid = smb_strtoul(oid_subid, NULL, 10, &error, SMB_STR_STANDARD); |
229 | 0 | if (error != 0) { |
230 | 0 | return WERR_INVALID_PARAMETER; |
231 | 0 | } |
232 | | |
233 | | /* encode oid in BER format */ |
234 | 0 | 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 | 0 | } |
238 | | |
239 | | /* get the prefix of the OID */ |
240 | 0 | if (last_subid < 128) { |
241 | 0 | _bin_oid->length -= 1; |
242 | 0 | } else { |
243 | 0 | _bin_oid->length -= 2; |
244 | 0 | } |
245 | | |
246 | | /* return last_value if requested */ |
247 | 0 | if (_last_subid) { |
248 | 0 | *_last_subid = last_subid; |
249 | 0 | } |
250 | |
|
251 | 0 | return WERR_OK; |
252 | 0 | } |
253 | | |
254 | | /** |
255 | | * Lookup partial-binary-oid in prefixMap |
256 | | */ |
257 | | WERROR dsdb_schema_pfm_find_binary_oid(const struct dsdb_schema_prefixmap *pfm, |
258 | | DATA_BLOB bin_oid, |
259 | | uint32_t *_idx) |
260 | 0 | { |
261 | 0 | uint32_t i; |
262 | |
|
263 | 0 | for (i = 0; i < pfm->length; i++) { |
264 | 0 | if (pfm->prefixes[i].bin_oid.length != bin_oid.length) { |
265 | 0 | continue; |
266 | 0 | } |
267 | | |
268 | 0 | if (memcmp(pfm->prefixes[i].bin_oid.data, bin_oid.data, bin_oid.length) == 0) { |
269 | 0 | if (_idx) { |
270 | 0 | *_idx = i; |
271 | 0 | } |
272 | 0 | return WERR_OK; |
273 | 0 | } |
274 | 0 | } |
275 | | |
276 | 0 | return WERR_NOT_FOUND; |
277 | 0 | } |
278 | | |
279 | | /** |
280 | | * Lookup full-oid in prefixMap |
281 | | * Note: this may be slow. |
282 | | */ |
283 | | WERROR dsdb_schema_pfm_find_oid(const struct dsdb_schema_prefixmap *pfm, |
284 | | const char *full_oid, |
285 | | uint32_t *_idx) |
286 | 0 | { |
287 | 0 | WERROR werr; |
288 | 0 | DATA_BLOB bin_oid; |
289 | |
|
290 | 0 | ZERO_STRUCT(bin_oid); |
291 | | |
292 | | /* make partial-binary-oid to look for */ |
293 | 0 | werr = _dsdb_pfm_make_binary_oid(full_oid, NULL, &bin_oid, NULL); |
294 | 0 | W_ERROR_NOT_OK_RETURN(werr); |
295 | | |
296 | | /* lookup the partial-oid */ |
297 | 0 | werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, _idx); |
298 | |
|
299 | 0 | data_blob_free(&bin_oid); |
300 | |
|
301 | 0 | return werr; |
302 | 0 | } |
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 | | 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 | 0 | { |
315 | 0 | WERROR werr; |
316 | 0 | uint32_t idx; |
317 | 0 | uint32_t lo_word, hi_word; |
318 | 0 | uint32_t last_subid; |
319 | 0 | DATA_BLOB bin_oid; |
320 | |
|
321 | 0 | if (!pfm) { |
322 | 0 | return WERR_INVALID_PARAMETER; |
323 | 0 | } |
324 | 0 | if (!oid) { |
325 | 0 | return WERR_INVALID_PARAMETER; |
326 | 0 | } |
327 | | |
328 | 0 | werr = _dsdb_pfm_make_binary_oid(oid, pfm, &bin_oid, &last_subid); |
329 | 0 | 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 | 0 | werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx); |
335 | 0 | if (W_ERROR_IS_OK(werr)) { |
336 | | /* free memory allocated for bin_oid */ |
337 | 0 | data_blob_free(&bin_oid); |
338 | 0 | } else { |
339 | | /* return error in read-only mode */ |
340 | 0 | 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 | 0 | } |
344 | | |
345 | | /* entry does not exists, add it */ |
346 | 0 | werr = dsdb_schema_pfm_add_entry(pfm, bin_oid, NULL, &idx); |
347 | 0 | W_ERROR_NOT_OK_RETURN(werr); |
348 | 0 | } |
349 | | |
350 | | /* compose the attid */ |
351 | 0 | lo_word = last_subid % 16384; /* actually get lower 14 bits: lo_word & 0x3FFF */ |
352 | 0 | 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 | 0 | lo_word += 32768; |
356 | 0 | } |
357 | 0 | hi_word = pfm->prefixes[idx].id; |
358 | | |
359 | | /* make ATTID: |
360 | | * HIWORD is prefixMap id |
361 | | * LOWORD is truncated binary-oid */ |
362 | 0 | *attid = (hi_word * 65536) + lo_word; |
363 | |
|
364 | 0 | return WERR_OK; |
365 | 0 | } |
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 | | WERROR dsdb_schema_pfm_make_attid(struct dsdb_schema_prefixmap *pfm, |
378 | | const char *oid, |
379 | | uint32_t *attid) |
380 | 0 | { |
381 | 0 | return dsdb_schema_pfm_make_attid_impl(pfm, oid, true, attid); |
382 | 0 | } |
383 | | |
384 | | /** |
385 | | * Make ATTID for given OID |
386 | | * Reference: [MS-DRSR] section 5.12.2 |
387 | | */ |
388 | | WERROR dsdb_schema_pfm_attid_from_oid(struct dsdb_schema_prefixmap *pfm, |
389 | | const char *oid, |
390 | | uint32_t *attid) |
391 | 0 | { |
392 | 0 | return dsdb_schema_pfm_make_attid_impl(pfm, oid, false, attid); |
393 | 0 | } |
394 | | |
395 | | /** |
396 | | * Make OID for given ATTID. |
397 | | * Reference: [MS-DRSR] section 5.12.2 |
398 | | */ |
399 | | 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 | 0 | { |
403 | 0 | uint32_t i; |
404 | 0 | uint32_t hi_word, lo_word; |
405 | 0 | DATA_BLOB bin_oid = {NULL, 0}; |
406 | 0 | char *oid; |
407 | 0 | struct dsdb_schema_prefixmap_oid *pfm_entry; |
408 | 0 | WERROR werr = WERR_OK; |
409 | | |
410 | | /* sanity check for attid requested */ |
411 | 0 | if (dsdb_pfm_get_attid_type(attid) != DSDB_ATTID_TYPE_PFM) { |
412 | 0 | return WERR_INVALID_PARAMETER; |
413 | 0 | } |
414 | | |
415 | | /* crack attid value */ |
416 | 0 | hi_word = attid >> 16; |
417 | 0 | lo_word = attid & 0xFFFF; |
418 | | |
419 | | /* locate corRespoNding prefixMap entry */ |
420 | 0 | pfm_entry = NULL; |
421 | 0 | for (i = 0; i < pfm->length; i++) { |
422 | 0 | if (hi_word == pfm->prefixes[i].id) { |
423 | 0 | pfm_entry = &pfm->prefixes[i]; |
424 | 0 | break; |
425 | 0 | } |
426 | 0 | } |
427 | |
|
428 | 0 | if (!pfm_entry) { |
429 | 0 | DEBUG(1,("Failed to find prefixMap entry for ATTID = 0x%08X (%d)\n", |
430 | 0 | attid, attid)); |
431 | 0 | return WERR_DS_NO_ATTRIBUTE_OR_VALUE; |
432 | 0 | } |
433 | | |
434 | | /* copy oid prefix making enough room */ |
435 | 0 | bin_oid.length = pfm_entry->bin_oid.length + 2; |
436 | 0 | bin_oid.data = talloc_array(mem_ctx, uint8_t, bin_oid.length); |
437 | 0 | W_ERROR_HAVE_NO_MEMORY(bin_oid.data); |
438 | 0 | memcpy(bin_oid.data, pfm_entry->bin_oid.data, pfm_entry->bin_oid.length); |
439 | |
|
440 | 0 | if (lo_word < 128) { |
441 | 0 | bin_oid.length = bin_oid.length - 1; |
442 | 0 | bin_oid.data[bin_oid.length-1] = lo_word; |
443 | 0 | } |
444 | 0 | else { |
445 | 0 | if (lo_word >= 32768) { |
446 | 0 | lo_word -= 32768; |
447 | 0 | } |
448 | 0 | bin_oid.data[bin_oid.length-2] = (0x80 | ((lo_word>>7) & 0x7f)); |
449 | 0 | bin_oid.data[bin_oid.length-1] = lo_word & 0x7f; |
450 | 0 | } |
451 | |
|
452 | 0 | if (!ber_read_OID_String(mem_ctx, bin_oid, &oid)) { |
453 | 0 | DEBUG(0,("ber_read_OID_String() failed for %s\n", |
454 | 0 | hex_encode_talloc(bin_oid.data, bin_oid.data, bin_oid.length))); |
455 | 0 | werr = WERR_INTERNAL_ERROR; |
456 | 0 | } |
457 | | |
458 | | /* free locally allocated memory */ |
459 | 0 | talloc_free(bin_oid.data); |
460 | |
|
461 | 0 | *_oid = oid; |
462 | |
|
463 | 0 | return werr; |
464 | 0 | } |
465 | | |
466 | | |
467 | | /** |
468 | | * Verifies drsuapi mappings. |
469 | | */ |
470 | | static WERROR _dsdb_drsuapi_pfm_verify(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr, |
471 | | bool have_schema_info) |
472 | 0 | { |
473 | 0 | uint32_t i; |
474 | 0 | uint32_t num_mappings; |
475 | 0 | struct drsuapi_DsReplicaOIDMapping *mapping; |
476 | | |
477 | | /* check input params */ |
478 | 0 | if (!ctr) { |
479 | 0 | return WERR_INVALID_PARAMETER; |
480 | 0 | } |
481 | 0 | if (!ctr->mappings) { |
482 | 0 | return WERR_INVALID_PARAMETER; |
483 | 0 | } |
484 | 0 | num_mappings = ctr->num_mappings; |
485 | |
|
486 | 0 | if (have_schema_info) { |
487 | 0 | DATA_BLOB blob; |
488 | |
|
489 | 0 | if (ctr->num_mappings < 2) { |
490 | 0 | return WERR_INVALID_PARAMETER; |
491 | 0 | } |
492 | | |
493 | | /* check last entry for being special */ |
494 | 0 | mapping = &ctr->mappings[ctr->num_mappings - 1]; |
495 | 0 | if (mapping->id_prefix != 0) { |
496 | 0 | return WERR_INVALID_PARAMETER; |
497 | 0 | } |
498 | | |
499 | | /* verify schemaInfo blob is valid one */ |
500 | 0 | blob = data_blob_const(mapping->oid.binary_oid, mapping->oid.length); |
501 | 0 | if (!dsdb_schema_info_blob_is_valid(&blob)) { |
502 | 0 | return WERR_INVALID_PARAMETER; |
503 | 0 | } |
504 | | |
505 | | /* get number of read mappings in the map */ |
506 | 0 | num_mappings--; |
507 | 0 | } |
508 | | |
509 | | /* now, verify rest of entries for being at least not null */ |
510 | 0 | for (i = 0; i < num_mappings; i++) { |
511 | 0 | mapping = &ctr->mappings[i]; |
512 | 0 | if (!mapping->oid.length) { |
513 | 0 | return WERR_INVALID_PARAMETER; |
514 | 0 | } |
515 | 0 | if (!mapping->oid.binary_oid) { |
516 | 0 | return WERR_INVALID_PARAMETER; |
517 | 0 | } |
518 | | /* check it is not the special entry */ |
519 | 0 | if (*mapping->oid.binary_oid == 0xFF) { |
520 | 0 | return WERR_INVALID_PARAMETER; |
521 | 0 | } |
522 | 0 | } |
523 | | |
524 | 0 | return WERR_OK; |
525 | 0 | } |
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 | | 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 | 0 | { |
542 | 0 | WERROR werr; |
543 | 0 | uint32_t i; |
544 | 0 | DATA_BLOB blob; |
545 | 0 | uint32_t num_mappings; |
546 | 0 | struct dsdb_schema_prefixmap *pfm; |
547 | |
|
548 | 0 | if (!_pfm) { |
549 | 0 | return WERR_INVALID_PARAMETER; |
550 | 0 | } |
551 | | |
552 | | /* |
553 | | * error out if schema_info is requested |
554 | | * but it is not in the drsuapi_prefixMap |
555 | | */ |
556 | 0 | if (_schema_info && !have_schema_info) { |
557 | 0 | return WERR_INVALID_PARAMETER; |
558 | 0 | } |
559 | | |
560 | | /* verify drsuapi_pefixMap */ |
561 | 0 | werr =_dsdb_drsuapi_pfm_verify(ctr, have_schema_info); |
562 | 0 | W_ERROR_NOT_OK_RETURN(werr); |
563 | | |
564 | | /* allocate mem for prefix map */ |
565 | 0 | num_mappings = ctr->num_mappings; |
566 | 0 | if (have_schema_info) { |
567 | 0 | num_mappings--; |
568 | 0 | } |
569 | 0 | pfm = _dsdb_schema_prefixmap_talloc(mem_ctx, num_mappings); |
570 | 0 | W_ERROR_HAVE_NO_MEMORY(pfm); |
571 | | |
572 | | /* copy entries from drsuapi_prefixMap */ |
573 | 0 | for (i = 0; i < pfm->length; i++) { |
574 | 0 | blob = data_blob_talloc(pfm, |
575 | 0 | ctr->mappings[i].oid.binary_oid, |
576 | 0 | ctr->mappings[i].oid.length); |
577 | 0 | if (!blob.data) { |
578 | 0 | talloc_free(pfm); |
579 | 0 | return WERR_NOT_ENOUGH_MEMORY; |
580 | 0 | } |
581 | 0 | pfm->prefixes[i].id = ctr->mappings[i].id_prefix; |
582 | 0 | pfm->prefixes[i].bin_oid = blob; |
583 | 0 | } |
584 | | |
585 | | /* fetch schema_info if requested */ |
586 | 0 | if (_schema_info) { |
587 | | /* by this time, i should have this value, |
588 | | * but set it here for clarity */ |
589 | 0 | i = ctr->num_mappings - 1; |
590 | |
|
591 | 0 | blob = data_blob_const(ctr->mappings[i].oid.binary_oid, |
592 | 0 | ctr->mappings[i].oid.length); |
593 | 0 | werr = dsdb_schema_info_from_blob(&blob, mem_ctx, _schema_info); |
594 | 0 | if (!W_ERROR_IS_OK(werr)) { |
595 | 0 | talloc_free(pfm); |
596 | 0 | return werr; |
597 | 0 | } |
598 | 0 | } |
599 | | |
600 | | /* schema_prefixMap created successfully */ |
601 | 0 | *_pfm = pfm; |
602 | |
|
603 | 0 | return WERR_OK; |
604 | 0 | } |
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 | | 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 | 0 | { |
619 | 0 | uint32_t i; |
620 | 0 | DATA_BLOB blob; |
621 | 0 | struct drsuapi_DsReplicaOIDMapping_Ctr *ctr; |
622 | |
|
623 | 0 | if (!_ctr) { |
624 | 0 | return WERR_INVALID_PARAMETER; |
625 | 0 | } |
626 | 0 | if (!pfm) { |
627 | 0 | return WERR_INVALID_PARAMETER; |
628 | 0 | } |
629 | 0 | if (pfm->length == 0) { |
630 | 0 | return WERR_INVALID_PARAMETER; |
631 | 0 | } |
632 | | |
633 | | /* allocate memory for the structure */ |
634 | 0 | ctr = talloc_zero(mem_ctx, struct drsuapi_DsReplicaOIDMapping_Ctr); |
635 | 0 | W_ERROR_HAVE_NO_MEMORY(ctr); |
636 | | |
637 | 0 | ctr->num_mappings = (schema_info ? pfm->length + 1 : pfm->length); |
638 | 0 | ctr->mappings = talloc_array(ctr, struct drsuapi_DsReplicaOIDMapping, ctr->num_mappings); |
639 | 0 | if (!ctr->mappings) { |
640 | 0 | talloc_free(ctr); |
641 | 0 | return WERR_NOT_ENOUGH_MEMORY; |
642 | 0 | } |
643 | | |
644 | | /* copy entries from schema_prefixMap */ |
645 | 0 | for (i = 0; i < pfm->length; i++) { |
646 | 0 | blob = data_blob_dup_talloc(ctr, pfm->prefixes[i].bin_oid); |
647 | 0 | if (!blob.data) { |
648 | 0 | talloc_free(ctr); |
649 | 0 | return WERR_NOT_ENOUGH_MEMORY; |
650 | 0 | } |
651 | 0 | ctr->mappings[i].id_prefix = pfm->prefixes[i].id; |
652 | 0 | ctr->mappings[i].oid.length = blob.length; |
653 | 0 | ctr->mappings[i].oid.binary_oid = blob.data; |
654 | 0 | } |
655 | | |
656 | | /* make schema_info entry if needed */ |
657 | 0 | if (schema_info) { |
658 | 0 | WERROR werr; |
659 | | |
660 | | /* by this time, i should have this value, |
661 | | * but set it here for clarity */ |
662 | 0 | i = ctr->num_mappings - 1; |
663 | |
|
664 | 0 | werr = dsdb_blob_from_schema_info(schema_info, ctr, &blob); |
665 | 0 | if (!W_ERROR_IS_OK(werr)) { |
666 | 0 | talloc_free(ctr); |
667 | 0 | return werr; |
668 | 0 | } |
669 | | |
670 | 0 | ctr->mappings[i].id_prefix = 0; |
671 | 0 | ctr->mappings[i].oid.length = blob.length; |
672 | 0 | ctr->mappings[i].oid.binary_oid = blob.data; |
673 | 0 | } |
674 | | |
675 | | /* drsuapi_prefixMap constructed successfully */ |
676 | 0 | *_ctr = ctr; |
677 | |
|
678 | 0 | return WERR_OK; |
679 | 0 | } |
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 | | WERROR dsdb_schema_pfm_contains_drsuapi_pfm(const struct dsdb_schema_prefixmap *pfm, |
687 | | const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr) |
688 | 0 | { |
689 | 0 | WERROR werr; |
690 | 0 | uint32_t i; |
691 | 0 | uint32_t idx; |
692 | 0 | DATA_BLOB bin_oid; |
693 | | |
694 | | /* verify drsuapi_pefixMap */ |
695 | 0 | werr = _dsdb_drsuapi_pfm_verify(ctr, true); |
696 | 0 | W_ERROR_NOT_OK_RETURN(werr); |
697 | | |
698 | | /* check pfm contains every entry from ctr, except the last one */ |
699 | 0 | for (i = 0; i < ctr->num_mappings - 1; i++) { |
700 | 0 | bin_oid.length = ctr->mappings[i].oid.length; |
701 | 0 | bin_oid.data = ctr->mappings[i].oid.binary_oid; |
702 | |
|
703 | 0 | werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx); |
704 | 0 | if (!W_ERROR_IS_OK(werr)) { |
705 | 0 | return WERR_DS_DRA_SCHEMA_MISMATCH; |
706 | 0 | } |
707 | 0 | } |
708 | | |
709 | 0 | return WERR_OK; |
710 | 0 | } |