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"
39 #include "lib/util/smb_strtox.h"
42 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
44 If mask_errors is true, then function succeeds but out data
45 is set to "<Unable to decode binary data>" message
47 \return 0 on success; -1 on error
49 static int ldif_write_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
50 const struct ldb_val
*in
, struct ldb_val
*out
,
52 ndr_pull_flags_fn_t pull_fn
,
53 ndr_print_fn_t print_fn
,
57 enum ndr_err_code err
;
58 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
59 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
61 p
= talloc_size(mem_ctx
, struct_size
);
62 err
= ndr_pull_struct_blob(in
, mem_ctx
,
64 if (err
!= NDR_ERR_SUCCESS
) {
65 /* fail in not in mask_error mode */
70 out
->data
= (uint8_t *)talloc_strdup(mem_ctx
, "<Unable to decode binary data>");
71 out
->length
= strlen((const char *)out
->data
);
74 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
, print_fn
, "NDR", p
);
76 if (out
->data
== NULL
) {
77 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
79 out
->length
= strlen((char *)out
->data
);
84 convert a ldif formatted objectSid to a NDR formatted blob
86 static int ldif_read_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
87 const struct ldb_val
*in
, struct ldb_val
*out
)
90 enum ndr_err_code ndr_err
;
92 if (in
->length
> DOM_SID_STR_BUFLEN
) {
96 memcpy(p
, in
->data
, in
->length
);
99 ret
= dom_sid_parse(p
, &sid
);
104 *out
= data_blob_talloc(mem_ctx
, NULL
,
105 ndr_size_dom_sid(&sid
, 0));
106 if (out
->data
== NULL
) {
110 ndr_err
= ndr_push_struct_into_fixed_blob(out
, &sid
,
111 (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
112 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
120 convert a NDR formatted blob to a ldif formatted objectSid
122 int ldif_write_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
123 const struct ldb_val
*in
, struct ldb_val
*out
)
126 enum ndr_err_code ndr_err
;
128 ndr_err
= ndr_pull_struct_blob_all_noalloc(in
, &sid
,
129 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
130 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
133 *out
= data_blob_string_const(dom_sid_string(mem_ctx
, &sid
));
134 if (out
->data
== NULL
) {
140 bool ldif_comparision_objectSid_isString(const struct ldb_val
*v
)
146 if (strncmp("S-", (const char *)v
->data
, 2) != 0) return false;
152 compare two objectSids
154 If the SIDs seem to be strings, they are converted to binary form.
156 static int ldif_comparison_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
157 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
159 bool v1_is_string
= ldif_comparision_objectSid_isString(v1
);
160 bool v2_is_string
= ldif_comparision_objectSid_isString(v2
);
161 struct ldb_val parsed_1
= {};
162 struct ldb_val parsed_2
= {};
165 * If the ldb_vals look like SID strings (i.e. start with "S-"
166 * or "s-"), we try to parse them as such. If that fails, we
167 * assume they are binary SIDs, even though that's not really
168 * possible -- the first two bytes of a struct dom_sid are the
169 * version (1), and the number of sub-auths (<= 15), neither
170 * of which are close to 'S' or '-'.
173 int r
= ldif_read_objectSid(ldb
, mem_ctx
, v1
, &parsed_1
);
179 int r
= ldif_read_objectSid(ldb
, mem_ctx
, v2
, &parsed_2
);
185 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
188 TALLOC_FREE(parsed_1
.data
);
191 TALLOC_FREE(parsed_2
.data
);
197 canonicalise a objectSid
199 static int ldif_canonicalise_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
200 const struct ldb_val
*in
, struct ldb_val
*out
)
202 if (ldif_comparision_objectSid_isString(in
)) {
203 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) != 0) {
204 /* Perhaps not a string after all */
205 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
209 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
212 static int extended_dn_read_SID(struct ldb_context
*ldb
, void *mem_ctx
,
213 const struct ldb_val
*in
, struct ldb_val
*out
)
216 enum ndr_err_code ndr_err
;
217 if (ldif_comparision_objectSid_isString(in
)) {
218 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) == 0) {
223 /* Perhaps not a string after all */
224 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
230 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
231 (const char *)in
->data
, in
->length
);
233 /* Check it looks like a SID */
234 ndr_err
= ndr_pull_struct_blob_all_noalloc(out
, &sid
,
235 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
236 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
243 convert a ldif formatted objectGUID to a NDR formatted blob
245 static int ldif_read_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
246 const struct ldb_val
*in
, struct ldb_val
*out
)
251 status
= GUID_from_data_blob(in
, &guid
);
252 if (!NT_STATUS_IS_OK(status
)) {
256 status
= GUID_to_ndr_blob(&guid
, mem_ctx
, out
);
257 if (!NT_STATUS_IS_OK(status
)) {
264 convert a NDR formatted blob to a ldif formatted objectGUID
266 static int ldif_write_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
267 const struct ldb_val
*in
, struct ldb_val
*out
)
272 status
= GUID_from_ndr_blob(in
, &guid
);
273 if (!NT_STATUS_IS_OK(status
)) {
276 out
->data
= (uint8_t *)GUID_string(mem_ctx
, &guid
);
277 if (out
->data
== NULL
) {
280 out
->length
= strlen((const char *)out
->data
);
284 static bool ldif_comparision_objectGUID_isString(const struct ldb_val
*v
)
286 if (v
->length
!= 36 && v
->length
!= 38) return false;
288 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
292 static int extended_dn_read_GUID(struct ldb_context
*ldb
, void *mem_ctx
,
293 const struct ldb_val
*in
, struct ldb_val
*out
)
296 if (in
->length
== 36 && ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) == 0) {
300 /* Try as 'hex' form */
301 if (in
->length
!= 32) {
305 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
311 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
312 (const char *)in
->data
, in
->length
);
314 /* Check it looks like a GUID */
315 if ((*out
).length
!= 16) {
324 compare two objectGUIDs
326 static int ldif_comparison_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
327 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
329 if (ldif_comparision_objectGUID_isString(v1
) && ldif_comparision_objectGUID_isString(v2
)) {
330 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
331 } else if (ldif_comparision_objectGUID_isString(v1
)
332 && !ldif_comparision_objectGUID_isString(v2
)) {
335 if (ldif_read_objectGUID(ldb
, mem_ctx
, v1
, &v
) != 0) {
336 /* Perhaps it wasn't a valid string after all */
337 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
339 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
342 } else if (!ldif_comparision_objectGUID_isString(v1
)
343 && ldif_comparision_objectGUID_isString(v2
)) {
346 if (ldif_read_objectGUID(ldb
, mem_ctx
, v2
, &v
) != 0) {
347 /* Perhaps it wasn't a valid string after all */
348 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
350 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
354 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
358 canonicalise a objectGUID
360 static int ldif_canonicalise_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
361 const struct ldb_val
*in
, struct ldb_val
*out
)
363 if (ldif_comparision_objectGUID_isString(in
)) {
364 if (ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) != 0) {
365 /* Perhaps it wasn't a valid string after all */
366 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
370 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
375 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
377 static int ldif_read_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
378 const struct ldb_val
*in
, struct ldb_val
*out
)
380 struct security_descriptor
*sd
;
381 enum ndr_err_code ndr_err
;
383 if (in
->length
>= 2 && isupper(in
->data
[0]) && in
->data
[1] == ':') {
385 * If it starts with an upper case character followed by ':',
386 * we know it's not NDR, but most likely SDDL...
388 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
390 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
398 sd
= talloc(mem_ctx
, struct security_descriptor
);
403 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
404 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
405 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
411 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, sd
,
412 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
414 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
422 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
424 static int ldif_write_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
425 const struct ldb_val
*in
, struct ldb_val
*out
)
427 struct security_descriptor
*sd
;
428 enum ndr_err_code ndr_err
;
430 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
431 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
432 sizeof(struct security_descriptor
),
433 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
,
434 (ndr_print_fn_t
)ndr_print_security_descriptor
,
439 sd
= talloc(mem_ctx
, struct security_descriptor
);
443 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
444 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
445 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
446 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
450 out
->data
= (uint8_t *)sddl_encode(mem_ctx
, sd
, samdb_domain_sid_cache_only(ldb
));
452 if (out
->data
== NULL
) {
455 out
->length
= strlen((const char *)out
->data
);
460 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
462 static int ldif_write_sddlSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
463 const struct ldb_val
*in
, struct ldb_val
*out
)
465 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
466 struct security_descriptor
*sd
;
467 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
469 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
470 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
,
471 (ndr_print_fn_t
)ndr_print_security_descriptor
,
473 out
->length
= strlen((const char *)out
->data
);
478 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
482 canonicalise an objectCategory. We use the long form as the canonical form:
483 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
485 Also any short name of an objectClass that points to a different
486 class (such as user) has the canonical form of the class it's
487 defaultObjectCategory points to (eg
488 cn=Person,cn=Schema,cn=Configuration,<basedn>)
491 static int ldif_canonicalise_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
492 const struct ldb_val
*in
, struct ldb_val
*out
)
494 struct ldb_dn
*dn1
= NULL
;
495 const struct dsdb_schema
*schema
= dsdb_get_schema(ldb
, NULL
);
496 const struct dsdb_class
*sclass
;
497 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
499 return LDB_ERR_OPERATIONS_ERROR
;
503 talloc_free(tmp_ctx
);
504 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
505 if (in
->data
&& !out
->data
) {
506 return LDB_ERR_OPERATIONS_ERROR
;
510 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, in
);
511 if ( ! ldb_dn_validate(dn1
)) {
512 const char *lDAPDisplayName
= talloc_strndup(tmp_ctx
, (char *)in
->data
, in
->length
);
513 sclass
= dsdb_class_by_lDAPDisplayName(schema
, lDAPDisplayName
);
515 struct ldb_dn
*dn
= ldb_dn_new(tmp_ctx
, ldb
,
516 sclass
->defaultObjectCategory
);
518 talloc_free(tmp_ctx
);
519 return LDB_ERR_OPERATIONS_ERROR
;
522 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn
));
523 talloc_free(tmp_ctx
);
526 return LDB_ERR_OPERATIONS_ERROR
;
530 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
531 talloc_free(tmp_ctx
);
533 if (in
->data
&& !out
->data
) {
534 return LDB_ERR_OPERATIONS_ERROR
;
539 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn1
));
540 talloc_free(tmp_ctx
);
543 return LDB_ERR_OPERATIONS_ERROR
;
548 static int ldif_comparison_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
549 const struct ldb_val
*v1
,
550 const struct ldb_val
*v2
)
552 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_objectCategory
,
557 convert a NDR formatted blob to a ldif formatted schemaInfo
559 static int ldif_write_schemaInfo(struct ldb_context
*ldb
, void *mem_ctx
,
560 const struct ldb_val
*in
, struct ldb_val
*out
)
562 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
563 sizeof(struct repsFromToBlob
),
564 (ndr_pull_flags_fn_t
)ndr_pull_schemaInfoBlob
,
565 (ndr_print_fn_t
)ndr_print_schemaInfoBlob
,
570 convert a ldif formatted prefixMap to a NDR formatted blob
572 static int ldif_read_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
573 const struct ldb_val
*in
, struct ldb_val
*out
)
575 struct prefixMapBlob
*blob
;
576 enum ndr_err_code ndr_err
;
577 char *string
, *line
, *p
, *oid
;
580 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
582 if (tmp_ctx
== NULL
) {
586 blob
= talloc_zero(tmp_ctx
, struct prefixMapBlob
);
588 talloc_free(tmp_ctx
);
592 /* use the switch value to detect if this is in the binary
595 if (in
->length
>= 4 && IVAL(in
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
596 ndr_err
= ndr_pull_struct_blob(in
, tmp_ctx
, blob
,
597 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
598 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
599 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
601 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
602 talloc_free(tmp_ctx
);
603 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
610 /* If this does not parse, then it is probably the text version, and we should try it that way */
611 blob
->version
= PREFIX_MAP_VERSION_DSDB
;
613 string
= talloc_strndup(mem_ctx
, (const char *)in
->data
, in
->length
);
614 if (string
== NULL
) {
620 while (line
&& line
[0]) {
627 p
=strchr(line
, '\n');
632 /* allow a trailing separator */
637 blob
->ctr
.dsdb
.mappings
= talloc_realloc(blob
,
638 blob
->ctr
.dsdb
.mappings
,
639 struct drsuapi_DsReplicaOIDMapping
,
640 blob
->ctr
.dsdb
.num_mappings
+1);
641 if (!blob
->ctr
.dsdb
.mappings
) {
642 talloc_free(tmp_ctx
);
646 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].id_prefix
=
647 smb_strtoul(line
, &oid
, 10, &error
, SMB_STR_STANDARD
);
649 if (oid
[0] != ':' || error
!= 0) {
650 talloc_free(tmp_ctx
);
654 /* we know there must be at least ":" */
657 if (!ber_write_partial_OID_String(blob
->ctr
.dsdb
.mappings
, &oid_blob
, oid
)) {
658 talloc_free(tmp_ctx
);
661 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.length
= oid_blob
.length
;
662 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.binary_oid
= oid_blob
.data
;
664 blob
->ctr
.dsdb
.num_mappings
++;
666 /* Now look past the terminator we added above */
674 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
676 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
677 talloc_free(tmp_ctx
);
678 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
685 convert a NDR formatted blob to a ldif formatted prefixMap
687 static int ldif_write_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
688 const struct ldb_val
*in
, struct ldb_val
*out
)
690 struct prefixMapBlob
*blob
;
691 enum ndr_err_code ndr_err
;
695 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
697 /* try to decode the blob as S4 prefixMap */
698 err
= ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
699 sizeof(struct prefixMapBlob
),
700 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
,
701 (ndr_print_fn_t
)ndr_print_prefixMapBlob
,
706 /* try parsing it as Windows PrefixMap value */
707 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
708 sizeof(struct drsuapi_MSPrefixMap_Ctr
),
709 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_MSPrefixMap_Ctr
,
710 (ndr_print_fn_t
)ndr_print_drsuapi_MSPrefixMap_Ctr
,
714 blob
= talloc(mem_ctx
, struct prefixMapBlob
);
718 ndr_err
= ndr_pull_struct_blob_all(in
, blob
,
720 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
721 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
724 if (blob
->version
!= PREFIX_MAP_VERSION_DSDB
) {
727 string
= talloc_strdup(mem_ctx
, "");
728 if (string
== NULL
) {
732 for (i
=0; i
< blob
->ctr
.dsdb
.num_mappings
; i
++) {
734 char *partial_oid
= NULL
;
737 talloc_asprintf_addbuf(&string
, ";");
740 oid_blob
= data_blob_const(blob
->ctr
.dsdb
.mappings
[i
].oid
.binary_oid
,
741 blob
->ctr
.dsdb
.mappings
[i
].oid
.length
);
742 if (!ber_read_partial_OID_String(blob
, oid_blob
, &partial_oid
)) {
743 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X\n",
744 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
));
747 talloc_asprintf_addbuf(&string
, "%u:%s",
748 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
,
750 talloc_free(discard_const(partial_oid
));
754 *out
= data_blob_string_const(string
);
762 static bool ldif_comparision_prefixMap_isString(const struct ldb_val
*v
)
768 if (IVAL(v
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
776 canonicalise a prefixMap
778 static int ldif_canonicalise_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
779 const struct ldb_val
*in
, struct ldb_val
*out
)
781 if (ldif_comparision_prefixMap_isString(in
)) {
782 return ldif_read_prefixMap(ldb
, mem_ctx
, in
, out
);
784 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
787 static int ldif_comparison_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
788 const struct ldb_val
*v1
,
789 const struct ldb_val
*v2
)
791 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_prefixMap
,
795 /* length limited conversion of a ldb_val to a int32_t */
796 static int val_to_int32(const struct ldb_val
*in
, int32_t *v
)
801 /* make sure we don't read past the end of the data */
802 if (in
->length
> sizeof(buf
)-1) {
803 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
805 strncpy(buf
, (char *)in
->data
, in
->length
);
808 /* We've to use "strtoll" here to have the intended overflows.
809 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
810 *v
= (int32_t) strtoll(buf
, &end
, 0);
812 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
817 /* length limited conversion of a ldb_val to a int64_t */
818 static int val_to_int64(const struct ldb_val
*in
, int64_t *v
)
823 /* make sure we don't read past the end of the data */
824 if (in
->length
> sizeof(buf
)-1) {
825 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
827 strncpy(buf
, (char *)in
->data
, in
->length
);
830 *v
= (int64_t) strtoll(buf
, &end
, 0);
832 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
837 /* Canonicalisation of two 32-bit integers */
838 static int ldif_canonicalise_int32(struct ldb_context
*ldb
, void *mem_ctx
,
839 const struct ldb_val
*in
, struct ldb_val
*out
)
844 ret
= val_to_int32(in
, &i
);
845 if (ret
!= LDB_SUCCESS
) {
848 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%d", i
);
849 if (out
->data
== NULL
) {
851 return LDB_ERR_OPERATIONS_ERROR
;
853 out
->length
= strlen((char *)out
->data
);
858 * Lexicographically sorted representation for a 32-bit integer
860 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
863 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
864 * corresponding documentation for 64-bit integers.
866 * The same rules apply but use INT32_MIN and INT32_MAX.
868 * String representation padding is done to 10 characters.
870 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
873 static int ldif_index_format_int32(struct ldb_context
*ldb
,
875 const struct ldb_val
*in
,
883 ret
= val_to_int32(in
, &i
);
884 if (ret
!= LDB_SUCCESS
) {
890 * i is negative, so this is subtraction rather than
894 i
= INT32_MAX
+ i
+ 1;
901 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%c%010ld", prefix
, (long)i
);
902 if (out
->data
== NULL
) {
904 return LDB_ERR_OPERATIONS_ERROR
;
907 len
= talloc_array_length(out
->data
) - 1;
909 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
910 __location__
": expected index format str %s to"
911 " have length 11 but got %zu",
912 (char*)out
->data
, len
);
913 return LDB_ERR_OPERATIONS_ERROR
;
920 /* Comparison of two 32-bit integers */
921 static int ldif_comparison_int32(struct ldb_context
*ldb
, void *mem_ctx
,
922 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
925 val_to_int32(v1
, &i1
);
926 val_to_int32(v2
, &i2
);
927 if (i1
== i2
) return 0;
928 return i1
> i2
? 1 : -1;
931 /* Canonicalisation of two 64-bit integers */
932 static int ldif_canonicalise_int64(struct ldb_context
*ldb
, void *mem_ctx
,
933 const struct ldb_val
*in
, struct ldb_val
*out
)
938 ret
= val_to_int64(in
, &i
);
939 if (ret
!= LDB_SUCCESS
) {
942 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%lld", (long long)i
);
943 if (out
->data
== NULL
) {
945 return LDB_ERR_OPERATIONS_ERROR
;
947 out
->length
= strlen((char *)out
->data
);
951 /* Comparison of two 64-bit integers */
952 static int ldif_comparison_int64(struct ldb_context
*ldb
, void *mem_ctx
,
953 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
956 val_to_int64(v1
, &i1
);
957 val_to_int64(v2
, &i2
);
958 if (i1
== i2
) return 0;
959 return i1
> i2
? 1 : -1;
963 convert a NDR formatted blob to a ldif formatted repsFromTo
965 static int ldif_write_repsFromTo(struct ldb_context
*ldb
, void *mem_ctx
,
966 const struct ldb_val
*in
, struct ldb_val
*out
)
968 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
969 sizeof(struct repsFromToBlob
),
970 (ndr_pull_flags_fn_t
)ndr_pull_repsFromToBlob
,
971 (ndr_print_fn_t
)ndr_print_repsFromToBlob
,
976 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
978 static int ldif_write_replPropertyMetaData(struct ldb_context
*ldb
, void *mem_ctx
,
979 const struct ldb_val
*in
, struct ldb_val
*out
)
981 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
982 sizeof(struct replPropertyMetaDataBlob
),
983 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaDataBlob
,
984 (ndr_print_fn_t
)ndr_print_replPropertyMetaDataBlob
,
989 convert a NDR formatted blob to a ldif formatted replUpToDateVector
991 static int ldif_write_replUpToDateVector(struct ldb_context
*ldb
, void *mem_ctx
,
992 const struct ldb_val
*in
, struct ldb_val
*out
)
994 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
995 sizeof(struct replUpToDateVectorBlob
),
996 (ndr_pull_flags_fn_t
)ndr_pull_replUpToDateVectorBlob
,
997 (ndr_print_fn_t
)ndr_print_replUpToDateVectorBlob
,
1001 static int ldif_write_dn_binary_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
1002 const struct ldb_val
*in
, struct ldb_val
*out
,
1004 ndr_pull_flags_fn_t pull_fn
,
1005 ndr_print_fn_t print_fn
,
1009 enum ndr_err_code err
;
1010 struct dsdb_dn
*dsdb_dn
= NULL
;
1011 char *dn_str
= NULL
;
1014 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
1015 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1018 dsdb_dn
= dsdb_dn_parse(mem_ctx
, ldb
, in
, DSDB_SYNTAX_BINARY_DN
);
1019 if (dsdb_dn
== NULL
) {
1020 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1023 p
= talloc_size(dsdb_dn
, struct_size
);
1025 TALLOC_FREE(dsdb_dn
);
1026 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1029 err
= ndr_pull_struct_blob(&dsdb_dn
->extra_part
, p
, p
, pull_fn
);
1030 if (err
!= NDR_ERR_SUCCESS
) {
1031 /* fail in not in mask_error mode */
1035 TALLOC_FREE(dsdb_dn
);
1036 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1039 dn_str
= ldb_dn_get_extended_linearized(dsdb_dn
, dsdb_dn
->dn
, 1);
1040 if (dn_str
== NULL
) {
1041 TALLOC_FREE(dsdb_dn
);
1042 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1045 str
= ndr_print_struct_string(mem_ctx
, print_fn
, dn_str
, p
);
1046 TALLOC_FREE(dsdb_dn
);
1048 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1051 *out
= data_blob_string_const(str
);
1055 static int ldif_write_msDS_RevealedUsers(struct ldb_context
*ldb
, void *mem_ctx
,
1056 const struct ldb_val
*in
, struct ldb_val
*out
)
1058 return ldif_write_dn_binary_NDR(ldb
, mem_ctx
, in
, out
,
1059 sizeof(struct replPropertyMetaData1
),
1060 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaData1
,
1061 (ndr_print_fn_t
)ndr_print_replPropertyMetaData1
,
1066 convert a NDR formatted blob to a ldif formatted dnsRecord
1068 static int ldif_write_dnsRecord(struct ldb_context
*ldb
, void *mem_ctx
,
1069 const struct ldb_val
*in
, struct ldb_val
*out
)
1071 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1072 sizeof(struct dnsp_DnssrvRpcRecord
),
1073 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
,
1074 (ndr_print_fn_t
)ndr_print_dnsp_DnssrvRpcRecord
,
1079 convert a NDR formatted blob to a ldif formatted dnsProperty
1081 static int ldif_write_dnsProperty(struct ldb_context
*ldb
, void *mem_ctx
,
1082 const struct ldb_val
*in
, struct ldb_val
*out
)
1084 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1085 sizeof(struct dnsp_DnsProperty
),
1086 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnsProperty
,
1087 (ndr_print_fn_t
)ndr_print_dnsp_DnsProperty
,
1092 convert a NDR formatted blob of a supplementalCredentials into text
1094 static int ldif_write_supplementalCredentialsBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1095 const struct ldb_val
*in
, struct ldb_val
*out
)
1097 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1098 sizeof(struct supplementalCredentialsBlob
),
1099 (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
,
1100 (ndr_print_fn_t
)ndr_print_supplementalCredentialsBlob
,
1105 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1107 static int ldif_write_trustAuthInOutBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1108 const struct ldb_val
*in
, struct ldb_val
*out
)
1110 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1111 sizeof(struct trustAuthInOutBlob
),
1112 (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
,
1113 (ndr_print_fn_t
)ndr_print_trustAuthInOutBlob
,
1118 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1120 static int ldif_write_ForestTrustInfo(struct ldb_context
*ldb
, void *mem_ctx
,
1121 const struct ldb_val
*in
, struct ldb_val
*out
)
1123 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1124 sizeof(struct ForestTrustInfo
),
1125 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
,
1126 (ndr_print_fn_t
)ndr_print_ForestTrustInfo
,
1130 convert a NDR formatted blob of a partialAttributeSet into text
1132 static int ldif_write_partialAttributeSet(struct ldb_context
*ldb
, void *mem_ctx
,
1133 const struct ldb_val
*in
, struct ldb_val
*out
)
1135 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1136 sizeof(struct partialAttributeSetBlob
),
1137 (ndr_pull_flags_fn_t
)ndr_pull_partialAttributeSetBlob
,
1138 (ndr_print_fn_t
)ndr_print_partialAttributeSetBlob
,
1143 static int extended_dn_write_hex(struct ldb_context
*ldb
, void *mem_ctx
,
1144 const struct ldb_val
*in
, struct ldb_val
*out
)
1146 *out
= data_blob_string_const(data_blob_hex_string_lower(mem_ctx
, in
));
1156 static int samba_ldb_dn_link_comparison(struct ldb_context
*ldb
, void *mem_ctx
,
1157 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1159 struct ldb_dn
*dn1
= NULL
, *dn2
= NULL
;
1162 if (dsdb_dn_is_deleted_val(v1
)) {
1163 /* If the DN is deleted, then we can't search for it */
1167 if (dsdb_dn_is_deleted_val(v2
)) {
1168 /* If the DN is deleted, then we can't search for it */
1172 dn1
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v1
);
1173 if ( ! ldb_dn_validate(dn1
)) return -1;
1175 dn2
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v2
);
1176 if ( ! ldb_dn_validate(dn2
)) {
1181 ret
= ldb_dn_compare(dn1
, dn2
);
1188 static int samba_ldb_dn_link_canonicalise(struct ldb_context
*ldb
, void *mem_ctx
,
1189 const struct ldb_val
*in
, struct ldb_val
*out
)
1197 dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, in
);
1198 if ( ! ldb_dn_validate(dn
)) {
1199 return LDB_ERR_INVALID_DN_SYNTAX
;
1202 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1203 * does not casually match a not deleted DN */
1204 if (dsdb_dn_is_deleted_val(in
)) {
1205 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
,
1207 dsdb_dn_val_rmd_flags(in
),
1208 ldb_dn_get_casefold(dn
));
1210 out
->data
= (uint8_t *)ldb_dn_alloc_casefold(mem_ctx
, dn
);
1213 if (out
->data
== NULL
) {
1216 out
->length
= strlen((char *)out
->data
);
1228 write a 64 bit 2-part range
1230 static int ldif_write_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1231 const struct ldb_val
*in
, struct ldb_val
*out
)
1235 ret
= val_to_int64(in
, &v
);
1236 if (ret
!= LDB_SUCCESS
) {
1239 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%lu-%lu",
1240 (unsigned long)(v
&0xFFFFFFFF),
1241 (unsigned long)(v
>>32));
1242 if (out
->data
== NULL
) {
1244 return LDB_ERR_OPERATIONS_ERROR
;
1246 out
->length
= strlen((char *)out
->data
);
1251 read a 64 bit 2-part range
1253 static int ldif_read_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1254 const struct ldb_val
*in
, struct ldb_val
*out
)
1256 unsigned long high
, low
;
1259 if (memchr(in
->data
, '-', in
->length
) == NULL
) {
1260 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1263 if (in
->length
> sizeof(buf
)-1) {
1264 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1266 strncpy(buf
, (const char *)in
->data
, in
->length
);
1267 buf
[in
->length
] = 0;
1269 if (sscanf(buf
, "%lu-%lu", &low
, &high
) != 2) {
1270 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1273 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%llu",
1274 (unsigned long long)(((uint64_t)high
)<<32) | (low
));
1276 if (out
->data
== NULL
) {
1278 return LDB_ERR_OPERATIONS_ERROR
;
1280 out
->length
= strlen((char *)out
->data
);
1285 when this operator_fn is set for a syntax, the backend calls is in
1286 preference to the comparison function. We are told the exact
1287 comparison operation that is needed, and we can return errors
1289 static int samba_syntax_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1290 const struct ldb_schema_attribute
*a
,
1291 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1293 switch (operation
) {
1297 case LDB_OP_SUBSTRING
:
1299 case LDB_OP_EXTENDED
:
1300 /* handled in the backends */
1301 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1303 case LDB_OP_GREATER
:
1305 case LDB_OP_EQUALITY
:
1307 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
1309 if (tmp_ctx
== NULL
) {
1310 return ldb_oom(ldb
);
1312 ret
= a
->syntax
->comparison_fn(ldb
, tmp_ctx
, v1
, v2
);
1313 talloc_free(tmp_ctx
);
1314 if (operation
== LDB_OP_GREATER
) {
1315 *matched
= (ret
>= 0);
1316 } else if (operation
== LDB_OP_LESS
) {
1317 *matched
= (ret
<= 0);
1319 *matched
= (ret
== 0);
1324 case LDB_OP_PRESENT
:
1329 /* we shouldn't get here */
1330 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1334 compare two binary objects. This is correct for sorting as the sort order is:
1341 rather than ldb_comparison_binary() which is:
1349 static int samba_ldb_comparison_binary(struct ldb_context
*ldb
, void *mem_ctx
,
1350 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1352 return data_blob_cmp(v1
, v2
);
1356 when this operator_fn is set for a syntax, the backend calls is in
1357 preference to the comparison function. We are told the exact
1358 comparison operation that is needed, and we can return errors.
1360 This mode optimises for ldb_comparison_binary() if we need equality,
1361 as this should be faster as it can do a length-check first.
1363 static int samba_syntax_binary_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1364 const struct ldb_schema_attribute
*a
,
1365 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1367 if (operation
== LDB_OP_EQUALITY
) {
1368 *matched
= (ldb_comparison_binary(ldb
, NULL
, v1
, v2
) == 0);
1371 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1375 see if two DNs match, comparing first by GUID, then by SID, and
1376 finally by string components
1378 static int samba_dn_extended_match(struct ldb_context
*ldb
,
1379 const struct ldb_val
*v1
,
1380 const struct ldb_val
*v2
,
1383 TALLOC_CTX
*tmp_ctx
;
1384 struct ldb_dn
*dn1
, *dn2
;
1385 const struct ldb_val
*guid1
, *guid2
, *sid1
, *sid2
;
1386 uint32_t rmd_flags1
, rmd_flags2
;
1388 tmp_ctx
= talloc_new(ldb
);
1390 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v1
);
1391 dn2
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v2
);
1393 /* couldn't parse as DN's */
1394 talloc_free(tmp_ctx
);
1399 rmd_flags1
= dsdb_dn_rmd_flags(dn1
);
1400 rmd_flags2
= dsdb_dn_rmd_flags(dn2
);
1402 if ((rmd_flags1
& DSDB_RMD_FLAG_DELETED
) !=
1403 (rmd_flags2
& DSDB_RMD_FLAG_DELETED
)) {
1404 /* only match if they have the same deletion status */
1405 talloc_free(tmp_ctx
);
1411 guid1
= ldb_dn_get_extended_component(dn1
, "GUID");
1412 guid2
= ldb_dn_get_extended_component(dn2
, "GUID");
1413 if (guid1
&& guid2
) {
1414 (*matched
) = (data_blob_cmp(guid1
, guid2
) == 0);
1415 talloc_free(tmp_ctx
);
1419 sid1
= ldb_dn_get_extended_component(dn1
, "SID");
1420 sid2
= ldb_dn_get_extended_component(dn2
, "SID");
1422 (*matched
) = (data_blob_cmp(sid1
, sid2
) == 0);
1423 talloc_free(tmp_ctx
);
1427 (*matched
) = (ldb_dn_compare(dn1
, dn2
) == 0);
1429 talloc_free(tmp_ctx
);
1434 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1436 static int samba_syntax_operator_dn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1437 const struct ldb_schema_attribute
*a
,
1438 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1440 if (operation
== LDB_OP_PRESENT
&& dsdb_dn_is_deleted_val(v1
)) {
1441 /* If the DN is deleted, then we can't search for it */
1443 /* should this be for equality too? */
1448 if (operation
== LDB_OP_EQUALITY
&&
1449 samba_dn_extended_match(ldb
, v1
, v2
, matched
) == LDB_SUCCESS
) {
1453 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1457 static const struct ldb_schema_syntax samba_syntaxes
[] = {
1459 .name
= LDB_SYNTAX_SAMBA_SID
,
1460 .ldif_read_fn
= ldif_read_objectSid
,
1461 .ldif_write_fn
= ldif_write_objectSid
,
1462 .canonicalise_fn
= ldif_canonicalise_objectSid
,
1463 .comparison_fn
= ldif_comparison_objectSid
,
1464 .operator_fn
= samba_syntax_operator_fn
1466 .name
= LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
,
1467 .ldif_read_fn
= ldif_read_ntSecurityDescriptor
,
1468 .ldif_write_fn
= ldif_write_ntSecurityDescriptor
,
1469 .canonicalise_fn
= ldb_handler_copy
,
1470 .comparison_fn
= samba_ldb_comparison_binary
,
1471 .operator_fn
= samba_syntax_binary_operator_fn
1473 .name
= LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
,
1474 .ldif_read_fn
= ldb_handler_copy
,
1475 .ldif_write_fn
= ldif_write_sddlSecurityDescriptor
,
1476 .canonicalise_fn
= ldb_handler_fold
,
1477 .comparison_fn
= ldb_comparison_fold
,
1478 .operator_fn
= samba_syntax_operator_fn
1480 .name
= LDB_SYNTAX_SAMBA_GUID
,
1481 .ldif_read_fn
= ldif_read_objectGUID
,
1482 .ldif_write_fn
= ldif_write_objectGUID
,
1483 .canonicalise_fn
= ldif_canonicalise_objectGUID
,
1484 .comparison_fn
= ldif_comparison_objectGUID
,
1485 .operator_fn
= samba_syntax_operator_fn
1487 .name
= LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
,
1488 .ldif_read_fn
= ldb_handler_copy
,
1489 .ldif_write_fn
= ldb_handler_copy
,
1490 .canonicalise_fn
= ldif_canonicalise_objectCategory
,
1491 .comparison_fn
= ldif_comparison_objectCategory
,
1492 .operator_fn
= samba_syntax_operator_fn
1494 .name
= LDB_SYNTAX_SAMBA_SCHEMAINFO
,
1495 .ldif_read_fn
= ldb_handler_copy
,
1496 .ldif_write_fn
= ldif_write_schemaInfo
,
1497 .canonicalise_fn
= ldb_handler_copy
,
1498 .comparison_fn
= samba_ldb_comparison_binary
,
1499 .operator_fn
= samba_syntax_binary_operator_fn
1501 .name
= LDB_SYNTAX_SAMBA_PREFIX_MAP
,
1502 .ldif_read_fn
= ldif_read_prefixMap
,
1503 .ldif_write_fn
= ldif_write_prefixMap
,
1504 .canonicalise_fn
= ldif_canonicalise_prefixMap
,
1505 .comparison_fn
= ldif_comparison_prefixMap
,
1506 .operator_fn
= samba_syntax_operator_fn
1508 .name
= LDB_SYNTAX_SAMBA_INT32
,
1509 .ldif_read_fn
= ldb_handler_copy
,
1510 .ldif_write_fn
= ldb_handler_copy
,
1511 .canonicalise_fn
= ldif_canonicalise_int32
,
1512 .index_format_fn
= ldif_index_format_int32
,
1513 .comparison_fn
= ldif_comparison_int32
,
1514 .operator_fn
= samba_syntax_operator_fn
1516 .name
= LDB_SYNTAX_SAMBA_REPSFROMTO
,
1517 .ldif_read_fn
= ldb_handler_copy
,
1518 .ldif_write_fn
= ldif_write_repsFromTo
,
1519 .canonicalise_fn
= ldb_handler_copy
,
1520 .comparison_fn
= samba_ldb_comparison_binary
,
1521 .operator_fn
= samba_syntax_binary_operator_fn
1523 .name
= LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
,
1524 .ldif_read_fn
= ldb_handler_copy
,
1525 .ldif_write_fn
= ldif_write_replPropertyMetaData
,
1526 .canonicalise_fn
= ldb_handler_copy
,
1527 .comparison_fn
= samba_ldb_comparison_binary
,
1528 .operator_fn
= samba_syntax_binary_operator_fn
1530 .name
= LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
,
1531 .ldif_read_fn
= ldb_handler_copy
,
1532 .ldif_write_fn
= ldif_write_replUpToDateVector
,
1533 .canonicalise_fn
= ldb_handler_copy
,
1534 .comparison_fn
= samba_ldb_comparison_binary
,
1535 .operator_fn
= samba_syntax_binary_operator_fn
1537 .name
= LDB_SYNTAX_SAMBA_REVEALEDUSERS
,
1538 .ldif_read_fn
= ldb_handler_copy
,
1539 .ldif_write_fn
= ldif_write_msDS_RevealedUsers
,
1540 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1541 .comparison_fn
= dsdb_dn_binary_comparison
,
1542 .operator_fn
= samba_syntax_operator_fn
1544 .name
= LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
,
1545 .ldif_read_fn
= ldb_handler_copy
,
1546 .ldif_write_fn
= ldif_write_trustAuthInOutBlob
,
1547 .canonicalise_fn
= ldb_handler_copy
,
1548 .comparison_fn
= samba_ldb_comparison_binary
,
1549 .operator_fn
= samba_syntax_binary_operator_fn
1551 .name
= LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
,
1552 .ldif_read_fn
= ldb_handler_copy
,
1553 .ldif_write_fn
= ldif_write_ForestTrustInfo
,
1554 .canonicalise_fn
= ldb_handler_copy
,
1555 .comparison_fn
= samba_ldb_comparison_binary
,
1556 .operator_fn
= samba_syntax_binary_operator_fn
1558 .name
= DSDB_SYNTAX_BINARY_DN
,
1559 .ldif_read_fn
= ldb_handler_copy
,
1560 .ldif_write_fn
= ldb_handler_copy
,
1561 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1562 .comparison_fn
= dsdb_dn_binary_comparison
,
1563 .operator_fn
= samba_syntax_operator_fn
1565 .name
= DSDB_SYNTAX_STRING_DN
,
1566 .ldif_read_fn
= ldb_handler_copy
,
1567 .ldif_write_fn
= ldb_handler_copy
,
1568 .canonicalise_fn
= dsdb_dn_string_canonicalise
,
1569 .comparison_fn
= dsdb_dn_string_comparison
,
1570 .operator_fn
= samba_syntax_operator_fn
1572 .name
= LDB_SYNTAX_DN
,
1573 .ldif_read_fn
= ldb_handler_copy
,
1574 .ldif_write_fn
= ldb_handler_copy
,
1575 .canonicalise_fn
= samba_ldb_dn_link_canonicalise
,
1576 .comparison_fn
= samba_ldb_dn_link_comparison
,
1577 .operator_fn
= samba_syntax_operator_dn
1579 .name
= LDB_SYNTAX_SAMBA_RANGE64
,
1580 .ldif_read_fn
= ldif_read_range64
,
1581 .ldif_write_fn
= ldif_write_range64
,
1582 .canonicalise_fn
= ldif_canonicalise_int64
,
1583 .comparison_fn
= ldif_comparison_int64
,
1584 .operator_fn
= samba_syntax_operator_fn
1586 .name
= LDB_SYNTAX_SAMBA_DNSRECORD
,
1587 .ldif_read_fn
= ldb_handler_copy
,
1588 .ldif_write_fn
= ldif_write_dnsRecord
,
1589 .canonicalise_fn
= ldb_handler_copy
,
1590 .comparison_fn
= samba_ldb_comparison_binary
,
1591 .operator_fn
= samba_syntax_binary_operator_fn
1593 .name
= LDB_SYNTAX_SAMBA_DNSPROPERTY
,
1594 .ldif_read_fn
= ldb_handler_copy
,
1595 .ldif_write_fn
= ldif_write_dnsProperty
,
1596 .canonicalise_fn
= ldb_handler_copy
,
1597 .comparison_fn
= samba_ldb_comparison_binary
,
1598 .operator_fn
= samba_syntax_binary_operator_fn
1600 .name
= LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
,
1601 .ldif_read_fn
= ldb_handler_copy
,
1602 .ldif_write_fn
= ldif_write_supplementalCredentialsBlob
,
1603 .canonicalise_fn
= ldb_handler_copy
,
1604 .comparison_fn
= samba_ldb_comparison_binary
,
1605 .operator_fn
= samba_syntax_binary_operator_fn
1607 .name
= LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
,
1608 .ldif_read_fn
= ldb_handler_copy
,
1609 .ldif_write_fn
= ldif_write_partialAttributeSet
,
1610 .canonicalise_fn
= ldb_handler_copy
,
1611 .comparison_fn
= samba_ldb_comparison_binary
,
1612 .operator_fn
= samba_syntax_binary_operator_fn
1614 .name
= LDB_SYNTAX_SAMBA_OCTET_STRING
,
1615 .ldif_read_fn
= ldb_handler_copy
,
1616 .ldif_write_fn
= ldb_handler_copy
,
1617 .canonicalise_fn
= ldb_handler_copy
,
1618 .comparison_fn
= samba_ldb_comparison_binary
,
1619 .operator_fn
= samba_syntax_binary_operator_fn
1623 static const struct ldb_dn_extended_syntax samba_dn_syntax
[] = {
1626 .read_fn
= extended_dn_read_SID
,
1627 .write_clear_fn
= ldif_write_objectSid
,
1628 .write_hex_fn
= extended_dn_write_hex
1631 .read_fn
= extended_dn_read_GUID
,
1632 .write_clear_fn
= ldif_write_objectGUID
,
1633 .write_hex_fn
= extended_dn_write_hex
1636 .read_fn
= ldb_handler_copy
,
1637 .write_clear_fn
= ldb_handler_copy
,
1638 .write_hex_fn
= ldb_handler_copy
1640 .name
= "RMD_INVOCID",
1641 .read_fn
= extended_dn_read_GUID
,
1642 .write_clear_fn
= ldif_write_objectGUID
,
1643 .write_hex_fn
= extended_dn_write_hex
1645 .name
= "RMD_FLAGS",
1646 .read_fn
= ldb_handler_copy
,
1647 .write_clear_fn
= ldb_handler_copy
,
1648 .write_hex_fn
= ldb_handler_copy
1650 .name
= "RMD_ADDTIME",
1651 .read_fn
= ldb_handler_copy
,
1652 .write_clear_fn
= ldb_handler_copy
,
1653 .write_hex_fn
= ldb_handler_copy
1655 .name
= "RMD_CHANGETIME",
1656 .read_fn
= ldb_handler_copy
,
1657 .write_clear_fn
= ldb_handler_copy
,
1658 .write_hex_fn
= ldb_handler_copy
1660 .name
= "RMD_LOCAL_USN",
1661 .read_fn
= ldb_handler_copy
,
1662 .write_clear_fn
= ldb_handler_copy
,
1663 .write_hex_fn
= ldb_handler_copy
1665 .name
= "RMD_ORIGINATING_USN",
1666 .read_fn
= ldb_handler_copy
,
1667 .write_clear_fn
= ldb_handler_copy
,
1668 .write_hex_fn
= ldb_handler_copy
1670 .name
= "RMD_VERSION",
1671 .read_fn
= ldb_handler_copy
,
1672 .write_clear_fn
= ldb_handler_copy
,
1673 .write_hex_fn
= ldb_handler_copy
1677 /* TODO: Should be dynamic at some point */
1678 static const struct {
1681 } samba_attributes
[] = {
1682 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
},
1683 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32
},
1684 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
},
1685 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO
},
1686 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP
},
1687 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1688 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1689 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
},
1690 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
},
1691 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS
},
1692 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1693 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1694 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
},
1695 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1696 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1697 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64
},
1698 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
},
1701 * these are extracted by searching
1702 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1704 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1705 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1706 * hat can be used to identify the set of policies when applied to a resource.
1707 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1708 * server, we ignore it here.
1710 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID
},
1711 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID
},
1712 { "objectSid", LDB_SYNTAX_SAMBA_SID
},
1713 { "tokenGroups", LDB_SYNTAX_SAMBA_SID
},
1714 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID
},
1715 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID
},
1716 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID
},
1717 { "sIDHistory", LDB_SYNTAX_SAMBA_SID
},
1718 { "syncWithSID", LDB_SYNTAX_SAMBA_SID
},
1721 * these are extracted by searching
1722 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1724 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID
},
1725 { "categoryId", LDB_SYNTAX_SAMBA_GUID
},
1726 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID
},
1727 { "currMachineId", LDB_SYNTAX_SAMBA_GUID
},
1728 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID
},
1729 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID
},
1730 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID
},
1731 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID
},
1732 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID
},
1733 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID
},
1734 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID
},
1735 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID
},
1736 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID
},
1737 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID
},
1738 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID
},
1739 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID
},
1740 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID
},
1741 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID
},
1742 { "objectGUID", LDB_SYNTAX_SAMBA_GUID
},
1743 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID
},
1744 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID
},
1745 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID
},
1746 { "siteGUID", LDB_SYNTAX_SAMBA_GUID
},
1747 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1748 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1749 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1750 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID
},
1751 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID
},
1754 * these are known to be GUIDs
1756 { "invocationId", LDB_SYNTAX_SAMBA_GUID
},
1757 { "parentGUID", LDB_SYNTAX_SAMBA_GUID
},
1759 /* These NDR encoded things we want to be able to read with --show-binary */
1760 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD
},
1761 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY
},
1762 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
},
1763 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
}
1766 const struct ldb_schema_syntax
*ldb_samba_syntax_by_name(struct ldb_context
*ldb
, const char *name
)
1769 const struct ldb_schema_syntax
*s
= NULL
;
1771 for (j
=0; j
< ARRAY_SIZE(samba_syntaxes
); j
++) {
1772 if (strcmp(name
, samba_syntaxes
[j
].name
) == 0) {
1773 s
= &samba_syntaxes
[j
];
1780 const struct ldb_schema_syntax
*ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context
*ldb
, const char *name
)
1783 const struct ldb_schema_syntax
*s
= NULL
;
1785 for (j
=0; j
< ARRAY_SIZE(samba_attributes
); j
++) {
1786 if (strcmp(samba_attributes
[j
].name
, name
) == 0) {
1787 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[j
].syntax
);
1795 static const char *secret_attributes
[] = {DSDB_SECRET_ATTRIBUTES
, "secret",
1796 "priorSecret", NULL
};
1799 register the samba ldif handlers
1801 int ldb_register_samba_handlers(struct ldb_context
*ldb
)
1806 if (ldb_get_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED") != NULL
) {
1810 ret
= ldb_set_opaque(ldb
, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE
, discard_const_p(char *, secret_attributes
));
1811 if (ret
!= LDB_SUCCESS
) {
1815 for (i
=0; i
< ARRAY_SIZE(samba_attributes
); i
++) {
1816 const struct ldb_schema_syntax
*s
= NULL
;
1818 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1821 s
= ldb_standard_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1825 return LDB_ERR_OPERATIONS_ERROR
;
1828 ret
= ldb_schema_attribute_add_with_syntax(ldb
, samba_attributes
[i
].name
, LDB_ATTR_FLAG_FIXED
, s
);
1829 if (ret
!= LDB_SUCCESS
) {
1834 for (i
=0; i
< ARRAY_SIZE(samba_dn_syntax
); i
++) {
1835 ret
= ldb_dn_extended_add_syntax(ldb
, LDB_ATTR_FLAG_FIXED
, &samba_dn_syntax
[i
]);
1836 if (ret
!= LDB_SUCCESS
) {
1842 ret
= ldb_register_samba_matching_rules(ldb
);
1843 if (ret
!= LDB_SUCCESS
) {
1848 ret
= ldb_set_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1849 if (ret
!= LDB_SUCCESS
) {