Line data Source code
1 : /*
2 : ldb database library - ldif handlers for Samba
3 :
4 : Copyright (C) Andrew Tridgell 2005
5 : Copyright (C) Andrew Bartlett 2006-2009
6 : Copyright (C) Matthias Dieter Wallnöfer 2009
7 : ** NOTE! The following LGPL license applies to the ldb
8 : ** library. This does NOT imply that all of Samba is released
9 : ** under the LGPL
10 :
11 : This library is free software; you can redistribute it and/or
12 : modify it under the terms of the GNU Lesser General Public
13 : License as published by the Free Software Foundation; either
14 : version 3 of the License, or (at your option) any later version.
15 :
16 : This library is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 : Lesser General Public License for more details.
20 :
21 : You should have received a copy of the GNU Lesser General Public
22 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "includes.h"
26 : #include <ldb.h>
27 : #include <ldb_module.h>
28 : #include "ldb_handlers.h"
29 : #include "dsdb/samdb/samdb.h"
30 : #include "dsdb/common/util.h"
31 : #include "librpc/gen_ndr/ndr_security.h"
32 : #include "librpc/gen_ndr/ndr_misc.h"
33 : #include "librpc/gen_ndr/ndr_drsblobs.h"
34 : #include "librpc/gen_ndr/ndr_dnsp.h"
35 : #include "librpc/ndr/libndr.h"
36 : #include "libcli/security/security.h"
37 : #include "param/param.h"
38 : #include "../lib/util/asn1.h"
39 : #include "lib/util/smb_strtox.h"
40 :
41 : /*
42 : use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
43 :
44 : If mask_errors is true, then function succeeds but out data
45 : is set to "<Unable to decode binary data>" message
46 :
47 : \return 0 on success; -1 on error
48 : */
49 802 : static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
50 : const struct ldb_val *in, struct ldb_val *out,
51 : size_t struct_size,
52 : ndr_pull_flags_fn_t pull_fn,
53 : ndr_print_fn_t print_fn,
54 : bool mask_errors)
55 : {
56 : uint8_t *p;
57 : enum ndr_err_code err;
58 802 : if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
59 790 : return ldb_handler_copy(ldb, mem_ctx, in, out);
60 : }
61 12 : p = talloc_size(mem_ctx, struct_size);
62 12 : err = ndr_pull_struct_blob(in, mem_ctx,
63 : p, pull_fn);
64 12 : if (err != NDR_ERR_SUCCESS) {
65 : /* fail in not in mask_error mode */
66 0 : if (!mask_errors) {
67 0 : return -1;
68 : }
69 0 : talloc_free(p);
70 0 : out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
71 0 : out->length = strlen((const char *)out->data);
72 0 : return 0;
73 : }
74 12 : out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
75 12 : talloc_free(p);
76 12 : if (out->data == NULL) {
77 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
78 : }
79 12 : out->length = strlen((char *)out->data);
80 12 : return 0;
81 : }
82 :
83 : /*
84 : convert a ldif formatted objectSid to a NDR formatted blob
85 : */
86 4874777 : static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
87 : const struct ldb_val *in, struct ldb_val *out)
88 : {
89 : bool ret;
90 : enum ndr_err_code ndr_err;
91 : struct dom_sid sid;
92 4874777 : if (in->length > DOM_SID_STR_BUFLEN) {
93 0 : return -1;
94 4874777 : } else {
95 4874777 : char p[in->length+1];
96 4874777 : memcpy(p, in->data, in->length);
97 4874777 : p[in->length] = '\0';
98 :
99 4874777 : ret = dom_sid_parse(p, &sid);
100 4874777 : if (ret == false) {
101 0 : return -1;
102 : }
103 :
104 4874777 : *out = data_blob_talloc(mem_ctx, NULL,
105 : ndr_size_dom_sid(&sid, 0));
106 4874777 : if (out->data == NULL) {
107 0 : return -1;
108 : }
109 :
110 4874777 : ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
111 : (ndr_push_flags_fn_t)ndr_push_dom_sid);
112 4874777 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
113 0 : return -1;
114 : }
115 : }
116 4874777 : return 0;
117 : }
118 :
119 : /*
120 : convert a NDR formatted blob to a ldif formatted objectSid
121 : */
122 2332673 : int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
123 : const struct ldb_val *in, struct ldb_val *out)
124 : {
125 : struct dom_sid sid;
126 : enum ndr_err_code ndr_err;
127 :
128 2332673 : ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
129 : (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
130 2332673 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
131 0 : return -1;
132 : }
133 2332673 : *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
134 2332673 : if (out->data == NULL) {
135 0 : return -1;
136 : }
137 2332673 : return 0;
138 : }
139 :
140 15454119 : bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
141 : {
142 15454119 : if (v->length < 3) {
143 0 : return false;
144 : }
145 :
146 15454119 : if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
147 :
148 4949442 : return true;
149 : }
150 :
151 : /*
152 : compare two objectSids
153 : */
154 1514651 : static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
155 : const struct ldb_val *v1, const struct ldb_val *v2)
156 : {
157 1514651 : if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
158 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
159 1514651 : } else if (ldif_comparision_objectSid_isString(v1)
160 81641 : && !ldif_comparision_objectSid_isString(v2)) {
161 : struct ldb_val v;
162 : int ret;
163 81641 : if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
164 : /* Perhaps not a string after all */
165 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
166 : }
167 81641 : ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
168 81641 : talloc_free(v.data);
169 81641 : return ret;
170 1433010 : } else if (!ldif_comparision_objectSid_isString(v1)
171 1433010 : && ldif_comparision_objectSid_isString(v2)) {
172 : struct ldb_val v;
173 : int ret;
174 0 : if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
175 : /* Perhaps not a string after all */
176 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
177 : }
178 0 : ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
179 0 : talloc_free(v.data);
180 0 : return ret;
181 : }
182 1433010 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
183 : }
184 :
185 : /*
186 : canonicalise a objectSid
187 : */
188 4738881 : static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
189 : const struct ldb_val *in, struct ldb_val *out)
190 : {
191 4738881 : if (ldif_comparision_objectSid_isString(in)) {
192 133786 : if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
193 : /* Perhaps not a string after all */
194 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
195 : }
196 133786 : return 0;
197 : }
198 4605095 : return ldb_handler_copy(ldb, mem_ctx, in, out);
199 : }
200 :
201 4656634 : static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
202 : const struct ldb_val *in, struct ldb_val *out)
203 : {
204 : struct dom_sid sid;
205 : enum ndr_err_code ndr_err;
206 4656634 : if (ldif_comparision_objectSid_isString(in)) {
207 4652374 : if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
208 4652374 : return 0;
209 : }
210 : }
211 :
212 : /* Perhaps not a string after all */
213 4260 : *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
214 :
215 4260 : if (!out->data) {
216 0 : return -1;
217 : }
218 :
219 8520 : (*out).length = strhex_to_str((char *)out->data, out->length,
220 4260 : (const char *)in->data, in->length);
221 :
222 : /* Check it looks like a SID */
223 4260 : ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
224 : (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
225 4260 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
226 0 : return -1;
227 : }
228 4260 : return 0;
229 : }
230 :
231 : /*
232 : convert a ldif formatted objectGUID to a NDR formatted blob
233 : */
234 61002622 : static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
235 : const struct ldb_val *in, struct ldb_val *out)
236 : {
237 : struct GUID guid;
238 : NTSTATUS status;
239 :
240 61002622 : status = GUID_from_data_blob(in, &guid);
241 61002622 : if (!NT_STATUS_IS_OK(status)) {
242 0 : return -1;
243 : }
244 :
245 61002622 : status = GUID_to_ndr_blob(&guid, mem_ctx, out);
246 61002622 : if (!NT_STATUS_IS_OK(status)) {
247 0 : return -1;
248 : }
249 61002622 : return 0;
250 : }
251 :
252 : /*
253 : convert a NDR formatted blob to a ldif formatted objectGUID
254 : */
255 6588185 : static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
256 : const struct ldb_val *in, struct ldb_val *out)
257 : {
258 : struct GUID guid;
259 : NTSTATUS status;
260 :
261 6588185 : status = GUID_from_ndr_blob(in, &guid);
262 6588185 : if (!NT_STATUS_IS_OK(status)) {
263 0 : return -1;
264 : }
265 6588185 : out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
266 6588185 : if (out->data == NULL) {
267 0 : return -1;
268 : }
269 6588185 : out->length = strlen((const char *)out->data);
270 6588185 : return 0;
271 : }
272 :
273 107901191 : static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
274 : {
275 107901191 : if (v->length != 36 && v->length != 38) return false;
276 :
277 : /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
278 50715743 : return true;
279 : }
280 :
281 17267529 : static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
282 : const struct ldb_val *in, struct ldb_val *out)
283 : {
284 :
285 17267529 : if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
286 16956589 : return 0;
287 : }
288 :
289 : /* Try as 'hex' form */
290 310940 : if (in->length != 32) {
291 1 : return -1;
292 : }
293 :
294 310939 : *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
295 :
296 310939 : if (!out->data) {
297 0 : return -1;
298 : }
299 :
300 621878 : (*out).length = strhex_to_str((char *)out->data, out->length,
301 310939 : (const char *)in->data, in->length);
302 :
303 : /* Check it looks like a GUID */
304 310939 : if ((*out).length != 16) {
305 0 : data_blob_free(out);
306 0 : return -1;
307 : }
308 :
309 310939 : return 0;
310 : }
311 :
312 : /*
313 : compare two objectGUIDs
314 : */
315 13011210 : static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
316 : const struct ldb_val *v1, const struct ldb_val *v2)
317 : {
318 13011210 : if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
319 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
320 13011210 : } else if (ldif_comparision_objectGUID_isString(v1)
321 8099133 : && !ldif_comparision_objectGUID_isString(v2)) {
322 : struct ldb_val v;
323 : int ret;
324 8099133 : if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
325 : /* Perhaps it wasn't a valid string after all */
326 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
327 : }
328 8099133 : ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
329 8099133 : talloc_free(v.data);
330 8099133 : return ret;
331 4912077 : } else if (!ldif_comparision_objectGUID_isString(v1)
332 4912077 : && ldif_comparision_objectGUID_isString(v2)) {
333 : struct ldb_val v;
334 : int ret;
335 0 : if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
336 : /* Perhaps it wasn't a valid string after all */
337 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
338 : }
339 0 : ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
340 0 : talloc_free(v.data);
341 0 : return ret;
342 : }
343 4912077 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
344 : }
345 :
346 : /*
347 : canonicalise a objectGUID
348 : */
349 55856351 : static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
350 : const struct ldb_val *in, struct ldb_val *out)
351 : {
352 55856351 : if (ldif_comparision_objectGUID_isString(in)) {
353 34517477 : if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
354 : /* Perhaps it wasn't a valid string after all */
355 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
356 : }
357 34517477 : return 0;
358 : }
359 21338874 : return ldb_handler_copy(ldb, mem_ctx, in, out);
360 : }
361 :
362 :
363 : /*
364 : convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
365 : */
366 2512 : static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
367 : const struct ldb_val *in, struct ldb_val *out)
368 : {
369 : struct security_descriptor *sd;
370 : enum ndr_err_code ndr_err;
371 :
372 2512 : sd = talloc(mem_ctx, struct security_descriptor);
373 2512 : if (sd == NULL) {
374 0 : return -1;
375 : }
376 :
377 2512 : ndr_err = ndr_pull_struct_blob(in, sd, sd,
378 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
379 2512 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
380 : /* If this does not parse, then it is probably SDDL, and we should try it that way */
381 :
382 233 : const struct dom_sid *sid = samdb_domain_sid(ldb);
383 233 : talloc_free(sd);
384 233 : sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
385 233 : if (sd == NULL) {
386 0 : return -1;
387 : }
388 : }
389 :
390 2512 : ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
391 : (ndr_push_flags_fn_t)ndr_push_security_descriptor);
392 2512 : talloc_free(sd);
393 2512 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
394 0 : return -1;
395 : }
396 :
397 2512 : return 0;
398 : }
399 :
400 : /*
401 : convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
402 : */
403 0 : static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
404 : const struct ldb_val *in, struct ldb_val *out)
405 : {
406 : struct security_descriptor *sd;
407 : enum ndr_err_code ndr_err;
408 :
409 0 : if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
410 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
411 : sizeof(struct security_descriptor),
412 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
413 : (ndr_print_fn_t)ndr_print_security_descriptor,
414 : true);
415 :
416 : }
417 :
418 0 : sd = talloc(mem_ctx, struct security_descriptor);
419 0 : if (sd == NULL) {
420 0 : return -1;
421 : }
422 : /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
423 0 : ndr_err = ndr_pull_struct_blob(in, sd, sd,
424 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
425 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
426 0 : talloc_free(sd);
427 0 : return -1;
428 : }
429 0 : out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
430 0 : talloc_free(sd);
431 0 : if (out->data == NULL) {
432 0 : return -1;
433 : }
434 0 : out->length = strlen((const char *)out->data);
435 0 : return 0;
436 : }
437 :
438 : /*
439 : convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
440 : */
441 692 : static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
442 : const struct ldb_val *in, struct ldb_val *out)
443 : {
444 692 : if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
445 : struct security_descriptor *sd;
446 0 : const struct dom_sid *sid = samdb_domain_sid(ldb);
447 :
448 0 : sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
449 0 : out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
450 : (ndr_print_fn_t)ndr_print_security_descriptor,
451 : "SDDL", sd);
452 0 : out->length = strlen((const char *)out->data);
453 0 : talloc_free(sd);
454 0 : return 0;
455 : }
456 :
457 692 : return ldb_handler_copy(ldb, mem_ctx, in, out);
458 : }
459 :
460 : /*
461 : canonicalise an objectCategory. We use the long form as the canonical form:
462 : 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
463 :
464 : Also any short name of an objectClass that points to a different
465 : class (such as user) has the canonical form of the class it's
466 : defaultObjectCategory points to (eg
467 : cn=Person,cn=Schema,cn=Configuration,<basedn>)
468 : */
469 :
470 1787602 : static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
471 : const struct ldb_val *in, struct ldb_val *out)
472 : {
473 1787602 : struct ldb_dn *dn1 = NULL;
474 1787602 : const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
475 : const struct dsdb_class *sclass;
476 1787602 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
477 1787602 : if (!tmp_ctx) {
478 0 : return LDB_ERR_OPERATIONS_ERROR;
479 : }
480 :
481 1787602 : if (!schema) {
482 2 : talloc_free(tmp_ctx);
483 2 : *out = data_blob_talloc(mem_ctx, in->data, in->length);
484 2 : if (in->data && !out->data) {
485 0 : return LDB_ERR_OPERATIONS_ERROR;
486 : }
487 2 : return LDB_SUCCESS;
488 : }
489 1787600 : dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
490 1787600 : if ( ! ldb_dn_validate(dn1)) {
491 11211 : const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
492 11211 : sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
493 11211 : if (sclass) {
494 11211 : struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
495 2370 : sclass->defaultObjectCategory);
496 11211 : if (dn == NULL) {
497 0 : talloc_free(tmp_ctx);
498 0 : return LDB_ERR_OPERATIONS_ERROR;
499 : }
500 :
501 11211 : *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
502 11211 : talloc_free(tmp_ctx);
503 :
504 11211 : if (!out->data) {
505 0 : return LDB_ERR_OPERATIONS_ERROR;
506 : }
507 11211 : return LDB_SUCCESS;
508 : } else {
509 0 : *out = data_blob_talloc(mem_ctx, in->data, in->length);
510 0 : talloc_free(tmp_ctx);
511 :
512 0 : if (in->data && !out->data) {
513 0 : return LDB_ERR_OPERATIONS_ERROR;
514 : }
515 0 : return LDB_SUCCESS;
516 : }
517 : }
518 1776389 : *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
519 1776389 : talloc_free(tmp_ctx);
520 :
521 1776389 : if (!out->data) {
522 0 : return LDB_ERR_OPERATIONS_ERROR;
523 : }
524 1776389 : return LDB_SUCCESS;
525 : }
526 :
527 69404 : static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
528 : const struct ldb_val *v1,
529 : const struct ldb_val *v2)
530 : {
531 69404 : return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
532 : v1, v2);
533 : }
534 :
535 : /*
536 : convert a NDR formatted blob to a ldif formatted schemaInfo
537 : */
538 17 : static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
539 : const struct ldb_val *in, struct ldb_val *out)
540 : {
541 17 : return ldif_write_NDR(ldb, mem_ctx, in, out,
542 : sizeof(struct repsFromToBlob),
543 : (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
544 : (ndr_print_fn_t)ndr_print_schemaInfoBlob,
545 : true);
546 : }
547 :
548 : /*
549 : convert a ldif formatted prefixMap to a NDR formatted blob
550 : */
551 322 : static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
552 : const struct ldb_val *in, struct ldb_val *out)
553 : {
554 : struct prefixMapBlob *blob;
555 : enum ndr_err_code ndr_err;
556 : char *string, *line, *p, *oid;
557 : DATA_BLOB oid_blob;
558 :
559 322 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
560 :
561 322 : if (tmp_ctx == NULL) {
562 0 : return -1;
563 : }
564 :
565 322 : blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
566 322 : if (blob == NULL) {
567 0 : talloc_free(tmp_ctx);
568 0 : return -1;
569 : }
570 :
571 : /* use the switch value to detect if this is in the binary
572 : * format
573 : */
574 322 : if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
575 70 : ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
576 : (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
577 70 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
578 70 : ndr_err = ndr_push_struct_blob(out, mem_ctx,
579 : blob,
580 : (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
581 70 : talloc_free(tmp_ctx);
582 70 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
583 0 : return -1;
584 : }
585 70 : return 0;
586 : }
587 : }
588 :
589 : /* If this does not parse, then it is probably the text version, and we should try it that way */
590 252 : blob->version = PREFIX_MAP_VERSION_DSDB;
591 :
592 252 : string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
593 252 : if (string == NULL) {
594 0 : talloc_free(blob);
595 0 : return -1;
596 : }
597 :
598 252 : line = string;
599 10795 : while (line && line[0]) {
600 10332 : int error = 0;
601 :
602 10332 : p=strchr(line, ';');
603 10332 : if (p) {
604 120 : p[0] = '\0';
605 : } else {
606 10212 : p=strchr(line, '\n');
607 10212 : if (p) {
608 10209 : p[0] = '\0';
609 : }
610 : }
611 : /* allow a trailing separator */
612 10332 : if (line == p) {
613 0 : break;
614 : }
615 :
616 10332 : blob->ctr.dsdb.mappings = talloc_realloc(blob,
617 : blob->ctr.dsdb.mappings,
618 : struct drsuapi_DsReplicaOIDMapping,
619 : blob->ctr.dsdb.num_mappings+1);
620 10332 : if (!blob->ctr.dsdb.mappings) {
621 0 : talloc_free(tmp_ctx);
622 0 : return -1;
623 : }
624 :
625 10332 : blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
626 10332 : smb_strtoul(line, &oid, 10, &error, SMB_STR_STANDARD);
627 :
628 10332 : if (oid[0] != ':' || error != 0) {
629 0 : talloc_free(tmp_ctx);
630 0 : return -1;
631 : }
632 :
633 : /* we know there must be at least ":" */
634 10332 : oid++;
635 :
636 10332 : if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
637 0 : talloc_free(tmp_ctx);
638 0 : return -1;
639 : }
640 10332 : blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
641 10332 : blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
642 :
643 10332 : blob->ctr.dsdb.num_mappings++;
644 :
645 : /* Now look past the terminator we added above */
646 10332 : if (p) {
647 10329 : line = p + 1;
648 : } else {
649 3 : line = NULL;
650 : }
651 : }
652 :
653 252 : ndr_err = ndr_push_struct_blob(out, mem_ctx,
654 : blob,
655 : (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
656 252 : talloc_free(tmp_ctx);
657 252 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
658 0 : return -1;
659 : }
660 252 : return 0;
661 : }
662 :
663 : /*
664 : convert a NDR formatted blob to a ldif formatted prefixMap
665 : */
666 3 : static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
667 : const struct ldb_val *in, struct ldb_val *out)
668 : {
669 : struct prefixMapBlob *blob;
670 : enum ndr_err_code ndr_err;
671 : char *string;
672 : uint32_t i;
673 :
674 3 : if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
675 : int err;
676 : /* try to decode the blob as S4 prefixMap */
677 0 : err = ldif_write_NDR(ldb, mem_ctx, in, out,
678 : sizeof(struct prefixMapBlob),
679 : (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
680 : (ndr_print_fn_t)ndr_print_prefixMapBlob,
681 : false);
682 0 : if (0 == err) {
683 0 : return err;
684 : }
685 : /* try parsing it as Windows PrefixMap value */
686 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
687 : sizeof(struct drsuapi_MSPrefixMap_Ctr),
688 : (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
689 : (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
690 : true);
691 : }
692 :
693 3 : blob = talloc(mem_ctx, struct prefixMapBlob);
694 3 : if (blob == NULL) {
695 0 : return -1;
696 : }
697 3 : ndr_err = ndr_pull_struct_blob_all(in, blob,
698 : blob,
699 : (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
700 3 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
701 0 : goto failed;
702 : }
703 3 : if (blob->version != PREFIX_MAP_VERSION_DSDB) {
704 0 : goto failed;
705 : }
706 3 : string = talloc_strdup(mem_ctx, "");
707 3 : if (string == NULL) {
708 0 : goto failed;
709 : }
710 :
711 252 : for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
712 : DATA_BLOB oid_blob;
713 123 : char *partial_oid = NULL;
714 :
715 123 : if (i > 0) {
716 120 : string = talloc_asprintf_append(string, ";");
717 : }
718 :
719 123 : oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
720 123 : blob->ctr.dsdb.mappings[i].oid.length);
721 123 : if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
722 0 : DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
723 : blob->ctr.dsdb.mappings[i].id_prefix));
724 0 : goto failed;
725 : }
726 246 : string = talloc_asprintf_append(string, "%u:%s",
727 123 : blob->ctr.dsdb.mappings[i].id_prefix,
728 : partial_oid);
729 123 : talloc_free(discard_const(partial_oid));
730 123 : if (string == NULL) {
731 0 : goto failed;
732 : }
733 : }
734 :
735 3 : talloc_free(blob);
736 3 : *out = data_blob_string_const(string);
737 3 : return 0;
738 :
739 0 : failed:
740 0 : talloc_free(blob);
741 0 : return -1;
742 : }
743 :
744 0 : static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
745 : {
746 0 : if (v->length < 4) {
747 0 : return true;
748 : }
749 :
750 0 : if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
751 0 : return false;
752 : }
753 :
754 0 : return true;
755 : }
756 :
757 : /*
758 : canonicalise a prefixMap
759 : */
760 0 : static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
761 : const struct ldb_val *in, struct ldb_val *out)
762 : {
763 0 : if (ldif_comparision_prefixMap_isString(in)) {
764 0 : return ldif_read_prefixMap(ldb, mem_ctx, in, out);
765 : }
766 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
767 : }
768 :
769 0 : static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
770 : const struct ldb_val *v1,
771 : const struct ldb_val *v2)
772 : {
773 0 : return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
774 : v1, v2);
775 : }
776 :
777 : /* length limited conversion of a ldb_val to a int32_t */
778 2069242 : static int val_to_int32(const struct ldb_val *in, int32_t *v)
779 : {
780 : char *end;
781 : char buf[64];
782 :
783 : /* make sure we don't read past the end of the data */
784 2069242 : if (in->length > sizeof(buf)-1) {
785 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
786 : }
787 2069242 : strncpy(buf, (char *)in->data, in->length);
788 2069242 : buf[in->length] = 0;
789 :
790 : /* We've to use "strtoll" here to have the intended overflows.
791 : * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
792 2069242 : *v = (int32_t) strtoll(buf, &end, 0);
793 2069242 : if (*end != 0) {
794 22 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
795 : }
796 2069220 : return LDB_SUCCESS;
797 : }
798 :
799 : /* length limited conversion of a ldb_val to a int64_t */
800 1300 : static int val_to_int64(const struct ldb_val *in, int64_t *v)
801 : {
802 : char *end;
803 : char buf[64];
804 :
805 : /* make sure we don't read past the end of the data */
806 1300 : if (in->length > sizeof(buf)-1) {
807 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
808 : }
809 1300 : strncpy(buf, (char *)in->data, in->length);
810 1300 : buf[in->length] = 0;
811 :
812 1300 : *v = (int64_t) strtoll(buf, &end, 0);
813 1300 : if (*end != 0) {
814 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
815 : }
816 1300 : return LDB_SUCCESS;
817 : }
818 :
819 : /* Canonicalisation of two 32-bit integers */
820 1051388 : static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
821 : const struct ldb_val *in, struct ldb_val *out)
822 : {
823 : int32_t i;
824 : int ret;
825 :
826 1051388 : ret = val_to_int32(in, &i);
827 1051388 : if (ret != LDB_SUCCESS) {
828 2 : return ret;
829 : }
830 1051386 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
831 1051386 : if (out->data == NULL) {
832 0 : ldb_oom(ldb);
833 0 : return LDB_ERR_OPERATIONS_ERROR;
834 : }
835 1051386 : out->length = strlen((char *)out->data);
836 1051386 : return 0;
837 : }
838 :
839 : /*
840 : * Lexicographically sorted representation for a 32-bit integer
841 : *
842 : * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
843 : * n o p
844 : *
845 : * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
846 : * corresponding documentation for 64-bit integers.
847 : *
848 : * The same rules apply but use INT32_MIN and INT32_MAX.
849 : *
850 : * String representation padding is done to 10 characters.
851 : *
852 : * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
853 : *
854 : */
855 449036 : static int ldif_index_format_int32(struct ldb_context *ldb,
856 : void *mem_ctx,
857 : const struct ldb_val *in,
858 : struct ldb_val *out)
859 : {
860 : int32_t i;
861 : int ret;
862 : char prefix;
863 : size_t len;
864 :
865 449036 : ret = val_to_int32(in, &i);
866 449036 : if (ret != LDB_SUCCESS) {
867 0 : return ret;
868 : }
869 :
870 449036 : if (i < 0) {
871 : /*
872 : * i is negative, so this is subtraction rather than
873 : * wrap-around.
874 : */
875 45216 : prefix = 'n';
876 45216 : i = INT32_MAX + i + 1;
877 403820 : } else if (i > 0) {
878 403808 : prefix = 'p';
879 : } else {
880 12 : prefix = 'o';
881 : }
882 :
883 449036 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
884 449036 : if (out->data == NULL) {
885 0 : ldb_oom(ldb);
886 0 : return LDB_ERR_OPERATIONS_ERROR;
887 : }
888 :
889 449036 : len = talloc_array_length(out->data) - 1;
890 449036 : if (len != 11) {
891 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
892 : __location__ ": expected index format str %s to"
893 : " have length 11 but got %zu",
894 0 : (char*)out->data, len);
895 0 : return LDB_ERR_OPERATIONS_ERROR;
896 : }
897 :
898 449036 : out->length = 11;
899 449036 : return 0;
900 : }
901 :
902 : /* Comparison of two 32-bit integers */
903 284409 : static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
904 : const struct ldb_val *v1, const struct ldb_val *v2)
905 : {
906 284409 : int32_t i1=0, i2=0;
907 284409 : val_to_int32(v1, &i1);
908 284409 : val_to_int32(v2, &i2);
909 284409 : if (i1 == i2) return 0;
910 186569 : return i1 > i2? 1 : -1;
911 : }
912 :
913 : /* Canonicalisation of two 64-bit integers */
914 754 : static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
915 : const struct ldb_val *in, struct ldb_val *out)
916 : {
917 : int64_t i;
918 : int ret;
919 :
920 754 : ret = val_to_int64(in, &i);
921 754 : if (ret != LDB_SUCCESS) {
922 0 : return ret;
923 : }
924 754 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
925 754 : if (out->data == NULL) {
926 0 : ldb_oom(ldb);
927 0 : return LDB_ERR_OPERATIONS_ERROR;
928 : }
929 754 : out->length = strlen((char *)out->data);
930 754 : return 0;
931 : }
932 :
933 : /* Comparison of two 64-bit integers */
934 196 : static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
935 : const struct ldb_val *v1, const struct ldb_val *v2)
936 : {
937 196 : int64_t i1=0, i2=0;
938 196 : val_to_int64(v1, &i1);
939 196 : val_to_int64(v2, &i2);
940 196 : if (i1 == i2) return 0;
941 0 : return i1 > i2? 1 : -1;
942 : }
943 :
944 : /*
945 : convert a NDR formatted blob to a ldif formatted repsFromTo
946 : */
947 1 : static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
948 : const struct ldb_val *in, struct ldb_val *out)
949 : {
950 1 : return ldif_write_NDR(ldb, mem_ctx, in, out,
951 : sizeof(struct repsFromToBlob),
952 : (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
953 : (ndr_print_fn_t)ndr_print_repsFromToBlob,
954 : true);
955 : }
956 :
957 : /*
958 : convert a NDR formatted blob to a ldif formatted replPropertyMetaData
959 : */
960 12 : static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
961 : const struct ldb_val *in, struct ldb_val *out)
962 : {
963 12 : return ldif_write_NDR(ldb, mem_ctx, in, out,
964 : sizeof(struct replPropertyMetaDataBlob),
965 : (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
966 : (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
967 : true);
968 : }
969 :
970 : /*
971 : convert a NDR formatted blob to a ldif formatted replUpToDateVector
972 : */
973 1 : static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
974 : const struct ldb_val *in, struct ldb_val *out)
975 : {
976 1 : return ldif_write_NDR(ldb, mem_ctx, in, out,
977 : sizeof(struct replUpToDateVectorBlob),
978 : (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
979 : (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
980 : true);
981 : }
982 :
983 0 : static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
984 : const struct ldb_val *in, struct ldb_val *out,
985 : size_t struct_size,
986 : ndr_pull_flags_fn_t pull_fn,
987 : ndr_print_fn_t print_fn,
988 : bool mask_errors)
989 : {
990 0 : uint8_t *p = NULL;
991 : enum ndr_err_code err;
992 0 : struct dsdb_dn *dsdb_dn = NULL;
993 0 : char *dn_str = NULL;
994 0 : char *str = NULL;
995 :
996 0 : if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
997 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
998 : }
999 :
1000 0 : dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
1001 0 : if (dsdb_dn == NULL) {
1002 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1003 : }
1004 :
1005 0 : p = talloc_size(dsdb_dn, struct_size);
1006 0 : if (p == NULL) {
1007 0 : TALLOC_FREE(dsdb_dn);
1008 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1009 : }
1010 :
1011 0 : err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
1012 0 : if (err != NDR_ERR_SUCCESS) {
1013 : /* fail in not in mask_error mode */
1014 0 : if (!mask_errors) {
1015 0 : return -1;
1016 : }
1017 0 : TALLOC_FREE(dsdb_dn);
1018 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1019 : }
1020 :
1021 0 : dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
1022 0 : if (dn_str == NULL) {
1023 0 : TALLOC_FREE(dsdb_dn);
1024 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1025 : }
1026 :
1027 0 : str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
1028 0 : TALLOC_FREE(dsdb_dn);
1029 0 : if (str == NULL) {
1030 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1031 : }
1032 :
1033 0 : *out = data_blob_string_const(str);
1034 0 : return 0;
1035 : }
1036 :
1037 0 : static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
1038 : const struct ldb_val *in, struct ldb_val *out)
1039 : {
1040 0 : return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
1041 : sizeof(struct replPropertyMetaData1),
1042 : (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
1043 : (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
1044 : true);
1045 : }
1046 :
1047 : /*
1048 : convert a NDR formatted blob to a ldif formatted dnsRecord
1049 : */
1050 572 : static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
1051 : const struct ldb_val *in, struct ldb_val *out)
1052 : {
1053 572 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1054 : sizeof(struct dnsp_DnssrvRpcRecord),
1055 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
1056 : (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
1057 : true);
1058 : }
1059 :
1060 : /*
1061 : convert a NDR formatted blob to a ldif formatted dnsProperty
1062 : */
1063 154 : static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1064 : const struct ldb_val *in, struct ldb_val *out)
1065 : {
1066 154 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1067 : sizeof(struct dnsp_DnsProperty),
1068 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1069 : (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1070 : true);
1071 : }
1072 :
1073 : /*
1074 : convert a NDR formatted blob of a supplementalCredentials into text
1075 : */
1076 45 : static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1077 : const struct ldb_val *in, struct ldb_val *out)
1078 : {
1079 45 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1080 : sizeof(struct supplementalCredentialsBlob),
1081 : (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1082 : (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1083 : true);
1084 : }
1085 :
1086 : /*
1087 : convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1088 : */
1089 0 : static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1090 : const struct ldb_val *in, struct ldb_val *out)
1091 : {
1092 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1093 : sizeof(struct trustAuthInOutBlob),
1094 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1095 : (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1096 : true);
1097 : }
1098 :
1099 : /*
1100 : convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1101 : */
1102 0 : static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1103 : const struct ldb_val *in, struct ldb_val *out)
1104 : {
1105 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1106 : sizeof(struct ForestTrustInfo),
1107 : (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1108 : (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1109 : true);
1110 : }
1111 : /*
1112 : convert a NDR formatted blob of a partialAttributeSet into text
1113 : */
1114 0 : static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1115 : const struct ldb_val *in, struct ldb_val *out)
1116 : {
1117 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1118 : sizeof(struct partialAttributeSetBlob),
1119 : (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1120 : (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1121 : true);
1122 : }
1123 :
1124 :
1125 5926997 : static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1126 : const struct ldb_val *in, struct ldb_val *out)
1127 : {
1128 5926997 : *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1129 5926997 : if (!out->data) {
1130 0 : return -1;
1131 : }
1132 5926997 : return 0;
1133 : }
1134 :
1135 : /*
1136 : compare two dns
1137 : */
1138 0 : static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1139 : const struct ldb_val *v1, const struct ldb_val *v2)
1140 : {
1141 0 : struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1142 : int ret;
1143 :
1144 0 : if (dsdb_dn_is_deleted_val(v1)) {
1145 : /* If the DN is deleted, then we can't search for it */
1146 0 : return -1;
1147 : }
1148 :
1149 0 : if (dsdb_dn_is_deleted_val(v2)) {
1150 : /* If the DN is deleted, then we can't search for it */
1151 0 : return -1;
1152 : }
1153 :
1154 0 : dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1155 0 : if ( ! ldb_dn_validate(dn1)) return -1;
1156 :
1157 0 : dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1158 0 : if ( ! ldb_dn_validate(dn2)) {
1159 0 : talloc_free(dn1);
1160 0 : return -1;
1161 : }
1162 :
1163 0 : ret = ldb_dn_compare(dn1, dn2);
1164 :
1165 0 : talloc_free(dn1);
1166 0 : talloc_free(dn2);
1167 0 : return ret;
1168 : }
1169 :
1170 13815 : static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1171 : const struct ldb_val *in, struct ldb_val *out)
1172 : {
1173 : struct ldb_dn *dn;
1174 13815 : int ret = -1;
1175 :
1176 13815 : out->length = 0;
1177 13815 : out->data = NULL;
1178 :
1179 13815 : dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1180 13815 : if ( ! ldb_dn_validate(dn)) {
1181 0 : return LDB_ERR_INVALID_DN_SYNTAX;
1182 : }
1183 :
1184 : /* By including the RMD_FLAGS of a deleted DN, we ensure it
1185 : * does not casually match a not deleted DN */
1186 13815 : if (dsdb_dn_is_deleted_val(in)) {
1187 0 : out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1188 : "<RMD_FLAGS=%u>%s",
1189 : dsdb_dn_val_rmd_flags(in),
1190 : ldb_dn_get_casefold(dn));
1191 : } else {
1192 13815 : out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1193 : }
1194 :
1195 13815 : if (out->data == NULL) {
1196 0 : goto done;
1197 : }
1198 13815 : out->length = strlen((char *)out->data);
1199 :
1200 13815 : ret = 0;
1201 :
1202 13815 : done:
1203 13815 : talloc_free(dn);
1204 :
1205 13815 : return ret;
1206 : }
1207 :
1208 :
1209 : /*
1210 : write a 64 bit 2-part range
1211 : */
1212 154 : static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1213 : const struct ldb_val *in, struct ldb_val *out)
1214 : {
1215 : int64_t v;
1216 : int ret;
1217 154 : ret = val_to_int64(in, &v);
1218 154 : if (ret != LDB_SUCCESS) {
1219 0 : return ret;
1220 : }
1221 308 : out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1222 154 : (unsigned long)(v&0xFFFFFFFF),
1223 154 : (unsigned long)(v>>32));
1224 154 : if (out->data == NULL) {
1225 0 : ldb_oom(ldb);
1226 0 : return LDB_ERR_OPERATIONS_ERROR;
1227 : }
1228 154 : out->length = strlen((char *)out->data);
1229 154 : return LDB_SUCCESS;
1230 : }
1231 :
1232 : /*
1233 : read a 64 bit 2-part range
1234 : */
1235 229 : static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1236 : const struct ldb_val *in, struct ldb_val *out)
1237 : {
1238 : unsigned long high, low;
1239 : char buf[64];
1240 :
1241 229 : if (memchr(in->data, '-', in->length) == NULL) {
1242 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1243 : }
1244 :
1245 229 : if (in->length > sizeof(buf)-1) {
1246 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1247 : }
1248 229 : strncpy(buf, (const char *)in->data, in->length);
1249 229 : buf[in->length] = 0;
1250 :
1251 229 : if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1252 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1253 : }
1254 :
1255 274 : out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1256 229 : (unsigned long long)(((uint64_t)high)<<32) | (low));
1257 :
1258 229 : if (out->data == NULL) {
1259 0 : ldb_oom(ldb);
1260 0 : return LDB_ERR_OPERATIONS_ERROR;
1261 : }
1262 229 : out->length = strlen((char *)out->data);
1263 229 : return LDB_SUCCESS;
1264 : }
1265 :
1266 : /*
1267 : when this operator_fn is set for a syntax, the backend calls is in
1268 : preference to the comparison function. We are told the exact
1269 : comparison operation that is needed, and we can return errors
1270 : */
1271 13834599 : static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1272 : const struct ldb_schema_attribute *a,
1273 : const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1274 : {
1275 13834599 : switch (operation) {
1276 0 : case LDB_OP_AND:
1277 : case LDB_OP_OR:
1278 : case LDB_OP_NOT:
1279 : case LDB_OP_SUBSTRING:
1280 : case LDB_OP_APPROX:
1281 : case LDB_OP_EXTENDED:
1282 : /* handled in the backends */
1283 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
1284 :
1285 13702337 : case LDB_OP_GREATER:
1286 : case LDB_OP_LESS:
1287 : case LDB_OP_EQUALITY:
1288 : {
1289 13702337 : TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1290 : int ret;
1291 13702337 : if (tmp_ctx == NULL) {
1292 0 : return ldb_oom(ldb);
1293 : }
1294 13702337 : ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1295 13702337 : talloc_free(tmp_ctx);
1296 13702337 : if (operation == LDB_OP_GREATER) {
1297 188 : *matched = (ret >= 0);
1298 13702149 : } else if (operation == LDB_OP_LESS) {
1299 146 : *matched = (ret <= 0);
1300 : } else {
1301 13702003 : *matched = (ret == 0);
1302 : }
1303 13702337 : return LDB_SUCCESS;
1304 : }
1305 :
1306 132262 : case LDB_OP_PRESENT:
1307 132262 : *matched = true;
1308 132262 : return LDB_SUCCESS;
1309 : }
1310 :
1311 : /* we shouldn't get here */
1312 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
1313 : }
1314 :
1315 : /*
1316 : compare two binary objects. This is correct for sorting as the sort order is:
1317 :
1318 : a
1319 : aa
1320 : b
1321 : bb
1322 :
1323 : rather than ldb_comparison_binary() which is:
1324 :
1325 : a
1326 : b
1327 : aa
1328 : bb
1329 :
1330 : */
1331 61896 : static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1332 : const struct ldb_val *v1, const struct ldb_val *v2)
1333 : {
1334 61896 : return data_blob_cmp(v1, v2);
1335 : }
1336 :
1337 : /*
1338 : when this operator_fn is set for a syntax, the backend calls is in
1339 : preference to the comparison function. We are told the exact
1340 : comparison operation that is needed, and we can return errors.
1341 :
1342 : This mode optimises for ldb_comparison_binary() if we need equality,
1343 : as this should be faster as it can do a length-check first.
1344 : */
1345 31 : static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1346 : const struct ldb_schema_attribute *a,
1347 : const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1348 : {
1349 31 : if (operation == LDB_OP_EQUALITY) {
1350 25 : *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1351 25 : return LDB_SUCCESS;
1352 : }
1353 6 : return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1354 : }
1355 :
1356 : /*
1357 : see if two DNs match, comparing first by GUID, then by SID, and
1358 : finally by string components
1359 : */
1360 245449 : static int samba_dn_extended_match(struct ldb_context *ldb,
1361 : const struct ldb_val *v1,
1362 : const struct ldb_val *v2,
1363 : bool *matched)
1364 : {
1365 : TALLOC_CTX *tmp_ctx;
1366 : struct ldb_dn *dn1, *dn2;
1367 : const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1368 : uint32_t rmd_flags1, rmd_flags2;
1369 :
1370 245449 : tmp_ctx = talloc_new(ldb);
1371 :
1372 245449 : dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1373 245449 : dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1374 245449 : if (!dn1 || !dn2) {
1375 : /* couldn't parse as DN's */
1376 0 : talloc_free(tmp_ctx);
1377 0 : (*matched) = false;
1378 0 : return LDB_SUCCESS;
1379 : }
1380 :
1381 245449 : rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1382 245449 : rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1383 :
1384 245449 : if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1385 : (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1386 : /* only match if they have the same deletion status */
1387 1097 : talloc_free(tmp_ctx);
1388 1097 : (*matched) = false;
1389 1097 : return LDB_SUCCESS;
1390 : }
1391 :
1392 :
1393 244352 : guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1394 244352 : guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1395 244352 : if (guid1 && guid2) {
1396 198092 : (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1397 198092 : talloc_free(tmp_ctx);
1398 198092 : return LDB_SUCCESS;
1399 : }
1400 :
1401 46260 : sid1 = ldb_dn_get_extended_component(dn1, "SID");
1402 46260 : sid2 = ldb_dn_get_extended_component(dn2, "SID");
1403 46260 : if (sid1 && sid2) {
1404 8623 : (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1405 8623 : talloc_free(tmp_ctx);
1406 8623 : return LDB_SUCCESS;
1407 : }
1408 :
1409 37637 : (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1410 :
1411 37637 : talloc_free(tmp_ctx);
1412 37637 : return LDB_SUCCESS;
1413 : }
1414 :
1415 : /*
1416 : special operation for DNs, to take account of the RMD_FLAGS deleted bit
1417 : */
1418 245902 : static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1419 : const struct ldb_schema_attribute *a,
1420 : const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1421 : {
1422 245902 : if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1423 : /* If the DN is deleted, then we can't search for it */
1424 :
1425 : /* should this be for equality too? */
1426 0 : *matched = false;
1427 0 : return LDB_SUCCESS;
1428 : }
1429 :
1430 491351 : if (operation == LDB_OP_EQUALITY &&
1431 245449 : samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1432 245449 : return LDB_SUCCESS;
1433 : }
1434 :
1435 453 : return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1436 : }
1437 :
1438 :
1439 : static const struct ldb_schema_syntax samba_syntaxes[] = {
1440 : {
1441 : .name = LDB_SYNTAX_SAMBA_SID,
1442 : .ldif_read_fn = ldif_read_objectSid,
1443 : .ldif_write_fn = ldif_write_objectSid,
1444 : .canonicalise_fn = ldif_canonicalise_objectSid,
1445 : .comparison_fn = ldif_comparison_objectSid,
1446 : .operator_fn = samba_syntax_operator_fn
1447 : },{
1448 : .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1449 : .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1450 : .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1451 : .canonicalise_fn = ldb_handler_copy,
1452 : .comparison_fn = samba_ldb_comparison_binary,
1453 : .operator_fn = samba_syntax_binary_operator_fn
1454 : },{
1455 : .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1456 : .ldif_read_fn = ldb_handler_copy,
1457 : .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1458 : .canonicalise_fn = ldb_handler_fold,
1459 : .comparison_fn = ldb_comparison_fold,
1460 : .operator_fn = samba_syntax_operator_fn
1461 : },{
1462 : .name = LDB_SYNTAX_SAMBA_GUID,
1463 : .ldif_read_fn = ldif_read_objectGUID,
1464 : .ldif_write_fn = ldif_write_objectGUID,
1465 : .canonicalise_fn = ldif_canonicalise_objectGUID,
1466 : .comparison_fn = ldif_comparison_objectGUID,
1467 : .operator_fn = samba_syntax_operator_fn
1468 : },{
1469 : .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1470 : .ldif_read_fn = ldb_handler_copy,
1471 : .ldif_write_fn = ldb_handler_copy,
1472 : .canonicalise_fn = ldif_canonicalise_objectCategory,
1473 : .comparison_fn = ldif_comparison_objectCategory,
1474 : .operator_fn = samba_syntax_operator_fn
1475 : },{
1476 : .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1477 : .ldif_read_fn = ldb_handler_copy,
1478 : .ldif_write_fn = ldif_write_schemaInfo,
1479 : .canonicalise_fn = ldb_handler_copy,
1480 : .comparison_fn = samba_ldb_comparison_binary,
1481 : .operator_fn = samba_syntax_binary_operator_fn
1482 : },{
1483 : .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1484 : .ldif_read_fn = ldif_read_prefixMap,
1485 : .ldif_write_fn = ldif_write_prefixMap,
1486 : .canonicalise_fn = ldif_canonicalise_prefixMap,
1487 : .comparison_fn = ldif_comparison_prefixMap,
1488 : .operator_fn = samba_syntax_operator_fn
1489 : },{
1490 : .name = LDB_SYNTAX_SAMBA_INT32,
1491 : .ldif_read_fn = ldb_handler_copy,
1492 : .ldif_write_fn = ldb_handler_copy,
1493 : .canonicalise_fn = ldif_canonicalise_int32,
1494 : .index_format_fn = ldif_index_format_int32,
1495 : .comparison_fn = ldif_comparison_int32,
1496 : .operator_fn = samba_syntax_operator_fn
1497 : },{
1498 : .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1499 : .ldif_read_fn = ldb_handler_copy,
1500 : .ldif_write_fn = ldif_write_repsFromTo,
1501 : .canonicalise_fn = ldb_handler_copy,
1502 : .comparison_fn = samba_ldb_comparison_binary,
1503 : .operator_fn = samba_syntax_binary_operator_fn
1504 : },{
1505 : .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1506 : .ldif_read_fn = ldb_handler_copy,
1507 : .ldif_write_fn = ldif_write_replPropertyMetaData,
1508 : .canonicalise_fn = ldb_handler_copy,
1509 : .comparison_fn = samba_ldb_comparison_binary,
1510 : .operator_fn = samba_syntax_binary_operator_fn
1511 : },{
1512 : .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1513 : .ldif_read_fn = ldb_handler_copy,
1514 : .ldif_write_fn = ldif_write_replUpToDateVector,
1515 : .canonicalise_fn = ldb_handler_copy,
1516 : .comparison_fn = samba_ldb_comparison_binary,
1517 : .operator_fn = samba_syntax_binary_operator_fn
1518 : },{
1519 : .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1520 : .ldif_read_fn = ldb_handler_copy,
1521 : .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1522 : .canonicalise_fn = dsdb_dn_binary_canonicalise,
1523 : .comparison_fn = dsdb_dn_binary_comparison,
1524 : .operator_fn = samba_syntax_operator_fn
1525 : },{
1526 : .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1527 : .ldif_read_fn = ldb_handler_copy,
1528 : .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1529 : .canonicalise_fn = ldb_handler_copy,
1530 : .comparison_fn = samba_ldb_comparison_binary,
1531 : .operator_fn = samba_syntax_binary_operator_fn
1532 : },{
1533 : .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1534 : .ldif_read_fn = ldb_handler_copy,
1535 : .ldif_write_fn = ldif_write_ForestTrustInfo,
1536 : .canonicalise_fn = ldb_handler_copy,
1537 : .comparison_fn = samba_ldb_comparison_binary,
1538 : .operator_fn = samba_syntax_binary_operator_fn
1539 : },{
1540 : .name = DSDB_SYNTAX_BINARY_DN,
1541 : .ldif_read_fn = ldb_handler_copy,
1542 : .ldif_write_fn = ldb_handler_copy,
1543 : .canonicalise_fn = dsdb_dn_binary_canonicalise,
1544 : .comparison_fn = dsdb_dn_binary_comparison,
1545 : .operator_fn = samba_syntax_operator_fn
1546 : },{
1547 : .name = DSDB_SYNTAX_STRING_DN,
1548 : .ldif_read_fn = ldb_handler_copy,
1549 : .ldif_write_fn = ldb_handler_copy,
1550 : .canonicalise_fn = dsdb_dn_string_canonicalise,
1551 : .comparison_fn = dsdb_dn_string_comparison,
1552 : .operator_fn = samba_syntax_operator_fn
1553 : },{
1554 : .name = LDB_SYNTAX_DN,
1555 : .ldif_read_fn = ldb_handler_copy,
1556 : .ldif_write_fn = ldb_handler_copy,
1557 : .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1558 : .comparison_fn = samba_ldb_dn_link_comparison,
1559 : .operator_fn = samba_syntax_operator_dn
1560 : },{
1561 : .name = LDB_SYNTAX_SAMBA_RANGE64,
1562 : .ldif_read_fn = ldif_read_range64,
1563 : .ldif_write_fn = ldif_write_range64,
1564 : .canonicalise_fn = ldif_canonicalise_int64,
1565 : .comparison_fn = ldif_comparison_int64,
1566 : .operator_fn = samba_syntax_operator_fn
1567 : },{
1568 : .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1569 : .ldif_read_fn = ldb_handler_copy,
1570 : .ldif_write_fn = ldif_write_dnsRecord,
1571 : .canonicalise_fn = ldb_handler_copy,
1572 : .comparison_fn = samba_ldb_comparison_binary,
1573 : .operator_fn = samba_syntax_binary_operator_fn
1574 : },{
1575 : .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1576 : .ldif_read_fn = ldb_handler_copy,
1577 : .ldif_write_fn = ldif_write_dnsProperty,
1578 : .canonicalise_fn = ldb_handler_copy,
1579 : .comparison_fn = samba_ldb_comparison_binary,
1580 : .operator_fn = samba_syntax_binary_operator_fn
1581 : },{
1582 : .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1583 : .ldif_read_fn = ldb_handler_copy,
1584 : .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1585 : .canonicalise_fn = ldb_handler_copy,
1586 : .comparison_fn = samba_ldb_comparison_binary,
1587 : .operator_fn = samba_syntax_binary_operator_fn
1588 : },{
1589 : .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1590 : .ldif_read_fn = ldb_handler_copy,
1591 : .ldif_write_fn = ldif_write_partialAttributeSet,
1592 : .canonicalise_fn = ldb_handler_copy,
1593 : .comparison_fn = samba_ldb_comparison_binary,
1594 : .operator_fn = samba_syntax_binary_operator_fn
1595 : },{
1596 : .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1597 : .ldif_read_fn = ldb_handler_copy,
1598 : .ldif_write_fn = ldb_handler_copy,
1599 : .canonicalise_fn = ldb_handler_copy,
1600 : .comparison_fn = samba_ldb_comparison_binary,
1601 : .operator_fn = samba_syntax_binary_operator_fn
1602 : }
1603 : };
1604 :
1605 : static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1606 : {
1607 : .name = "SID",
1608 : .read_fn = extended_dn_read_SID,
1609 : .write_clear_fn = ldif_write_objectSid,
1610 : .write_hex_fn = extended_dn_write_hex
1611 : },{
1612 : .name = "GUID",
1613 : .read_fn = extended_dn_read_GUID,
1614 : .write_clear_fn = ldif_write_objectGUID,
1615 : .write_hex_fn = extended_dn_write_hex
1616 : },{
1617 : .name = "WKGUID",
1618 : .read_fn = ldb_handler_copy,
1619 : .write_clear_fn = ldb_handler_copy,
1620 : .write_hex_fn = ldb_handler_copy
1621 : },{
1622 : .name = "RMD_INVOCID",
1623 : .read_fn = extended_dn_read_GUID,
1624 : .write_clear_fn = ldif_write_objectGUID,
1625 : .write_hex_fn = extended_dn_write_hex
1626 : },{
1627 : .name = "RMD_FLAGS",
1628 : .read_fn = ldb_handler_copy,
1629 : .write_clear_fn = ldb_handler_copy,
1630 : .write_hex_fn = ldb_handler_copy
1631 : },{
1632 : .name = "RMD_ADDTIME",
1633 : .read_fn = ldb_handler_copy,
1634 : .write_clear_fn = ldb_handler_copy,
1635 : .write_hex_fn = ldb_handler_copy
1636 : },{
1637 : .name = "RMD_CHANGETIME",
1638 : .read_fn = ldb_handler_copy,
1639 : .write_clear_fn = ldb_handler_copy,
1640 : .write_hex_fn = ldb_handler_copy
1641 : },{
1642 : .name = "RMD_LOCAL_USN",
1643 : .read_fn = ldb_handler_copy,
1644 : .write_clear_fn = ldb_handler_copy,
1645 : .write_hex_fn = ldb_handler_copy
1646 : },{
1647 : .name = "RMD_ORIGINATING_USN",
1648 : .read_fn = ldb_handler_copy,
1649 : .write_clear_fn = ldb_handler_copy,
1650 : .write_hex_fn = ldb_handler_copy
1651 : },{
1652 : .name = "RMD_VERSION",
1653 : .read_fn = ldb_handler_copy,
1654 : .write_clear_fn = ldb_handler_copy,
1655 : .write_hex_fn = ldb_handler_copy
1656 : }
1657 : };
1658 :
1659 : /* TODO: Should be dynamic at some point */
1660 : static const struct {
1661 : const char *name;
1662 : const char *syntax;
1663 : } samba_attributes[] = {
1664 : { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1665 : { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1666 : { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1667 : { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1668 : { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1669 : { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1670 : { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1671 : { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1672 : { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1673 : { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1674 : { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1675 : { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1676 : { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1677 : { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1678 : { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1679 : { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1680 : { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1681 :
1682 : /*
1683 : * these are extracted by searching
1684 : * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1685 : *
1686 : * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1687 : * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1688 : * hat can be used to identify the set of policies when applied to a resource.
1689 : * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1690 : * server, we ignore it here.
1691 : */
1692 : { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1693 : { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1694 : { "objectSid", LDB_SYNTAX_SAMBA_SID },
1695 : { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1696 : { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1697 : { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1698 : { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1699 : { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1700 : { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1701 :
1702 : /*
1703 : * these are extracted by searching
1704 : * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1705 : */
1706 : { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1707 : { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1708 : { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1709 : { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1710 : { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1711 : { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1712 : { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1713 : { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1714 : { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1715 : { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1716 : { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1717 : { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1718 : { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1719 : { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1720 : { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1721 : { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1722 : { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1723 : { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1724 : { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1725 : { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1726 : { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1727 : { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1728 : { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1729 : { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1730 : { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1731 : { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1732 : { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1733 : { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1734 :
1735 : /*
1736 : * these are known to be GUIDs
1737 : */
1738 : { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1739 : { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1740 :
1741 : /* These NDR encoded things we want to be able to read with --show-binary */
1742 : { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1743 : { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1744 : { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1745 : { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1746 : };
1747 :
1748 40297025 : const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1749 : {
1750 : unsigned int j;
1751 40297025 : const struct ldb_schema_syntax *s = NULL;
1752 :
1753 611247950 : for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1754 597310816 : if (strcmp(name, samba_syntaxes[j].name) == 0) {
1755 26359891 : s = &samba_syntaxes[j];
1756 26359891 : break;
1757 : }
1758 : }
1759 40297025 : return s;
1760 : }
1761 :
1762 27545885 : const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1763 : {
1764 : unsigned int j;
1765 27545885 : const struct ldb_schema_syntax *s = NULL;
1766 :
1767 1645883427 : for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1768 1619467457 : if (strcmp(samba_attributes[j].name, name) == 0) {
1769 1129915 : s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1770 1129915 : break;
1771 : }
1772 : }
1773 :
1774 27545885 : return s;
1775 : }
1776 :
1777 : static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1778 : "priorSecret", NULL};
1779 :
1780 : /*
1781 : register the samba ldif handlers
1782 : */
1783 320538 : int ldb_register_samba_handlers(struct ldb_context *ldb)
1784 : {
1785 : unsigned int i;
1786 : int ret;
1787 :
1788 320538 : if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1789 108019 : return LDB_SUCCESS;
1790 : }
1791 :
1792 212519 : ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1793 212519 : if (ret != LDB_SUCCESS) {
1794 0 : return ret;
1795 : }
1796 :
1797 12963659 : for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1798 12751140 : const struct ldb_schema_syntax *s = NULL;
1799 :
1800 12751140 : s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1801 :
1802 12751140 : if (!s) {
1803 0 : s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1804 : }
1805 :
1806 12751140 : if (!s) {
1807 0 : return LDB_ERR_OPERATIONS_ERROR;
1808 : }
1809 :
1810 12751140 : ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1811 12751140 : if (ret != LDB_SUCCESS) {
1812 0 : return ret;
1813 : }
1814 : }
1815 :
1816 2337709 : for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1817 2125190 : ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1818 2125190 : if (ret != LDB_SUCCESS) {
1819 0 : return ret;
1820 : }
1821 :
1822 : }
1823 :
1824 212519 : ret = ldb_register_samba_matching_rules(ldb);
1825 212519 : if (ret != LDB_SUCCESS) {
1826 0 : talloc_free(ldb);
1827 0 : return LDB_SUCCESS;
1828 : }
1829 :
1830 212519 : ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1831 212519 : if (ret != LDB_SUCCESS) {
1832 0 : return ret;
1833 : }
1834 :
1835 212519 : return LDB_SUCCESS;
1836 : }
|