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);
95 *out = data_blob_talloc(mem_ctx, NULL,
96 ndr_size_dom_sid(sid, 0));
97 if (out->data == NULL) {
101 ndr_err = ndr_push_struct_into_fixed_blob(out, sid,
102 (ndr_push_flags_fn_t)ndr_push_dom_sid);
104 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
111 convert a NDR formatted blob to a ldif formatted objectSid
113 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
114 const struct ldb_val *in, struct ldb_val *out)
117 enum ndr_err_code ndr_err;
119 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
120 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
121 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
124 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
125 if (out->data == NULL) {
131 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
137 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
143 compare two objectSids
145 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
146 const struct ldb_val *v1, const struct ldb_val *v2)
148 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
149 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
150 } else if (ldif_comparision_objectSid_isString(v1)
151 && !ldif_comparision_objectSid_isString(v2)) {
154 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
155 /* Perhaps not a string after all */
156 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
158 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
161 } else if (!ldif_comparision_objectSid_isString(v1)
162 && ldif_comparision_objectSid_isString(v2)) {
165 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
166 /* Perhaps not a string after all */
167 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
169 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
173 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
177 canonicalise a objectSid
179 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
180 const struct ldb_val *in, struct ldb_val *out)
182 if (ldif_comparision_objectSid_isString(in)) {
183 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
184 /* Perhaps not a string after all */
185 return ldb_handler_copy(ldb, mem_ctx, in, out);
189 return ldb_handler_copy(ldb, mem_ctx, in, out);
192 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
193 const struct ldb_val *in, struct ldb_val *out)
196 enum ndr_err_code ndr_err;
197 if (ldif_comparision_objectSid_isString(in)) {
198 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
203 /* Perhaps not a string after all */
204 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
210 (*out).length = strhex_to_str((char *)out->data, out->length,
211 (const char *)in->data, in->length);
213 /* Check it looks like a SID */
214 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
215 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
216 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
223 convert a ldif formatted objectGUID to a NDR formatted blob
225 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
226 const struct ldb_val *in, struct ldb_val *out)
231 status = GUID_from_data_blob(in, &guid);
232 if (!NT_STATUS_IS_OK(status)) {
236 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
237 if (!NT_STATUS_IS_OK(status)) {
244 convert a NDR formatted blob to a ldif formatted objectGUID
246 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
247 const struct ldb_val *in, struct ldb_val *out)
252 status = GUID_from_ndr_blob(in, &guid);
253 if (!NT_STATUS_IS_OK(status)) {
256 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
257 if (out->data == NULL) {
260 out->length = strlen((const char *)out->data);
264 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
266 if (v->length != 36 && v->length != 38) return false;
268 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
272 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
273 const struct ldb_val *in, struct ldb_val *out)
276 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
280 /* Try as 'hex' form */
281 if (in->length != 32) {
285 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
291 (*out).length = strhex_to_str((char *)out->data, out->length,
292 (const char *)in->data, in->length);
294 /* Check it looks like a GUID */
295 if ((*out).length != 16) {
304 compare two objectGUIDs
306 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
307 const struct ldb_val *v1, const struct ldb_val *v2)
309 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
310 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
311 } else if (ldif_comparision_objectGUID_isString(v1)
312 && !ldif_comparision_objectGUID_isString(v2)) {
315 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
316 /* Perhaps it wasn't a valid string after all */
317 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
319 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
322 } else if (!ldif_comparision_objectGUID_isString(v1)
323 && ldif_comparision_objectGUID_isString(v2)) {
326 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
327 /* Perhaps it wasn't a valid string after all */
328 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
330 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
334 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
338 canonicalise a objectGUID
340 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
341 const struct ldb_val *in, struct ldb_val *out)
343 if (ldif_comparision_objectGUID_isString(in)) {
344 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
345 /* Perhaps it wasn't a valid string after all */
346 return ldb_handler_copy(ldb, mem_ctx, in, out);
350 return ldb_handler_copy(ldb, mem_ctx, in, out);
355 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
357 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
358 const struct ldb_val *in, struct ldb_val *out)
360 struct security_descriptor *sd;
361 enum ndr_err_code ndr_err;
363 sd = talloc(mem_ctx, struct security_descriptor);
368 ndr_err = ndr_pull_struct_blob(in, sd, sd,
369 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
370 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
371 /* If this does not parse, then it is probably SDDL, and we should try it that way */
373 const struct dom_sid *sid = samdb_domain_sid(ldb);
375 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
381 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
382 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
384 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
392 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
394 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
395 const struct ldb_val *in, struct ldb_val *out)
397 struct security_descriptor *sd;
398 enum ndr_err_code ndr_err;
400 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
401 return ldif_write_NDR(ldb, mem_ctx, in, out,
402 sizeof(struct security_descriptor),
403 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
404 (ndr_print_fn_t)ndr_print_security_descriptor,
409 sd = talloc(mem_ctx, struct security_descriptor);
413 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
414 ndr_err = ndr_pull_struct_blob(in, sd, sd,
415 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
416 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
420 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
422 if (out->data == NULL) {
425 out->length = strlen((const char *)out->data);
430 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
432 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
433 const struct ldb_val *in, struct ldb_val *out)
435 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
436 struct security_descriptor *sd;
437 const struct dom_sid *sid = samdb_domain_sid(ldb);
439 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
440 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
441 (ndr_print_fn_t)ndr_print_security_descriptor,
443 out->length = strlen((const char *)out->data);
448 return ldb_handler_copy(ldb, mem_ctx, in, out);
452 canonicalise an objectCategory. We use the long form as the canonical form:
453 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
455 Also any short name of an objectClass that points to a different
456 class (such as user) has the canonical form of the class it's
457 defaultObjectCategory points to (eg
458 cn=Person,cn=Schema,cn=Configuration,<basedn>)
461 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
462 const struct ldb_val *in, struct ldb_val *out)
464 struct ldb_dn *dn1 = NULL;
465 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
466 const struct dsdb_class *sclass;
467 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
469 return LDB_ERR_OPERATIONS_ERROR;
473 talloc_free(tmp_ctx);
474 *out = data_blob_talloc(mem_ctx, in->data, in->length);
475 if (in->data && !out->data) {
476 return LDB_ERR_OPERATIONS_ERROR;
480 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
481 if ( ! ldb_dn_validate(dn1)) {
482 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
483 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
485 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
486 sclass->defaultObjectCategory);
488 talloc_free(tmp_ctx);
489 return LDB_ERR_OPERATIONS_ERROR;
492 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
493 talloc_free(tmp_ctx);
496 return LDB_ERR_OPERATIONS_ERROR;
500 *out = data_blob_talloc(mem_ctx, in->data, in->length);
501 talloc_free(tmp_ctx);
503 if (in->data && !out->data) {
504 return LDB_ERR_OPERATIONS_ERROR;
509 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
510 talloc_free(tmp_ctx);
513 return LDB_ERR_OPERATIONS_ERROR;
518 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
519 const struct ldb_val *v1,
520 const struct ldb_val *v2)
522 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
527 convert a NDR formatted blob to a ldif formatted schemaInfo
529 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
530 const struct ldb_val *in, struct ldb_val *out)
532 return ldif_write_NDR(ldb, mem_ctx, in, out,
533 sizeof(struct repsFromToBlob),
534 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
535 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
540 convert a ldif formatted prefixMap to a NDR formatted blob
542 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
543 const struct ldb_val *in, struct ldb_val *out)
545 struct prefixMapBlob *blob;
546 enum ndr_err_code ndr_err;
547 char *string, *line, *p, *oid;
550 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
552 if (tmp_ctx == NULL) {
556 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
558 talloc_free(tmp_ctx);
562 /* use the switch value to detect if this is in the binary
565 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
566 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
567 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
568 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
569 ndr_err = ndr_push_struct_blob(out, mem_ctx,
571 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
572 talloc_free(tmp_ctx);
573 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
580 /* If this does not parse, then it is probably the text version, and we should try it that way */
581 blob->version = PREFIX_MAP_VERSION_DSDB;
583 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
584 if (string == NULL) {
590 while (line && line[0]) {
595 p=strchr(line, '\n');
600 /* allow a trailing separator */
605 blob->ctr.dsdb.mappings = talloc_realloc(blob,
606 blob->ctr.dsdb.mappings,
607 struct drsuapi_DsReplicaOIDMapping,
608 blob->ctr.dsdb.num_mappings+1);
609 if (!blob->ctr.dsdb.mappings) {
610 talloc_free(tmp_ctx);
614 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
617 talloc_free(tmp_ctx);
621 /* we know there must be at least ":" */
624 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
625 talloc_free(tmp_ctx);
628 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
629 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
631 blob->ctr.dsdb.num_mappings++;
633 /* Now look past the terminator we added above */
641 ndr_err = ndr_push_struct_blob(out, mem_ctx,
643 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
644 talloc_free(tmp_ctx);
645 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
652 convert a NDR formatted blob to a ldif formatted prefixMap
654 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
655 const struct ldb_val *in, struct ldb_val *out)
657 struct prefixMapBlob *blob;
658 enum ndr_err_code ndr_err;
662 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
664 /* try to decode the blob as S4 prefixMap */
665 err = ldif_write_NDR(ldb, mem_ctx, in, out,
666 sizeof(struct prefixMapBlob),
667 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
668 (ndr_print_fn_t)ndr_print_prefixMapBlob,
673 /* try parsing it as Windows PrefixMap value */
674 return ldif_write_NDR(ldb, mem_ctx, in, out,
675 sizeof(struct drsuapi_MSPrefixMap_Ctr),
676 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
677 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
681 blob = talloc(mem_ctx, struct prefixMapBlob);
685 ndr_err = ndr_pull_struct_blob_all(in, blob,
687 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
688 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
691 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
694 string = talloc_strdup(mem_ctx, "");
695 if (string == NULL) {
699 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
701 char *partial_oid = NULL;
704 string = talloc_asprintf_append(string, ";");
707 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
708 blob->ctr.dsdb.mappings[i].oid.length);
709 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
710 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
711 blob->ctr.dsdb.mappings[i].id_prefix));
714 string = talloc_asprintf_append(string, "%u:%s",
715 blob->ctr.dsdb.mappings[i].id_prefix,
717 talloc_free(discard_const(partial_oid));
718 if (string == NULL) {
724 *out = data_blob_string_const(string);
732 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
738 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
746 canonicalise a prefixMap
748 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
749 const struct ldb_val *in, struct ldb_val *out)
751 if (ldif_comparision_prefixMap_isString(in)) {
752 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
754 return ldb_handler_copy(ldb, mem_ctx, in, out);
757 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
758 const struct ldb_val *v1,
759 const struct ldb_val *v2)
761 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
765 /* length limited conversion of a ldb_val to a int32_t */
766 static int val_to_int32(const struct ldb_val *in, int32_t *v)
771 /* make sure we don't read past the end of the data */
772 if (in->length > sizeof(buf)-1) {
773 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
775 strncpy(buf, (char *)in->data, in->length);
778 /* We've to use "strtoll" here to have the intended overflows.
779 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
780 *v = (int32_t) strtoll(buf, &end, 0);
782 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
787 /* length limited conversion of a ldb_val to a int64_t */
788 static int val_to_int64(const struct ldb_val *in, int64_t *v)
793 /* make sure we don't read past the end of the data */
794 if (in->length > sizeof(buf)-1) {
795 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
797 strncpy(buf, (char *)in->data, in->length);
800 *v = (int64_t) strtoll(buf, &end, 0);
802 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
807 /* Canonicalisation of two 32-bit integers */
808 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
809 const struct ldb_val *in, struct ldb_val *out)
814 ret = val_to_int32(in, &i);
815 if (ret != LDB_SUCCESS) {
818 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
819 if (out->data == NULL) {
821 return LDB_ERR_OPERATIONS_ERROR;
823 out->length = strlen((char *)out->data);
827 /* Comparison of two 32-bit integers */
828 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
829 const struct ldb_val *v1, const struct ldb_val *v2)
832 val_to_int32(v1, &i1);
833 val_to_int32(v2, &i2);
834 if (i1 == i2) return 0;
835 return i1 > i2? 1 : -1;
838 /* Canonicalisation of two 64-bit integers */
839 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
840 const struct ldb_val *in, struct ldb_val *out)
845 ret = val_to_int64(in, &i);
846 if (ret != LDB_SUCCESS) {
849 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
850 if (out->data == NULL) {
852 return LDB_ERR_OPERATIONS_ERROR;
854 out->length = strlen((char *)out->data);
858 /* Comparison of two 64-bit integers */
859 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
860 const struct ldb_val *v1, const struct ldb_val *v2)
863 val_to_int64(v1, &i1);
864 val_to_int64(v2, &i2);
865 if (i1 == i2) return 0;
866 return i1 > i2? 1 : -1;
870 convert a NDR formatted blob to a ldif formatted repsFromTo
872 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
873 const struct ldb_val *in, struct ldb_val *out)
875 return ldif_write_NDR(ldb, mem_ctx, in, out,
876 sizeof(struct repsFromToBlob),
877 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
878 (ndr_print_fn_t)ndr_print_repsFromToBlob,
883 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
885 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
886 const struct ldb_val *in, struct ldb_val *out)
888 return ldif_write_NDR(ldb, mem_ctx, in, out,
889 sizeof(struct replPropertyMetaDataBlob),
890 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
891 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
896 convert a NDR formatted blob to a ldif formatted replUpToDateVector
898 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
899 const struct ldb_val *in, struct ldb_val *out)
901 return ldif_write_NDR(ldb, mem_ctx, in, out,
902 sizeof(struct replUpToDateVectorBlob),
903 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
904 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
908 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
909 const struct ldb_val *in, struct ldb_val *out,
911 ndr_pull_flags_fn_t pull_fn,
912 ndr_print_fn_t print_fn,
916 enum ndr_err_code err;
917 struct dsdb_dn *dsdb_dn = NULL;
921 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
922 return ldb_handler_copy(ldb, mem_ctx, in, out);
925 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
926 if (dsdb_dn == NULL) {
927 return ldb_handler_copy(ldb, mem_ctx, in, out);
930 p = talloc_size(dsdb_dn, struct_size);
932 TALLOC_FREE(dsdb_dn);
933 return ldb_handler_copy(ldb, mem_ctx, in, out);
936 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
937 if (err != NDR_ERR_SUCCESS) {
938 /* fail in not in mask_error mode */
942 TALLOC_FREE(dsdb_dn);
943 return ldb_handler_copy(ldb, mem_ctx, in, out);
946 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
947 if (dn_str == NULL) {
948 TALLOC_FREE(dsdb_dn);
949 return ldb_handler_copy(ldb, mem_ctx, in, out);
952 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
953 TALLOC_FREE(dsdb_dn);
955 return ldb_handler_copy(ldb, mem_ctx, in, out);
958 *out = data_blob_string_const(str);
962 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
963 const struct ldb_val *in, struct ldb_val *out)
965 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
966 sizeof(struct replPropertyMetaData1),
967 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
968 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
973 convert a NDR formatted blob to a ldif formatted dnsRecord
975 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
976 const struct ldb_val *in, struct ldb_val *out)
978 return ldif_write_NDR(ldb, mem_ctx, in, out,
979 sizeof(struct dnsp_DnssrvRpcRecord),
980 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
981 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
986 convert a NDR formatted blob to a ldif formatted dnsProperty
988 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
989 const struct ldb_val *in, struct ldb_val *out)
991 return ldif_write_NDR(ldb, mem_ctx, in, out,
992 sizeof(struct dnsp_DnsProperty),
993 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
994 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
999 convert a NDR formatted blob of a supplementalCredentials into text
1001 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1002 const struct ldb_val *in, struct ldb_val *out)
1004 return ldif_write_NDR(ldb, mem_ctx, in, out,
1005 sizeof(struct supplementalCredentialsBlob),
1006 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1007 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1012 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1014 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1015 const struct ldb_val *in, struct ldb_val *out)
1017 return ldif_write_NDR(ldb, mem_ctx, in, out,
1018 sizeof(struct trustAuthInOutBlob),
1019 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1020 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1025 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1027 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1028 const struct ldb_val *in, struct ldb_val *out)
1030 return ldif_write_NDR(ldb, mem_ctx, in, out,
1031 sizeof(struct ForestTrustInfo),
1032 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1033 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1037 convert a NDR formatted blob of a partialAttributeSet into text
1039 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1040 const struct ldb_val *in, struct ldb_val *out)
1042 return ldif_write_NDR(ldb, mem_ctx, in, out,
1043 sizeof(struct partialAttributeSetBlob),
1044 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1045 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1050 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1051 const struct ldb_val *in, struct ldb_val *out)
1053 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1063 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1064 const struct ldb_val *v1, const struct ldb_val *v2)
1066 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1069 if (dsdb_dn_is_deleted_val(v1)) {
1070 /* If the DN is deleted, then we can't search for it */
1074 if (dsdb_dn_is_deleted_val(v2)) {
1075 /* If the DN is deleted, then we can't search for it */
1079 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1080 if ( ! ldb_dn_validate(dn1)) return -1;
1082 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1083 if ( ! ldb_dn_validate(dn2)) {
1088 ret = ldb_dn_compare(dn1, dn2);
1095 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1096 const struct ldb_val *in, struct ldb_val *out)
1104 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1105 if ( ! ldb_dn_validate(dn)) {
1106 return LDB_ERR_INVALID_DN_SYNTAX;
1109 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1110 * does not casually match a not deleted DN */
1111 if (dsdb_dn_is_deleted_val(in)) {
1112 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1114 dsdb_dn_val_rmd_flags(in),
1115 ldb_dn_get_casefold(dn));
1117 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1120 if (out->data == NULL) {
1123 out->length = strlen((char *)out->data);
1135 write a 64 bit 2-part range
1137 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1138 const struct ldb_val *in, struct ldb_val *out)
1142 ret = val_to_int64(in, &v);
1143 if (ret != LDB_SUCCESS) {
1146 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1147 (unsigned long)(v&0xFFFFFFFF),
1148 (unsigned long)(v>>32));
1149 if (out->data == NULL) {
1151 return LDB_ERR_OPERATIONS_ERROR;
1153 out->length = strlen((char *)out->data);
1158 read a 64 bit 2-part range
1160 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1161 const struct ldb_val *in, struct ldb_val *out)
1163 unsigned long high, low;
1166 if (memchr(in->data, '-', in->length) == NULL) {
1167 return ldb_handler_copy(ldb, mem_ctx, in, out);
1170 if (in->length > sizeof(buf)-1) {
1171 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1173 strncpy(buf, (const char *)in->data, in->length);
1174 buf[in->length] = 0;
1176 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1177 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1180 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1181 (unsigned long long)(((uint64_t)high)<<32) | (low));
1183 if (out->data == NULL) {
1185 return LDB_ERR_OPERATIONS_ERROR;
1187 out->length = strlen((char *)out->data);
1192 when this operator_fn is set for a syntax, the backend calls is in
1193 preference to the comparison function. We are told the exact
1194 comparison operation that is needed, and we can return errors
1196 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1197 const struct ldb_schema_attribute *a,
1198 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1200 switch (operation) {
1204 case LDB_OP_SUBSTRING:
1206 case LDB_OP_EXTENDED:
1207 /* handled in the backends */
1208 return LDB_ERR_INAPPROPRIATE_MATCHING;
1210 case LDB_OP_GREATER:
1212 case LDB_OP_EQUALITY:
1214 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1216 if (tmp_ctx == NULL) {
1217 return ldb_oom(ldb);
1219 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1220 talloc_free(tmp_ctx);
1221 if (operation == LDB_OP_GREATER) {
1222 *matched = (ret >= 0);
1223 } else if (operation == LDB_OP_LESS) {
1224 *matched = (ret <= 0);
1226 *matched = (ret == 0);
1231 case LDB_OP_PRESENT:
1236 /* we shouldn't get here */
1237 return LDB_ERR_INAPPROPRIATE_MATCHING;
1241 compare two binary objects. This is correct for sorting as the sort order is:
1248 rather than ldb_comparison_binary() which is:
1256 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1257 const struct ldb_val *v1, const struct ldb_val *v2)
1259 return data_blob_cmp(v1, v2);
1263 when this operator_fn is set for a syntax, the backend calls is in
1264 preference to the comparison function. We are told the exact
1265 comparison operation that is needed, and we can return errors.
1267 This mode optimises for ldb_comparison_binary() if we need equality,
1268 as this should be faster as it can do a length-check first.
1270 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1271 const struct ldb_schema_attribute *a,
1272 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1274 if (operation == LDB_OP_EQUALITY) {
1275 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1278 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1282 see if two DNs match, comparing first by GUID, then by SID, and
1283 finally by string components
1285 static int samba_dn_extended_match(struct ldb_context *ldb,
1286 const struct ldb_val *v1,
1287 const struct ldb_val *v2,
1290 TALLOC_CTX *tmp_ctx;
1291 struct ldb_dn *dn1, *dn2;
1292 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1293 uint32_t rmd_flags1, rmd_flags2;
1295 tmp_ctx = talloc_new(ldb);
1297 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1298 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1300 /* couldn't parse as DN's */
1301 talloc_free(tmp_ctx);
1306 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1307 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1309 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1310 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1311 /* only match if they have the same deletion status */
1312 talloc_free(tmp_ctx);
1318 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1319 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1320 if (guid1 && guid2) {
1321 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1322 talloc_free(tmp_ctx);
1326 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1327 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1329 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1330 talloc_free(tmp_ctx);
1334 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1336 talloc_free(tmp_ctx);
1341 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1343 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1344 const struct ldb_schema_attribute *a,
1345 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1347 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1348 /* If the DN is deleted, then we can't search for it */
1350 /* should this be for equality too? */
1355 if (operation == LDB_OP_EQUALITY &&
1356 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1360 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1364 static const struct ldb_schema_syntax samba_syntaxes[] = {
1366 .name = LDB_SYNTAX_SAMBA_SID,
1367 .ldif_read_fn = ldif_read_objectSid,
1368 .ldif_write_fn = ldif_write_objectSid,
1369 .canonicalise_fn = ldif_canonicalise_objectSid,
1370 .comparison_fn = ldif_comparison_objectSid,
1371 .operator_fn = samba_syntax_operator_fn
1373 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1374 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1375 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1376 .canonicalise_fn = ldb_handler_copy,
1377 .comparison_fn = samba_ldb_comparison_binary,
1378 .operator_fn = samba_syntax_binary_operator_fn
1380 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1381 .ldif_read_fn = ldb_handler_copy,
1382 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1383 .canonicalise_fn = ldb_handler_fold,
1384 .comparison_fn = ldb_comparison_fold,
1385 .operator_fn = samba_syntax_operator_fn
1387 .name = LDB_SYNTAX_SAMBA_GUID,
1388 .ldif_read_fn = ldif_read_objectGUID,
1389 .ldif_write_fn = ldif_write_objectGUID,
1390 .canonicalise_fn = ldif_canonicalise_objectGUID,
1391 .comparison_fn = ldif_comparison_objectGUID,
1392 .operator_fn = samba_syntax_operator_fn
1394 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1395 .ldif_read_fn = ldb_handler_copy,
1396 .ldif_write_fn = ldb_handler_copy,
1397 .canonicalise_fn = ldif_canonicalise_objectCategory,
1398 .comparison_fn = ldif_comparison_objectCategory,
1399 .operator_fn = samba_syntax_operator_fn
1401 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1402 .ldif_read_fn = ldb_handler_copy,
1403 .ldif_write_fn = ldif_write_schemaInfo,
1404 .canonicalise_fn = ldb_handler_copy,
1405 .comparison_fn = samba_ldb_comparison_binary,
1406 .operator_fn = samba_syntax_binary_operator_fn
1408 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1409 .ldif_read_fn = ldif_read_prefixMap,
1410 .ldif_write_fn = ldif_write_prefixMap,
1411 .canonicalise_fn = ldif_canonicalise_prefixMap,
1412 .comparison_fn = ldif_comparison_prefixMap,
1413 .operator_fn = samba_syntax_operator_fn
1415 .name = LDB_SYNTAX_SAMBA_INT32,
1416 .ldif_read_fn = ldb_handler_copy,
1417 .ldif_write_fn = ldb_handler_copy,
1418 .canonicalise_fn = ldif_canonicalise_int32,
1419 .comparison_fn = ldif_comparison_int32,
1420 .operator_fn = samba_syntax_operator_fn
1422 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1423 .ldif_read_fn = ldb_handler_copy,
1424 .ldif_write_fn = ldif_write_repsFromTo,
1425 .canonicalise_fn = ldb_handler_copy,
1426 .comparison_fn = samba_ldb_comparison_binary,
1427 .operator_fn = samba_syntax_binary_operator_fn
1429 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1430 .ldif_read_fn = ldb_handler_copy,
1431 .ldif_write_fn = ldif_write_replPropertyMetaData,
1432 .canonicalise_fn = ldb_handler_copy,
1433 .comparison_fn = samba_ldb_comparison_binary,
1434 .operator_fn = samba_syntax_binary_operator_fn
1436 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1437 .ldif_read_fn = ldb_handler_copy,
1438 .ldif_write_fn = ldif_write_replUpToDateVector,
1439 .canonicalise_fn = ldb_handler_copy,
1440 .comparison_fn = samba_ldb_comparison_binary,
1441 .operator_fn = samba_syntax_binary_operator_fn
1443 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1444 .ldif_read_fn = ldb_handler_copy,
1445 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1446 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1447 .comparison_fn = dsdb_dn_binary_comparison,
1448 .operator_fn = samba_syntax_operator_fn
1450 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1451 .ldif_read_fn = ldb_handler_copy,
1452 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1453 .canonicalise_fn = ldb_handler_copy,
1454 .comparison_fn = samba_ldb_comparison_binary,
1455 .operator_fn = samba_syntax_binary_operator_fn
1457 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1458 .ldif_read_fn = ldb_handler_copy,
1459 .ldif_write_fn = ldif_write_ForestTrustInfo,
1460 .canonicalise_fn = ldb_handler_copy,
1461 .comparison_fn = samba_ldb_comparison_binary,
1462 .operator_fn = samba_syntax_binary_operator_fn
1464 .name = DSDB_SYNTAX_BINARY_DN,
1465 .ldif_read_fn = ldb_handler_copy,
1466 .ldif_write_fn = ldb_handler_copy,
1467 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1468 .comparison_fn = dsdb_dn_binary_comparison,
1469 .operator_fn = samba_syntax_operator_fn
1471 .name = DSDB_SYNTAX_STRING_DN,
1472 .ldif_read_fn = ldb_handler_copy,
1473 .ldif_write_fn = ldb_handler_copy,
1474 .canonicalise_fn = dsdb_dn_string_canonicalise,
1475 .comparison_fn = dsdb_dn_string_comparison,
1476 .operator_fn = samba_syntax_operator_fn
1478 .name = LDB_SYNTAX_DN,
1479 .ldif_read_fn = ldb_handler_copy,
1480 .ldif_write_fn = ldb_handler_copy,
1481 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1482 .comparison_fn = samba_ldb_dn_link_comparison,
1483 .operator_fn = samba_syntax_operator_dn
1485 .name = LDB_SYNTAX_SAMBA_RANGE64,
1486 .ldif_read_fn = ldif_read_range64,
1487 .ldif_write_fn = ldif_write_range64,
1488 .canonicalise_fn = ldif_canonicalise_int64,
1489 .comparison_fn = ldif_comparison_int64,
1490 .operator_fn = samba_syntax_operator_fn
1492 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1493 .ldif_read_fn = ldb_handler_copy,
1494 .ldif_write_fn = ldif_write_dnsRecord,
1495 .canonicalise_fn = ldb_handler_copy,
1496 .comparison_fn = samba_ldb_comparison_binary,
1497 .operator_fn = samba_syntax_binary_operator_fn
1499 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1500 .ldif_read_fn = ldb_handler_copy,
1501 .ldif_write_fn = ldif_write_dnsProperty,
1502 .canonicalise_fn = ldb_handler_copy,
1503 .comparison_fn = samba_ldb_comparison_binary,
1504 .operator_fn = samba_syntax_binary_operator_fn
1506 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1507 .ldif_read_fn = ldb_handler_copy,
1508 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1509 .canonicalise_fn = ldb_handler_copy,
1510 .comparison_fn = samba_ldb_comparison_binary,
1511 .operator_fn = samba_syntax_binary_operator_fn
1513 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1514 .ldif_read_fn = ldb_handler_copy,
1515 .ldif_write_fn = ldif_write_partialAttributeSet,
1516 .canonicalise_fn = ldb_handler_copy,
1517 .comparison_fn = samba_ldb_comparison_binary,
1518 .operator_fn = samba_syntax_binary_operator_fn
1520 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1521 .ldif_read_fn = ldb_handler_copy,
1522 .ldif_write_fn = ldb_handler_copy,
1523 .canonicalise_fn = ldb_handler_copy,
1524 .comparison_fn = samba_ldb_comparison_binary,
1525 .operator_fn = samba_syntax_binary_operator_fn
1529 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1532 .read_fn = extended_dn_read_SID,
1533 .write_clear_fn = ldif_write_objectSid,
1534 .write_hex_fn = extended_dn_write_hex
1537 .read_fn = extended_dn_read_GUID,
1538 .write_clear_fn = ldif_write_objectGUID,
1539 .write_hex_fn = extended_dn_write_hex
1542 .read_fn = ldb_handler_copy,
1543 .write_clear_fn = ldb_handler_copy,
1544 .write_hex_fn = ldb_handler_copy
1546 .name = "RMD_INVOCID",
1547 .read_fn = extended_dn_read_GUID,
1548 .write_clear_fn = ldif_write_objectGUID,
1549 .write_hex_fn = extended_dn_write_hex
1551 .name = "RMD_FLAGS",
1552 .read_fn = ldb_handler_copy,
1553 .write_clear_fn = ldb_handler_copy,
1554 .write_hex_fn = ldb_handler_copy
1556 .name = "RMD_ADDTIME",
1557 .read_fn = ldb_handler_copy,
1558 .write_clear_fn = ldb_handler_copy,
1559 .write_hex_fn = ldb_handler_copy
1561 .name = "RMD_CHANGETIME",
1562 .read_fn = ldb_handler_copy,
1563 .write_clear_fn = ldb_handler_copy,
1564 .write_hex_fn = ldb_handler_copy
1566 .name = "RMD_LOCAL_USN",
1567 .read_fn = ldb_handler_copy,
1568 .write_clear_fn = ldb_handler_copy,
1569 .write_hex_fn = ldb_handler_copy
1571 .name = "RMD_ORIGINATING_USN",
1572 .read_fn = ldb_handler_copy,
1573 .write_clear_fn = ldb_handler_copy,
1574 .write_hex_fn = ldb_handler_copy
1576 .name = "RMD_VERSION",
1577 .read_fn = ldb_handler_copy,
1578 .write_clear_fn = ldb_handler_copy,
1579 .write_hex_fn = ldb_handler_copy
1583 /* TODO: Should be dynamic at some point */
1584 static const struct {
1587 } samba_attributes[] = {
1588 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1589 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1590 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1591 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1592 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1593 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1594 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1595 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1596 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1597 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1598 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1599 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1600 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1601 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1602 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1603 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1604 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1607 * these are extracted by searching
1608 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1610 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1611 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1612 * hat can be used to identify the set of policies when applied to a resource.
1613 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1614 * server, we ignore it here.
1616 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1617 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1618 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1619 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1620 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1621 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1622 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1623 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1624 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1627 * these are extracted by searching
1628 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1630 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1631 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1632 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1633 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1634 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1635 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1636 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1637 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1638 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1639 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1640 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1641 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1642 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1643 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1644 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1645 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1646 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1647 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1648 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1649 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1650 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1651 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1652 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1653 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1654 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1655 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1656 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1657 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1660 * these are known to be GUIDs
1662 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1663 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1665 /* These NDR encoded things we want to be able to read with --show-binary */
1666 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1667 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1668 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1669 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1672 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1675 const struct ldb_schema_syntax *s = NULL;
1677 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1678 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1679 s = &samba_syntaxes[j];
1686 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1689 const struct ldb_schema_syntax *s = NULL;
1691 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1692 if (strcmp(samba_attributes[j].name, name) == 0) {
1693 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1701 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret", NULL};
1704 register the samba ldif handlers
1706 int ldb_register_samba_handlers(struct ldb_context *ldb)
1711 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1715 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1716 if (ret != LDB_SUCCESS) {
1720 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1721 const struct ldb_schema_syntax *s = NULL;
1723 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1726 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1730 return LDB_ERR_OPERATIONS_ERROR;
1733 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1734 if (ret != LDB_SUCCESS) {
1739 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1740 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1741 if (ret != LDB_SUCCESS) {
1747 ret = ldb_register_samba_matching_rules(ldb);
1748 if (ret != LDB_SUCCESS) {
1753 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1754 if (ret != LDB_SUCCESS) {