/src/samba/source4/dsdb/common/dsdb_dn.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | Samba utility functions |
4 | | |
5 | | Copyright (C) Andrew Tridgell 2009 |
6 | | Copyright (C) Andrew Bartlett <abartlet@samba.org> 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 <ldb_module.h> |
25 | | #include "librpc/ndr/libndr.h" |
26 | | #include "libcli/security/dom_sid.h" |
27 | | #include "lib/util/smb_strtox.h" |
28 | | |
29 | | enum dsdb_dn_format dsdb_dn_oid_to_format(const char *oid) |
30 | 0 | { |
31 | 0 | if (strcmp(oid, LDB_SYNTAX_DN) == 0) { |
32 | 0 | return DSDB_NORMAL_DN; |
33 | 0 | } else if (strcmp(oid, DSDB_SYNTAX_BINARY_DN) == 0) { |
34 | 0 | return DSDB_BINARY_DN; |
35 | 0 | } else if (strcmp(oid, DSDB_SYNTAX_STRING_DN) == 0) { |
36 | 0 | return DSDB_STRING_DN; |
37 | 0 | } else if (strcmp(oid, DSDB_SYNTAX_OR_NAME) == 0) { |
38 | 0 | return DSDB_NORMAL_DN; |
39 | 0 | } else { |
40 | 0 | return DSDB_INVALID_DN; |
41 | 0 | } |
42 | 0 | } |
43 | | |
44 | | static struct dsdb_dn *dsdb_dn_construct_internal(TALLOC_CTX *mem_ctx, |
45 | | struct ldb_dn *dn, |
46 | | DATA_BLOB extra_part, |
47 | | enum dsdb_dn_format dn_format, |
48 | | const char *oid) |
49 | 0 | { |
50 | 0 | struct dsdb_dn *dsdb_dn = NULL; |
51 | |
|
52 | 0 | switch (dn_format) { |
53 | 0 | case DSDB_BINARY_DN: |
54 | 0 | case DSDB_STRING_DN: |
55 | 0 | break; |
56 | 0 | case DSDB_NORMAL_DN: |
57 | 0 | if (extra_part.length != 0) { |
58 | 0 | errno = EINVAL; |
59 | 0 | return NULL; |
60 | 0 | } |
61 | 0 | break; |
62 | 0 | case DSDB_INVALID_DN: |
63 | 0 | default: |
64 | 0 | errno = EINVAL; |
65 | 0 | return NULL; |
66 | 0 | } |
67 | | |
68 | 0 | dsdb_dn = talloc(mem_ctx, struct dsdb_dn); |
69 | 0 | if (!dsdb_dn) { |
70 | 0 | errno = ENOMEM; |
71 | 0 | return NULL; |
72 | 0 | } |
73 | 0 | dsdb_dn->dn = talloc_steal(dsdb_dn, dn); |
74 | 0 | dsdb_dn->extra_part = extra_part; |
75 | 0 | dsdb_dn->dn_format = dn_format; |
76 | |
|
77 | 0 | dsdb_dn->oid = oid; |
78 | 0 | talloc_steal(dsdb_dn, extra_part.data); |
79 | 0 | return dsdb_dn; |
80 | 0 | } |
81 | | |
82 | | struct dsdb_dn *dsdb_dn_construct(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, DATA_BLOB extra_part, |
83 | | const char *oid) |
84 | 0 | { |
85 | 0 | enum dsdb_dn_format dn_format = dsdb_dn_oid_to_format(oid); |
86 | 0 | return dsdb_dn_construct_internal(mem_ctx, dn, extra_part, dn_format, oid); |
87 | 0 | } |
88 | | |
89 | | struct dsdb_dn *dsdb_dn_parse_trusted(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, |
90 | | const struct ldb_val *dn_blob, const char *dn_oid) |
91 | 0 | { |
92 | 0 | struct dsdb_dn *dsdb_dn; |
93 | 0 | struct ldb_dn *dn; |
94 | 0 | size_t len; |
95 | 0 | TALLOC_CTX *tmp_ctx; |
96 | 0 | char *p1; |
97 | 0 | char *p2; |
98 | 0 | uint32_t blen; |
99 | 0 | struct ldb_val bval; |
100 | 0 | struct ldb_val dval; |
101 | 0 | char *dn_str; |
102 | 0 | int error = 0; |
103 | |
|
104 | 0 | enum dsdb_dn_format dn_format = dsdb_dn_oid_to_format(dn_oid); |
105 | |
|
106 | 0 | if (dn_blob == NULL || dn_blob->data == NULL || dn_blob->length == 0) { |
107 | 0 | return NULL; |
108 | 0 | } |
109 | | |
110 | 0 | switch (dn_format) { |
111 | 0 | case DSDB_INVALID_DN: |
112 | 0 | return NULL; |
113 | 0 | case DSDB_NORMAL_DN: |
114 | 0 | { |
115 | 0 | dn = ldb_dn_from_ldb_val(mem_ctx, ldb, dn_blob); |
116 | 0 | if (!dn) { |
117 | 0 | talloc_free(dn); |
118 | 0 | return NULL; |
119 | 0 | } |
120 | 0 | return dsdb_dn_construct_internal(mem_ctx, dn, data_blob_null, dn_format, dn_oid); |
121 | 0 | } |
122 | 0 | case DSDB_BINARY_DN: |
123 | 0 | if (dn_blob->length < 2 || dn_blob->data[0] != 'B' || dn_blob->data[1] != ':') { |
124 | 0 | return NULL; |
125 | 0 | } |
126 | 0 | break; |
127 | 0 | case DSDB_STRING_DN: |
128 | 0 | if (dn_blob->length < 2 || dn_blob->data[0] != 'S' || dn_blob->data[1] != ':') { |
129 | 0 | return NULL; |
130 | 0 | } |
131 | 0 | break; |
132 | 0 | default: |
133 | 0 | return NULL; |
134 | 0 | } |
135 | | |
136 | 0 | if (strlen((const char*)dn_blob->data) != dn_blob->length) { |
137 | | /* The RDN must not contain a character with value 0x0 */ |
138 | 0 | return NULL; |
139 | 0 | } |
140 | | |
141 | 0 | tmp_ctx = talloc_new(mem_ctx); |
142 | 0 | if (tmp_ctx == NULL) { |
143 | 0 | return NULL; |
144 | 0 | } |
145 | | |
146 | 0 | len = dn_blob->length - 2; |
147 | 0 | p1 = talloc_strndup(tmp_ctx, (const char *)dn_blob->data + 2, len); |
148 | 0 | if (!p1) { |
149 | 0 | goto failed; |
150 | 0 | } |
151 | | |
152 | 0 | errno = 0; |
153 | 0 | blen = smb_strtoul(p1, &p2, 10, &error, SMB_STR_STANDARD); |
154 | 0 | if (error != 0) { |
155 | 0 | DEBUG(10, (__location__ ": failed\n")); |
156 | 0 | goto failed; |
157 | 0 | } |
158 | 0 | if (p2 == NULL) { |
159 | 0 | DEBUG(10, (__location__ ": failed\n")); |
160 | 0 | goto failed; |
161 | 0 | } |
162 | 0 | if (p2[0] != ':') { |
163 | 0 | DEBUG(10, (__location__ ": failed\n")); |
164 | 0 | goto failed; |
165 | 0 | } |
166 | 0 | len -= PTR_DIFF(p2,p1);//??? |
167 | 0 | p1 = p2+1; |
168 | 0 | len--; |
169 | | |
170 | 0 | if (blen >= len) { |
171 | 0 | DEBUG(10, (__location__ ": blen=%u len=%u\n", (unsigned)blen, (unsigned)len)); |
172 | 0 | goto failed; |
173 | 0 | } |
174 | | |
175 | 0 | p2 = p1 + blen; |
176 | 0 | if (p2[0] != ':') { |
177 | 0 | DEBUG(10, (__location__ ": %s", p2)); |
178 | 0 | goto failed; |
179 | 0 | } |
180 | 0 | dn_str = p2+1; |
181 | | |
182 | | |
183 | 0 | switch (dn_format) { |
184 | 0 | case DSDB_BINARY_DN: |
185 | 0 | if ((blen % 2 != 0)) { |
186 | 0 | DEBUG(10, (__location__ ": blen=%u - not an even number\n", (unsigned)blen)); |
187 | 0 | goto failed; |
188 | 0 | } |
189 | | |
190 | 0 | if (blen >= 2) { |
191 | 0 | bval.length = (blen/2)+1; |
192 | 0 | bval.data = talloc_size(tmp_ctx, bval.length); |
193 | 0 | if (bval.data == NULL) { |
194 | 0 | DEBUG(10, (__location__ ": err\n")); |
195 | 0 | goto failed; |
196 | 0 | } |
197 | 0 | bval.data[bval.length-1] = 0; |
198 | | |
199 | 0 | bval.length = strhex_to_str((char *)bval.data, bval.length, |
200 | 0 | p1, blen); |
201 | 0 | if (bval.length != (blen / 2)) { |
202 | 0 | DEBUG(10, (__location__ ": non hexadecimal characters found in binary prefix\n")); |
203 | 0 | goto failed; |
204 | 0 | } |
205 | 0 | } else { |
206 | 0 | bval = data_blob_null; |
207 | 0 | } |
208 | | |
209 | 0 | break; |
210 | 0 | case DSDB_STRING_DN: |
211 | 0 | bval = data_blob(p1, blen); |
212 | 0 | break; |
213 | 0 | default: |
214 | | /* never reached */ |
215 | 0 | return NULL; |
216 | 0 | } |
217 | | |
218 | | |
219 | 0 | dval.data = (uint8_t *)dn_str; |
220 | 0 | dval.length = strlen(dn_str); |
221 | | |
222 | 0 | dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &dval); |
223 | 0 | if (!dn) { |
224 | 0 | DEBUG(10, (__location__ ": err\n")); |
225 | 0 | goto failed; |
226 | 0 | } |
227 | | |
228 | 0 | dsdb_dn = dsdb_dn_construct(mem_ctx, dn, bval, dn_oid); |
229 | | |
230 | 0 | talloc_free(tmp_ctx); |
231 | 0 | return dsdb_dn; |
232 | | |
233 | 0 | failed: |
234 | 0 | talloc_free(tmp_ctx); |
235 | 0 | return NULL; |
236 | 0 | } |
237 | | |
238 | | struct dsdb_dn *dsdb_dn_parse(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, |
239 | | const struct ldb_val *dn_blob, const char *dn_oid) |
240 | 0 | { |
241 | 0 | struct dsdb_dn *dsdb_dn = dsdb_dn_parse_trusted(mem_ctx, ldb, |
242 | 0 | dn_blob, dn_oid); |
243 | 0 | if (dsdb_dn == NULL) { |
244 | 0 | return NULL; |
245 | 0 | } |
246 | 0 | if (ldb_dn_validate(dsdb_dn->dn) == false) { |
247 | 0 | DEBUG(10, ("could not parse %.*s as a %s DN\n", |
248 | 0 | (int)dn_blob->length, dn_blob->data, |
249 | 0 | dn_oid)); |
250 | 0 | return NULL; |
251 | 0 | } |
252 | 0 | return dsdb_dn; |
253 | 0 | } |
254 | | |
255 | | static char *dsdb_dn_get_with_postfix(TALLOC_CTX *mem_ctx, |
256 | | struct dsdb_dn *dsdb_dn, |
257 | | const char *postfix) |
258 | 0 | { |
259 | 0 | if (!postfix) { |
260 | 0 | return NULL; |
261 | 0 | } |
262 | | |
263 | 0 | switch (dsdb_dn->dn_format) { |
264 | 0 | case DSDB_NORMAL_DN: |
265 | 0 | { |
266 | 0 | return talloc_strdup(mem_ctx, postfix); |
267 | 0 | } |
268 | 0 | case DSDB_BINARY_DN: |
269 | 0 | { |
270 | 0 | char *hexstr = data_blob_hex_string_upper(mem_ctx, &dsdb_dn->extra_part); |
271 | | |
272 | 0 | char *p = talloc_asprintf(mem_ctx, "B:%u:%s:%s", (unsigned)(dsdb_dn->extra_part.length*2), hexstr, |
273 | 0 | postfix); |
274 | 0 | talloc_free(hexstr); |
275 | 0 | return p; |
276 | 0 | } |
277 | 0 | case DSDB_STRING_DN: |
278 | 0 | { |
279 | 0 | return talloc_asprintf(mem_ctx, "S:%u:%*.*s:%s", |
280 | 0 | (unsigned)(dsdb_dn->extra_part.length), |
281 | 0 | (int)(dsdb_dn->extra_part.length), |
282 | 0 | (int)(dsdb_dn->extra_part.length), |
283 | 0 | (const char *)dsdb_dn->extra_part.data, |
284 | 0 | postfix); |
285 | 0 | } |
286 | 0 | default: |
287 | 0 | return NULL; |
288 | 0 | } |
289 | 0 | } |
290 | | |
291 | | char *dsdb_dn_get_linearized(TALLOC_CTX *mem_ctx, |
292 | | struct dsdb_dn *dsdb_dn) |
293 | 0 | { |
294 | 0 | const char *postfix = ldb_dn_get_linearized(dsdb_dn->dn); |
295 | 0 | return dsdb_dn_get_with_postfix(mem_ctx, dsdb_dn, postfix); |
296 | 0 | } |
297 | | |
298 | | char *dsdb_dn_get_casefold(TALLOC_CTX *mem_ctx, |
299 | | struct dsdb_dn *dsdb_dn) |
300 | 0 | { |
301 | 0 | const char *postfix = ldb_dn_get_casefold(dsdb_dn->dn); |
302 | 0 | return dsdb_dn_get_with_postfix(mem_ctx, dsdb_dn, postfix); |
303 | 0 | } |
304 | | |
305 | | char *dsdb_dn_get_extended_linearized(TALLOC_CTX *mem_ctx, |
306 | | struct dsdb_dn *dsdb_dn, |
307 | | int mode) |
308 | 0 | { |
309 | 0 | char *postfix = ldb_dn_get_extended_linearized(mem_ctx, dsdb_dn->dn, mode); |
310 | 0 | char *ret = dsdb_dn_get_with_postfix(mem_ctx, dsdb_dn, postfix); |
311 | 0 | talloc_free(postfix); |
312 | 0 | return ret; |
313 | 0 | } |
314 | | |
315 | | int dsdb_dn_binary_canonicalise(struct ldb_context *ldb, void *mem_ctx, |
316 | | const struct ldb_val *in, struct ldb_val *out) |
317 | 0 | { |
318 | 0 | struct dsdb_dn *dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN); |
319 | | |
320 | 0 | if (!dsdb_dn) { |
321 | 0 | return -1; |
322 | 0 | } |
323 | 0 | *out = data_blob_string_const(dsdb_dn_get_casefold(mem_ctx, dsdb_dn)); |
324 | 0 | talloc_free(dsdb_dn); |
325 | 0 | if (!out->data) { |
326 | 0 | return -1; |
327 | 0 | } |
328 | 0 | return 0; |
329 | 0 | } |
330 | | |
331 | | int dsdb_dn_binary_comparison(struct ldb_context *ldb, void *mem_ctx, |
332 | | const struct ldb_val *v1, |
333 | | const struct ldb_val *v2) |
334 | 0 | { |
335 | 0 | return ldb_any_comparison(ldb, mem_ctx, dsdb_dn_binary_canonicalise, v1, v2); |
336 | 0 | } |
337 | | |
338 | | int dsdb_dn_string_canonicalise(struct ldb_context *ldb, void *mem_ctx, |
339 | | const struct ldb_val *in, struct ldb_val *out) |
340 | 0 | { |
341 | 0 | struct dsdb_dn *dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_STRING_DN); |
342 | | |
343 | 0 | if (!dsdb_dn) { |
344 | 0 | return -1; |
345 | 0 | } |
346 | 0 | *out = data_blob_string_const(dsdb_dn_get_casefold(mem_ctx, dsdb_dn)); |
347 | 0 | talloc_free(dsdb_dn); |
348 | 0 | if (!out->data) { |
349 | 0 | return -1; |
350 | 0 | } |
351 | 0 | return 0; |
352 | 0 | } |
353 | | |
354 | | int dsdb_dn_string_comparison(struct ldb_context *ldb, void *mem_ctx, |
355 | | const struct ldb_val *v1, |
356 | | const struct ldb_val *v2) |
357 | 0 | { |
358 | 0 | return ldb_any_comparison(ldb, mem_ctx, dsdb_dn_string_canonicalise, v1, v2); |
359 | 0 | } |
360 | | |
361 | | /* |
362 | | * format a drsuapi_DsReplicaObjectIdentifier naming context as a string for debugging |
363 | | * |
364 | | * When forming a DN for DB access you must use drs_ObjectIdentifier_to_dn() |
365 | | */ |
366 | | char *drs_ObjectIdentifier_to_debug_string(TALLOC_CTX *mem_ctx, |
367 | | struct drsuapi_DsReplicaObjectIdentifier *nc) |
368 | 0 | { |
369 | 0 | char *ret = NULL; |
370 | 0 | TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); |
371 | 0 | if (!GUID_all_zero(&nc->guid)) { |
372 | 0 | char *guid = GUID_string(tmp_ctx, &nc->guid); |
373 | 0 | if (guid) { |
374 | 0 | ret = talloc_asprintf_append(ret, "<GUID=%s>;", guid); |
375 | 0 | } |
376 | 0 | } |
377 | 0 | if (nc->__ndr_size_sid != 0 && nc->sid.sid_rev_num != 0) { |
378 | 0 | const char *sid = dom_sid_string(tmp_ctx, &nc->sid); |
379 | 0 | if (sid) { |
380 | 0 | ret = talloc_asprintf_append(ret, "<SID=%s>;", sid); |
381 | 0 | } |
382 | 0 | } |
383 | 0 | if (nc->__ndr_size_dn != 0 && nc->dn) { |
384 | 0 | ret = talloc_asprintf_append(ret, "%s", nc->dn); |
385 | 0 | } |
386 | 0 | talloc_free(tmp_ctx); |
387 | 0 | talloc_steal(mem_ctx, ret); |
388 | 0 | return ret; |
389 | 0 | } |
390 | | |
391 | | /* |
392 | | * Safely convert a drsuapi_DsReplicaObjectIdentifier into an LDB DN |
393 | | * |
394 | | * We need to have GUID and SID priority and not allow extended |
395 | | * components in the DN. |
396 | | * |
397 | | * We must also totally honour the priority even if the string DN is not valid or able to parse as a DN. |
398 | | */ |
399 | | static struct ldb_dn *drs_ObjectIdentifier_to_dn(TALLOC_CTX *mem_ctx, |
400 | | struct ldb_context *ldb, |
401 | | struct drsuapi_DsReplicaObjectIdentifier *nc) |
402 | 0 | { |
403 | 0 | struct ldb_dn *new_dn = NULL; |
404 | |
|
405 | 0 | if (!GUID_all_zero(&nc->guid)) { |
406 | 0 | struct GUID_txt_buf buf; |
407 | 0 | char *guid = GUID_buf_string(&nc->guid, &buf); |
408 | |
|
409 | 0 | new_dn = ldb_dn_new_fmt(mem_ctx, |
410 | 0 | ldb, |
411 | 0 | "<GUID=%s>", |
412 | 0 | guid); |
413 | 0 | if (new_dn == NULL) { |
414 | 0 | DBG_ERR("Failed to prepare drs_ObjectIdentifier " |
415 | 0 | "GUID %s into a DN\n", |
416 | 0 | guid); |
417 | 0 | return NULL; |
418 | 0 | } |
419 | | |
420 | 0 | return new_dn; |
421 | 0 | } |
422 | | |
423 | 0 | if (nc->__ndr_size_sid != 0 && nc->sid.sid_rev_num != 0) { |
424 | 0 | struct dom_sid_buf buf; |
425 | 0 | char *sid = dom_sid_str_buf(&nc->sid, &buf); |
426 | |
|
427 | 0 | new_dn = ldb_dn_new_fmt(mem_ctx, |
428 | 0 | ldb, |
429 | 0 | "<SID=%s>", |
430 | 0 | sid); |
431 | 0 | if (new_dn == NULL) { |
432 | 0 | DBG_ERR("Failed to prepare drs_ObjectIdentifier " |
433 | 0 | "SID %s into a DN\n", |
434 | 0 | sid); |
435 | 0 | return NULL; |
436 | 0 | } |
437 | 0 | return new_dn; |
438 | 0 | } |
439 | | |
440 | 0 | if (nc->__ndr_size_dn != 0 && nc->dn) { |
441 | 0 | int dn_comp_num = 0; |
442 | 0 | bool new_dn_valid = false; |
443 | |
|
444 | 0 | new_dn = ldb_dn_new(mem_ctx, ldb, nc->dn); |
445 | 0 | if (new_dn == NULL) { |
446 | | /* Set to WARNING as this is user-controlled, don't print the value into the logs */ |
447 | 0 | DBG_WARNING("Failed to parse string DN in " |
448 | 0 | "drs_ObjectIdentifier into an LDB DN\n"); |
449 | 0 | return NULL; |
450 | 0 | } |
451 | | |
452 | 0 | new_dn_valid = ldb_dn_validate(new_dn); |
453 | 0 | if (!new_dn_valid) { |
454 | | /* |
455 | | * Set to WARNING as this is user-controlled, |
456 | | * but can print the value into the logs as it |
457 | | * parsed a bit |
458 | | */ |
459 | 0 | DBG_WARNING("Failed to validate string DN [%s] in " |
460 | 0 | "drs_ObjectIdentifier as an LDB DN\n", |
461 | 0 | ldb_dn_get_linearized(new_dn)); |
462 | 0 | return NULL; |
463 | 0 | } |
464 | | |
465 | 0 | dn_comp_num = ldb_dn_get_comp_num(new_dn); |
466 | 0 | if (dn_comp_num <= 0) { |
467 | | /* |
468 | | * Set to WARNING as this is user-controlled, |
469 | | * but can print the value into the logs as it |
470 | | * parsed a bit |
471 | | */ |
472 | 0 | DBG_WARNING("DN [%s] in drs_ObjectIdentifier " |
473 | 0 | "must have 1 or more components\n", |
474 | 0 | ldb_dn_get_linearized(new_dn)); |
475 | 0 | return NULL; |
476 | 0 | } |
477 | | |
478 | 0 | if (ldb_dn_is_special(new_dn)) { |
479 | | /* |
480 | | * Set to WARNING as this is user-controlled, |
481 | | * but can print the value into the logs as it |
482 | | * parsed a bit |
483 | | */ |
484 | 0 | DBG_WARNING("New string DN [%s] in " |
485 | 0 | "drs_ObjectIdentifier is a " |
486 | 0 | "special LDB DN\n", |
487 | 0 | ldb_dn_get_linearized(new_dn)); |
488 | 0 | return NULL; |
489 | 0 | } |
490 | | |
491 | | /* |
492 | | * We want this just to be a string DN, extended |
493 | | * components are manually handled above |
494 | | */ |
495 | 0 | if (ldb_dn_has_extended(new_dn)) { |
496 | | /* |
497 | | * Set to WARNING as this is user-controlled, |
498 | | * but can print the value into the logs as it |
499 | | * parsed a bit |
500 | | */ |
501 | 0 | DBG_WARNING("Refusing to parse New string DN [%s] in " |
502 | 0 | "drs_ObjectIdentifier as an " |
503 | 0 | "extended LDB DN " |
504 | 0 | "(GUIDs and SIDs should be in the " |
505 | 0 | ".guid and .sid IDL elements, " |
506 | 0 | "not in the string\n", |
507 | 0 | ldb_dn_get_extended_linearized(mem_ctx, |
508 | 0 | new_dn, |
509 | 0 | 1)); |
510 | 0 | return NULL; |
511 | 0 | } |
512 | 0 | return new_dn; |
513 | 0 | } |
514 | | |
515 | 0 | DBG_WARNING("Refusing to parse empty string DN " |
516 | 0 | "(and no GUID or SID) " |
517 | 0 | "drs_ObjectIdentifier into a empty " |
518 | 0 | "(eg RootDSE) LDB DN\n"); |
519 | 0 | return NULL; |
520 | 0 | } |
521 | | |
522 | | /* |
523 | | * Safely convert a drsuapi_DsReplicaObjectIdentifier into a validated |
524 | | * LDB DN of an existing DB entry, and/or find the NC root |
525 | | * |
526 | | * We need to have GUID and SID priority and not allow extended |
527 | | * components in the DN. |
528 | | * |
529 | | * We must also totally honour the priority even if the string DN is |
530 | | * not valid or able to parse as a DN. |
531 | | * |
532 | | * Finally, we must return the DN as found in the DB, as otherwise a |
533 | | * subsequent ldb_dn_compare(dn, nc_root) will fail (as this is based |
534 | | * on the string components). |
535 | | */ |
536 | | int drs_ObjectIdentifier_to_dn_and_nc_root(TALLOC_CTX *mem_ctx, |
537 | | struct ldb_context *ldb, |
538 | | struct drsuapi_DsReplicaObjectIdentifier *nc, |
539 | | struct ldb_dn **normalised_dn, |
540 | | struct ldb_dn **nc_root) |
541 | 0 | { |
542 | 0 | int ret; |
543 | 0 | struct ldb_dn *new_dn = NULL; |
544 | |
|
545 | 0 | new_dn = drs_ObjectIdentifier_to_dn(mem_ctx, |
546 | 0 | ldb, |
547 | 0 | nc); |
548 | 0 | if (new_dn == NULL) { |
549 | 0 | return LDB_ERR_INVALID_DN_SYNTAX; |
550 | 0 | } |
551 | | |
552 | 0 | ret = dsdb_normalise_dn_and_find_nc_root(ldb, |
553 | 0 | mem_ctx, |
554 | 0 | new_dn, |
555 | 0 | normalised_dn, |
556 | 0 | nc_root); |
557 | 0 | if (ret != LDB_SUCCESS) { |
558 | | /* |
559 | | * dsdb_normalise_dn_and_find_nc_root() sets LDB error |
560 | | * strings, and the functions it calls do also |
561 | | */ |
562 | 0 | DBG_NOTICE("Failed to find DN \"%s\" -> \"%s\" for normalisation: %s (%s)\n", |
563 | 0 | drs_ObjectIdentifier_to_debug_string(mem_ctx, nc), |
564 | 0 | ldb_dn_get_extended_linearized(mem_ctx, new_dn, 1), |
565 | 0 | ldb_errstring(ldb), |
566 | 0 | ldb_strerror(ret)); |
567 | 0 | } |
568 | |
|
569 | 0 | TALLOC_FREE(new_dn); |
570 | 0 | return ret; |
571 | 0 | } |