ldb-samba:ldif_handlers: dn_link_comparison: sort invalid DNs
[samba.git] / lib / ldb-samba / ldif_handlers.c
blobf77f86fdcc00349bbfbcb4ab62d41d6534be4301
1 /*
2 ldb database library - ldif handlers for Samba
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
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.
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.
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/>.
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"
42 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
44 If mask_errors is true, then function succeeds but out data
45 is set to "<Unable to decode binary data>" message
47 \return 0 on success; -1 on error
49 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)
56 uint8_t *p;
57 enum ndr_err_code err;
58 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
59 return ldb_handler_copy(ldb, mem_ctx, in, out);
61 p = talloc_size(mem_ctx, struct_size);
62 err = ndr_pull_struct_blob(in, mem_ctx,
63 p, pull_fn);
64 if (err != NDR_ERR_SUCCESS) {
65 /* fail in not in mask_error mode */
66 if (!mask_errors) {
67 return -1;
69 talloc_free(p);
70 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
71 out->length = strlen((const char *)out->data);
72 return 0;
74 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
75 talloc_free(p);
76 if (out->data == NULL) {
77 return ldb_handler_copy(ldb, mem_ctx, in, out);
79 out->length = strlen((char *)out->data);
80 return 0;
84 convert a ldif formatted objectSid to a NDR formatted blob
86 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
87 const struct ldb_val *in, struct ldb_val *out)
89 bool ret;
90 enum ndr_err_code ndr_err;
91 struct dom_sid sid;
92 if (in->length > DOM_SID_STR_BUFLEN) {
93 return -1;
94 } else {
95 char p[in->length+1];
96 memcpy(p, in->data, in->length);
97 p[in->length] = '\0';
99 ret = dom_sid_parse(p, &sid);
100 if (ret == false) {
101 return -1;
104 *out = data_blob_talloc(mem_ctx, NULL,
105 ndr_size_dom_sid(&sid, 0));
106 if (out->data == NULL) {
107 return -1;
110 ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
111 (ndr_push_flags_fn_t)ndr_push_dom_sid);
112 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
113 TALLOC_FREE(out->data);
114 return -1;
117 return 0;
121 convert a NDR formatted blob to a ldif formatted objectSid
123 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
124 const struct ldb_val *in, struct ldb_val *out)
126 struct dom_sid sid;
127 enum ndr_err_code ndr_err;
129 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
130 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
131 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
132 return -1;
134 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
135 if (out->data == NULL) {
136 return -1;
138 return 0;
141 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
143 if (v->length < 3) {
144 return false;
147 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
149 return true;
153 compare two objectSids
155 If the SIDs seem to be strings, they are converted to binary form.
157 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
158 const struct ldb_val *v1, const struct ldb_val *v2)
160 bool v1_is_string = ldif_comparision_objectSid_isString(v1);
161 bool v2_is_string = ldif_comparision_objectSid_isString(v2);
162 struct ldb_val parsed_1 = {};
163 struct ldb_val parsed_2 = {};
164 int ret;
166 * If the ldb_vals look like SID strings (i.e. start with "S-"
167 * or "s-"), we try to parse them as such. If that fails, we
168 * assume they are binary SIDs, even though that's not really
169 * possible -- the first two bytes of a struct dom_sid are the
170 * version (1), and the number of sub-auths (<= 15), neither
171 * of which are close to 'S' or '-'.
173 if (v1_is_string) {
174 int r = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1);
175 if (r == 0) {
176 v1 = &parsed_1;
179 if (v2_is_string) {
180 int r = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2);
181 if (r == 0) {
182 v2 = &parsed_2;
186 ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
188 if (v1_is_string) {
189 TALLOC_FREE(parsed_1.data);
191 if (v2_is_string) {
192 TALLOC_FREE(parsed_2.data);
194 return ret;
198 canonicalise a objectSid
200 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
201 const struct ldb_val *in, struct ldb_val *out)
203 if (ldif_comparision_objectSid_isString(in)) {
204 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
205 /* Perhaps not a string after all */
206 return ldb_handler_copy(ldb, mem_ctx, in, out);
208 return 0;
210 return ldb_handler_copy(ldb, mem_ctx, in, out);
213 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
214 const struct ldb_val *in, struct ldb_val *out)
216 struct dom_sid sid;
217 enum ndr_err_code ndr_err;
218 if (ldif_comparision_objectSid_isString(in)) {
219 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
220 return 0;
224 /* Perhaps not a string after all */
225 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
227 if (!out->data) {
228 return -1;
231 (*out).length = strhex_to_str((char *)out->data, out->length,
232 (const char *)in->data, in->length);
234 /* Check it looks like a SID */
235 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
236 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
237 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
238 TALLOC_FREE(out->data);
239 return -1;
241 return 0;
245 convert a ldif formatted objectGUID to a NDR formatted blob
247 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
248 const struct ldb_val *in, struct ldb_val *out)
250 struct GUID guid;
251 NTSTATUS status;
253 status = GUID_from_data_blob(in, &guid);
254 if (!NT_STATUS_IS_OK(status)) {
255 return -1;
258 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
259 if (!NT_STATUS_IS_OK(status)) {
260 return -1;
262 return 0;
266 convert a NDR formatted blob to a ldif formatted objectGUID
268 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
269 const struct ldb_val *in, struct ldb_val *out)
271 struct GUID guid;
272 NTSTATUS status;
274 status = GUID_from_ndr_blob(in, &guid);
275 if (!NT_STATUS_IS_OK(status)) {
276 return -1;
278 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
279 if (out->data == NULL) {
280 return -1;
282 out->length = strlen((const char *)out->data);
283 return 0;
286 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
288 if (v->length != 36 && v->length != 38) return false;
290 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
291 return true;
294 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
295 const struct ldb_val *in, struct ldb_val *out)
298 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
299 return 0;
302 /* Try as 'hex' form */
303 if (in->length != 32) {
304 return -1;
307 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
309 if (!out->data) {
310 return -1;
313 (*out).length = strhex_to_str((char *)out->data, out->length,
314 (const char *)in->data, in->length);
316 /* Check it looks like a GUID */
317 if ((*out).length != 16) {
318 data_blob_free(out);
319 return -1;
322 return 0;
326 compare two objectGUIDs
328 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
329 const struct ldb_val *v1, const struct ldb_val *v2)
331 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
332 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
333 } else if (ldif_comparision_objectGUID_isString(v1)
334 && !ldif_comparision_objectGUID_isString(v2)) {
335 struct ldb_val v;
336 int ret;
337 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
338 /* Perhaps it wasn't a valid string after all */
339 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
341 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
342 talloc_free(v.data);
343 return ret;
344 } else if (!ldif_comparision_objectGUID_isString(v1)
345 && ldif_comparision_objectGUID_isString(v2)) {
346 struct ldb_val v;
347 int ret;
348 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
349 /* Perhaps it wasn't a valid string after all */
350 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
352 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
353 talloc_free(v.data);
354 return ret;
356 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
360 canonicalise a objectGUID
362 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
363 const struct ldb_val *in, struct ldb_val *out)
365 if (ldif_comparision_objectGUID_isString(in)) {
366 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
367 /* Perhaps it wasn't a valid string after all */
368 return ldb_handler_copy(ldb, mem_ctx, in, out);
370 return 0;
372 return ldb_handler_copy(ldb, mem_ctx, in, out);
377 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
379 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
380 const struct ldb_val *in, struct ldb_val *out)
382 struct security_descriptor *sd;
383 enum ndr_err_code ndr_err;
385 if (in->length >= 2 && isupper(in->data[0]) && in->data[1] == ':') {
387 * If it starts with an upper case character followed by ':',
388 * we know it's not NDR, but most likely SDDL...
390 const struct dom_sid *sid = samdb_domain_sid(ldb);
392 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
393 if (sd == NULL) {
394 return -1;
397 goto decoded;
400 sd = talloc(mem_ctx, struct security_descriptor);
401 if (sd == NULL) {
402 return -1;
405 ndr_err = ndr_pull_struct_blob(in, sd, sd,
406 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
407 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
408 talloc_free(sd);
409 return -1;
412 decoded:
413 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
414 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
415 talloc_free(sd);
416 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
417 return -1;
420 return 0;
424 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
426 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
427 const struct ldb_val *in, struct ldb_val *out)
429 struct security_descriptor *sd;
430 enum ndr_err_code ndr_err;
432 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
433 return ldif_write_NDR(ldb, mem_ctx, in, out,
434 sizeof(struct security_descriptor),
435 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
436 (ndr_print_fn_t)ndr_print_security_descriptor,
437 true);
441 sd = talloc(mem_ctx, struct security_descriptor);
442 if (sd == NULL) {
443 return -1;
445 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
446 ndr_err = ndr_pull_struct_blob(in, sd, sd,
447 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
448 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
449 talloc_free(sd);
450 return -1;
452 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
453 talloc_free(sd);
454 if (out->data == NULL) {
455 return -1;
457 out->length = strlen((const char *)out->data);
458 return 0;
462 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
464 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
465 const struct ldb_val *in, struct ldb_val *out)
467 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
468 struct security_descriptor *sd;
469 const struct dom_sid *sid = samdb_domain_sid(ldb);
471 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
472 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
473 (ndr_print_fn_t)ndr_print_security_descriptor,
474 "SDDL", sd);
475 out->length = strlen((const char *)out->data);
476 talloc_free(sd);
477 return 0;
480 return ldb_handler_copy(ldb, mem_ctx, in, out);
484 canonicalise an objectCategory. We use the long form as the canonical form:
485 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
487 Also any short name of an objectClass that points to a different
488 class (such as user) has the canonical form of the class it's
489 defaultObjectCategory points to (eg
490 cn=Person,cn=Schema,cn=Configuration,<basedn>)
493 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
494 const struct ldb_val *in, struct ldb_val *out)
496 struct ldb_dn *dn1 = NULL;
497 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
498 const struct dsdb_class *sclass;
499 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
500 if (!tmp_ctx) {
501 return LDB_ERR_OPERATIONS_ERROR;
504 if (!schema) {
505 talloc_free(tmp_ctx);
506 *out = data_blob_talloc(mem_ctx, in->data, in->length);
507 if (in->data && !out->data) {
508 return LDB_ERR_OPERATIONS_ERROR;
510 return LDB_SUCCESS;
512 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
513 if ( ! ldb_dn_validate(dn1)) {
514 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
515 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
516 if (sclass) {
517 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
518 sclass->defaultObjectCategory);
519 if (dn == NULL) {
520 talloc_free(tmp_ctx);
521 return LDB_ERR_OPERATIONS_ERROR;
524 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
525 talloc_free(tmp_ctx);
527 if (!out->data) {
528 return LDB_ERR_OPERATIONS_ERROR;
530 return LDB_SUCCESS;
531 } else {
532 *out = data_blob_talloc(mem_ctx, in->data, in->length);
533 talloc_free(tmp_ctx);
535 if (in->data && !out->data) {
536 return LDB_ERR_OPERATIONS_ERROR;
538 return LDB_SUCCESS;
541 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
542 talloc_free(tmp_ctx);
544 if (!out->data) {
545 return LDB_ERR_OPERATIONS_ERROR;
547 return LDB_SUCCESS;
550 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
551 const struct ldb_val *v1,
552 const struct ldb_val *v2)
554 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
555 v1, v2);
559 convert a NDR formatted blob to a ldif formatted schemaInfo
561 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
562 const struct ldb_val *in, struct ldb_val *out)
564 return ldif_write_NDR(ldb, mem_ctx, in, out,
565 sizeof(struct repsFromToBlob),
566 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
567 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
568 true);
572 convert a ldif formatted prefixMap to a NDR formatted blob
574 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
575 const struct ldb_val *in, struct ldb_val *out)
577 struct prefixMapBlob *blob;
578 enum ndr_err_code ndr_err;
579 char *string, *line, *p, *oid;
580 DATA_BLOB oid_blob;
582 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
584 if (tmp_ctx == NULL) {
585 return -1;
588 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
589 if (blob == NULL) {
590 talloc_free(tmp_ctx);
591 return -1;
594 /* use the switch value to detect if this is in the binary
595 * format
597 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
598 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
599 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
600 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
601 ndr_err = ndr_push_struct_blob(out, mem_ctx,
602 blob,
603 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
604 talloc_free(tmp_ctx);
605 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
606 return -1;
608 return 0;
612 /* If this does not parse, then it is probably the text version, and we should try it that way */
613 blob->version = PREFIX_MAP_VERSION_DSDB;
615 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
616 if (string == NULL) {
617 talloc_free(blob);
618 return -1;
621 line = string;
622 while (line && line[0]) {
623 int error = 0;
625 p=strchr(line, ';');
626 if (p) {
627 p[0] = '\0';
628 } else {
629 p=strchr(line, '\n');
630 if (p) {
631 p[0] = '\0';
634 /* allow a trailing separator */
635 if (line == p) {
636 break;
639 blob->ctr.dsdb.mappings = talloc_realloc(blob,
640 blob->ctr.dsdb.mappings,
641 struct drsuapi_DsReplicaOIDMapping,
642 blob->ctr.dsdb.num_mappings+1);
643 if (!blob->ctr.dsdb.mappings) {
644 talloc_free(tmp_ctx);
645 return -1;
648 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
649 smb_strtoul(line, &oid, 10, &error, SMB_STR_STANDARD);
651 if (oid[0] != ':' || error != 0) {
652 talloc_free(tmp_ctx);
653 return -1;
656 /* we know there must be at least ":" */
657 oid++;
659 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
660 talloc_free(tmp_ctx);
661 return -1;
663 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
664 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
666 blob->ctr.dsdb.num_mappings++;
668 /* Now look past the terminator we added above */
669 if (p) {
670 line = p + 1;
671 } else {
672 line = NULL;
676 ndr_err = ndr_push_struct_blob(out, mem_ctx,
677 blob,
678 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
679 talloc_free(tmp_ctx);
680 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
681 return -1;
683 return 0;
687 convert a NDR formatted blob to a ldif formatted prefixMap
689 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
690 const struct ldb_val *in, struct ldb_val *out)
692 struct prefixMapBlob *blob;
693 enum ndr_err_code ndr_err;
694 char *string;
695 uint32_t i;
697 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
698 int err;
699 /* try to decode the blob as S4 prefixMap */
700 err = ldif_write_NDR(ldb, mem_ctx, in, out,
701 sizeof(struct prefixMapBlob),
702 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
703 (ndr_print_fn_t)ndr_print_prefixMapBlob,
704 false);
705 if (0 == err) {
706 return err;
708 /* try parsing it as Windows PrefixMap value */
709 return ldif_write_NDR(ldb, mem_ctx, in, out,
710 sizeof(struct drsuapi_MSPrefixMap_Ctr),
711 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
712 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
713 true);
716 blob = talloc(mem_ctx, struct prefixMapBlob);
717 if (blob == NULL) {
718 return -1;
720 ndr_err = ndr_pull_struct_blob_all(in, blob,
721 blob,
722 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
723 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
724 goto failed;
726 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
727 goto failed;
729 string = talloc_strdup(mem_ctx, "");
730 if (string == NULL) {
731 goto failed;
734 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
735 DATA_BLOB oid_blob;
736 char *partial_oid = NULL;
738 if (i > 0) {
739 talloc_asprintf_addbuf(&string, ";");
742 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
743 blob->ctr.dsdb.mappings[i].oid.length);
744 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
745 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X\n",
746 blob->ctr.dsdb.mappings[i].id_prefix));
747 goto failed;
749 talloc_asprintf_addbuf(&string, "%u:%s",
750 blob->ctr.dsdb.mappings[i].id_prefix,
751 partial_oid);
752 talloc_free(discard_const(partial_oid));
755 talloc_free(blob);
756 *out = data_blob_string_const(string);
757 return 0;
759 failed:
760 talloc_free(blob);
761 return -1;
764 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
766 if (v->length < 4) {
767 return true;
770 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
771 return false;
774 return true;
778 canonicalise a prefixMap
780 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
781 const struct ldb_val *in, struct ldb_val *out)
783 if (ldif_comparision_prefixMap_isString(in)) {
784 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
786 return ldb_handler_copy(ldb, mem_ctx, in, out);
789 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
790 const struct ldb_val *v1,
791 const struct ldb_val *v2)
793 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
794 v1, v2);
797 /* length limited conversion of a ldb_val to a int32_t */
798 static int val_to_int32(const struct ldb_val *in, int32_t *v)
800 char *end;
801 char buf[64];
803 /* make sure we don't read past the end of the data */
804 if (in->length > sizeof(buf)-1) {
805 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
807 strncpy(buf, (char *)in->data, in->length);
808 buf[in->length] = 0;
810 /* We've to use "strtoll" here to have the intended overflows.
811 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
812 *v = (int32_t) strtoll(buf, &end, 0);
813 if (*end != 0) {
814 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
816 return LDB_SUCCESS;
819 /* length limited conversion of a ldb_val to a int64_t */
820 static int val_to_int64(const struct ldb_val *in, int64_t *v)
822 char *end;
823 char buf[64];
825 /* make sure we don't read past the end of the data */
826 if (in->length > sizeof(buf)-1) {
827 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
829 strncpy(buf, (char *)in->data, in->length);
830 buf[in->length] = 0;
832 *v = (int64_t) strtoll(buf, &end, 0);
833 if (*end != 0) {
834 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
836 return LDB_SUCCESS;
839 /* Canonicalisation of two 32-bit integers */
840 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
841 const struct ldb_val *in, struct ldb_val *out)
843 int32_t i;
844 int ret;
846 ret = val_to_int32(in, &i);
847 if (ret != LDB_SUCCESS) {
848 return ret;
850 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
851 if (out->data == NULL) {
852 ldb_oom(ldb);
853 return LDB_ERR_OPERATIONS_ERROR;
855 out->length = strlen((char *)out->data);
856 return 0;
860 * Lexicographically sorted representation for a 32-bit integer
862 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
863 * n o p
865 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
866 * corresponding documentation for 64-bit integers.
868 * The same rules apply but use INT32_MIN and INT32_MAX.
870 * String representation padding is done to 10 characters.
872 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
875 static int ldif_index_format_int32(struct ldb_context *ldb,
876 void *mem_ctx,
877 const struct ldb_val *in,
878 struct ldb_val *out)
880 int32_t i;
881 int ret;
882 char prefix;
883 size_t len;
885 ret = val_to_int32(in, &i);
886 if (ret != LDB_SUCCESS) {
887 return ret;
890 if (i < 0) {
892 * i is negative, so this is subtraction rather than
893 * wrap-around.
895 prefix = 'n';
896 i = INT32_MAX + i + 1;
897 } else if (i > 0) {
898 prefix = 'p';
899 } else {
900 prefix = 'o';
903 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
904 if (out->data == NULL) {
905 ldb_oom(ldb);
906 return LDB_ERR_OPERATIONS_ERROR;
909 len = talloc_array_length(out->data) - 1;
910 if (len != 11) {
911 ldb_debug(ldb, LDB_DEBUG_ERROR,
912 __location__ ": expected index format str %s to"
913 " have length 11 but got %zu",
914 (char*)out->data, len);
915 return LDB_ERR_OPERATIONS_ERROR;
918 out->length = 11;
919 return 0;
922 /* Comparison of two 32-bit integers */
923 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
924 const struct ldb_val *v1, const struct ldb_val *v2)
926 int32_t i1=0, i2=0;
927 val_to_int32(v1, &i1);
928 val_to_int32(v2, &i2);
929 if (i1 == i2) return 0;
930 return i1 > i2? 1 : -1;
933 /* Canonicalisation of two 64-bit integers */
934 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
935 const struct ldb_val *in, struct ldb_val *out)
937 int64_t i;
938 int ret;
940 ret = val_to_int64(in, &i);
941 if (ret != LDB_SUCCESS) {
942 return ret;
944 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
945 if (out->data == NULL) {
946 ldb_oom(ldb);
947 return LDB_ERR_OPERATIONS_ERROR;
949 out->length = strlen((char *)out->data);
950 return 0;
953 /* Comparison of two 64-bit integers */
954 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
955 const struct ldb_val *v1, const struct ldb_val *v2)
957 int64_t i1=0, i2=0;
958 val_to_int64(v1, &i1);
959 val_to_int64(v2, &i2);
960 if (i1 == i2) return 0;
961 return i1 > i2? 1 : -1;
965 convert a NDR formatted blob to a ldif formatted repsFromTo
967 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
968 const struct ldb_val *in, struct ldb_val *out)
970 return ldif_write_NDR(ldb, mem_ctx, in, out,
971 sizeof(struct repsFromToBlob),
972 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
973 (ndr_print_fn_t)ndr_print_repsFromToBlob,
974 true);
978 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
980 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
981 const struct ldb_val *in, struct ldb_val *out)
983 return ldif_write_NDR(ldb, mem_ctx, in, out,
984 sizeof(struct replPropertyMetaDataBlob),
985 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
986 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
987 true);
991 convert a NDR formatted blob to a ldif formatted replUpToDateVector
993 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
994 const struct ldb_val *in, struct ldb_val *out)
996 return ldif_write_NDR(ldb, mem_ctx, in, out,
997 sizeof(struct replUpToDateVectorBlob),
998 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
999 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
1000 true);
1003 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
1004 const struct ldb_val *in, struct ldb_val *out,
1005 size_t struct_size,
1006 ndr_pull_flags_fn_t pull_fn,
1007 ndr_print_fn_t print_fn,
1008 bool mask_errors)
1010 uint8_t *p = NULL;
1011 enum ndr_err_code err;
1012 struct dsdb_dn *dsdb_dn = NULL;
1013 char *dn_str = NULL;
1014 char *str = NULL;
1016 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
1017 return ldb_handler_copy(ldb, mem_ctx, in, out);
1020 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
1021 if (dsdb_dn == NULL) {
1022 return ldb_handler_copy(ldb, mem_ctx, in, out);
1025 p = talloc_size(dsdb_dn, struct_size);
1026 if (p == NULL) {
1027 TALLOC_FREE(dsdb_dn);
1028 return ldb_handler_copy(ldb, mem_ctx, in, out);
1031 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
1032 if (err != NDR_ERR_SUCCESS) {
1033 /* fail in not in mask_error mode */
1034 if (!mask_errors) {
1035 return -1;
1037 TALLOC_FREE(dsdb_dn);
1038 return ldb_handler_copy(ldb, mem_ctx, in, out);
1041 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
1042 if (dn_str == NULL) {
1043 TALLOC_FREE(dsdb_dn);
1044 return ldb_handler_copy(ldb, mem_ctx, in, out);
1047 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
1048 TALLOC_FREE(dsdb_dn);
1049 if (str == NULL) {
1050 return ldb_handler_copy(ldb, mem_ctx, in, out);
1053 *out = data_blob_string_const(str);
1054 return 0;
1057 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
1058 const struct ldb_val *in, struct ldb_val *out)
1060 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
1061 sizeof(struct replPropertyMetaData1),
1062 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
1063 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
1064 true);
1068 convert a NDR formatted blob to a ldif formatted dnsRecord
1070 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
1071 const struct ldb_val *in, struct ldb_val *out)
1073 return ldif_write_NDR(ldb, mem_ctx, in, out,
1074 sizeof(struct dnsp_DnssrvRpcRecord),
1075 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
1076 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
1077 true);
1081 convert a NDR formatted blob to a ldif formatted dnsProperty
1083 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1084 const struct ldb_val *in, struct ldb_val *out)
1086 return ldif_write_NDR(ldb, mem_ctx, in, out,
1087 sizeof(struct dnsp_DnsProperty),
1088 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1089 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1090 true);
1094 convert a NDR formatted blob of a supplementalCredentials into text
1096 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1097 const struct ldb_val *in, struct ldb_val *out)
1099 return ldif_write_NDR(ldb, mem_ctx, in, out,
1100 sizeof(struct supplementalCredentialsBlob),
1101 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1102 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1103 true);
1107 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1109 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1110 const struct ldb_val *in, struct ldb_val *out)
1112 return ldif_write_NDR(ldb, mem_ctx, in, out,
1113 sizeof(struct trustAuthInOutBlob),
1114 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1115 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1116 true);
1120 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1122 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1123 const struct ldb_val *in, struct ldb_val *out)
1125 return ldif_write_NDR(ldb, mem_ctx, in, out,
1126 sizeof(struct ForestTrustInfo),
1127 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1128 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1129 true);
1132 convert a NDR formatted blob of a partialAttributeSet into text
1134 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1135 const struct ldb_val *in, struct ldb_val *out)
1137 return ldif_write_NDR(ldb, mem_ctx, in, out,
1138 sizeof(struct partialAttributeSetBlob),
1139 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1140 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1141 true);
1145 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1146 const struct ldb_val *in, struct ldb_val *out)
1148 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1149 if (!out->data) {
1150 return -1;
1152 return 0;
1156 compare two dns
1158 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1159 const struct ldb_val *v1, const struct ldb_val *v2)
1161 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1162 int ret;
1165 * In a sort context, Deleted DNs get shifted to the end.
1166 * They never match in an equality
1168 if (dsdb_dn_is_deleted_val(v1)) {
1169 if (! dsdb_dn_is_deleted_val(v2)) {
1170 return 1;
1173 * They are both deleted!
1175 * The soundest thing to do at this point is carry on
1176 * and compare the DNs normally. This matches the
1177 * behaviour of samba_dn_extended_match() below.
1179 } else if (dsdb_dn_is_deleted_val(v2)) {
1180 return -1;
1183 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1184 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1186 if ( ! ldb_dn_validate(dn1)) {
1187 TALLOC_FREE(dn1);
1188 if ( ! ldb_dn_validate(dn2)) {
1189 TALLOC_FREE(dn2);
1190 return 0;
1192 TALLOC_FREE(dn2);
1193 return 1;
1196 if ( ! ldb_dn_validate(dn2)) {
1197 TALLOC_FREE(dn1);
1198 TALLOC_FREE(dn2);
1199 return -1;
1202 ret = ldb_dn_compare(dn1, dn2);
1204 talloc_free(dn1);
1205 talloc_free(dn2);
1206 return ret;
1209 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1210 const struct ldb_val *in, struct ldb_val *out)
1212 struct ldb_dn *dn;
1213 int ret = -1;
1215 out->length = 0;
1216 out->data = NULL;
1218 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1219 if ( ! ldb_dn_validate(dn)) {
1220 return LDB_ERR_INVALID_DN_SYNTAX;
1223 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1224 * does not casually match a not deleted DN */
1225 if (dsdb_dn_is_deleted_val(in)) {
1226 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1227 "<RMD_FLAGS=%u>%s",
1228 dsdb_dn_val_rmd_flags(in),
1229 ldb_dn_get_casefold(dn));
1230 } else {
1231 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1234 if (out->data == NULL) {
1235 goto done;
1237 out->length = strlen((char *)out->data);
1239 ret = 0;
1241 done:
1242 talloc_free(dn);
1244 return ret;
1249 write a 64 bit 2-part range
1251 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1252 const struct ldb_val *in, struct ldb_val *out)
1254 int64_t v;
1255 int ret;
1256 ret = val_to_int64(in, &v);
1257 if (ret != LDB_SUCCESS) {
1258 return ret;
1260 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1261 (unsigned long)(v&0xFFFFFFFF),
1262 (unsigned long)(v>>32));
1263 if (out->data == NULL) {
1264 ldb_oom(ldb);
1265 return LDB_ERR_OPERATIONS_ERROR;
1267 out->length = strlen((char *)out->data);
1268 return LDB_SUCCESS;
1272 read a 64 bit 2-part range
1274 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1275 const struct ldb_val *in, struct ldb_val *out)
1277 unsigned long high, low;
1278 char buf[64];
1280 if (memchr(in->data, '-', in->length) == NULL) {
1281 return ldb_handler_copy(ldb, mem_ctx, in, out);
1284 if (in->length > sizeof(buf)-1) {
1285 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1287 strncpy(buf, (const char *)in->data, in->length);
1288 buf[in->length] = 0;
1290 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1291 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1294 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1295 (unsigned long long)(((uint64_t)high)<<32) | (low));
1297 if (out->data == NULL) {
1298 ldb_oom(ldb);
1299 return LDB_ERR_OPERATIONS_ERROR;
1301 out->length = strlen((char *)out->data);
1302 return LDB_SUCCESS;
1306 when this operator_fn is set for a syntax, the backend calls is in
1307 preference to the comparison function. We are told the exact
1308 comparison operation that is needed, and we can return errors
1310 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1311 const struct ldb_schema_attribute *a,
1312 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1314 switch (operation) {
1315 case LDB_OP_AND:
1316 case LDB_OP_OR:
1317 case LDB_OP_NOT:
1318 case LDB_OP_SUBSTRING:
1319 case LDB_OP_APPROX:
1320 case LDB_OP_EXTENDED:
1321 /* handled in the backends */
1322 return LDB_ERR_INAPPROPRIATE_MATCHING;
1324 case LDB_OP_GREATER:
1325 case LDB_OP_LESS:
1326 case LDB_OP_EQUALITY:
1328 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1329 int ret;
1330 if (tmp_ctx == NULL) {
1331 return ldb_oom(ldb);
1333 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1334 talloc_free(tmp_ctx);
1335 if (operation == LDB_OP_GREATER) {
1336 *matched = (ret >= 0);
1337 } else if (operation == LDB_OP_LESS) {
1338 *matched = (ret <= 0);
1339 } else {
1340 *matched = (ret == 0);
1342 return LDB_SUCCESS;
1345 case LDB_OP_PRESENT:
1346 *matched = true;
1347 return LDB_SUCCESS;
1350 /* we shouldn't get here */
1351 return LDB_ERR_INAPPROPRIATE_MATCHING;
1355 compare two binary objects. This is correct for sorting as the sort order is:
1362 rather than ldb_comparison_binary() which is:
1370 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1371 const struct ldb_val *v1, const struct ldb_val *v2)
1373 return data_blob_cmp(v1, v2);
1377 when this operator_fn is set for a syntax, the backend calls is in
1378 preference to the comparison function. We are told the exact
1379 comparison operation that is needed, and we can return errors.
1381 This mode optimises for ldb_comparison_binary() if we need equality,
1382 as this should be faster as it can do a length-check first.
1384 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1385 const struct ldb_schema_attribute *a,
1386 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1388 if (operation == LDB_OP_EQUALITY) {
1389 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1390 return LDB_SUCCESS;
1392 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1396 see if two DNs match, comparing first by GUID, then by SID, and
1397 finally by string components
1399 static int samba_dn_extended_match(struct ldb_context *ldb,
1400 const struct ldb_val *v1,
1401 const struct ldb_val *v2,
1402 bool *matched)
1404 TALLOC_CTX *tmp_ctx;
1405 struct ldb_dn *dn1, *dn2;
1406 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1407 uint32_t rmd_flags1, rmd_flags2;
1409 tmp_ctx = talloc_new(ldb);
1411 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1412 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1413 if (!dn1 || !dn2) {
1414 /* couldn't parse as DN's */
1415 talloc_free(tmp_ctx);
1416 (*matched) = false;
1417 return LDB_SUCCESS;
1420 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1421 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1423 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1424 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1425 /* only match if they have the same deletion status */
1426 talloc_free(tmp_ctx);
1427 (*matched) = false;
1428 return LDB_SUCCESS;
1432 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1433 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1434 if (guid1 && guid2) {
1435 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1436 talloc_free(tmp_ctx);
1437 return LDB_SUCCESS;
1440 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1441 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1442 if (sid1 && sid2) {
1443 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1444 talloc_free(tmp_ctx);
1445 return LDB_SUCCESS;
1448 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1450 talloc_free(tmp_ctx);
1451 return LDB_SUCCESS;
1455 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1457 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1458 const struct ldb_schema_attribute *a,
1459 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1461 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1462 /* If the DN is deleted, then we can't search for it */
1464 /* should this be for equality too? */
1465 *matched = false;
1466 return LDB_SUCCESS;
1469 if (operation == LDB_OP_EQUALITY &&
1470 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1471 return LDB_SUCCESS;
1474 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1478 static const struct ldb_schema_syntax samba_syntaxes[] = {
1480 .name = LDB_SYNTAX_SAMBA_SID,
1481 .ldif_read_fn = ldif_read_objectSid,
1482 .ldif_write_fn = ldif_write_objectSid,
1483 .canonicalise_fn = ldif_canonicalise_objectSid,
1484 .comparison_fn = ldif_comparison_objectSid,
1485 .operator_fn = samba_syntax_operator_fn
1487 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1488 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1489 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1490 .canonicalise_fn = ldb_handler_copy,
1491 .comparison_fn = samba_ldb_comparison_binary,
1492 .operator_fn = samba_syntax_binary_operator_fn
1494 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1495 .ldif_read_fn = ldb_handler_copy,
1496 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1497 .canonicalise_fn = ldb_handler_fold,
1498 .comparison_fn = ldb_comparison_fold,
1499 .operator_fn = samba_syntax_operator_fn
1501 .name = LDB_SYNTAX_SAMBA_GUID,
1502 .ldif_read_fn = ldif_read_objectGUID,
1503 .ldif_write_fn = ldif_write_objectGUID,
1504 .canonicalise_fn = ldif_canonicalise_objectGUID,
1505 .comparison_fn = ldif_comparison_objectGUID,
1506 .operator_fn = samba_syntax_operator_fn
1508 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1509 .ldif_read_fn = ldb_handler_copy,
1510 .ldif_write_fn = ldb_handler_copy,
1511 .canonicalise_fn = ldif_canonicalise_objectCategory,
1512 .comparison_fn = ldif_comparison_objectCategory,
1513 .operator_fn = samba_syntax_operator_fn
1515 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1516 .ldif_read_fn = ldb_handler_copy,
1517 .ldif_write_fn = ldif_write_schemaInfo,
1518 .canonicalise_fn = ldb_handler_copy,
1519 .comparison_fn = samba_ldb_comparison_binary,
1520 .operator_fn = samba_syntax_binary_operator_fn
1522 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1523 .ldif_read_fn = ldif_read_prefixMap,
1524 .ldif_write_fn = ldif_write_prefixMap,
1525 .canonicalise_fn = ldif_canonicalise_prefixMap,
1526 .comparison_fn = ldif_comparison_prefixMap,
1527 .operator_fn = samba_syntax_operator_fn
1529 .name = LDB_SYNTAX_SAMBA_INT32,
1530 .ldif_read_fn = ldb_handler_copy,
1531 .ldif_write_fn = ldb_handler_copy,
1532 .canonicalise_fn = ldif_canonicalise_int32,
1533 .index_format_fn = ldif_index_format_int32,
1534 .comparison_fn = ldif_comparison_int32,
1535 .operator_fn = samba_syntax_operator_fn
1537 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1538 .ldif_read_fn = ldb_handler_copy,
1539 .ldif_write_fn = ldif_write_repsFromTo,
1540 .canonicalise_fn = ldb_handler_copy,
1541 .comparison_fn = samba_ldb_comparison_binary,
1542 .operator_fn = samba_syntax_binary_operator_fn
1544 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1545 .ldif_read_fn = ldb_handler_copy,
1546 .ldif_write_fn = ldif_write_replPropertyMetaData,
1547 .canonicalise_fn = ldb_handler_copy,
1548 .comparison_fn = samba_ldb_comparison_binary,
1549 .operator_fn = samba_syntax_binary_operator_fn
1551 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1552 .ldif_read_fn = ldb_handler_copy,
1553 .ldif_write_fn = ldif_write_replUpToDateVector,
1554 .canonicalise_fn = ldb_handler_copy,
1555 .comparison_fn = samba_ldb_comparison_binary,
1556 .operator_fn = samba_syntax_binary_operator_fn
1558 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1559 .ldif_read_fn = ldb_handler_copy,
1560 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1561 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1562 .comparison_fn = dsdb_dn_binary_comparison,
1563 .operator_fn = samba_syntax_operator_fn
1565 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1566 .ldif_read_fn = ldb_handler_copy,
1567 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1568 .canonicalise_fn = ldb_handler_copy,
1569 .comparison_fn = samba_ldb_comparison_binary,
1570 .operator_fn = samba_syntax_binary_operator_fn
1572 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1573 .ldif_read_fn = ldb_handler_copy,
1574 .ldif_write_fn = ldif_write_ForestTrustInfo,
1575 .canonicalise_fn = ldb_handler_copy,
1576 .comparison_fn = samba_ldb_comparison_binary,
1577 .operator_fn = samba_syntax_binary_operator_fn
1579 .name = DSDB_SYNTAX_BINARY_DN,
1580 .ldif_read_fn = ldb_handler_copy,
1581 .ldif_write_fn = ldb_handler_copy,
1582 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1583 .comparison_fn = dsdb_dn_binary_comparison,
1584 .operator_fn = samba_syntax_operator_fn
1586 .name = DSDB_SYNTAX_STRING_DN,
1587 .ldif_read_fn = ldb_handler_copy,
1588 .ldif_write_fn = ldb_handler_copy,
1589 .canonicalise_fn = dsdb_dn_string_canonicalise,
1590 .comparison_fn = dsdb_dn_string_comparison,
1591 .operator_fn = samba_syntax_operator_fn
1593 .name = LDB_SYNTAX_DN,
1594 .ldif_read_fn = ldb_handler_copy,
1595 .ldif_write_fn = ldb_handler_copy,
1596 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1597 .comparison_fn = samba_ldb_dn_link_comparison,
1598 .operator_fn = samba_syntax_operator_dn
1600 .name = LDB_SYNTAX_SAMBA_RANGE64,
1601 .ldif_read_fn = ldif_read_range64,
1602 .ldif_write_fn = ldif_write_range64,
1603 .canonicalise_fn = ldif_canonicalise_int64,
1604 .comparison_fn = ldif_comparison_int64,
1605 .operator_fn = samba_syntax_operator_fn
1607 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1608 .ldif_read_fn = ldb_handler_copy,
1609 .ldif_write_fn = ldif_write_dnsRecord,
1610 .canonicalise_fn = ldb_handler_copy,
1611 .comparison_fn = samba_ldb_comparison_binary,
1612 .operator_fn = samba_syntax_binary_operator_fn
1614 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1615 .ldif_read_fn = ldb_handler_copy,
1616 .ldif_write_fn = ldif_write_dnsProperty,
1617 .canonicalise_fn = ldb_handler_copy,
1618 .comparison_fn = samba_ldb_comparison_binary,
1619 .operator_fn = samba_syntax_binary_operator_fn
1621 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1622 .ldif_read_fn = ldb_handler_copy,
1623 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1624 .canonicalise_fn = ldb_handler_copy,
1625 .comparison_fn = samba_ldb_comparison_binary,
1626 .operator_fn = samba_syntax_binary_operator_fn
1628 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1629 .ldif_read_fn = ldb_handler_copy,
1630 .ldif_write_fn = ldif_write_partialAttributeSet,
1631 .canonicalise_fn = ldb_handler_copy,
1632 .comparison_fn = samba_ldb_comparison_binary,
1633 .operator_fn = samba_syntax_binary_operator_fn
1635 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1636 .ldif_read_fn = ldb_handler_copy,
1637 .ldif_write_fn = ldb_handler_copy,
1638 .canonicalise_fn = ldb_handler_copy,
1639 .comparison_fn = samba_ldb_comparison_binary,
1640 .operator_fn = samba_syntax_binary_operator_fn
1644 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1646 .name = "SID",
1647 .read_fn = extended_dn_read_SID,
1648 .write_clear_fn = ldif_write_objectSid,
1649 .write_hex_fn = extended_dn_write_hex
1651 .name = "GUID",
1652 .read_fn = extended_dn_read_GUID,
1653 .write_clear_fn = ldif_write_objectGUID,
1654 .write_hex_fn = extended_dn_write_hex
1656 .name = "WKGUID",
1657 .read_fn = ldb_handler_copy,
1658 .write_clear_fn = ldb_handler_copy,
1659 .write_hex_fn = ldb_handler_copy
1661 .name = "RMD_INVOCID",
1662 .read_fn = extended_dn_read_GUID,
1663 .write_clear_fn = ldif_write_objectGUID,
1664 .write_hex_fn = extended_dn_write_hex
1666 .name = "RMD_FLAGS",
1667 .read_fn = ldb_handler_copy,
1668 .write_clear_fn = ldb_handler_copy,
1669 .write_hex_fn = ldb_handler_copy
1671 .name = "RMD_ADDTIME",
1672 .read_fn = ldb_handler_copy,
1673 .write_clear_fn = ldb_handler_copy,
1674 .write_hex_fn = ldb_handler_copy
1676 .name = "RMD_CHANGETIME",
1677 .read_fn = ldb_handler_copy,
1678 .write_clear_fn = ldb_handler_copy,
1679 .write_hex_fn = ldb_handler_copy
1681 .name = "RMD_LOCAL_USN",
1682 .read_fn = ldb_handler_copy,
1683 .write_clear_fn = ldb_handler_copy,
1684 .write_hex_fn = ldb_handler_copy
1686 .name = "RMD_ORIGINATING_USN",
1687 .read_fn = ldb_handler_copy,
1688 .write_clear_fn = ldb_handler_copy,
1689 .write_hex_fn = ldb_handler_copy
1691 .name = "RMD_VERSION",
1692 .read_fn = ldb_handler_copy,
1693 .write_clear_fn = ldb_handler_copy,
1694 .write_hex_fn = ldb_handler_copy
1698 /* TODO: Should be dynamic at some point */
1699 static const struct {
1700 const char *name;
1701 const char *syntax;
1702 } samba_attributes[] = {
1703 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1704 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1705 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1706 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1707 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1708 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1709 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1710 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1711 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1712 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1713 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1714 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1715 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1716 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1717 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1718 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1719 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1722 * these are extracted by searching
1723 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1725 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1726 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1727 * hat can be used to identify the set of policies when applied to a resource.
1728 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1729 * server, we ignore it here.
1731 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1732 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1733 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1734 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1735 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1736 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1737 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1738 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1739 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1742 * these are extracted by searching
1743 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1745 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1746 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1747 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1748 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1749 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1750 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1751 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1752 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1753 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1754 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1755 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1756 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1757 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1758 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1759 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1760 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1761 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1762 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1763 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1764 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1765 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1766 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1767 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1768 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1769 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1770 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1771 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1772 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1775 * these are known to be GUIDs
1777 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1778 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1780 /* These NDR encoded things we want to be able to read with --show-binary */
1781 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1782 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1783 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1784 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1787 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1789 unsigned int j;
1790 const struct ldb_schema_syntax *s = NULL;
1792 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1793 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1794 s = &samba_syntaxes[j];
1795 break;
1798 return s;
1801 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1803 unsigned int j;
1804 const struct ldb_schema_syntax *s = NULL;
1806 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1807 if (strcmp(samba_attributes[j].name, name) == 0) {
1808 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1809 break;
1813 return s;
1816 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1817 "priorSecret", NULL};
1820 register the samba ldif handlers
1822 int ldb_register_samba_handlers(struct ldb_context *ldb)
1824 unsigned int i;
1825 int ret;
1827 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1828 return LDB_SUCCESS;
1831 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1832 if (ret != LDB_SUCCESS) {
1833 return ret;
1836 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1837 const struct ldb_schema_syntax *s = NULL;
1839 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1841 if (!s) {
1842 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1845 if (!s) {
1846 return LDB_ERR_OPERATIONS_ERROR;
1849 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1850 if (ret != LDB_SUCCESS) {
1851 return ret;
1855 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1856 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1857 if (ret != LDB_SUCCESS) {
1858 return ret;
1863 ret = ldb_register_samba_matching_rules(ldb);
1864 if (ret != LDB_SUCCESS) {
1865 talloc_free(ldb);
1866 return LDB_SUCCESS;
1869 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1870 if (ret != LDB_SUCCESS) {
1871 return ret;
1874 return LDB_SUCCESS;