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 "librpc/gen_ndr/ndr_security.h"
31 #include "librpc/gen_ndr/ndr_misc.h"
32 #include "librpc/gen_ndr/ndr_drsblobs.h"
33 #include "librpc/gen_ndr/ndr_dnsp.h"
34 #include "librpc/ndr/libndr.h"
35 #include "libcli/security/security.h"
36 #include "param/param.h"
37 #include "../lib/util/asn1.h"
40 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
42 If mask_errors is true, then function succeeds but out data
43 is set to "<Unable to decode binary data>" message
45 \return 0 on success; -1 on error
47 static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
48 const struct ldb_val *in, struct ldb_val *out,
50 ndr_pull_flags_fn_t pull_fn,
51 ndr_print_fn_t print_fn,
55 enum ndr_err_code err;
56 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
57 return ldb_handler_copy(ldb, mem_ctx, in, out);
59 p = talloc_size(mem_ctx, struct_size);
60 err = ndr_pull_struct_blob(in, mem_ctx,
62 if (err != NDR_ERR_SUCCESS) {
63 /* fail in not in mask_error mode */
68 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
69 out->length = strlen((const char *)out->data);
72 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
74 if (out->data == NULL) {
75 return ldb_handler_copy(ldb, mem_ctx, in, out);
77 out->length = strlen((char *)out->data);
82 convert a ldif formatted objectSid to a NDR formatted blob
84 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
85 const struct ldb_val *in, struct ldb_val *out)
87 enum ndr_err_code ndr_err;
89 sid = dom_sid_parse_length(mem_ctx, in);
93 ndr_err = ndr_push_struct_blob(out, mem_ctx, sid,
94 (ndr_push_flags_fn_t)ndr_push_dom_sid);
96 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
103 convert a NDR formatted blob to a ldif formatted objectSid
105 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
106 const struct ldb_val *in, struct ldb_val *out)
109 enum ndr_err_code ndr_err;
111 sid = talloc(mem_ctx, struct dom_sid);
115 ndr_err = ndr_pull_struct_blob_all(in, sid, sid,
116 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
117 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
121 *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
123 if (out->data == NULL) {
129 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
135 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
141 compare two objectSids
143 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
144 const struct ldb_val *v1, const struct ldb_val *v2)
146 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
147 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
148 } else if (ldif_comparision_objectSid_isString(v1)
149 && !ldif_comparision_objectSid_isString(v2)) {
152 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
153 /* Perhaps not a string after all */
154 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
156 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
159 } else if (!ldif_comparision_objectSid_isString(v1)
160 && ldif_comparision_objectSid_isString(v2)) {
163 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
164 /* Perhaps not a string after all */
165 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
167 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
171 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
175 canonicalise a objectSid
177 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
178 const struct ldb_val *in, struct ldb_val *out)
180 if (ldif_comparision_objectSid_isString(in)) {
181 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
182 /* Perhaps not a string after all */
183 return ldb_handler_copy(ldb, mem_ctx, in, out);
187 return ldb_handler_copy(ldb, mem_ctx, in, out);
190 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
191 const struct ldb_val *in, struct ldb_val *out)
194 enum ndr_err_code ndr_err;
195 if (ldif_comparision_objectSid_isString(in)) {
196 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
201 /* Perhaps not a string after all */
202 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
208 (*out).length = strhex_to_str((char *)out->data, out->length,
209 (const char *)in->data, in->length);
211 /* Check it looks like a SID */
212 ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, &sid,
213 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
214 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
221 convert a ldif formatted objectGUID to a NDR formatted blob
223 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
224 const struct ldb_val *in, struct ldb_val *out)
229 status = GUID_from_data_blob(in, &guid);
230 if (!NT_STATUS_IS_OK(status)) {
234 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
235 if (!NT_STATUS_IS_OK(status)) {
242 convert a NDR formatted blob to a ldif formatted objectGUID
244 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
245 const struct ldb_val *in, struct ldb_val *out)
250 status = GUID_from_ndr_blob(in, &guid);
251 if (!NT_STATUS_IS_OK(status)) {
254 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
255 if (out->data == NULL) {
258 out->length = strlen((const char *)out->data);
262 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
264 if (v->length != 36 && v->length != 38) return false;
266 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
270 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
271 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 status = GUID_from_ndr_blob(out, &guid);
296 if (!NT_STATUS_IS_OK(status)) {
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(mem_ctx, ldb,
486 sclass->defaultObjectCategory);
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,
905 convert a NDR formatted blob to a ldif formatted dnsRecord
907 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
908 const struct ldb_val *in, struct ldb_val *out)
910 return ldif_write_NDR(ldb, mem_ctx, in, out,
911 sizeof(struct dnsp_DnssrvRpcRecord),
912 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
913 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
918 convert a NDR formatted blob of a supplementalCredentials into text
920 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
921 const struct ldb_val *in, struct ldb_val *out)
923 return ldif_write_NDR(ldb, mem_ctx, in, out,
924 sizeof(struct supplementalCredentialsBlob),
925 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
926 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
931 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
933 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
934 const struct ldb_val *in, struct ldb_val *out)
936 return ldif_write_NDR(ldb, mem_ctx, in, out,
937 sizeof(struct trustAuthInOutBlob),
938 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
939 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
944 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
945 const struct ldb_val *in, struct ldb_val *out)
947 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
957 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
958 const struct ldb_val *v1, const struct ldb_val *v2)
960 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
963 if (dsdb_dn_is_deleted_val(v1)) {
964 /* If the DN is deleted, then we can't search for it */
968 if (dsdb_dn_is_deleted_val(v2)) {
969 /* If the DN is deleted, then we can't search for it */
973 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
974 if ( ! ldb_dn_validate(dn1)) return -1;
976 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
977 if ( ! ldb_dn_validate(dn2)) {
982 ret = ldb_dn_compare(dn1, dn2);
989 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
990 const struct ldb_val *in, struct ldb_val *out)
998 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
999 if ( ! ldb_dn_validate(dn)) {
1000 return LDB_ERR_INVALID_DN_SYNTAX;
1003 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1004 * does not casually match a not deleted DN */
1005 if (dsdb_dn_is_deleted_val(in)) {
1006 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1008 dsdb_dn_val_rmd_flags(in),
1009 ldb_dn_get_casefold(dn));
1011 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1014 if (out->data == NULL) {
1017 out->length = strlen((char *)out->data);
1029 write a 64 bit 2-part range
1031 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1032 const struct ldb_val *in, struct ldb_val *out)
1036 ret = val_to_int64(in, &v);
1037 if (ret != LDB_SUCCESS) {
1040 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1041 (unsigned long)(v&0xFFFFFFFF),
1042 (unsigned long)(v>>32));
1043 if (out->data == NULL) {
1045 return LDB_ERR_OPERATIONS_ERROR;
1047 out->length = strlen((char *)out->data);
1052 read a 64 bit 2-part range
1054 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1055 const struct ldb_val *in, struct ldb_val *out)
1057 unsigned long high, low;
1060 if (memchr(in->data, '-', in->length) == NULL) {
1061 return ldb_handler_copy(ldb, mem_ctx, in, out);
1064 if (in->length > sizeof(buf)-1) {
1065 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1067 strncpy(buf, (const char *)in->data, in->length);
1068 buf[in->length] = 0;
1070 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1071 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1074 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1075 (unsigned long long)(((uint64_t)high)<<32) | (low));
1077 if (out->data == NULL) {
1079 return LDB_ERR_OPERATIONS_ERROR;
1081 out->length = strlen((char *)out->data);
1086 when this operator_fn is set for a syntax, the backend calls is in
1087 preference to the comparison function. We are told the exact
1088 comparison operation that is needed, and we can return errors
1090 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1091 const struct ldb_schema_attribute *a,
1092 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1094 switch (operation) {
1098 case LDB_OP_SUBSTRING:
1100 case LDB_OP_EXTENDED:
1101 /* handled in the backends */
1102 return LDB_ERR_INAPPROPRIATE_MATCHING;
1104 case LDB_OP_GREATER:
1106 case LDB_OP_EQUALITY:
1108 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1110 if (tmp_ctx == NULL) {
1111 return ldb_oom(ldb);
1113 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1114 talloc_free(tmp_ctx);
1115 if (operation == LDB_OP_GREATER) {
1116 *matched = (ret > 0);
1117 } else if (operation == LDB_OP_LESS) {
1118 *matched = (ret < 0);
1120 *matched = (ret == 0);
1125 case LDB_OP_PRESENT:
1130 /* we shouldn't get here */
1131 return LDB_ERR_INAPPROPRIATE_MATCHING;
1135 see if two DNs match, comparing first by GUID, then by SID, and
1136 finally by string components
1138 static int samba_dn_extended_match(struct ldb_context *ldb,
1139 const struct ldb_val *v1,
1140 const struct ldb_val *v2,
1143 TALLOC_CTX *tmp_ctx;
1144 struct ldb_dn *dn1, *dn2;
1145 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1146 uint32_t rmd_flags1, rmd_flags2;
1148 tmp_ctx = talloc_new(ldb);
1150 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1151 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1153 /* couldn't parse as DN's */
1154 talloc_free(tmp_ctx);
1159 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1160 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1162 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1163 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1164 /* only match if they have the same deletion status */
1165 talloc_free(tmp_ctx);
1171 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1172 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1173 if (guid1 && guid2) {
1174 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1175 talloc_free(tmp_ctx);
1179 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1180 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1182 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1183 talloc_free(tmp_ctx);
1187 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1189 talloc_free(tmp_ctx);
1194 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1196 static int samba_syntax_operator_dn(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 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1201 /* If the DN is deleted, then we can't search for it */
1203 /* should this be for equality too? */
1208 if (operation == LDB_OP_EQUALITY &&
1209 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1213 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1217 static const struct ldb_schema_syntax samba_syntaxes[] = {
1219 .name = LDB_SYNTAX_SAMBA_SID,
1220 .ldif_read_fn = ldif_read_objectSid,
1221 .ldif_write_fn = ldif_write_objectSid,
1222 .canonicalise_fn = ldif_canonicalise_objectSid,
1223 .comparison_fn = ldif_comparison_objectSid,
1224 .operator_fn = samba_syntax_operator_fn
1226 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1227 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1228 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1229 .canonicalise_fn = ldb_handler_copy,
1230 .comparison_fn = ldb_comparison_binary,
1231 .operator_fn = samba_syntax_operator_fn
1233 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1234 .ldif_read_fn = ldb_handler_copy,
1235 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1236 .canonicalise_fn = ldb_handler_fold,
1237 .comparison_fn = ldb_comparison_fold,
1238 .operator_fn = samba_syntax_operator_fn
1240 .name = LDB_SYNTAX_SAMBA_GUID,
1241 .ldif_read_fn = ldif_read_objectGUID,
1242 .ldif_write_fn = ldif_write_objectGUID,
1243 .canonicalise_fn = ldif_canonicalise_objectGUID,
1244 .comparison_fn = ldif_comparison_objectGUID,
1245 .operator_fn = samba_syntax_operator_fn
1247 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1248 .ldif_read_fn = ldb_handler_copy,
1249 .ldif_write_fn = ldb_handler_copy,
1250 .canonicalise_fn = ldif_canonicalise_objectCategory,
1251 .comparison_fn = ldif_comparison_objectCategory,
1252 .operator_fn = samba_syntax_operator_fn
1254 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1255 .ldif_read_fn = ldb_handler_copy,
1256 .ldif_write_fn = ldif_write_schemaInfo,
1257 .canonicalise_fn = ldb_handler_copy,
1258 .comparison_fn = ldb_comparison_binary,
1259 .operator_fn = samba_syntax_operator_fn
1261 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1262 .ldif_read_fn = ldif_read_prefixMap,
1263 .ldif_write_fn = ldif_write_prefixMap,
1264 .canonicalise_fn = ldif_canonicalise_prefixMap,
1265 .comparison_fn = ldif_comparison_prefixMap,
1266 .operator_fn = samba_syntax_operator_fn
1268 .name = LDB_SYNTAX_SAMBA_INT32,
1269 .ldif_read_fn = ldb_handler_copy,
1270 .ldif_write_fn = ldb_handler_copy,
1271 .canonicalise_fn = ldif_canonicalise_int32,
1272 .comparison_fn = ldif_comparison_int32,
1273 .operator_fn = samba_syntax_operator_fn
1275 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1276 .ldif_read_fn = ldb_handler_copy,
1277 .ldif_write_fn = ldif_write_repsFromTo,
1278 .canonicalise_fn = ldb_handler_copy,
1279 .comparison_fn = ldb_comparison_binary,
1280 .operator_fn = samba_syntax_operator_fn
1282 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1283 .ldif_read_fn = ldb_handler_copy,
1284 .ldif_write_fn = ldif_write_replPropertyMetaData,
1285 .canonicalise_fn = ldb_handler_copy,
1286 .comparison_fn = ldb_comparison_binary,
1287 .operator_fn = samba_syntax_operator_fn
1289 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1290 .ldif_read_fn = ldb_handler_copy,
1291 .ldif_write_fn = ldif_write_replUpToDateVector,
1292 .canonicalise_fn = ldb_handler_copy,
1293 .comparison_fn = ldb_comparison_binary,
1294 .operator_fn = samba_syntax_operator_fn
1296 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1297 .ldif_read_fn = ldb_handler_copy,
1298 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1299 .canonicalise_fn = ldb_handler_copy,
1300 .comparison_fn = ldb_comparison_binary,
1301 .operator_fn = samba_syntax_operator_fn
1303 .name = DSDB_SYNTAX_BINARY_DN,
1304 .ldif_read_fn = ldb_handler_copy,
1305 .ldif_write_fn = ldb_handler_copy,
1306 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1307 .comparison_fn = dsdb_dn_binary_comparison,
1308 .operator_fn = samba_syntax_operator_fn
1310 .name = DSDB_SYNTAX_STRING_DN,
1311 .ldif_read_fn = ldb_handler_copy,
1312 .ldif_write_fn = ldb_handler_copy,
1313 .canonicalise_fn = dsdb_dn_string_canonicalise,
1314 .comparison_fn = dsdb_dn_string_comparison,
1315 .operator_fn = samba_syntax_operator_fn
1317 .name = LDB_SYNTAX_DN,
1318 .ldif_read_fn = ldb_handler_copy,
1319 .ldif_write_fn = ldb_handler_copy,
1320 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1321 .comparison_fn = samba_ldb_dn_link_comparison,
1322 .operator_fn = samba_syntax_operator_dn
1324 .name = LDB_SYNTAX_SAMBA_RANGE64,
1325 .ldif_read_fn = ldif_read_range64,
1326 .ldif_write_fn = ldif_write_range64,
1327 .canonicalise_fn = ldif_canonicalise_int64,
1328 .comparison_fn = ldif_comparison_int64,
1329 .operator_fn = samba_syntax_operator_fn
1331 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1332 .ldif_read_fn = ldb_handler_copy,
1333 .ldif_write_fn = ldif_write_dnsRecord,
1334 .canonicalise_fn = ldb_handler_copy,
1335 .comparison_fn = ldb_comparison_binary,
1336 .operator_fn = samba_syntax_operator_fn
1338 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1339 .ldif_read_fn = ldb_handler_copy,
1340 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1341 .canonicalise_fn = ldb_handler_copy,
1342 .comparison_fn = ldb_comparison_binary,
1343 .operator_fn = samba_syntax_operator_fn
1347 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1350 .read_fn = extended_dn_read_SID,
1351 .write_clear_fn = ldif_write_objectSid,
1352 .write_hex_fn = extended_dn_write_hex
1355 .read_fn = extended_dn_read_GUID,
1356 .write_clear_fn = ldif_write_objectGUID,
1357 .write_hex_fn = extended_dn_write_hex
1360 .read_fn = ldb_handler_copy,
1361 .write_clear_fn = ldb_handler_copy,
1362 .write_hex_fn = ldb_handler_copy
1364 .name = "RMD_INVOCID",
1365 .read_fn = extended_dn_read_GUID,
1366 .write_clear_fn = ldif_write_objectGUID,
1367 .write_hex_fn = extended_dn_write_hex
1369 .name = "RMD_FLAGS",
1370 .read_fn = ldb_handler_copy,
1371 .write_clear_fn = ldb_handler_copy,
1372 .write_hex_fn = ldb_handler_copy
1374 .name = "RMD_ADDTIME",
1375 .read_fn = ldb_handler_copy,
1376 .write_clear_fn = ldb_handler_copy,
1377 .write_hex_fn = ldb_handler_copy
1379 .name = "RMD_CHANGETIME",
1380 .read_fn = ldb_handler_copy,
1381 .write_clear_fn = ldb_handler_copy,
1382 .write_hex_fn = ldb_handler_copy
1384 .name = "RMD_LOCAL_USN",
1385 .read_fn = ldb_handler_copy,
1386 .write_clear_fn = ldb_handler_copy,
1387 .write_hex_fn = ldb_handler_copy
1389 .name = "RMD_ORIGINATING_USN",
1390 .read_fn = ldb_handler_copy,
1391 .write_clear_fn = ldb_handler_copy,
1392 .write_hex_fn = ldb_handler_copy
1394 .name = "RMD_VERSION",
1395 .read_fn = ldb_handler_copy,
1396 .write_clear_fn = ldb_handler_copy,
1397 .write_hex_fn = ldb_handler_copy
1401 /* TODO: Should be dynamic at some point */
1402 static const struct {
1405 } samba_attributes[] = {
1406 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1407 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1408 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1409 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1410 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1411 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1412 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1413 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1414 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1415 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1416 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1417 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1418 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1419 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1420 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1421 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1422 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1423 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1426 * these are extracted by searching
1427 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1429 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1430 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1431 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1432 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1433 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1434 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1435 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1436 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1437 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1438 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1439 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1440 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1441 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1442 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1443 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1444 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1445 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1446 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1447 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1448 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1449 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1450 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1451 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1452 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1455 * these are known to be GUIDs
1457 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1458 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1459 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1461 /* These NDR encoded things we want to be able to read with --show-binary */
1462 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1463 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS}
1466 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1469 const struct ldb_schema_syntax *s = NULL;
1471 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1472 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1473 s = &samba_syntaxes[j];
1480 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1483 const struct ldb_schema_syntax *s = NULL;
1485 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1486 if (strcmp(samba_attributes[j].name, name) == 0) {
1487 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1496 register the samba ldif handlers
1498 int ldb_register_samba_handlers(struct ldb_context *ldb)
1503 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1507 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1508 const struct ldb_schema_syntax *s = NULL;
1510 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1513 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1517 return LDB_ERR_OPERATIONS_ERROR;
1520 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1521 if (ret != LDB_SUCCESS) {
1526 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1527 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1528 if (ret != LDB_SUCCESS) {
1534 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1535 if (ret != LDB_SUCCESS) {