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
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/>.
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"
41 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
43 If mask_errors is true, then function succeeds but out data
44 is set to "<Unable to decode binary data>" message
46 \return 0 on success; -1 on error
48 static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
49 const struct ldb_val *in, struct ldb_val *out,
51 ndr_pull_flags_fn_t pull_fn,
52 ndr_print_fn_t print_fn,
56 enum ndr_err_code err;
57 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
58 return ldb_handler_copy(ldb, mem_ctx, in, out);
60 p = talloc_size(mem_ctx, struct_size);
61 err = ndr_pull_struct_blob(in, mem_ctx,
63 if (err != NDR_ERR_SUCCESS) {
64 /* fail in not in mask_error mode */
69 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
70 out->length = strlen((const char *)out->data);
73 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
75 if (out->data == NULL) {
76 return ldb_handler_copy(ldb, mem_ctx, in, out);
78 out->length = strlen((char *)out->data);
83 convert a ldif formatted objectSid to a NDR formatted blob
85 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
86 const struct ldb_val *in, struct ldb_val *out)
88 enum ndr_err_code ndr_err;
90 sid = dom_sid_parse_length(mem_ctx, in);
94 ndr_err = ndr_push_struct_blob(out, mem_ctx, sid,
95 (ndr_push_flags_fn_t)ndr_push_dom_sid);
97 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
104 convert a NDR formatted blob to a ldif formatted objectSid
106 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
107 const struct ldb_val *in, struct ldb_val *out)
110 enum ndr_err_code ndr_err;
112 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
113 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
114 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
117 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
118 if (out->data == NULL) {
124 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
130 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
136 compare two objectSids
138 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
139 const struct ldb_val *v1, const struct ldb_val *v2)
141 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
142 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
143 } else if (ldif_comparision_objectSid_isString(v1)
144 && !ldif_comparision_objectSid_isString(v2)) {
147 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
148 /* Perhaps not a string after all */
149 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
151 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
154 } else if (!ldif_comparision_objectSid_isString(v1)
155 && ldif_comparision_objectSid_isString(v2)) {
158 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
159 /* Perhaps not a string after all */
160 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
162 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
166 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
170 canonicalise a objectSid
172 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
173 const struct ldb_val *in, struct ldb_val *out)
175 if (ldif_comparision_objectSid_isString(in)) {
176 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
177 /* Perhaps not a string after all */
178 return ldb_handler_copy(ldb, mem_ctx, in, out);
182 return ldb_handler_copy(ldb, mem_ctx, in, out);
185 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
186 const struct ldb_val *in, struct ldb_val *out)
189 enum ndr_err_code ndr_err;
190 if (ldif_comparision_objectSid_isString(in)) {
191 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
196 /* Perhaps not a string after all */
197 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
203 (*out).length = strhex_to_str((char *)out->data, out->length,
204 (const char *)in->data, in->length);
206 /* Check it looks like a SID */
207 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
208 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
209 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
216 convert a ldif formatted objectGUID to a NDR formatted blob
218 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
219 const struct ldb_val *in, struct ldb_val *out)
224 status = GUID_from_data_blob(in, &guid);
225 if (!NT_STATUS_IS_OK(status)) {
229 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
230 if (!NT_STATUS_IS_OK(status)) {
237 convert a NDR formatted blob to a ldif formatted objectGUID
239 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
240 const struct ldb_val *in, struct ldb_val *out)
245 status = GUID_from_ndr_blob(in, &guid);
246 if (!NT_STATUS_IS_OK(status)) {
249 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
250 if (out->data == NULL) {
253 out->length = strlen((const char *)out->data);
257 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
259 if (v->length != 36 && v->length != 38) return false;
261 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
265 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
266 const struct ldb_val *in, struct ldb_val *out)
271 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
275 /* Try as 'hex' form */
276 if (in->length != 32) {
280 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
286 (*out).length = strhex_to_str((char *)out->data, out->length,
287 (const char *)in->data, in->length);
289 /* Check it looks like a GUID */
290 status = GUID_from_ndr_blob(out, &guid);
291 if (!NT_STATUS_IS_OK(status)) {
299 compare two objectGUIDs
301 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
302 const struct ldb_val *v1, const struct ldb_val *v2)
304 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
305 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
306 } else if (ldif_comparision_objectGUID_isString(v1)
307 && !ldif_comparision_objectGUID_isString(v2)) {
310 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
311 /* Perhaps it wasn't a valid string after all */
312 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
314 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
317 } else if (!ldif_comparision_objectGUID_isString(v1)
318 && ldif_comparision_objectGUID_isString(v2)) {
321 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
322 /* Perhaps it wasn't a valid string after all */
323 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
325 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
329 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
333 canonicalise a objectGUID
335 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
336 const struct ldb_val *in, struct ldb_val *out)
338 if (ldif_comparision_objectGUID_isString(in)) {
339 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
340 /* Perhaps it wasn't a valid string after all */
341 return ldb_handler_copy(ldb, mem_ctx, in, out);
345 return ldb_handler_copy(ldb, mem_ctx, in, out);
350 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
352 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
353 const struct ldb_val *in, struct ldb_val *out)
355 struct security_descriptor *sd;
356 enum ndr_err_code ndr_err;
358 sd = talloc(mem_ctx, struct security_descriptor);
363 ndr_err = ndr_pull_struct_blob(in, sd, sd,
364 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
365 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
366 /* If this does not parse, then it is probably SDDL, and we should try it that way */
368 const struct dom_sid *sid = samdb_domain_sid(ldb);
370 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
376 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
377 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
379 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
387 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
389 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
390 const struct ldb_val *in, struct ldb_val *out)
392 struct security_descriptor *sd;
393 enum ndr_err_code ndr_err;
395 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
396 return ldif_write_NDR(ldb, mem_ctx, in, out,
397 sizeof(struct security_descriptor),
398 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
399 (ndr_print_fn_t)ndr_print_security_descriptor,
404 sd = talloc(mem_ctx, struct security_descriptor);
408 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
409 ndr_err = ndr_pull_struct_blob(in, sd, sd,
410 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
411 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
415 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
417 if (out->data == NULL) {
420 out->length = strlen((const char *)out->data);
425 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
427 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
428 const struct ldb_val *in, struct ldb_val *out)
430 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
431 struct security_descriptor *sd;
432 const struct dom_sid *sid = samdb_domain_sid(ldb);
434 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
435 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
436 (ndr_print_fn_t)ndr_print_security_descriptor,
438 out->length = strlen((const char *)out->data);
443 return ldb_handler_copy(ldb, mem_ctx, in, out);
447 canonicalise an objectCategory. We use the long form as the canonical form:
448 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
450 Also any short name of an objectClass that points to a different
451 class (such as user) has the canonical form of the class it's
452 defaultObjectCategory points to (eg
453 cn=Person,cn=Schema,cn=Configuration,<basedn>)
456 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
457 const struct ldb_val *in, struct ldb_val *out)
459 struct ldb_dn *dn1 = NULL;
460 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
461 const struct dsdb_class *sclass;
462 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
464 return LDB_ERR_OPERATIONS_ERROR;
468 talloc_free(tmp_ctx);
469 *out = data_blob_talloc(mem_ctx, in->data, in->length);
470 if (in->data && !out->data) {
471 return LDB_ERR_OPERATIONS_ERROR;
475 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
476 if ( ! ldb_dn_validate(dn1)) {
477 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
478 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
480 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
481 sclass->defaultObjectCategory);
483 talloc_free(tmp_ctx);
484 return LDB_ERR_OPERATIONS_ERROR;
487 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
488 talloc_free(tmp_ctx);
491 return LDB_ERR_OPERATIONS_ERROR;
495 *out = data_blob_talloc(mem_ctx, in->data, in->length);
496 talloc_free(tmp_ctx);
498 if (in->data && !out->data) {
499 return LDB_ERR_OPERATIONS_ERROR;
504 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
505 talloc_free(tmp_ctx);
508 return LDB_ERR_OPERATIONS_ERROR;
513 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
514 const struct ldb_val *v1,
515 const struct ldb_val *v2)
517 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
522 convert a NDR formatted blob to a ldif formatted schemaInfo
524 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
525 const struct ldb_val *in, struct ldb_val *out)
527 return ldif_write_NDR(ldb, mem_ctx, in, out,
528 sizeof(struct repsFromToBlob),
529 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
530 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
535 convert a ldif formatted prefixMap to a NDR formatted blob
537 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
538 const struct ldb_val *in, struct ldb_val *out)
540 struct prefixMapBlob *blob;
541 enum ndr_err_code ndr_err;
542 char *string, *line, *p, *oid;
545 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
547 if (tmp_ctx == NULL) {
551 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
553 talloc_free(tmp_ctx);
557 /* use the switch value to detect if this is in the binary
560 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
561 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
562 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
563 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
564 ndr_err = ndr_push_struct_blob(out, mem_ctx,
566 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
567 talloc_free(tmp_ctx);
568 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
575 /* If this does not parse, then it is probably the text version, and we should try it that way */
576 blob->version = PREFIX_MAP_VERSION_DSDB;
578 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
579 if (string == NULL) {
585 while (line && line[0]) {
590 p=strchr(line, '\n');
595 /* allow a trailing separator */
600 blob->ctr.dsdb.mappings = talloc_realloc(blob,
601 blob->ctr.dsdb.mappings,
602 struct drsuapi_DsReplicaOIDMapping,
603 blob->ctr.dsdb.num_mappings+1);
604 if (!blob->ctr.dsdb.mappings) {
605 talloc_free(tmp_ctx);
609 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
612 talloc_free(tmp_ctx);
616 /* we know there must be at least ":" */
619 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
620 talloc_free(tmp_ctx);
623 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
624 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
626 blob->ctr.dsdb.num_mappings++;
628 /* Now look past the terminator we added above */
636 ndr_err = ndr_push_struct_blob(out, mem_ctx,
638 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
639 talloc_free(tmp_ctx);
640 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
647 convert a NDR formatted blob to a ldif formatted prefixMap
649 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
650 const struct ldb_val *in, struct ldb_val *out)
652 struct prefixMapBlob *blob;
653 enum ndr_err_code ndr_err;
657 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
659 /* try to decode the blob as S4 prefixMap */
660 err = ldif_write_NDR(ldb, mem_ctx, in, out,
661 sizeof(struct prefixMapBlob),
662 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
663 (ndr_print_fn_t)ndr_print_prefixMapBlob,
668 /* try parsing it as Windows PrefixMap value */
669 return ldif_write_NDR(ldb, mem_ctx, in, out,
670 sizeof(struct drsuapi_MSPrefixMap_Ctr),
671 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
672 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
676 blob = talloc(mem_ctx, struct prefixMapBlob);
680 ndr_err = ndr_pull_struct_blob_all(in, blob,
682 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
683 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
686 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
689 string = talloc_strdup(mem_ctx, "");
690 if (string == NULL) {
694 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
696 char *partial_oid = NULL;
699 string = talloc_asprintf_append(string, ";");
702 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
703 blob->ctr.dsdb.mappings[i].oid.length);
704 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
705 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
706 blob->ctr.dsdb.mappings[i].id_prefix));
709 string = talloc_asprintf_append(string, "%u:%s",
710 blob->ctr.dsdb.mappings[i].id_prefix,
712 talloc_free(discard_const(partial_oid));
713 if (string == NULL) {
719 *out = data_blob_string_const(string);
727 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
733 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
741 canonicalise a prefixMap
743 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
744 const struct ldb_val *in, struct ldb_val *out)
746 if (ldif_comparision_prefixMap_isString(in)) {
747 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
749 return ldb_handler_copy(ldb, mem_ctx, in, out);
752 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
753 const struct ldb_val *v1,
754 const struct ldb_val *v2)
756 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
760 /* length limited conversion of a ldb_val to a int32_t */
761 static int val_to_int32(const struct ldb_val *in, int32_t *v)
766 /* make sure we don't read past the end of the data */
767 if (in->length > sizeof(buf)-1) {
768 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
770 strncpy(buf, (char *)in->data, in->length);
773 /* We've to use "strtoll" here to have the intended overflows.
774 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
775 *v = (int32_t) strtoll(buf, &end, 0);
777 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
782 /* length limited conversion of a ldb_val to a int64_t */
783 static int val_to_int64(const struct ldb_val *in, int64_t *v)
788 /* make sure we don't read past the end of the data */
789 if (in->length > sizeof(buf)-1) {
790 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
792 strncpy(buf, (char *)in->data, in->length);
795 *v = (int64_t) strtoll(buf, &end, 0);
797 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
802 /* Canonicalisation of two 32-bit integers */
803 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
804 const struct ldb_val *in, struct ldb_val *out)
809 ret = val_to_int32(in, &i);
810 if (ret != LDB_SUCCESS) {
813 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
814 if (out->data == NULL) {
816 return LDB_ERR_OPERATIONS_ERROR;
818 out->length = strlen((char *)out->data);
822 /* Comparison of two 32-bit integers */
823 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
824 const struct ldb_val *v1, const struct ldb_val *v2)
827 val_to_int32(v1, &i1);
828 val_to_int32(v2, &i2);
829 if (i1 == i2) return 0;
830 return i1 > i2? 1 : -1;
833 /* Canonicalisation of two 64-bit integers */
834 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
835 const struct ldb_val *in, struct ldb_val *out)
840 ret = val_to_int64(in, &i);
841 if (ret != LDB_SUCCESS) {
844 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
845 if (out->data == NULL) {
847 return LDB_ERR_OPERATIONS_ERROR;
849 out->length = strlen((char *)out->data);
853 /* Comparison of two 64-bit integers */
854 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
855 const struct ldb_val *v1, const struct ldb_val *v2)
858 val_to_int64(v1, &i1);
859 val_to_int64(v2, &i2);
860 if (i1 == i2) return 0;
861 return i1 > i2? 1 : -1;
865 convert a NDR formatted blob to a ldif formatted repsFromTo
867 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
868 const struct ldb_val *in, struct ldb_val *out)
870 return ldif_write_NDR(ldb, mem_ctx, in, out,
871 sizeof(struct repsFromToBlob),
872 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
873 (ndr_print_fn_t)ndr_print_repsFromToBlob,
878 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
880 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
881 const struct ldb_val *in, struct ldb_val *out)
883 return ldif_write_NDR(ldb, mem_ctx, in, out,
884 sizeof(struct replPropertyMetaDataBlob),
885 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
886 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
891 convert a NDR formatted blob to a ldif formatted replUpToDateVector
893 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
894 const struct ldb_val *in, struct ldb_val *out)
896 return ldif_write_NDR(ldb, mem_ctx, in, out,
897 sizeof(struct replUpToDateVectorBlob),
898 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
899 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
903 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
904 const struct ldb_val *in, struct ldb_val *out,
906 ndr_pull_flags_fn_t pull_fn,
907 ndr_print_fn_t print_fn,
911 enum ndr_err_code err;
912 struct dsdb_dn *dsdb_dn = NULL;
916 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
917 return ldb_handler_copy(ldb, mem_ctx, in, out);
920 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
921 if (dsdb_dn == NULL) {
922 return ldb_handler_copy(ldb, mem_ctx, in, out);
925 p = talloc_size(dsdb_dn, struct_size);
927 TALLOC_FREE(dsdb_dn);
928 return ldb_handler_copy(ldb, mem_ctx, in, out);
931 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
932 if (err != NDR_ERR_SUCCESS) {
933 /* fail in not in mask_error mode */
937 TALLOC_FREE(dsdb_dn);
938 return ldb_handler_copy(ldb, mem_ctx, in, out);
941 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
942 if (dn_str == NULL) {
943 TALLOC_FREE(dsdb_dn);
944 return ldb_handler_copy(ldb, mem_ctx, in, out);
947 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
948 TALLOC_FREE(dsdb_dn);
950 return ldb_handler_copy(ldb, mem_ctx, in, out);
953 *out = data_blob_string_const(str);
957 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
958 const struct ldb_val *in, struct ldb_val *out)
960 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
961 sizeof(struct replPropertyMetaData1),
962 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
963 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
968 convert a NDR formatted blob to a ldif formatted dnsRecord
970 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
971 const struct ldb_val *in, struct ldb_val *out)
973 return ldif_write_NDR(ldb, mem_ctx, in, out,
974 sizeof(struct dnsp_DnssrvRpcRecord),
975 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
976 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
981 convert a NDR formatted blob to a ldif formatted dnsProperty
983 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
984 const struct ldb_val *in, struct ldb_val *out)
986 return ldif_write_NDR(ldb, mem_ctx, in, out,
987 sizeof(struct dnsp_DnsProperty),
988 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
989 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
994 convert a NDR formatted blob of a supplementalCredentials into text
996 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
997 const struct ldb_val *in, struct ldb_val *out)
999 return ldif_write_NDR(ldb, mem_ctx, in, out,
1000 sizeof(struct supplementalCredentialsBlob),
1001 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1002 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1007 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1009 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1010 const struct ldb_val *in, struct ldb_val *out)
1012 return ldif_write_NDR(ldb, mem_ctx, in, out,
1013 sizeof(struct trustAuthInOutBlob),
1014 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1015 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1020 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1022 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1023 const struct ldb_val *in, struct ldb_val *out)
1025 return ldif_write_NDR(ldb, mem_ctx, in, out,
1026 sizeof(struct ForestTrustInfo),
1027 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1028 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1032 convert a NDR formatted blob of a partialAttributeSet into text
1034 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1035 const struct ldb_val *in, struct ldb_val *out)
1037 return ldif_write_NDR(ldb, mem_ctx, in, out,
1038 sizeof(struct partialAttributeSetBlob),
1039 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1040 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1045 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1046 const struct ldb_val *in, struct ldb_val *out)
1048 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1058 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1059 const struct ldb_val *v1, const struct ldb_val *v2)
1061 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1064 if (dsdb_dn_is_deleted_val(v1)) {
1065 /* If the DN is deleted, then we can't search for it */
1069 if (dsdb_dn_is_deleted_val(v2)) {
1070 /* If the DN is deleted, then we can't search for it */
1074 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1075 if ( ! ldb_dn_validate(dn1)) return -1;
1077 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1078 if ( ! ldb_dn_validate(dn2)) {
1083 ret = ldb_dn_compare(dn1, dn2);
1090 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1091 const struct ldb_val *in, struct ldb_val *out)
1099 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1100 if ( ! ldb_dn_validate(dn)) {
1101 return LDB_ERR_INVALID_DN_SYNTAX;
1104 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1105 * does not casually match a not deleted DN */
1106 if (dsdb_dn_is_deleted_val(in)) {
1107 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1109 dsdb_dn_val_rmd_flags(in),
1110 ldb_dn_get_casefold(dn));
1112 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1115 if (out->data == NULL) {
1118 out->length = strlen((char *)out->data);
1130 write a 64 bit 2-part range
1132 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1133 const struct ldb_val *in, struct ldb_val *out)
1137 ret = val_to_int64(in, &v);
1138 if (ret != LDB_SUCCESS) {
1141 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1142 (unsigned long)(v&0xFFFFFFFF),
1143 (unsigned long)(v>>32));
1144 if (out->data == NULL) {
1146 return LDB_ERR_OPERATIONS_ERROR;
1148 out->length = strlen((char *)out->data);
1153 read a 64 bit 2-part range
1155 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1156 const struct ldb_val *in, struct ldb_val *out)
1158 unsigned long high, low;
1161 if (memchr(in->data, '-', in->length) == NULL) {
1162 return ldb_handler_copy(ldb, mem_ctx, in, out);
1165 if (in->length > sizeof(buf)-1) {
1166 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1168 strncpy(buf, (const char *)in->data, in->length);
1169 buf[in->length] = 0;
1171 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1172 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1175 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1176 (unsigned long long)(((uint64_t)high)<<32) | (low));
1178 if (out->data == NULL) {
1180 return LDB_ERR_OPERATIONS_ERROR;
1182 out->length = strlen((char *)out->data);
1187 when this operator_fn is set for a syntax, the backend calls is in
1188 preference to the comparison function. We are told the exact
1189 comparison operation that is needed, and we can return errors
1191 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1192 const struct ldb_schema_attribute *a,
1193 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1195 switch (operation) {
1199 case LDB_OP_SUBSTRING:
1201 case LDB_OP_EXTENDED:
1202 /* handled in the backends */
1203 return LDB_ERR_INAPPROPRIATE_MATCHING;
1205 case LDB_OP_GREATER:
1207 case LDB_OP_EQUALITY:
1209 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1211 if (tmp_ctx == NULL) {
1212 return ldb_oom(ldb);
1214 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1215 talloc_free(tmp_ctx);
1216 if (operation == LDB_OP_GREATER) {
1217 *matched = (ret >= 0);
1218 } else if (operation == LDB_OP_LESS) {
1219 *matched = (ret <= 0);
1221 *matched = (ret == 0);
1226 case LDB_OP_PRESENT:
1231 /* we shouldn't get here */
1232 return LDB_ERR_INAPPROPRIATE_MATCHING;
1236 compare two binary objects. This is correct for sorting as the sort order is:
1243 rather than ldb_comparison_binary() which is:
1251 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1252 const struct ldb_val *v1, const struct ldb_val *v2)
1254 return data_blob_cmp(v1, v2);
1258 when this operator_fn is set for a syntax, the backend calls is in
1259 preference to the comparison function. We are told the exact
1260 comparison operation that is needed, and we can return errors.
1262 This mode optimises for ldb_comparison_binary() if we need equality,
1263 as this should be faster as it can do a length-check first.
1265 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1266 const struct ldb_schema_attribute *a,
1267 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1269 if (operation == LDB_OP_EQUALITY) {
1270 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1273 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1277 see if two DNs match, comparing first by GUID, then by SID, and
1278 finally by string components
1280 static int samba_dn_extended_match(struct ldb_context *ldb,
1281 const struct ldb_val *v1,
1282 const struct ldb_val *v2,
1285 TALLOC_CTX *tmp_ctx;
1286 struct ldb_dn *dn1, *dn2;
1287 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1288 uint32_t rmd_flags1, rmd_flags2;
1290 tmp_ctx = talloc_new(ldb);
1292 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1293 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1295 /* couldn't parse as DN's */
1296 talloc_free(tmp_ctx);
1301 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1302 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1304 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1305 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1306 /* only match if they have the same deletion status */
1307 talloc_free(tmp_ctx);
1313 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1314 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1315 if (guid1 && guid2) {
1316 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1317 talloc_free(tmp_ctx);
1321 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1322 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1324 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1325 talloc_free(tmp_ctx);
1329 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1331 talloc_free(tmp_ctx);
1336 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1338 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1339 const struct ldb_schema_attribute *a,
1340 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1342 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1343 /* If the DN is deleted, then we can't search for it */
1345 /* should this be for equality too? */
1350 if (operation == LDB_OP_EQUALITY &&
1351 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1355 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1359 static const struct ldb_schema_syntax samba_syntaxes[] = {
1361 .name = LDB_SYNTAX_SAMBA_SID,
1362 .ldif_read_fn = ldif_read_objectSid,
1363 .ldif_write_fn = ldif_write_objectSid,
1364 .canonicalise_fn = ldif_canonicalise_objectSid,
1365 .comparison_fn = ldif_comparison_objectSid,
1366 .operator_fn = samba_syntax_operator_fn
1368 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1369 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1370 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1371 .canonicalise_fn = ldb_handler_copy,
1372 .comparison_fn = samba_ldb_comparison_binary,
1373 .operator_fn = samba_syntax_binary_operator_fn
1375 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1376 .ldif_read_fn = ldb_handler_copy,
1377 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1378 .canonicalise_fn = ldb_handler_fold,
1379 .comparison_fn = ldb_comparison_fold,
1380 .operator_fn = samba_syntax_operator_fn
1382 .name = LDB_SYNTAX_SAMBA_GUID,
1383 .ldif_read_fn = ldif_read_objectGUID,
1384 .ldif_write_fn = ldif_write_objectGUID,
1385 .canonicalise_fn = ldif_canonicalise_objectGUID,
1386 .comparison_fn = ldif_comparison_objectGUID,
1387 .operator_fn = samba_syntax_operator_fn
1389 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1390 .ldif_read_fn = ldb_handler_copy,
1391 .ldif_write_fn = ldb_handler_copy,
1392 .canonicalise_fn = ldif_canonicalise_objectCategory,
1393 .comparison_fn = ldif_comparison_objectCategory,
1394 .operator_fn = samba_syntax_operator_fn
1396 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1397 .ldif_read_fn = ldb_handler_copy,
1398 .ldif_write_fn = ldif_write_schemaInfo,
1399 .canonicalise_fn = ldb_handler_copy,
1400 .comparison_fn = samba_ldb_comparison_binary,
1401 .operator_fn = samba_syntax_binary_operator_fn
1403 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1404 .ldif_read_fn = ldif_read_prefixMap,
1405 .ldif_write_fn = ldif_write_prefixMap,
1406 .canonicalise_fn = ldif_canonicalise_prefixMap,
1407 .comparison_fn = ldif_comparison_prefixMap,
1408 .operator_fn = samba_syntax_operator_fn
1410 .name = LDB_SYNTAX_SAMBA_INT32,
1411 .ldif_read_fn = ldb_handler_copy,
1412 .ldif_write_fn = ldb_handler_copy,
1413 .canonicalise_fn = ldif_canonicalise_int32,
1414 .comparison_fn = ldif_comparison_int32,
1415 .operator_fn = samba_syntax_operator_fn
1417 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1418 .ldif_read_fn = ldb_handler_copy,
1419 .ldif_write_fn = ldif_write_repsFromTo,
1420 .canonicalise_fn = ldb_handler_copy,
1421 .comparison_fn = samba_ldb_comparison_binary,
1422 .operator_fn = samba_syntax_binary_operator_fn
1424 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1425 .ldif_read_fn = ldb_handler_copy,
1426 .ldif_write_fn = ldif_write_replPropertyMetaData,
1427 .canonicalise_fn = ldb_handler_copy,
1428 .comparison_fn = samba_ldb_comparison_binary,
1429 .operator_fn = samba_syntax_binary_operator_fn
1431 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1432 .ldif_read_fn = ldb_handler_copy,
1433 .ldif_write_fn = ldif_write_replUpToDateVector,
1434 .canonicalise_fn = ldb_handler_copy,
1435 .comparison_fn = samba_ldb_comparison_binary,
1436 .operator_fn = samba_syntax_binary_operator_fn
1438 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1439 .ldif_read_fn = ldb_handler_copy,
1440 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1441 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1442 .comparison_fn = dsdb_dn_binary_comparison,
1443 .operator_fn = samba_syntax_operator_fn
1445 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1446 .ldif_read_fn = ldb_handler_copy,
1447 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1448 .canonicalise_fn = ldb_handler_copy,
1449 .comparison_fn = samba_ldb_comparison_binary,
1450 .operator_fn = samba_syntax_binary_operator_fn
1452 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1453 .ldif_read_fn = ldb_handler_copy,
1454 .ldif_write_fn = ldif_write_ForestTrustInfo,
1455 .canonicalise_fn = ldb_handler_copy,
1456 .comparison_fn = samba_ldb_comparison_binary,
1457 .operator_fn = samba_syntax_binary_operator_fn
1459 .name = DSDB_SYNTAX_BINARY_DN,
1460 .ldif_read_fn = ldb_handler_copy,
1461 .ldif_write_fn = ldb_handler_copy,
1462 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1463 .comparison_fn = dsdb_dn_binary_comparison,
1464 .operator_fn = samba_syntax_operator_fn
1466 .name = DSDB_SYNTAX_STRING_DN,
1467 .ldif_read_fn = ldb_handler_copy,
1468 .ldif_write_fn = ldb_handler_copy,
1469 .canonicalise_fn = dsdb_dn_string_canonicalise,
1470 .comparison_fn = dsdb_dn_string_comparison,
1471 .operator_fn = samba_syntax_operator_fn
1473 .name = LDB_SYNTAX_DN,
1474 .ldif_read_fn = ldb_handler_copy,
1475 .ldif_write_fn = ldb_handler_copy,
1476 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1477 .comparison_fn = samba_ldb_dn_link_comparison,
1478 .operator_fn = samba_syntax_operator_dn
1480 .name = LDB_SYNTAX_SAMBA_RANGE64,
1481 .ldif_read_fn = ldif_read_range64,
1482 .ldif_write_fn = ldif_write_range64,
1483 .canonicalise_fn = ldif_canonicalise_int64,
1484 .comparison_fn = ldif_comparison_int64,
1485 .operator_fn = samba_syntax_operator_fn
1487 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1488 .ldif_read_fn = ldb_handler_copy,
1489 .ldif_write_fn = ldif_write_dnsRecord,
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_DNSPROPERTY,
1495 .ldif_read_fn = ldb_handler_copy,
1496 .ldif_write_fn = ldif_write_dnsProperty,
1497 .canonicalise_fn = ldb_handler_copy,
1498 .comparison_fn = samba_ldb_comparison_binary,
1499 .operator_fn = samba_syntax_binary_operator_fn
1501 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1502 .ldif_read_fn = ldb_handler_copy,
1503 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1504 .canonicalise_fn = ldb_handler_copy,
1505 .comparison_fn = samba_ldb_comparison_binary,
1506 .operator_fn = samba_syntax_binary_operator_fn
1508 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1509 .ldif_read_fn = ldb_handler_copy,
1510 .ldif_write_fn = ldif_write_partialAttributeSet,
1511 .canonicalise_fn = ldb_handler_copy,
1512 .comparison_fn = samba_ldb_comparison_binary,
1513 .operator_fn = samba_syntax_binary_operator_fn
1515 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1516 .ldif_read_fn = ldb_handler_copy,
1517 .ldif_write_fn = ldb_handler_copy,
1518 .canonicalise_fn = ldb_handler_copy,
1519 .comparison_fn = samba_ldb_comparison_binary,
1520 .operator_fn = samba_syntax_binary_operator_fn
1524 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1527 .read_fn = extended_dn_read_SID,
1528 .write_clear_fn = ldif_write_objectSid,
1529 .write_hex_fn = extended_dn_write_hex
1532 .read_fn = extended_dn_read_GUID,
1533 .write_clear_fn = ldif_write_objectGUID,
1534 .write_hex_fn = extended_dn_write_hex
1537 .read_fn = ldb_handler_copy,
1538 .write_clear_fn = ldb_handler_copy,
1539 .write_hex_fn = ldb_handler_copy
1541 .name = "RMD_INVOCID",
1542 .read_fn = extended_dn_read_GUID,
1543 .write_clear_fn = ldif_write_objectGUID,
1544 .write_hex_fn = extended_dn_write_hex
1546 .name = "RMD_FLAGS",
1547 .read_fn = ldb_handler_copy,
1548 .write_clear_fn = ldb_handler_copy,
1549 .write_hex_fn = ldb_handler_copy
1551 .name = "RMD_ADDTIME",
1552 .read_fn = ldb_handler_copy,
1553 .write_clear_fn = ldb_handler_copy,
1554 .write_hex_fn = ldb_handler_copy
1556 .name = "RMD_CHANGETIME",
1557 .read_fn = ldb_handler_copy,
1558 .write_clear_fn = ldb_handler_copy,
1559 .write_hex_fn = ldb_handler_copy
1561 .name = "RMD_LOCAL_USN",
1562 .read_fn = ldb_handler_copy,
1563 .write_clear_fn = ldb_handler_copy,
1564 .write_hex_fn = ldb_handler_copy
1566 .name = "RMD_ORIGINATING_USN",
1567 .read_fn = ldb_handler_copy,
1568 .write_clear_fn = ldb_handler_copy,
1569 .write_hex_fn = ldb_handler_copy
1571 .name = "RMD_VERSION",
1572 .read_fn = ldb_handler_copy,
1573 .write_clear_fn = ldb_handler_copy,
1574 .write_hex_fn = ldb_handler_copy
1578 /* TODO: Should be dynamic at some point */
1579 static const struct {
1582 } samba_attributes[] = {
1583 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1584 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1585 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1586 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1587 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1588 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1589 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1590 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1591 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1592 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1593 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1594 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1595 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1596 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1597 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1598 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1599 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1602 * these are extracted by searching
1603 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1605 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1606 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1607 * hat can be used to identify the set of policies when applied to a resource.
1608 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1609 * server, we ignore it here.
1611 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1612 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1613 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1614 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1615 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1616 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1617 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1618 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1619 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1622 * these are extracted by searching
1623 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1625 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1626 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1627 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1628 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1629 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1630 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1631 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1632 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1633 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1634 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1635 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1636 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1637 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1638 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1639 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1640 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1641 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1642 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1643 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1644 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1645 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1646 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1647 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1648 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1649 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1650 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1651 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1652 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1655 * these are known to be GUIDs
1657 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1658 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1660 /* These NDR encoded things we want to be able to read with --show-binary */
1661 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1662 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1663 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1664 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1667 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1670 const struct ldb_schema_syntax *s = NULL;
1672 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1673 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1674 s = &samba_syntaxes[j];
1681 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1684 const struct ldb_schema_syntax *s = NULL;
1686 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1687 if (strcmp(samba_attributes[j].name, name) == 0) {
1688 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1696 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret", NULL};
1699 register the samba ldif handlers
1701 int ldb_register_samba_handlers(struct ldb_context *ldb)
1706 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1710 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1711 if (ret != LDB_SUCCESS) {
1715 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1716 const struct ldb_schema_syntax *s = NULL;
1718 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1721 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1725 return LDB_ERR_OPERATIONS_ERROR;
1728 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1729 if (ret != LDB_SUCCESS) {
1734 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1735 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1736 if (ret != LDB_SUCCESS) {
1742 ret = ldb_register_samba_matching_rules(ldb);
1743 if (ret != LDB_SUCCESS) {
1748 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1749 if (ret != LDB_SUCCESS) {