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 canonicalise an objectCategory. We use the short form as the canonical form:
431 cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
434 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
435 const struct ldb_val *in, struct ldb_val *out)
437 struct ldb_dn *dn1 = NULL;
438 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
439 const struct dsdb_class *sclass;
440 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
442 return LDB_ERR_OPERATIONS_ERROR;
446 talloc_free(tmp_ctx);
447 *out = data_blob_talloc(mem_ctx, in->data, in->length);
448 if (in->data && !out->data) {
449 return LDB_ERR_OPERATIONS_ERROR;
453 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
454 if ( ! ldb_dn_validate(dn1)) {
455 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
456 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
458 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
459 sclass->defaultObjectCategory);
460 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
461 talloc_free(tmp_ctx);
464 return LDB_ERR_OPERATIONS_ERROR;
468 *out = data_blob_talloc(mem_ctx, in->data, in->length);
469 talloc_free(tmp_ctx);
471 if (in->data && !out->data) {
472 return LDB_ERR_OPERATIONS_ERROR;
477 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
478 talloc_free(tmp_ctx);
481 return LDB_ERR_OPERATIONS_ERROR;
486 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
487 const struct ldb_val *v1,
488 const struct ldb_val *v2)
490 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
495 convert a NDR formatted blob to a ldif formatted schemaInfo
497 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
498 const struct ldb_val *in, struct ldb_val *out)
500 return ldif_write_NDR(ldb, mem_ctx, in, out,
501 sizeof(struct repsFromToBlob),
502 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
503 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
508 convert a ldif formatted prefixMap to a NDR formatted blob
510 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
511 const struct ldb_val *in, struct ldb_val *out)
513 struct prefixMapBlob *blob;
514 enum ndr_err_code ndr_err;
515 char *string, *line, *p, *oid;
518 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
520 if (tmp_ctx == NULL) {
524 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
526 talloc_free(tmp_ctx);
530 /* use the switch value to detect if this is in the binary
533 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
534 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
535 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
536 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
537 ndr_err = ndr_push_struct_blob(out, mem_ctx,
539 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
540 talloc_free(tmp_ctx);
541 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
548 /* If this does not parse, then it is probably the text version, and we should try it that way */
549 blob->version = PREFIX_MAP_VERSION_DSDB;
551 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
552 if (string == NULL) {
558 while (line && line[0]) {
563 p=strchr(line, '\n');
568 /* allow a trailing separator */
573 blob->ctr.dsdb.mappings = talloc_realloc(blob,
574 blob->ctr.dsdb.mappings,
575 struct drsuapi_DsReplicaOIDMapping,
576 blob->ctr.dsdb.num_mappings+1);
577 if (!blob->ctr.dsdb.mappings) {
578 talloc_free(tmp_ctx);
582 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
585 talloc_free(tmp_ctx);
589 /* we know there must be at least ":" */
592 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
593 talloc_free(tmp_ctx);
596 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
597 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
599 blob->ctr.dsdb.num_mappings++;
601 /* Now look past the terminator we added above */
609 ndr_err = ndr_push_struct_blob(out, mem_ctx,
611 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
612 talloc_free(tmp_ctx);
613 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
620 convert a NDR formatted blob to a ldif formatted prefixMap
622 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
623 const struct ldb_val *in, struct ldb_val *out)
625 struct prefixMapBlob *blob;
626 enum ndr_err_code ndr_err;
630 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
632 /* try to decode the blob as S4 prefixMap */
633 err = ldif_write_NDR(ldb, mem_ctx, in, out,
634 sizeof(struct prefixMapBlob),
635 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
636 (ndr_print_fn_t)ndr_print_prefixMapBlob,
641 /* try parsing it as Windows PrefixMap value */
642 return ldif_write_NDR(ldb, mem_ctx, in, out,
643 sizeof(struct drsuapi_MSPrefixMap_Ctr),
644 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
645 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
649 blob = talloc(mem_ctx, struct prefixMapBlob);
653 ndr_err = ndr_pull_struct_blob_all(in, blob,
655 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
656 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
659 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
662 string = talloc_strdup(mem_ctx, "");
663 if (string == NULL) {
667 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
669 char *partial_oid = NULL;
672 string = talloc_asprintf_append(string, ";");
675 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
676 blob->ctr.dsdb.mappings[i].oid.length);
677 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
678 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
679 blob->ctr.dsdb.mappings[i].id_prefix));
682 string = talloc_asprintf_append(string, "%u:%s",
683 blob->ctr.dsdb.mappings[i].id_prefix,
685 talloc_free(discard_const(partial_oid));
686 if (string == NULL) {
692 *out = data_blob_string_const(string);
700 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
706 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
714 canonicalise a prefixMap
716 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
717 const struct ldb_val *in, struct ldb_val *out)
719 if (ldif_comparision_prefixMap_isString(in)) {
720 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
722 return ldb_handler_copy(ldb, mem_ctx, in, out);
725 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
726 const struct ldb_val *v1,
727 const struct ldb_val *v2)
729 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
733 /* length limited conversion of a ldb_val to a int32_t */
734 static int val_to_int32(const struct ldb_val *in, int32_t *v)
739 /* make sure we don't read past the end of the data */
740 if (in->length > sizeof(buf)-1) {
741 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
743 strncpy(buf, (char *)in->data, in->length);
746 /* We've to use "strtoll" here to have the intended overflows.
747 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
748 *v = (int32_t) strtoll(buf, &end, 0);
750 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
755 /* length limited conversion of a ldb_val to a int64_t */
756 static int val_to_int64(const struct ldb_val *in, int64_t *v)
761 /* make sure we don't read past the end of the data */
762 if (in->length > sizeof(buf)-1) {
763 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
765 strncpy(buf, (char *)in->data, in->length);
768 *v = (int64_t) strtoll(buf, &end, 0);
770 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
775 /* Canonicalisation of two 32-bit integers */
776 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
777 const struct ldb_val *in, struct ldb_val *out)
782 ret = val_to_int32(in, &i);
783 if (ret != LDB_SUCCESS) {
786 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
787 if (out->data == NULL) {
789 return LDB_ERR_OPERATIONS_ERROR;
791 out->length = strlen((char *)out->data);
795 /* Comparison of two 32-bit integers */
796 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
797 const struct ldb_val *v1, const struct ldb_val *v2)
800 val_to_int32(v1, &i1);
801 val_to_int32(v2, &i2);
802 if (i1 == i2) return 0;
803 return i1 > i2? 1 : -1;
806 /* Canonicalisation of two 64-bit integers */
807 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
808 const struct ldb_val *in, struct ldb_val *out)
813 ret = val_to_int64(in, &i);
814 if (ret != LDB_SUCCESS) {
817 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
818 if (out->data == NULL) {
820 return LDB_ERR_OPERATIONS_ERROR;
822 out->length = strlen((char *)out->data);
826 /* Comparison of two 64-bit integers */
827 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
828 const struct ldb_val *v1, const struct ldb_val *v2)
831 val_to_int64(v1, &i1);
832 val_to_int64(v2, &i2);
833 if (i1 == i2) return 0;
834 return i1 > i2? 1 : -1;
838 convert a NDR formatted blob to a ldif formatted repsFromTo
840 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
841 const struct ldb_val *in, struct ldb_val *out)
843 return ldif_write_NDR(ldb, mem_ctx, in, out,
844 sizeof(struct repsFromToBlob),
845 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
846 (ndr_print_fn_t)ndr_print_repsFromToBlob,
851 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
853 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
854 const struct ldb_val *in, struct ldb_val *out)
856 return ldif_write_NDR(ldb, mem_ctx, in, out,
857 sizeof(struct replPropertyMetaDataBlob),
858 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
859 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
864 convert a NDR formatted blob to a ldif formatted replUpToDateVector
866 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
867 const struct ldb_val *in, struct ldb_val *out)
869 return ldif_write_NDR(ldb, mem_ctx, in, out,
870 sizeof(struct replUpToDateVectorBlob),
871 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
872 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
878 convert a NDR formatted blob to a ldif formatted dnsRecord
880 static int ldif_write_dnsRecord(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 dnsp_DnssrvRpcRecord),
885 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
886 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
891 convert a NDR formatted blob of a supplementalCredentials into text
893 static int ldif_write_supplementalCredentialsBlob(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 supplementalCredentialsBlob),
898 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
899 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
904 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
905 const struct ldb_val *in, struct ldb_val *out)
907 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
917 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
918 const struct ldb_val *v1, const struct ldb_val *v2)
920 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
923 if (dsdb_dn_is_deleted_val(v1)) {
924 /* If the DN is deleted, then we can't search for it */
928 if (dsdb_dn_is_deleted_val(v2)) {
929 /* If the DN is deleted, then we can't search for it */
933 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
934 if ( ! ldb_dn_validate(dn1)) return -1;
936 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
937 if ( ! ldb_dn_validate(dn2)) {
942 ret = ldb_dn_compare(dn1, dn2);
949 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
950 const struct ldb_val *in, struct ldb_val *out)
958 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
959 if ( ! ldb_dn_validate(dn)) {
960 return LDB_ERR_INVALID_DN_SYNTAX;
963 /* By including the RMD_FLAGS of a deleted DN, we ensure it
964 * does not casually match a not deleted DN */
965 if (dsdb_dn_is_deleted_val(in)) {
966 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
968 dsdb_dn_val_rmd_flags(in),
969 ldb_dn_get_casefold(dn));
971 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
974 if (out->data == NULL) {
977 out->length = strlen((char *)out->data);
989 write a 64 bit 2-part range
991 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
992 const struct ldb_val *in, struct ldb_val *out)
996 ret = val_to_int64(in, &v);
997 if (ret != LDB_SUCCESS) {
1000 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1001 (unsigned long)(v&0xFFFFFFFF),
1002 (unsigned long)(v>>32));
1003 if (out->data == NULL) {
1005 return LDB_ERR_OPERATIONS_ERROR;
1007 out->length = strlen((char *)out->data);
1012 read a 64 bit 2-part range
1014 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1015 const struct ldb_val *in, struct ldb_val *out)
1017 unsigned long high, low;
1020 if (memchr(in->data, '-', in->length) == NULL) {
1021 return ldb_handler_copy(ldb, mem_ctx, in, out);
1024 if (in->length > sizeof(buf)-1) {
1025 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1027 strncpy(buf, (const char *)in->data, in->length);
1028 buf[in->length] = 0;
1030 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1031 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1034 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1035 (unsigned long long)(((uint64_t)high)<<32) | (low));
1037 if (out->data == NULL) {
1039 return LDB_ERR_OPERATIONS_ERROR;
1041 out->length = strlen((char *)out->data);
1046 when this operator_fn is set for a syntax, the backend calls is in
1047 preference to the comparison function. We are told the exact
1048 comparison operation that is needed, and we can return errors
1050 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1051 const struct ldb_schema_attribute *a,
1052 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1054 switch (operation) {
1058 case LDB_OP_SUBSTRING:
1060 case LDB_OP_EXTENDED:
1061 /* handled in the backends */
1062 return LDB_ERR_INAPPROPRIATE_MATCHING;
1064 case LDB_OP_GREATER:
1066 case LDB_OP_EQUALITY:
1068 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1070 if (tmp_ctx == NULL) {
1071 return ldb_oom(ldb);
1073 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1074 talloc_free(tmp_ctx);
1075 if (operation == LDB_OP_GREATER) {
1076 *matched = (ret > 0);
1077 } else if (operation == LDB_OP_LESS) {
1078 *matched = (ret < 0);
1080 *matched = (ret == 0);
1085 case LDB_OP_PRESENT:
1090 /* we shouldn't get here */
1091 return LDB_ERR_INAPPROPRIATE_MATCHING;
1095 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1097 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1098 const struct ldb_schema_attribute *a,
1099 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1101 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1102 /* If the DN is deleted, then we can't search for it */
1106 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1110 static const struct ldb_schema_syntax samba_syntaxes[] = {
1112 .name = LDB_SYNTAX_SAMBA_SID,
1113 .ldif_read_fn = ldif_read_objectSid,
1114 .ldif_write_fn = ldif_write_objectSid,
1115 .canonicalise_fn = ldif_canonicalise_objectSid,
1116 .comparison_fn = ldif_comparison_objectSid,
1117 .operator_fn = samba_syntax_operator_fn
1119 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1120 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1121 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1122 .canonicalise_fn = ldb_handler_copy,
1123 .comparison_fn = ldb_comparison_binary,
1124 .operator_fn = samba_syntax_operator_fn
1126 .name = LDB_SYNTAX_SAMBA_GUID,
1127 .ldif_read_fn = ldif_read_objectGUID,
1128 .ldif_write_fn = ldif_write_objectGUID,
1129 .canonicalise_fn = ldif_canonicalise_objectGUID,
1130 .comparison_fn = ldif_comparison_objectGUID,
1131 .operator_fn = samba_syntax_operator_fn
1133 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1134 .ldif_read_fn = ldb_handler_copy,
1135 .ldif_write_fn = ldb_handler_copy,
1136 .canonicalise_fn = ldif_canonicalise_objectCategory,
1137 .comparison_fn = ldif_comparison_objectCategory,
1138 .operator_fn = samba_syntax_operator_fn
1140 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1141 .ldif_read_fn = ldb_handler_copy,
1142 .ldif_write_fn = ldif_write_schemaInfo,
1143 .canonicalise_fn = ldb_handler_copy,
1144 .comparison_fn = ldb_comparison_binary,
1145 .operator_fn = samba_syntax_operator_fn
1147 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1148 .ldif_read_fn = ldif_read_prefixMap,
1149 .ldif_write_fn = ldif_write_prefixMap,
1150 .canonicalise_fn = ldif_canonicalise_prefixMap,
1151 .comparison_fn = ldif_comparison_prefixMap,
1152 .operator_fn = samba_syntax_operator_fn
1154 .name = LDB_SYNTAX_SAMBA_INT32,
1155 .ldif_read_fn = ldb_handler_copy,
1156 .ldif_write_fn = ldb_handler_copy,
1157 .canonicalise_fn = ldif_canonicalise_int32,
1158 .comparison_fn = ldif_comparison_int32,
1159 .operator_fn = samba_syntax_operator_fn
1161 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1162 .ldif_read_fn = ldb_handler_copy,
1163 .ldif_write_fn = ldif_write_repsFromTo,
1164 .canonicalise_fn = ldb_handler_copy,
1165 .comparison_fn = ldb_comparison_binary,
1166 .operator_fn = samba_syntax_operator_fn
1168 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1169 .ldif_read_fn = ldb_handler_copy,
1170 .ldif_write_fn = ldif_write_replPropertyMetaData,
1171 .canonicalise_fn = ldb_handler_copy,
1172 .comparison_fn = ldb_comparison_binary,
1173 .operator_fn = samba_syntax_operator_fn
1175 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1176 .ldif_read_fn = ldb_handler_copy,
1177 .ldif_write_fn = ldif_write_replUpToDateVector,
1178 .canonicalise_fn = ldb_handler_copy,
1179 .comparison_fn = ldb_comparison_binary,
1180 .operator_fn = samba_syntax_operator_fn
1182 .name = DSDB_SYNTAX_BINARY_DN,
1183 .ldif_read_fn = ldb_handler_copy,
1184 .ldif_write_fn = ldb_handler_copy,
1185 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1186 .comparison_fn = dsdb_dn_binary_comparison,
1187 .operator_fn = samba_syntax_operator_fn
1189 .name = DSDB_SYNTAX_STRING_DN,
1190 .ldif_read_fn = ldb_handler_copy,
1191 .ldif_write_fn = ldb_handler_copy,
1192 .canonicalise_fn = dsdb_dn_string_canonicalise,
1193 .comparison_fn = dsdb_dn_string_comparison,
1194 .operator_fn = samba_syntax_operator_fn
1196 .name = LDB_SYNTAX_DN,
1197 .ldif_read_fn = ldb_handler_copy,
1198 .ldif_write_fn = ldb_handler_copy,
1199 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1200 .comparison_fn = samba_ldb_dn_link_comparison,
1201 .operator_fn = samba_syntax_operator_dn
1203 .name = LDB_SYNTAX_SAMBA_RANGE64,
1204 .ldif_read_fn = ldif_read_range64,
1205 .ldif_write_fn = ldif_write_range64,
1206 .canonicalise_fn = ldif_canonicalise_int64,
1207 .comparison_fn = ldif_comparison_int64,
1208 .operator_fn = samba_syntax_operator_fn
1210 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1211 .ldif_read_fn = ldb_handler_copy,
1212 .ldif_write_fn = ldif_write_dnsRecord,
1213 .canonicalise_fn = ldb_handler_copy,
1214 .comparison_fn = ldb_comparison_binary,
1215 .operator_fn = samba_syntax_operator_fn
1217 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1218 .ldif_read_fn = ldb_handler_copy,
1219 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1220 .canonicalise_fn = ldb_handler_copy,
1221 .comparison_fn = ldb_comparison_binary,
1222 .operator_fn = samba_syntax_operator_fn
1226 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1229 .read_fn = extended_dn_read_SID,
1230 .write_clear_fn = ldif_write_objectSid,
1231 .write_hex_fn = extended_dn_write_hex
1234 .read_fn = extended_dn_read_GUID,
1235 .write_clear_fn = ldif_write_objectGUID,
1236 .write_hex_fn = extended_dn_write_hex
1239 .read_fn = ldb_handler_copy,
1240 .write_clear_fn = ldb_handler_copy,
1241 .write_hex_fn = ldb_handler_copy
1243 .name = "RMD_INVOCID",
1244 .read_fn = extended_dn_read_GUID,
1245 .write_clear_fn = ldif_write_objectGUID,
1246 .write_hex_fn = extended_dn_write_hex
1248 .name = "RMD_FLAGS",
1249 .read_fn = ldb_handler_copy,
1250 .write_clear_fn = ldb_handler_copy,
1251 .write_hex_fn = ldb_handler_copy
1253 .name = "RMD_ADDTIME",
1254 .read_fn = ldb_handler_copy,
1255 .write_clear_fn = ldb_handler_copy,
1256 .write_hex_fn = ldb_handler_copy
1258 .name = "RMD_CHANGETIME",
1259 .read_fn = ldb_handler_copy,
1260 .write_clear_fn = ldb_handler_copy,
1261 .write_hex_fn = ldb_handler_copy
1263 .name = "RMD_LOCAL_USN",
1264 .read_fn = ldb_handler_copy,
1265 .write_clear_fn = ldb_handler_copy,
1266 .write_hex_fn = ldb_handler_copy
1268 .name = "RMD_ORIGINATING_USN",
1269 .read_fn = ldb_handler_copy,
1270 .write_clear_fn = ldb_handler_copy,
1271 .write_hex_fn = ldb_handler_copy
1273 .name = "RMD_VERSION",
1274 .read_fn = ldb_handler_copy,
1275 .write_clear_fn = ldb_handler_copy,
1276 .write_hex_fn = ldb_handler_copy
1280 /* TODO: Should be dynamic at some point */
1281 static const struct {
1284 } samba_attributes[] = {
1285 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1286 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1287 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1288 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1289 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1290 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1291 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1292 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1293 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1294 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1295 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1296 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1297 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1298 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1299 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1302 * these are extracted by searching
1303 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1305 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1306 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1307 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1308 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1309 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1310 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1311 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1312 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1313 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1314 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1315 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1316 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1317 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1318 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1319 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1320 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1321 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1322 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1323 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1324 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1325 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1326 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1327 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1328 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1331 * these are known to be GUIDs
1333 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1334 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1335 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1337 /* These NDR encoded things we want to be able to read with --show-binary */
1338 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1339 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS}
1342 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1345 const struct ldb_schema_syntax *s = NULL;
1347 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1348 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1349 s = &samba_syntaxes[j];
1356 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1359 const struct ldb_schema_syntax *s = NULL;
1361 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1362 if (strcmp(samba_attributes[j].name, name) == 0) {
1363 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1372 register the samba ldif handlers
1374 int ldb_register_samba_handlers(struct ldb_context *ldb)
1379 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1383 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1384 const struct ldb_schema_syntax *s = NULL;
1386 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1389 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1393 return LDB_ERR_OPERATIONS_ERROR;
1396 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1397 if (ret != LDB_SUCCESS) {
1402 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1403 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1404 if (ret != LDB_SUCCESS) {
1410 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1411 if (ret != LDB_SUCCESS) {