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)
89 enum ndr_err_code ndr_err;
91 if (in->length > DOM_SID_STR_BUFLEN) {
95 memcpy(p, in->data, in->length);
98 ret = dom_sid_parse(p, &sid);
103 *out = data_blob_talloc(mem_ctx, NULL,
104 ndr_size_dom_sid(&sid, 0));
105 if (out->data == NULL) {
109 ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
110 (ndr_push_flags_fn_t)ndr_push_dom_sid);
111 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
119 convert a NDR formatted blob to a ldif formatted objectSid
121 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
122 const struct ldb_val *in, struct ldb_val *out)
125 enum ndr_err_code ndr_err;
127 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
128 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
129 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
132 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
133 if (out->data == NULL) {
139 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
145 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
151 compare two objectSids
153 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
154 const struct ldb_val *v1, const struct ldb_val *v2)
156 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
157 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
158 } else if (ldif_comparision_objectSid_isString(v1)
159 && !ldif_comparision_objectSid_isString(v2)) {
162 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
163 /* Perhaps not a string after all */
164 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
166 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
169 } else if (!ldif_comparision_objectSid_isString(v1)
170 && ldif_comparision_objectSid_isString(v2)) {
173 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
174 /* Perhaps not a string after all */
175 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
177 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
181 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
185 canonicalise a objectSid
187 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
188 const struct ldb_val *in, struct ldb_val *out)
190 if (ldif_comparision_objectSid_isString(in)) {
191 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
192 /* Perhaps not a string after all */
193 return ldb_handler_copy(ldb, mem_ctx, in, out);
197 return ldb_handler_copy(ldb, mem_ctx, in, out);
200 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
201 const struct ldb_val *in, struct ldb_val *out)
204 enum ndr_err_code ndr_err;
205 if (ldif_comparision_objectSid_isString(in)) {
206 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
211 /* Perhaps not a string after all */
212 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
218 (*out).length = strhex_to_str((char *)out->data, out->length,
219 (const char *)in->data, in->length);
221 /* Check it looks like a SID */
222 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
223 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
224 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
231 convert a ldif formatted objectGUID to a NDR formatted blob
233 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
234 const struct ldb_val *in, struct ldb_val *out)
239 status = GUID_from_data_blob(in, &guid);
240 if (!NT_STATUS_IS_OK(status)) {
244 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
245 if (!NT_STATUS_IS_OK(status)) {
252 convert a NDR formatted blob to a ldif formatted objectGUID
254 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
255 const struct ldb_val *in, struct ldb_val *out)
260 status = GUID_from_ndr_blob(in, &guid);
261 if (!NT_STATUS_IS_OK(status)) {
264 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
265 if (out->data == NULL) {
268 out->length = strlen((const char *)out->data);
272 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
274 if (v->length != 36 && v->length != 38) return false;
276 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
280 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
281 const struct ldb_val *in, struct ldb_val *out)
284 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
288 /* Try as 'hex' form */
289 if (in->length != 32) {
293 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
299 (*out).length = strhex_to_str((char *)out->data, out->length,
300 (const char *)in->data, in->length);
302 /* Check it looks like a GUID */
303 if ((*out).length != 16) {
312 compare two objectGUIDs
314 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
315 const struct ldb_val *v1, const struct ldb_val *v2)
317 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
318 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
319 } else if (ldif_comparision_objectGUID_isString(v1)
320 && !ldif_comparision_objectGUID_isString(v2)) {
323 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
324 /* Perhaps it wasn't a valid string after all */
325 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
327 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
330 } else if (!ldif_comparision_objectGUID_isString(v1)
331 && ldif_comparision_objectGUID_isString(v2)) {
334 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
335 /* Perhaps it wasn't a valid string after all */
336 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
338 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
342 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
346 canonicalise a objectGUID
348 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
349 const struct ldb_val *in, struct ldb_val *out)
351 if (ldif_comparision_objectGUID_isString(in)) {
352 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
353 /* Perhaps it wasn't a valid string after all */
354 return ldb_handler_copy(ldb, mem_ctx, in, out);
358 return ldb_handler_copy(ldb, mem_ctx, in, out);
363 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
365 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
366 const struct ldb_val *in, struct ldb_val *out)
368 struct security_descriptor *sd;
369 enum ndr_err_code ndr_err;
371 sd = talloc(mem_ctx, struct security_descriptor);
376 ndr_err = ndr_pull_struct_blob(in, sd, sd,
377 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
378 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
379 /* If this does not parse, then it is probably SDDL, and we should try it that way */
381 const struct dom_sid *sid = samdb_domain_sid(ldb);
383 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
389 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
390 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
392 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
400 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
402 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
403 const struct ldb_val *in, struct ldb_val *out)
405 struct security_descriptor *sd;
406 enum ndr_err_code ndr_err;
408 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
409 return ldif_write_NDR(ldb, mem_ctx, in, out,
410 sizeof(struct security_descriptor),
411 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
412 (ndr_print_fn_t)ndr_print_security_descriptor,
417 sd = talloc(mem_ctx, struct security_descriptor);
421 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
422 ndr_err = ndr_pull_struct_blob(in, sd, sd,
423 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
424 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
428 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
430 if (out->data == NULL) {
433 out->length = strlen((const char *)out->data);
438 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
440 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
441 const struct ldb_val *in, struct ldb_val *out)
443 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
444 struct security_descriptor *sd;
445 const struct dom_sid *sid = samdb_domain_sid(ldb);
447 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
448 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
449 (ndr_print_fn_t)ndr_print_security_descriptor,
451 out->length = strlen((const char *)out->data);
456 return ldb_handler_copy(ldb, mem_ctx, in, out);
460 canonicalise an objectCategory. We use the long form as the canonical form:
461 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
463 Also any short name of an objectClass that points to a different
464 class (such as user) has the canonical form of the class it's
465 defaultObjectCategory points to (eg
466 cn=Person,cn=Schema,cn=Configuration,<basedn>)
469 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
470 const struct ldb_val *in, struct ldb_val *out)
472 struct ldb_dn *dn1 = NULL;
473 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
474 const struct dsdb_class *sclass;
475 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
477 return LDB_ERR_OPERATIONS_ERROR;
481 talloc_free(tmp_ctx);
482 *out = data_blob_talloc(mem_ctx, in->data, in->length);
483 if (in->data && !out->data) {
484 return LDB_ERR_OPERATIONS_ERROR;
488 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
489 if ( ! ldb_dn_validate(dn1)) {
490 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
491 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
493 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
494 sclass->defaultObjectCategory);
496 talloc_free(tmp_ctx);
497 return LDB_ERR_OPERATIONS_ERROR;
500 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
501 talloc_free(tmp_ctx);
504 return LDB_ERR_OPERATIONS_ERROR;
508 *out = data_blob_talloc(mem_ctx, in->data, in->length);
509 talloc_free(tmp_ctx);
511 if (in->data && !out->data) {
512 return LDB_ERR_OPERATIONS_ERROR;
517 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
518 talloc_free(tmp_ctx);
521 return LDB_ERR_OPERATIONS_ERROR;
526 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
527 const struct ldb_val *v1,
528 const struct ldb_val *v2)
530 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
535 convert a NDR formatted blob to a ldif formatted schemaInfo
537 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
538 const struct ldb_val *in, struct ldb_val *out)
540 return ldif_write_NDR(ldb, mem_ctx, in, out,
541 sizeof(struct repsFromToBlob),
542 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
543 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
548 convert a ldif formatted prefixMap to a NDR formatted blob
550 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
551 const struct ldb_val *in, struct ldb_val *out)
553 struct prefixMapBlob *blob;
554 enum ndr_err_code ndr_err;
555 char *string, *line, *p, *oid;
558 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
560 if (tmp_ctx == NULL) {
564 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
566 talloc_free(tmp_ctx);
570 /* use the switch value to detect if this is in the binary
573 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
574 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
575 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
576 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
577 ndr_err = ndr_push_struct_blob(out, mem_ctx,
579 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
580 talloc_free(tmp_ctx);
581 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
588 /* If this does not parse, then it is probably the text version, and we should try it that way */
589 blob->version = PREFIX_MAP_VERSION_DSDB;
591 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
592 if (string == NULL) {
598 while (line && line[0]) {
605 p=strchr(line, '\n');
610 /* allow a trailing separator */
615 blob->ctr.dsdb.mappings = talloc_realloc(blob,
616 blob->ctr.dsdb.mappings,
617 struct drsuapi_DsReplicaOIDMapping,
618 blob->ctr.dsdb.num_mappings+1);
619 if (!blob->ctr.dsdb.mappings) {
620 talloc_free(tmp_ctx);
624 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
625 strtoul_err(line, &oid, 10, &error);
627 if (oid[0] != ':' || error != 0) {
628 talloc_free(tmp_ctx);
632 /* we know there must be at least ":" */
635 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
636 talloc_free(tmp_ctx);
639 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
640 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
642 blob->ctr.dsdb.num_mappings++;
644 /* Now look past the terminator we added above */
652 ndr_err = ndr_push_struct_blob(out, mem_ctx,
654 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
655 talloc_free(tmp_ctx);
656 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
663 convert a NDR formatted blob to a ldif formatted prefixMap
665 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
666 const struct ldb_val *in, struct ldb_val *out)
668 struct prefixMapBlob *blob;
669 enum ndr_err_code ndr_err;
673 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
675 /* try to decode the blob as S4 prefixMap */
676 err = ldif_write_NDR(ldb, mem_ctx, in, out,
677 sizeof(struct prefixMapBlob),
678 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
679 (ndr_print_fn_t)ndr_print_prefixMapBlob,
684 /* try parsing it as Windows PrefixMap value */
685 return ldif_write_NDR(ldb, mem_ctx, in, out,
686 sizeof(struct drsuapi_MSPrefixMap_Ctr),
687 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
688 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
692 blob = talloc(mem_ctx, struct prefixMapBlob);
696 ndr_err = ndr_pull_struct_blob_all(in, blob,
698 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
699 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
702 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
705 string = talloc_strdup(mem_ctx, "");
706 if (string == NULL) {
710 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
712 char *partial_oid = NULL;
715 string = talloc_asprintf_append(string, ";");
718 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
719 blob->ctr.dsdb.mappings[i].oid.length);
720 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
721 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
722 blob->ctr.dsdb.mappings[i].id_prefix));
725 string = talloc_asprintf_append(string, "%u:%s",
726 blob->ctr.dsdb.mappings[i].id_prefix,
728 talloc_free(discard_const(partial_oid));
729 if (string == NULL) {
735 *out = data_blob_string_const(string);
743 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
749 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
757 canonicalise a prefixMap
759 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
760 const struct ldb_val *in, struct ldb_val *out)
762 if (ldif_comparision_prefixMap_isString(in)) {
763 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
765 return ldb_handler_copy(ldb, mem_ctx, in, out);
768 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
769 const struct ldb_val *v1,
770 const struct ldb_val *v2)
772 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
776 /* length limited conversion of a ldb_val to a int32_t */
777 static int val_to_int32(const struct ldb_val *in, int32_t *v)
782 /* make sure we don't read past the end of the data */
783 if (in->length > sizeof(buf)-1) {
784 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
786 strncpy(buf, (char *)in->data, in->length);
789 /* We've to use "strtoll" here to have the intended overflows.
790 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
791 *v = (int32_t) strtoll(buf, &end, 0);
793 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
798 /* length limited conversion of a ldb_val to a int64_t */
799 static int val_to_int64(const struct ldb_val *in, int64_t *v)
804 /* make sure we don't read past the end of the data */
805 if (in->length > sizeof(buf)-1) {
806 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
808 strncpy(buf, (char *)in->data, in->length);
811 *v = (int64_t) strtoll(buf, &end, 0);
813 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
818 /* Canonicalisation of two 32-bit integers */
819 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
820 const struct ldb_val *in, struct ldb_val *out)
825 ret = val_to_int32(in, &i);
826 if (ret != LDB_SUCCESS) {
829 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
830 if (out->data == NULL) {
832 return LDB_ERR_OPERATIONS_ERROR;
834 out->length = strlen((char *)out->data);
839 * Lexicographically sorted representation for a 32-bit integer
841 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
844 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
845 * corresponding documentation for 64-bit integers.
847 * The same rules apply but use INT32_MIN and INT32_MAX.
849 * String representation padding is done to 10 characters.
851 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
854 static int ldif_index_format_int32(struct ldb_context *ldb,
856 const struct ldb_val *in,
864 ret = val_to_int32(in, &i);
865 if (ret != LDB_SUCCESS) {
871 * i is negative, so this is subtraction rather than
875 i = INT32_MAX + i + 1;
882 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
883 if (out->data == NULL) {
885 return LDB_ERR_OPERATIONS_ERROR;
888 len = talloc_array_length(out->data) - 1;
890 ldb_debug(ldb, LDB_DEBUG_ERROR,
891 __location__ ": expected index format str %s to"
892 " have length 11 but got %zu",
893 (char*)out->data, len);
894 return LDB_ERR_OPERATIONS_ERROR;
901 /* Comparison of two 32-bit integers */
902 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
903 const struct ldb_val *v1, const struct ldb_val *v2)
906 val_to_int32(v1, &i1);
907 val_to_int32(v2, &i2);
908 if (i1 == i2) return 0;
909 return i1 > i2? 1 : -1;
912 /* Canonicalisation of two 64-bit integers */
913 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
914 const struct ldb_val *in, struct ldb_val *out)
919 ret = val_to_int64(in, &i);
920 if (ret != LDB_SUCCESS) {
923 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
924 if (out->data == NULL) {
926 return LDB_ERR_OPERATIONS_ERROR;
928 out->length = strlen((char *)out->data);
932 /* Comparison of two 64-bit integers */
933 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
934 const struct ldb_val *v1, const struct ldb_val *v2)
937 val_to_int64(v1, &i1);
938 val_to_int64(v2, &i2);
939 if (i1 == i2) return 0;
940 return i1 > i2? 1 : -1;
944 convert a NDR formatted blob to a ldif formatted repsFromTo
946 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
947 const struct ldb_val *in, struct ldb_val *out)
949 return ldif_write_NDR(ldb, mem_ctx, in, out,
950 sizeof(struct repsFromToBlob),
951 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
952 (ndr_print_fn_t)ndr_print_repsFromToBlob,
957 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
959 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
960 const struct ldb_val *in, struct ldb_val *out)
962 return ldif_write_NDR(ldb, mem_ctx, in, out,
963 sizeof(struct replPropertyMetaDataBlob),
964 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
965 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
970 convert a NDR formatted blob to a ldif formatted replUpToDateVector
972 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
973 const struct ldb_val *in, struct ldb_val *out)
975 return ldif_write_NDR(ldb, mem_ctx, in, out,
976 sizeof(struct replUpToDateVectorBlob),
977 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
978 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
982 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
983 const struct ldb_val *in, struct ldb_val *out,
985 ndr_pull_flags_fn_t pull_fn,
986 ndr_print_fn_t print_fn,
990 enum ndr_err_code err;
991 struct dsdb_dn *dsdb_dn = NULL;
995 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
996 return ldb_handler_copy(ldb, mem_ctx, in, out);
999 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
1000 if (dsdb_dn == NULL) {
1001 return ldb_handler_copy(ldb, mem_ctx, in, out);
1004 p = talloc_size(dsdb_dn, struct_size);
1006 TALLOC_FREE(dsdb_dn);
1007 return ldb_handler_copy(ldb, mem_ctx, in, out);
1010 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
1011 if (err != NDR_ERR_SUCCESS) {
1012 /* fail in not in mask_error mode */
1016 TALLOC_FREE(dsdb_dn);
1017 return ldb_handler_copy(ldb, mem_ctx, in, out);
1020 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
1021 if (dn_str == NULL) {
1022 TALLOC_FREE(dsdb_dn);
1023 return ldb_handler_copy(ldb, mem_ctx, in, out);
1026 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
1027 TALLOC_FREE(dsdb_dn);
1029 return ldb_handler_copy(ldb, mem_ctx, in, out);
1032 *out = data_blob_string_const(str);
1036 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
1037 const struct ldb_val *in, struct ldb_val *out)
1039 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
1040 sizeof(struct replPropertyMetaData1),
1041 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
1042 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
1047 convert a NDR formatted blob to a ldif formatted dnsRecord
1049 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
1050 const struct ldb_val *in, struct ldb_val *out)
1052 return ldif_write_NDR(ldb, mem_ctx, in, out,
1053 sizeof(struct dnsp_DnssrvRpcRecord),
1054 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
1055 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
1060 convert a NDR formatted blob to a ldif formatted dnsProperty
1062 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1063 const struct ldb_val *in, struct ldb_val *out)
1065 return ldif_write_NDR(ldb, mem_ctx, in, out,
1066 sizeof(struct dnsp_DnsProperty),
1067 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1068 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1073 convert a NDR formatted blob of a supplementalCredentials into text
1075 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1076 const struct ldb_val *in, struct ldb_val *out)
1078 return ldif_write_NDR(ldb, mem_ctx, in, out,
1079 sizeof(struct supplementalCredentialsBlob),
1080 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1081 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1086 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1088 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1089 const struct ldb_val *in, struct ldb_val *out)
1091 return ldif_write_NDR(ldb, mem_ctx, in, out,
1092 sizeof(struct trustAuthInOutBlob),
1093 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1094 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1099 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1101 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1102 const struct ldb_val *in, struct ldb_val *out)
1104 return ldif_write_NDR(ldb, mem_ctx, in, out,
1105 sizeof(struct ForestTrustInfo),
1106 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1107 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1111 convert a NDR formatted blob of a partialAttributeSet into text
1113 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1114 const struct ldb_val *in, struct ldb_val *out)
1116 return ldif_write_NDR(ldb, mem_ctx, in, out,
1117 sizeof(struct partialAttributeSetBlob),
1118 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1119 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1124 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1125 const struct ldb_val *in, struct ldb_val *out)
1127 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1137 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1138 const struct ldb_val *v1, const struct ldb_val *v2)
1140 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1143 if (dsdb_dn_is_deleted_val(v1)) {
1144 /* If the DN is deleted, then we can't search for it */
1148 if (dsdb_dn_is_deleted_val(v2)) {
1149 /* If the DN is deleted, then we can't search for it */
1153 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1154 if ( ! ldb_dn_validate(dn1)) return -1;
1156 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1157 if ( ! ldb_dn_validate(dn2)) {
1162 ret = ldb_dn_compare(dn1, dn2);
1169 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1170 const struct ldb_val *in, struct ldb_val *out)
1178 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1179 if ( ! ldb_dn_validate(dn)) {
1180 return LDB_ERR_INVALID_DN_SYNTAX;
1183 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1184 * does not casually match a not deleted DN */
1185 if (dsdb_dn_is_deleted_val(in)) {
1186 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1188 dsdb_dn_val_rmd_flags(in),
1189 ldb_dn_get_casefold(dn));
1191 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1194 if (out->data == NULL) {
1197 out->length = strlen((char *)out->data);
1209 write a 64 bit 2-part range
1211 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1212 const struct ldb_val *in, struct ldb_val *out)
1216 ret = val_to_int64(in, &v);
1217 if (ret != LDB_SUCCESS) {
1220 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1221 (unsigned long)(v&0xFFFFFFFF),
1222 (unsigned long)(v>>32));
1223 if (out->data == NULL) {
1225 return LDB_ERR_OPERATIONS_ERROR;
1227 out->length = strlen((char *)out->data);
1232 read a 64 bit 2-part range
1234 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1235 const struct ldb_val *in, struct ldb_val *out)
1237 unsigned long high, low;
1240 if (memchr(in->data, '-', in->length) == NULL) {
1241 return ldb_handler_copy(ldb, mem_ctx, in, out);
1244 if (in->length > sizeof(buf)-1) {
1245 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1247 strncpy(buf, (const char *)in->data, in->length);
1248 buf[in->length] = 0;
1250 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1251 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1254 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1255 (unsigned long long)(((uint64_t)high)<<32) | (low));
1257 if (out->data == NULL) {
1259 return LDB_ERR_OPERATIONS_ERROR;
1261 out->length = strlen((char *)out->data);
1266 when this operator_fn is set for a syntax, the backend calls is in
1267 preference to the comparison function. We are told the exact
1268 comparison operation that is needed, and we can return errors
1270 static int samba_syntax_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 switch (operation) {
1278 case LDB_OP_SUBSTRING:
1280 case LDB_OP_EXTENDED:
1281 /* handled in the backends */
1282 return LDB_ERR_INAPPROPRIATE_MATCHING;
1284 case LDB_OP_GREATER:
1286 case LDB_OP_EQUALITY:
1288 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1290 if (tmp_ctx == NULL) {
1291 return ldb_oom(ldb);
1293 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1294 talloc_free(tmp_ctx);
1295 if (operation == LDB_OP_GREATER) {
1296 *matched = (ret >= 0);
1297 } else if (operation == LDB_OP_LESS) {
1298 *matched = (ret <= 0);
1300 *matched = (ret == 0);
1305 case LDB_OP_PRESENT:
1310 /* we shouldn't get here */
1311 return LDB_ERR_INAPPROPRIATE_MATCHING;
1315 compare two binary objects. This is correct for sorting as the sort order is:
1322 rather than ldb_comparison_binary() which is:
1330 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1331 const struct ldb_val *v1, const struct ldb_val *v2)
1333 return data_blob_cmp(v1, v2);
1337 when this operator_fn is set for a syntax, the backend calls is in
1338 preference to the comparison function. We are told the exact
1339 comparison operation that is needed, and we can return errors.
1341 This mode optimises for ldb_comparison_binary() if we need equality,
1342 as this should be faster as it can do a length-check first.
1344 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1345 const struct ldb_schema_attribute *a,
1346 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1348 if (operation == LDB_OP_EQUALITY) {
1349 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1352 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1356 see if two DNs match, comparing first by GUID, then by SID, and
1357 finally by string components
1359 static int samba_dn_extended_match(struct ldb_context *ldb,
1360 const struct ldb_val *v1,
1361 const struct ldb_val *v2,
1364 TALLOC_CTX *tmp_ctx;
1365 struct ldb_dn *dn1, *dn2;
1366 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1367 uint32_t rmd_flags1, rmd_flags2;
1369 tmp_ctx = talloc_new(ldb);
1371 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1372 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1374 /* couldn't parse as DN's */
1375 talloc_free(tmp_ctx);
1380 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1381 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1383 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1384 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1385 /* only match if they have the same deletion status */
1386 talloc_free(tmp_ctx);
1392 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1393 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1394 if (guid1 && guid2) {
1395 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1396 talloc_free(tmp_ctx);
1400 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1401 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1403 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1404 talloc_free(tmp_ctx);
1408 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1410 talloc_free(tmp_ctx);
1415 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1417 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1418 const struct ldb_schema_attribute *a,
1419 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1421 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1422 /* If the DN is deleted, then we can't search for it */
1424 /* should this be for equality too? */
1429 if (operation == LDB_OP_EQUALITY &&
1430 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1434 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1438 static const struct ldb_schema_syntax samba_syntaxes[] = {
1440 .name = LDB_SYNTAX_SAMBA_SID,
1441 .ldif_read_fn = ldif_read_objectSid,
1442 .ldif_write_fn = ldif_write_objectSid,
1443 .canonicalise_fn = ldif_canonicalise_objectSid,
1444 .comparison_fn = ldif_comparison_objectSid,
1445 .operator_fn = samba_syntax_operator_fn
1447 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1448 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1449 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1450 .canonicalise_fn = ldb_handler_copy,
1451 .comparison_fn = samba_ldb_comparison_binary,
1452 .operator_fn = samba_syntax_binary_operator_fn
1454 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1455 .ldif_read_fn = ldb_handler_copy,
1456 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1457 .canonicalise_fn = ldb_handler_fold,
1458 .comparison_fn = ldb_comparison_fold,
1459 .operator_fn = samba_syntax_operator_fn
1461 .name = LDB_SYNTAX_SAMBA_GUID,
1462 .ldif_read_fn = ldif_read_objectGUID,
1463 .ldif_write_fn = ldif_write_objectGUID,
1464 .canonicalise_fn = ldif_canonicalise_objectGUID,
1465 .comparison_fn = ldif_comparison_objectGUID,
1466 .operator_fn = samba_syntax_operator_fn
1468 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1469 .ldif_read_fn = ldb_handler_copy,
1470 .ldif_write_fn = ldb_handler_copy,
1471 .canonicalise_fn = ldif_canonicalise_objectCategory,
1472 .comparison_fn = ldif_comparison_objectCategory,
1473 .operator_fn = samba_syntax_operator_fn
1475 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1476 .ldif_read_fn = ldb_handler_copy,
1477 .ldif_write_fn = ldif_write_schemaInfo,
1478 .canonicalise_fn = ldb_handler_copy,
1479 .comparison_fn = samba_ldb_comparison_binary,
1480 .operator_fn = samba_syntax_binary_operator_fn
1482 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1483 .ldif_read_fn = ldif_read_prefixMap,
1484 .ldif_write_fn = ldif_write_prefixMap,
1485 .canonicalise_fn = ldif_canonicalise_prefixMap,
1486 .comparison_fn = ldif_comparison_prefixMap,
1487 .operator_fn = samba_syntax_operator_fn
1489 .name = LDB_SYNTAX_SAMBA_INT32,
1490 .ldif_read_fn = ldb_handler_copy,
1491 .ldif_write_fn = ldb_handler_copy,
1492 .canonicalise_fn = ldif_canonicalise_int32,
1493 .index_format_fn = ldif_index_format_int32,
1494 .comparison_fn = ldif_comparison_int32,
1495 .operator_fn = samba_syntax_operator_fn
1497 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1498 .ldif_read_fn = ldb_handler_copy,
1499 .ldif_write_fn = ldif_write_repsFromTo,
1500 .canonicalise_fn = ldb_handler_copy,
1501 .comparison_fn = samba_ldb_comparison_binary,
1502 .operator_fn = samba_syntax_binary_operator_fn
1504 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1505 .ldif_read_fn = ldb_handler_copy,
1506 .ldif_write_fn = ldif_write_replPropertyMetaData,
1507 .canonicalise_fn = ldb_handler_copy,
1508 .comparison_fn = samba_ldb_comparison_binary,
1509 .operator_fn = samba_syntax_binary_operator_fn
1511 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1512 .ldif_read_fn = ldb_handler_copy,
1513 .ldif_write_fn = ldif_write_replUpToDateVector,
1514 .canonicalise_fn = ldb_handler_copy,
1515 .comparison_fn = samba_ldb_comparison_binary,
1516 .operator_fn = samba_syntax_binary_operator_fn
1518 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1519 .ldif_read_fn = ldb_handler_copy,
1520 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1521 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1522 .comparison_fn = dsdb_dn_binary_comparison,
1523 .operator_fn = samba_syntax_operator_fn
1525 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1526 .ldif_read_fn = ldb_handler_copy,
1527 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1528 .canonicalise_fn = ldb_handler_copy,
1529 .comparison_fn = samba_ldb_comparison_binary,
1530 .operator_fn = samba_syntax_binary_operator_fn
1532 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1533 .ldif_read_fn = ldb_handler_copy,
1534 .ldif_write_fn = ldif_write_ForestTrustInfo,
1535 .canonicalise_fn = ldb_handler_copy,
1536 .comparison_fn = samba_ldb_comparison_binary,
1537 .operator_fn = samba_syntax_binary_operator_fn
1539 .name = DSDB_SYNTAX_BINARY_DN,
1540 .ldif_read_fn = ldb_handler_copy,
1541 .ldif_write_fn = ldb_handler_copy,
1542 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1543 .comparison_fn = dsdb_dn_binary_comparison,
1544 .operator_fn = samba_syntax_operator_fn
1546 .name = DSDB_SYNTAX_STRING_DN,
1547 .ldif_read_fn = ldb_handler_copy,
1548 .ldif_write_fn = ldb_handler_copy,
1549 .canonicalise_fn = dsdb_dn_string_canonicalise,
1550 .comparison_fn = dsdb_dn_string_comparison,
1551 .operator_fn = samba_syntax_operator_fn
1553 .name = LDB_SYNTAX_DN,
1554 .ldif_read_fn = ldb_handler_copy,
1555 .ldif_write_fn = ldb_handler_copy,
1556 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1557 .comparison_fn = samba_ldb_dn_link_comparison,
1558 .operator_fn = samba_syntax_operator_dn
1560 .name = LDB_SYNTAX_SAMBA_RANGE64,
1561 .ldif_read_fn = ldif_read_range64,
1562 .ldif_write_fn = ldif_write_range64,
1563 .canonicalise_fn = ldif_canonicalise_int64,
1564 .comparison_fn = ldif_comparison_int64,
1565 .operator_fn = samba_syntax_operator_fn
1567 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1568 .ldif_read_fn = ldb_handler_copy,
1569 .ldif_write_fn = ldif_write_dnsRecord,
1570 .canonicalise_fn = ldb_handler_copy,
1571 .comparison_fn = samba_ldb_comparison_binary,
1572 .operator_fn = samba_syntax_binary_operator_fn
1574 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1575 .ldif_read_fn = ldb_handler_copy,
1576 .ldif_write_fn = ldif_write_dnsProperty,
1577 .canonicalise_fn = ldb_handler_copy,
1578 .comparison_fn = samba_ldb_comparison_binary,
1579 .operator_fn = samba_syntax_binary_operator_fn
1581 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1582 .ldif_read_fn = ldb_handler_copy,
1583 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1584 .canonicalise_fn = ldb_handler_copy,
1585 .comparison_fn = samba_ldb_comparison_binary,
1586 .operator_fn = samba_syntax_binary_operator_fn
1588 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1589 .ldif_read_fn = ldb_handler_copy,
1590 .ldif_write_fn = ldif_write_partialAttributeSet,
1591 .canonicalise_fn = ldb_handler_copy,
1592 .comparison_fn = samba_ldb_comparison_binary,
1593 .operator_fn = samba_syntax_binary_operator_fn
1595 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1596 .ldif_read_fn = ldb_handler_copy,
1597 .ldif_write_fn = ldb_handler_copy,
1598 .canonicalise_fn = ldb_handler_copy,
1599 .comparison_fn = samba_ldb_comparison_binary,
1600 .operator_fn = samba_syntax_binary_operator_fn
1604 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1607 .read_fn = extended_dn_read_SID,
1608 .write_clear_fn = ldif_write_objectSid,
1609 .write_hex_fn = extended_dn_write_hex
1612 .read_fn = extended_dn_read_GUID,
1613 .write_clear_fn = ldif_write_objectGUID,
1614 .write_hex_fn = extended_dn_write_hex
1617 .read_fn = ldb_handler_copy,
1618 .write_clear_fn = ldb_handler_copy,
1619 .write_hex_fn = ldb_handler_copy
1621 .name = "RMD_INVOCID",
1622 .read_fn = extended_dn_read_GUID,
1623 .write_clear_fn = ldif_write_objectGUID,
1624 .write_hex_fn = extended_dn_write_hex
1626 .name = "RMD_FLAGS",
1627 .read_fn = ldb_handler_copy,
1628 .write_clear_fn = ldb_handler_copy,
1629 .write_hex_fn = ldb_handler_copy
1631 .name = "RMD_ADDTIME",
1632 .read_fn = ldb_handler_copy,
1633 .write_clear_fn = ldb_handler_copy,
1634 .write_hex_fn = ldb_handler_copy
1636 .name = "RMD_CHANGETIME",
1637 .read_fn = ldb_handler_copy,
1638 .write_clear_fn = ldb_handler_copy,
1639 .write_hex_fn = ldb_handler_copy
1641 .name = "RMD_LOCAL_USN",
1642 .read_fn = ldb_handler_copy,
1643 .write_clear_fn = ldb_handler_copy,
1644 .write_hex_fn = ldb_handler_copy
1646 .name = "RMD_ORIGINATING_USN",
1647 .read_fn = ldb_handler_copy,
1648 .write_clear_fn = ldb_handler_copy,
1649 .write_hex_fn = ldb_handler_copy
1651 .name = "RMD_VERSION",
1652 .read_fn = ldb_handler_copy,
1653 .write_clear_fn = ldb_handler_copy,
1654 .write_hex_fn = ldb_handler_copy
1658 /* TODO: Should be dynamic at some point */
1659 static const struct {
1662 } samba_attributes[] = {
1663 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1664 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1665 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1666 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1667 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1668 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1669 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1670 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1671 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1672 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1673 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1674 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1675 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1676 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1677 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1678 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1679 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1682 * these are extracted by searching
1683 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1685 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1686 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1687 * hat can be used to identify the set of policies when applied to a resource.
1688 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1689 * server, we ignore it here.
1691 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1692 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1693 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1694 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1695 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1696 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1697 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1698 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1699 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1702 * these are extracted by searching
1703 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1705 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1706 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1707 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1708 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1709 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1710 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1711 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1712 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1713 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1714 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1715 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1716 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1717 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1718 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1719 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1720 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1721 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1722 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1723 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1724 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1725 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1726 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1727 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1728 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1729 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1730 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1731 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1732 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1735 * these are known to be GUIDs
1737 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1738 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1740 /* These NDR encoded things we want to be able to read with --show-binary */
1741 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1742 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1743 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1744 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1747 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1750 const struct ldb_schema_syntax *s = NULL;
1752 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1753 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1754 s = &samba_syntaxes[j];
1761 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1764 const struct ldb_schema_syntax *s = NULL;
1766 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1767 if (strcmp(samba_attributes[j].name, name) == 0) {
1768 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1776 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1777 "priorSecret", NULL};
1780 register the samba ldif handlers
1782 int ldb_register_samba_handlers(struct ldb_context *ldb)
1787 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1791 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1792 if (ret != LDB_SUCCESS) {
1796 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1797 const struct ldb_schema_syntax *s = NULL;
1799 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1802 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1806 return LDB_ERR_OPERATIONS_ERROR;
1809 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1810 if (ret != LDB_SUCCESS) {
1815 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1816 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1817 if (ret != LDB_SUCCESS) {
1823 ret = ldb_register_samba_matching_rules(ldb);
1824 if (ret != LDB_SUCCESS) {
1829 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1830 if (ret != LDB_SUCCESS) {