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 static int ldif_comparison_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
155 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
157 if (ldif_comparision_objectSid_isString(v1
) && ldif_comparision_objectSid_isString(v2
)) {
158 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
159 } else if (ldif_comparision_objectSid_isString(v1
)
160 && !ldif_comparision_objectSid_isString(v2
)) {
163 if (ldif_read_objectSid(ldb
, mem_ctx
, v1
, &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
, &v
, v2
);
170 } else if (!ldif_comparision_objectSid_isString(v1
)
171 && ldif_comparision_objectSid_isString(v2
)) {
174 if (ldif_read_objectSid(ldb
, mem_ctx
, v2
, &v
) != 0) {
175 /* Perhaps not a string after all */
176 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
178 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
182 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
186 canonicalise a objectSid
188 static int ldif_canonicalise_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
189 const struct ldb_val
*in
, struct ldb_val
*out
)
191 if (ldif_comparision_objectSid_isString(in
)) {
192 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) != 0) {
193 /* Perhaps not a string after all */
194 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
198 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
201 static int extended_dn_read_SID(struct ldb_context
*ldb
, void *mem_ctx
,
202 const struct ldb_val
*in
, struct ldb_val
*out
)
205 enum ndr_err_code ndr_err
;
206 if (ldif_comparision_objectSid_isString(in
)) {
207 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) == 0) {
212 /* Perhaps not a string after all */
213 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
219 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
220 (const char *)in
->data
, in
->length
);
222 /* Check it looks like a SID */
223 ndr_err
= ndr_pull_struct_blob_all_noalloc(out
, &sid
,
224 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
225 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
232 convert a ldif formatted objectGUID to a NDR formatted blob
234 static int ldif_read_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
235 const struct ldb_val
*in
, struct ldb_val
*out
)
240 status
= GUID_from_data_blob(in
, &guid
);
241 if (!NT_STATUS_IS_OK(status
)) {
245 status
= GUID_to_ndr_blob(&guid
, mem_ctx
, out
);
246 if (!NT_STATUS_IS_OK(status
)) {
253 convert a NDR formatted blob to a ldif formatted objectGUID
255 static int ldif_write_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
256 const struct ldb_val
*in
, struct ldb_val
*out
)
261 status
= GUID_from_ndr_blob(in
, &guid
);
262 if (!NT_STATUS_IS_OK(status
)) {
265 out
->data
= (uint8_t *)GUID_string(mem_ctx
, &guid
);
266 if (out
->data
== NULL
) {
269 out
->length
= strlen((const char *)out
->data
);
273 static bool ldif_comparision_objectGUID_isString(const struct ldb_val
*v
)
275 if (v
->length
!= 36 && v
->length
!= 38) return false;
277 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
281 static int extended_dn_read_GUID(struct ldb_context
*ldb
, void *mem_ctx
,
282 const struct ldb_val
*in
, struct ldb_val
*out
)
285 if (in
->length
== 36 && ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) == 0) {
289 /* Try as 'hex' form */
290 if (in
->length
!= 32) {
294 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
300 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
301 (const char *)in
->data
, in
->length
);
303 /* Check it looks like a GUID */
304 if ((*out
).length
!= 16) {
313 compare two objectGUIDs
315 static int ldif_comparison_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
316 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
318 if (ldif_comparision_objectGUID_isString(v1
) && ldif_comparision_objectGUID_isString(v2
)) {
319 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
320 } else if (ldif_comparision_objectGUID_isString(v1
)
321 && !ldif_comparision_objectGUID_isString(v2
)) {
324 if (ldif_read_objectGUID(ldb
, mem_ctx
, v1
, &v
) != 0) {
325 /* Perhaps it wasn't a valid string after all */
326 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
328 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
331 } else if (!ldif_comparision_objectGUID_isString(v1
)
332 && ldif_comparision_objectGUID_isString(v2
)) {
335 if (ldif_read_objectGUID(ldb
, mem_ctx
, v2
, &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
, v1
, &v
);
343 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
347 canonicalise a objectGUID
349 static int ldif_canonicalise_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
350 const struct ldb_val
*in
, struct ldb_val
*out
)
352 if (ldif_comparision_objectGUID_isString(in
)) {
353 if (ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) != 0) {
354 /* Perhaps it wasn't a valid string after all */
355 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
359 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
364 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
366 static int ldif_read_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
367 const struct ldb_val
*in
, struct ldb_val
*out
)
369 struct security_descriptor
*sd
;
370 enum ndr_err_code ndr_err
;
372 sd
= talloc(mem_ctx
, struct security_descriptor
);
377 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
378 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
379 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
380 /* If this does not parse, then it is probably SDDL, and we should try it that way */
382 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
384 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
390 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, sd
,
391 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
393 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
401 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
403 static int ldif_write_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
404 const struct ldb_val
*in
, struct ldb_val
*out
)
406 struct security_descriptor
*sd
;
407 enum ndr_err_code ndr_err
;
409 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
410 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
411 sizeof(struct security_descriptor
),
412 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
,
413 (ndr_print_fn_t
)ndr_print_security_descriptor
,
418 sd
= talloc(mem_ctx
, struct security_descriptor
);
422 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
423 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
424 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
425 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
429 out
->data
= (uint8_t *)sddl_encode(mem_ctx
, sd
, samdb_domain_sid_cache_only(ldb
));
431 if (out
->data
== NULL
) {
434 out
->length
= strlen((const char *)out
->data
);
439 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
441 static int ldif_write_sddlSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
442 const struct ldb_val
*in
, struct ldb_val
*out
)
444 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
445 struct security_descriptor
*sd
;
446 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
448 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
449 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
,
450 (ndr_print_fn_t
)ndr_print_security_descriptor
,
452 out
->length
= strlen((const char *)out
->data
);
457 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
461 canonicalise an objectCategory. We use the long form as the canonical form:
462 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
464 Also any short name of an objectClass that points to a different
465 class (such as user) has the canonical form of the class it's
466 defaultObjectCategory points to (eg
467 cn=Person,cn=Schema,cn=Configuration,<basedn>)
470 static int ldif_canonicalise_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
471 const struct ldb_val
*in
, struct ldb_val
*out
)
473 struct ldb_dn
*dn1
= NULL
;
474 const struct dsdb_schema
*schema
= dsdb_get_schema(ldb
, NULL
);
475 const struct dsdb_class
*sclass
;
476 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
478 return LDB_ERR_OPERATIONS_ERROR
;
482 talloc_free(tmp_ctx
);
483 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
484 if (in
->data
&& !out
->data
) {
485 return LDB_ERR_OPERATIONS_ERROR
;
489 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, in
);
490 if ( ! ldb_dn_validate(dn1
)) {
491 const char *lDAPDisplayName
= talloc_strndup(tmp_ctx
, (char *)in
->data
, in
->length
);
492 sclass
= dsdb_class_by_lDAPDisplayName(schema
, lDAPDisplayName
);
494 struct ldb_dn
*dn
= ldb_dn_new(tmp_ctx
, ldb
,
495 sclass
->defaultObjectCategory
);
497 talloc_free(tmp_ctx
);
498 return LDB_ERR_OPERATIONS_ERROR
;
501 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn
));
502 talloc_free(tmp_ctx
);
505 return LDB_ERR_OPERATIONS_ERROR
;
509 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
510 talloc_free(tmp_ctx
);
512 if (in
->data
&& !out
->data
) {
513 return LDB_ERR_OPERATIONS_ERROR
;
518 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn1
));
519 talloc_free(tmp_ctx
);
522 return LDB_ERR_OPERATIONS_ERROR
;
527 static int ldif_comparison_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
528 const struct ldb_val
*v1
,
529 const struct ldb_val
*v2
)
531 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_objectCategory
,
536 convert a NDR formatted blob to a ldif formatted schemaInfo
538 static int ldif_write_schemaInfo(struct ldb_context
*ldb
, void *mem_ctx
,
539 const struct ldb_val
*in
, struct ldb_val
*out
)
541 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
542 sizeof(struct repsFromToBlob
),
543 (ndr_pull_flags_fn_t
)ndr_pull_schemaInfoBlob
,
544 (ndr_print_fn_t
)ndr_print_schemaInfoBlob
,
549 convert a ldif formatted prefixMap to a NDR formatted blob
551 static int ldif_read_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
552 const struct ldb_val
*in
, struct ldb_val
*out
)
554 struct prefixMapBlob
*blob
;
555 enum ndr_err_code ndr_err
;
556 char *string
, *line
, *p
, *oid
;
559 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
561 if (tmp_ctx
== NULL
) {
565 blob
= talloc_zero(tmp_ctx
, struct prefixMapBlob
);
567 talloc_free(tmp_ctx
);
571 /* use the switch value to detect if this is in the binary
574 if (in
->length
>= 4 && IVAL(in
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
575 ndr_err
= ndr_pull_struct_blob(in
, tmp_ctx
, blob
,
576 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
577 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
578 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
580 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
581 talloc_free(tmp_ctx
);
582 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
589 /* If this does not parse, then it is probably the text version, and we should try it that way */
590 blob
->version
= PREFIX_MAP_VERSION_DSDB
;
592 string
= talloc_strndup(mem_ctx
, (const char *)in
->data
, in
->length
);
593 if (string
== NULL
) {
599 while (line
&& line
[0]) {
606 p
=strchr(line
, '\n');
611 /* allow a trailing separator */
616 blob
->ctr
.dsdb
.mappings
= talloc_realloc(blob
,
617 blob
->ctr
.dsdb
.mappings
,
618 struct drsuapi_DsReplicaOIDMapping
,
619 blob
->ctr
.dsdb
.num_mappings
+1);
620 if (!blob
->ctr
.dsdb
.mappings
) {
621 talloc_free(tmp_ctx
);
625 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].id_prefix
=
626 smb_strtoul(line
, &oid
, 10, &error
, SMB_STR_STANDARD
);
628 if (oid
[0] != ':' || error
!= 0) {
629 talloc_free(tmp_ctx
);
633 /* we know there must be at least ":" */
636 if (!ber_write_partial_OID_String(blob
->ctr
.dsdb
.mappings
, &oid_blob
, oid
)) {
637 talloc_free(tmp_ctx
);
640 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.length
= oid_blob
.length
;
641 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.binary_oid
= oid_blob
.data
;
643 blob
->ctr
.dsdb
.num_mappings
++;
645 /* Now look past the terminator we added above */
653 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
655 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
656 talloc_free(tmp_ctx
);
657 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
664 convert a NDR formatted blob to a ldif formatted prefixMap
666 static int ldif_write_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
667 const struct ldb_val
*in
, struct ldb_val
*out
)
669 struct prefixMapBlob
*blob
;
670 enum ndr_err_code ndr_err
;
674 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
676 /* try to decode the blob as S4 prefixMap */
677 err
= ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
678 sizeof(struct prefixMapBlob
),
679 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
,
680 (ndr_print_fn_t
)ndr_print_prefixMapBlob
,
685 /* try parsing it as Windows PrefixMap value */
686 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
687 sizeof(struct drsuapi_MSPrefixMap_Ctr
),
688 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_MSPrefixMap_Ctr
,
689 (ndr_print_fn_t
)ndr_print_drsuapi_MSPrefixMap_Ctr
,
693 blob
= talloc(mem_ctx
, struct prefixMapBlob
);
697 ndr_err
= ndr_pull_struct_blob_all(in
, blob
,
699 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
700 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
703 if (blob
->version
!= PREFIX_MAP_VERSION_DSDB
) {
706 string
= talloc_strdup(mem_ctx
, "");
707 if (string
== NULL
) {
711 for (i
=0; i
< blob
->ctr
.dsdb
.num_mappings
; i
++) {
713 char *partial_oid
= NULL
;
716 string
= talloc_asprintf_append(string
, ";");
719 oid_blob
= data_blob_const(blob
->ctr
.dsdb
.mappings
[i
].oid
.binary_oid
,
720 blob
->ctr
.dsdb
.mappings
[i
].oid
.length
);
721 if (!ber_read_partial_OID_String(blob
, oid_blob
, &partial_oid
)) {
722 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
723 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
));
726 string
= talloc_asprintf_append(string
, "%u:%s",
727 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
,
729 talloc_free(discard_const(partial_oid
));
730 if (string
== NULL
) {
736 *out
= data_blob_string_const(string
);
744 static bool ldif_comparision_prefixMap_isString(const struct ldb_val
*v
)
750 if (IVAL(v
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
758 canonicalise a prefixMap
760 static int ldif_canonicalise_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
761 const struct ldb_val
*in
, struct ldb_val
*out
)
763 if (ldif_comparision_prefixMap_isString(in
)) {
764 return ldif_read_prefixMap(ldb
, mem_ctx
, in
, out
);
766 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
769 static int ldif_comparison_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
770 const struct ldb_val
*v1
,
771 const struct ldb_val
*v2
)
773 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_prefixMap
,
777 /* length limited conversion of a ldb_val to a int32_t */
778 static int val_to_int32(const struct ldb_val
*in
, int32_t *v
)
783 /* make sure we don't read past the end of the data */
784 if (in
->length
> sizeof(buf
)-1) {
785 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
787 strncpy(buf
, (char *)in
->data
, in
->length
);
790 /* We've to use "strtoll" here to have the intended overflows.
791 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
792 *v
= (int32_t) strtoll(buf
, &end
, 0);
794 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
799 /* length limited conversion of a ldb_val to a int64_t */
800 static int val_to_int64(const struct ldb_val
*in
, int64_t *v
)
805 /* make sure we don't read past the end of the data */
806 if (in
->length
> sizeof(buf
)-1) {
807 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
809 strncpy(buf
, (char *)in
->data
, in
->length
);
812 *v
= (int64_t) strtoll(buf
, &end
, 0);
814 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
819 /* Canonicalisation of two 32-bit integers */
820 static int ldif_canonicalise_int32(struct ldb_context
*ldb
, void *mem_ctx
,
821 const struct ldb_val
*in
, struct ldb_val
*out
)
826 ret
= val_to_int32(in
, &i
);
827 if (ret
!= LDB_SUCCESS
) {
830 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%d", i
);
831 if (out
->data
== NULL
) {
833 return LDB_ERR_OPERATIONS_ERROR
;
835 out
->length
= strlen((char *)out
->data
);
840 * Lexicographically sorted representation for a 32-bit integer
842 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
845 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
846 * corresponding documentation for 64-bit integers.
848 * The same rules apply but use INT32_MIN and INT32_MAX.
850 * String representation padding is done to 10 characters.
852 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
855 static int ldif_index_format_int32(struct ldb_context
*ldb
,
857 const struct ldb_val
*in
,
865 ret
= val_to_int32(in
, &i
);
866 if (ret
!= LDB_SUCCESS
) {
872 * i is negative, so this is subtraction rather than
876 i
= INT32_MAX
+ i
+ 1;
883 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%c%010ld", prefix
, (long)i
);
884 if (out
->data
== NULL
) {
886 return LDB_ERR_OPERATIONS_ERROR
;
889 len
= talloc_array_length(out
->data
) - 1;
891 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
892 __location__
": expected index format str %s to"
893 " have length 11 but got %zu",
894 (char*)out
->data
, len
);
895 return LDB_ERR_OPERATIONS_ERROR
;
902 /* Comparison of two 32-bit integers */
903 static int ldif_comparison_int32(struct ldb_context
*ldb
, void *mem_ctx
,
904 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
907 val_to_int32(v1
, &i1
);
908 val_to_int32(v2
, &i2
);
909 if (i1
== i2
) return 0;
910 return i1
> i2
? 1 : -1;
913 /* Canonicalisation of two 64-bit integers */
914 static int ldif_canonicalise_int64(struct ldb_context
*ldb
, void *mem_ctx
,
915 const struct ldb_val
*in
, struct ldb_val
*out
)
920 ret
= val_to_int64(in
, &i
);
921 if (ret
!= LDB_SUCCESS
) {
924 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%lld", (long long)i
);
925 if (out
->data
== NULL
) {
927 return LDB_ERR_OPERATIONS_ERROR
;
929 out
->length
= strlen((char *)out
->data
);
933 /* Comparison of two 64-bit integers */
934 static int ldif_comparison_int64(struct ldb_context
*ldb
, void *mem_ctx
,
935 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
938 val_to_int64(v1
, &i1
);
939 val_to_int64(v2
, &i2
);
940 if (i1
== i2
) return 0;
941 return i1
> i2
? 1 : -1;
945 convert a NDR formatted blob to a ldif formatted repsFromTo
947 static int ldif_write_repsFromTo(struct ldb_context
*ldb
, void *mem_ctx
,
948 const struct ldb_val
*in
, struct ldb_val
*out
)
950 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
951 sizeof(struct repsFromToBlob
),
952 (ndr_pull_flags_fn_t
)ndr_pull_repsFromToBlob
,
953 (ndr_print_fn_t
)ndr_print_repsFromToBlob
,
958 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
960 static int ldif_write_replPropertyMetaData(struct ldb_context
*ldb
, void *mem_ctx
,
961 const struct ldb_val
*in
, struct ldb_val
*out
)
963 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
964 sizeof(struct replPropertyMetaDataBlob
),
965 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaDataBlob
,
966 (ndr_print_fn_t
)ndr_print_replPropertyMetaDataBlob
,
971 convert a NDR formatted blob to a ldif formatted replUpToDateVector
973 static int ldif_write_replUpToDateVector(struct ldb_context
*ldb
, void *mem_ctx
,
974 const struct ldb_val
*in
, struct ldb_val
*out
)
976 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
977 sizeof(struct replUpToDateVectorBlob
),
978 (ndr_pull_flags_fn_t
)ndr_pull_replUpToDateVectorBlob
,
979 (ndr_print_fn_t
)ndr_print_replUpToDateVectorBlob
,
983 static int ldif_write_dn_binary_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
984 const struct ldb_val
*in
, struct ldb_val
*out
,
986 ndr_pull_flags_fn_t pull_fn
,
987 ndr_print_fn_t print_fn
,
991 enum ndr_err_code err
;
992 struct dsdb_dn
*dsdb_dn
= NULL
;
996 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
997 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1000 dsdb_dn
= dsdb_dn_parse(mem_ctx
, ldb
, in
, DSDB_SYNTAX_BINARY_DN
);
1001 if (dsdb_dn
== NULL
) {
1002 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1005 p
= talloc_size(dsdb_dn
, struct_size
);
1007 TALLOC_FREE(dsdb_dn
);
1008 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1011 err
= ndr_pull_struct_blob(&dsdb_dn
->extra_part
, p
, p
, pull_fn
);
1012 if (err
!= NDR_ERR_SUCCESS
) {
1013 /* fail in not in mask_error mode */
1017 TALLOC_FREE(dsdb_dn
);
1018 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1021 dn_str
= ldb_dn_get_extended_linearized(dsdb_dn
, dsdb_dn
->dn
, 1);
1022 if (dn_str
== NULL
) {
1023 TALLOC_FREE(dsdb_dn
);
1024 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1027 str
= ndr_print_struct_string(mem_ctx
, print_fn
, dn_str
, p
);
1028 TALLOC_FREE(dsdb_dn
);
1030 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1033 *out
= data_blob_string_const(str
);
1037 static int ldif_write_msDS_RevealedUsers(struct ldb_context
*ldb
, void *mem_ctx
,
1038 const struct ldb_val
*in
, struct ldb_val
*out
)
1040 return ldif_write_dn_binary_NDR(ldb
, mem_ctx
, in
, out
,
1041 sizeof(struct replPropertyMetaData1
),
1042 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaData1
,
1043 (ndr_print_fn_t
)ndr_print_replPropertyMetaData1
,
1048 convert a NDR formatted blob to a ldif formatted dnsRecord
1050 static int ldif_write_dnsRecord(struct ldb_context
*ldb
, void *mem_ctx
,
1051 const struct ldb_val
*in
, struct ldb_val
*out
)
1053 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1054 sizeof(struct dnsp_DnssrvRpcRecord
),
1055 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
,
1056 (ndr_print_fn_t
)ndr_print_dnsp_DnssrvRpcRecord
,
1061 convert a NDR formatted blob to a ldif formatted dnsProperty
1063 static int ldif_write_dnsProperty(struct ldb_context
*ldb
, void *mem_ctx
,
1064 const struct ldb_val
*in
, struct ldb_val
*out
)
1066 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1067 sizeof(struct dnsp_DnsProperty
),
1068 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnsProperty
,
1069 (ndr_print_fn_t
)ndr_print_dnsp_DnsProperty
,
1074 convert a NDR formatted blob of a supplementalCredentials into text
1076 static int ldif_write_supplementalCredentialsBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1077 const struct ldb_val
*in
, struct ldb_val
*out
)
1079 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1080 sizeof(struct supplementalCredentialsBlob
),
1081 (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
,
1082 (ndr_print_fn_t
)ndr_print_supplementalCredentialsBlob
,
1087 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1089 static int ldif_write_trustAuthInOutBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1090 const struct ldb_val
*in
, struct ldb_val
*out
)
1092 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1093 sizeof(struct trustAuthInOutBlob
),
1094 (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
,
1095 (ndr_print_fn_t
)ndr_print_trustAuthInOutBlob
,
1100 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1102 static int ldif_write_ForestTrustInfo(struct ldb_context
*ldb
, void *mem_ctx
,
1103 const struct ldb_val
*in
, struct ldb_val
*out
)
1105 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1106 sizeof(struct ForestTrustInfo
),
1107 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
,
1108 (ndr_print_fn_t
)ndr_print_ForestTrustInfo
,
1112 convert a NDR formatted blob of a partialAttributeSet into text
1114 static int ldif_write_partialAttributeSet(struct ldb_context
*ldb
, void *mem_ctx
,
1115 const struct ldb_val
*in
, struct ldb_val
*out
)
1117 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1118 sizeof(struct partialAttributeSetBlob
),
1119 (ndr_pull_flags_fn_t
)ndr_pull_partialAttributeSetBlob
,
1120 (ndr_print_fn_t
)ndr_print_partialAttributeSetBlob
,
1125 static int extended_dn_write_hex(struct ldb_context
*ldb
, void *mem_ctx
,
1126 const struct ldb_val
*in
, struct ldb_val
*out
)
1128 *out
= data_blob_string_const(data_blob_hex_string_lower(mem_ctx
, in
));
1138 static int samba_ldb_dn_link_comparison(struct ldb_context
*ldb
, void *mem_ctx
,
1139 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1141 struct ldb_dn
*dn1
= NULL
, *dn2
= NULL
;
1144 if (dsdb_dn_is_deleted_val(v1
)) {
1145 /* If the DN is deleted, then we can't search for it */
1149 if (dsdb_dn_is_deleted_val(v2
)) {
1150 /* If the DN is deleted, then we can't search for it */
1154 dn1
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v1
);
1155 if ( ! ldb_dn_validate(dn1
)) return -1;
1157 dn2
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v2
);
1158 if ( ! ldb_dn_validate(dn2
)) {
1163 ret
= ldb_dn_compare(dn1
, dn2
);
1170 static int samba_ldb_dn_link_canonicalise(struct ldb_context
*ldb
, void *mem_ctx
,
1171 const struct ldb_val
*in
, struct ldb_val
*out
)
1179 dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, in
);
1180 if ( ! ldb_dn_validate(dn
)) {
1181 return LDB_ERR_INVALID_DN_SYNTAX
;
1184 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1185 * does not casually match a not deleted DN */
1186 if (dsdb_dn_is_deleted_val(in
)) {
1187 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
,
1189 dsdb_dn_val_rmd_flags(in
),
1190 ldb_dn_get_casefold(dn
));
1192 out
->data
= (uint8_t *)ldb_dn_alloc_casefold(mem_ctx
, dn
);
1195 if (out
->data
== NULL
) {
1198 out
->length
= strlen((char *)out
->data
);
1210 write a 64 bit 2-part range
1212 static int ldif_write_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1213 const struct ldb_val
*in
, struct ldb_val
*out
)
1217 ret
= val_to_int64(in
, &v
);
1218 if (ret
!= LDB_SUCCESS
) {
1221 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%lu-%lu",
1222 (unsigned long)(v
&0xFFFFFFFF),
1223 (unsigned long)(v
>>32));
1224 if (out
->data
== NULL
) {
1226 return LDB_ERR_OPERATIONS_ERROR
;
1228 out
->length
= strlen((char *)out
->data
);
1233 read a 64 bit 2-part range
1235 static int ldif_read_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1236 const struct ldb_val
*in
, struct ldb_val
*out
)
1238 unsigned long high
, low
;
1241 if (memchr(in
->data
, '-', in
->length
) == NULL
) {
1242 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1245 if (in
->length
> sizeof(buf
)-1) {
1246 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1248 strncpy(buf
, (const char *)in
->data
, in
->length
);
1249 buf
[in
->length
] = 0;
1251 if (sscanf(buf
, "%lu-%lu", &low
, &high
) != 2) {
1252 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1255 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%llu",
1256 (unsigned long long)(((uint64_t)high
)<<32) | (low
));
1258 if (out
->data
== NULL
) {
1260 return LDB_ERR_OPERATIONS_ERROR
;
1262 out
->length
= strlen((char *)out
->data
);
1267 when this operator_fn is set for a syntax, the backend calls is in
1268 preference to the comparison function. We are told the exact
1269 comparison operation that is needed, and we can return errors
1271 static int samba_syntax_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1272 const struct ldb_schema_attribute
*a
,
1273 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1275 switch (operation
) {
1279 case LDB_OP_SUBSTRING
:
1281 case LDB_OP_EXTENDED
:
1282 /* handled in the backends */
1283 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1285 case LDB_OP_GREATER
:
1287 case LDB_OP_EQUALITY
:
1289 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
1291 if (tmp_ctx
== NULL
) {
1292 return ldb_oom(ldb
);
1294 ret
= a
->syntax
->comparison_fn(ldb
, tmp_ctx
, v1
, v2
);
1295 talloc_free(tmp_ctx
);
1296 if (operation
== LDB_OP_GREATER
) {
1297 *matched
= (ret
>= 0);
1298 } else if (operation
== LDB_OP_LESS
) {
1299 *matched
= (ret
<= 0);
1301 *matched
= (ret
== 0);
1306 case LDB_OP_PRESENT
:
1311 /* we shouldn't get here */
1312 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1316 compare two binary objects. This is correct for sorting as the sort order is:
1323 rather than ldb_comparison_binary() which is:
1331 static int samba_ldb_comparison_binary(struct ldb_context
*ldb
, void *mem_ctx
,
1332 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1334 return data_blob_cmp(v1
, v2
);
1338 when this operator_fn is set for a syntax, the backend calls is in
1339 preference to the comparison function. We are told the exact
1340 comparison operation that is needed, and we can return errors.
1342 This mode optimises for ldb_comparison_binary() if we need equality,
1343 as this should be faster as it can do a length-check first.
1345 static int samba_syntax_binary_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1346 const struct ldb_schema_attribute
*a
,
1347 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1349 if (operation
== LDB_OP_EQUALITY
) {
1350 *matched
= (ldb_comparison_binary(ldb
, NULL
, v1
, v2
) == 0);
1353 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1357 see if two DNs match, comparing first by GUID, then by SID, and
1358 finally by string components
1360 static int samba_dn_extended_match(struct ldb_context
*ldb
,
1361 const struct ldb_val
*v1
,
1362 const struct ldb_val
*v2
,
1365 TALLOC_CTX
*tmp_ctx
;
1366 struct ldb_dn
*dn1
, *dn2
;
1367 const struct ldb_val
*guid1
, *guid2
, *sid1
, *sid2
;
1368 uint32_t rmd_flags1
, rmd_flags2
;
1370 tmp_ctx
= talloc_new(ldb
);
1372 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v1
);
1373 dn2
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v2
);
1375 /* couldn't parse as DN's */
1376 talloc_free(tmp_ctx
);
1381 rmd_flags1
= dsdb_dn_rmd_flags(dn1
);
1382 rmd_flags2
= dsdb_dn_rmd_flags(dn2
);
1384 if ((rmd_flags1
& DSDB_RMD_FLAG_DELETED
) !=
1385 (rmd_flags2
& DSDB_RMD_FLAG_DELETED
)) {
1386 /* only match if they have the same deletion status */
1387 talloc_free(tmp_ctx
);
1393 guid1
= ldb_dn_get_extended_component(dn1
, "GUID");
1394 guid2
= ldb_dn_get_extended_component(dn2
, "GUID");
1395 if (guid1
&& guid2
) {
1396 (*matched
) = (data_blob_cmp(guid1
, guid2
) == 0);
1397 talloc_free(tmp_ctx
);
1401 sid1
= ldb_dn_get_extended_component(dn1
, "SID");
1402 sid2
= ldb_dn_get_extended_component(dn2
, "SID");
1404 (*matched
) = (data_blob_cmp(sid1
, sid2
) == 0);
1405 talloc_free(tmp_ctx
);
1409 (*matched
) = (ldb_dn_compare(dn1
, dn2
) == 0);
1411 talloc_free(tmp_ctx
);
1416 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1418 static int samba_syntax_operator_dn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1419 const struct ldb_schema_attribute
*a
,
1420 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1422 if (operation
== LDB_OP_PRESENT
&& dsdb_dn_is_deleted_val(v1
)) {
1423 /* If the DN is deleted, then we can't search for it */
1425 /* should this be for equality too? */
1430 if (operation
== LDB_OP_EQUALITY
&&
1431 samba_dn_extended_match(ldb
, v1
, v2
, matched
) == LDB_SUCCESS
) {
1435 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1439 static const struct ldb_schema_syntax samba_syntaxes
[] = {
1441 .name
= LDB_SYNTAX_SAMBA_SID
,
1442 .ldif_read_fn
= ldif_read_objectSid
,
1443 .ldif_write_fn
= ldif_write_objectSid
,
1444 .canonicalise_fn
= ldif_canonicalise_objectSid
,
1445 .comparison_fn
= ldif_comparison_objectSid
,
1446 .operator_fn
= samba_syntax_operator_fn
1448 .name
= LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
,
1449 .ldif_read_fn
= ldif_read_ntSecurityDescriptor
,
1450 .ldif_write_fn
= ldif_write_ntSecurityDescriptor
,
1451 .canonicalise_fn
= ldb_handler_copy
,
1452 .comparison_fn
= samba_ldb_comparison_binary
,
1453 .operator_fn
= samba_syntax_binary_operator_fn
1455 .name
= LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
,
1456 .ldif_read_fn
= ldb_handler_copy
,
1457 .ldif_write_fn
= ldif_write_sddlSecurityDescriptor
,
1458 .canonicalise_fn
= ldb_handler_fold
,
1459 .comparison_fn
= ldb_comparison_fold
,
1460 .operator_fn
= samba_syntax_operator_fn
1462 .name
= LDB_SYNTAX_SAMBA_GUID
,
1463 .ldif_read_fn
= ldif_read_objectGUID
,
1464 .ldif_write_fn
= ldif_write_objectGUID
,
1465 .canonicalise_fn
= ldif_canonicalise_objectGUID
,
1466 .comparison_fn
= ldif_comparison_objectGUID
,
1467 .operator_fn
= samba_syntax_operator_fn
1469 .name
= LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
,
1470 .ldif_read_fn
= ldb_handler_copy
,
1471 .ldif_write_fn
= ldb_handler_copy
,
1472 .canonicalise_fn
= ldif_canonicalise_objectCategory
,
1473 .comparison_fn
= ldif_comparison_objectCategory
,
1474 .operator_fn
= samba_syntax_operator_fn
1476 .name
= LDB_SYNTAX_SAMBA_SCHEMAINFO
,
1477 .ldif_read_fn
= ldb_handler_copy
,
1478 .ldif_write_fn
= ldif_write_schemaInfo
,
1479 .canonicalise_fn
= ldb_handler_copy
,
1480 .comparison_fn
= samba_ldb_comparison_binary
,
1481 .operator_fn
= samba_syntax_binary_operator_fn
1483 .name
= LDB_SYNTAX_SAMBA_PREFIX_MAP
,
1484 .ldif_read_fn
= ldif_read_prefixMap
,
1485 .ldif_write_fn
= ldif_write_prefixMap
,
1486 .canonicalise_fn
= ldif_canonicalise_prefixMap
,
1487 .comparison_fn
= ldif_comparison_prefixMap
,
1488 .operator_fn
= samba_syntax_operator_fn
1490 .name
= LDB_SYNTAX_SAMBA_INT32
,
1491 .ldif_read_fn
= ldb_handler_copy
,
1492 .ldif_write_fn
= ldb_handler_copy
,
1493 .canonicalise_fn
= ldif_canonicalise_int32
,
1494 .index_format_fn
= ldif_index_format_int32
,
1495 .comparison_fn
= ldif_comparison_int32
,
1496 .operator_fn
= samba_syntax_operator_fn
1498 .name
= LDB_SYNTAX_SAMBA_REPSFROMTO
,
1499 .ldif_read_fn
= ldb_handler_copy
,
1500 .ldif_write_fn
= ldif_write_repsFromTo
,
1501 .canonicalise_fn
= ldb_handler_copy
,
1502 .comparison_fn
= samba_ldb_comparison_binary
,
1503 .operator_fn
= samba_syntax_binary_operator_fn
1505 .name
= LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
,
1506 .ldif_read_fn
= ldb_handler_copy
,
1507 .ldif_write_fn
= ldif_write_replPropertyMetaData
,
1508 .canonicalise_fn
= ldb_handler_copy
,
1509 .comparison_fn
= samba_ldb_comparison_binary
,
1510 .operator_fn
= samba_syntax_binary_operator_fn
1512 .name
= LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
,
1513 .ldif_read_fn
= ldb_handler_copy
,
1514 .ldif_write_fn
= ldif_write_replUpToDateVector
,
1515 .canonicalise_fn
= ldb_handler_copy
,
1516 .comparison_fn
= samba_ldb_comparison_binary
,
1517 .operator_fn
= samba_syntax_binary_operator_fn
1519 .name
= LDB_SYNTAX_SAMBA_REVEALEDUSERS
,
1520 .ldif_read_fn
= ldb_handler_copy
,
1521 .ldif_write_fn
= ldif_write_msDS_RevealedUsers
,
1522 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1523 .comparison_fn
= dsdb_dn_binary_comparison
,
1524 .operator_fn
= samba_syntax_operator_fn
1526 .name
= LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
,
1527 .ldif_read_fn
= ldb_handler_copy
,
1528 .ldif_write_fn
= ldif_write_trustAuthInOutBlob
,
1529 .canonicalise_fn
= ldb_handler_copy
,
1530 .comparison_fn
= samba_ldb_comparison_binary
,
1531 .operator_fn
= samba_syntax_binary_operator_fn
1533 .name
= LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
,
1534 .ldif_read_fn
= ldb_handler_copy
,
1535 .ldif_write_fn
= ldif_write_ForestTrustInfo
,
1536 .canonicalise_fn
= ldb_handler_copy
,
1537 .comparison_fn
= samba_ldb_comparison_binary
,
1538 .operator_fn
= samba_syntax_binary_operator_fn
1540 .name
= DSDB_SYNTAX_BINARY_DN
,
1541 .ldif_read_fn
= ldb_handler_copy
,
1542 .ldif_write_fn
= ldb_handler_copy
,
1543 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1544 .comparison_fn
= dsdb_dn_binary_comparison
,
1545 .operator_fn
= samba_syntax_operator_fn
1547 .name
= DSDB_SYNTAX_STRING_DN
,
1548 .ldif_read_fn
= ldb_handler_copy
,
1549 .ldif_write_fn
= ldb_handler_copy
,
1550 .canonicalise_fn
= dsdb_dn_string_canonicalise
,
1551 .comparison_fn
= dsdb_dn_string_comparison
,
1552 .operator_fn
= samba_syntax_operator_fn
1554 .name
= LDB_SYNTAX_DN
,
1555 .ldif_read_fn
= ldb_handler_copy
,
1556 .ldif_write_fn
= ldb_handler_copy
,
1557 .canonicalise_fn
= samba_ldb_dn_link_canonicalise
,
1558 .comparison_fn
= samba_ldb_dn_link_comparison
,
1559 .operator_fn
= samba_syntax_operator_dn
1561 .name
= LDB_SYNTAX_SAMBA_RANGE64
,
1562 .ldif_read_fn
= ldif_read_range64
,
1563 .ldif_write_fn
= ldif_write_range64
,
1564 .canonicalise_fn
= ldif_canonicalise_int64
,
1565 .comparison_fn
= ldif_comparison_int64
,
1566 .operator_fn
= samba_syntax_operator_fn
1568 .name
= LDB_SYNTAX_SAMBA_DNSRECORD
,
1569 .ldif_read_fn
= ldb_handler_copy
,
1570 .ldif_write_fn
= ldif_write_dnsRecord
,
1571 .canonicalise_fn
= ldb_handler_copy
,
1572 .comparison_fn
= samba_ldb_comparison_binary
,
1573 .operator_fn
= samba_syntax_binary_operator_fn
1575 .name
= LDB_SYNTAX_SAMBA_DNSPROPERTY
,
1576 .ldif_read_fn
= ldb_handler_copy
,
1577 .ldif_write_fn
= ldif_write_dnsProperty
,
1578 .canonicalise_fn
= ldb_handler_copy
,
1579 .comparison_fn
= samba_ldb_comparison_binary
,
1580 .operator_fn
= samba_syntax_binary_operator_fn
1582 .name
= LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
,
1583 .ldif_read_fn
= ldb_handler_copy
,
1584 .ldif_write_fn
= ldif_write_supplementalCredentialsBlob
,
1585 .canonicalise_fn
= ldb_handler_copy
,
1586 .comparison_fn
= samba_ldb_comparison_binary
,
1587 .operator_fn
= samba_syntax_binary_operator_fn
1589 .name
= LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
,
1590 .ldif_read_fn
= ldb_handler_copy
,
1591 .ldif_write_fn
= ldif_write_partialAttributeSet
,
1592 .canonicalise_fn
= ldb_handler_copy
,
1593 .comparison_fn
= samba_ldb_comparison_binary
,
1594 .operator_fn
= samba_syntax_binary_operator_fn
1596 .name
= LDB_SYNTAX_SAMBA_OCTET_STRING
,
1597 .ldif_read_fn
= ldb_handler_copy
,
1598 .ldif_write_fn
= ldb_handler_copy
,
1599 .canonicalise_fn
= ldb_handler_copy
,
1600 .comparison_fn
= samba_ldb_comparison_binary
,
1601 .operator_fn
= samba_syntax_binary_operator_fn
1605 static const struct ldb_dn_extended_syntax samba_dn_syntax
[] = {
1608 .read_fn
= extended_dn_read_SID
,
1609 .write_clear_fn
= ldif_write_objectSid
,
1610 .write_hex_fn
= extended_dn_write_hex
1613 .read_fn
= extended_dn_read_GUID
,
1614 .write_clear_fn
= ldif_write_objectGUID
,
1615 .write_hex_fn
= extended_dn_write_hex
1618 .read_fn
= ldb_handler_copy
,
1619 .write_clear_fn
= ldb_handler_copy
,
1620 .write_hex_fn
= ldb_handler_copy
1622 .name
= "RMD_INVOCID",
1623 .read_fn
= extended_dn_read_GUID
,
1624 .write_clear_fn
= ldif_write_objectGUID
,
1625 .write_hex_fn
= extended_dn_write_hex
1627 .name
= "RMD_FLAGS",
1628 .read_fn
= ldb_handler_copy
,
1629 .write_clear_fn
= ldb_handler_copy
,
1630 .write_hex_fn
= ldb_handler_copy
1632 .name
= "RMD_ADDTIME",
1633 .read_fn
= ldb_handler_copy
,
1634 .write_clear_fn
= ldb_handler_copy
,
1635 .write_hex_fn
= ldb_handler_copy
1637 .name
= "RMD_CHANGETIME",
1638 .read_fn
= ldb_handler_copy
,
1639 .write_clear_fn
= ldb_handler_copy
,
1640 .write_hex_fn
= ldb_handler_copy
1642 .name
= "RMD_LOCAL_USN",
1643 .read_fn
= ldb_handler_copy
,
1644 .write_clear_fn
= ldb_handler_copy
,
1645 .write_hex_fn
= ldb_handler_copy
1647 .name
= "RMD_ORIGINATING_USN",
1648 .read_fn
= ldb_handler_copy
,
1649 .write_clear_fn
= ldb_handler_copy
,
1650 .write_hex_fn
= ldb_handler_copy
1652 .name
= "RMD_VERSION",
1653 .read_fn
= ldb_handler_copy
,
1654 .write_clear_fn
= ldb_handler_copy
,
1655 .write_hex_fn
= ldb_handler_copy
1659 /* TODO: Should be dynamic at some point */
1660 static const struct {
1663 } samba_attributes
[] = {
1664 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
},
1665 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32
},
1666 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
},
1667 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO
},
1668 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP
},
1669 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1670 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1671 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
},
1672 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
},
1673 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS
},
1674 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1675 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1676 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
},
1677 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1678 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1679 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64
},
1680 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
},
1683 * these are extracted by searching
1684 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1686 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1687 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1688 * hat can be used to identify the set of policies when applied to a resource.
1689 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1690 * server, we ignore it here.
1692 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID
},
1693 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID
},
1694 { "objectSid", LDB_SYNTAX_SAMBA_SID
},
1695 { "tokenGroups", LDB_SYNTAX_SAMBA_SID
},
1696 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID
},
1697 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID
},
1698 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID
},
1699 { "sIDHistory", LDB_SYNTAX_SAMBA_SID
},
1700 { "syncWithSID", LDB_SYNTAX_SAMBA_SID
},
1703 * these are extracted by searching
1704 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1706 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID
},
1707 { "categoryId", LDB_SYNTAX_SAMBA_GUID
},
1708 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID
},
1709 { "currMachineId", LDB_SYNTAX_SAMBA_GUID
},
1710 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID
},
1711 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID
},
1712 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID
},
1713 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID
},
1714 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID
},
1715 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID
},
1716 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID
},
1717 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID
},
1718 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID
},
1719 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID
},
1720 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID
},
1721 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID
},
1722 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID
},
1723 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID
},
1724 { "objectGUID", LDB_SYNTAX_SAMBA_GUID
},
1725 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID
},
1726 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID
},
1727 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID
},
1728 { "siteGUID", LDB_SYNTAX_SAMBA_GUID
},
1729 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1730 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1731 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1732 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID
},
1733 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID
},
1736 * these are known to be GUIDs
1738 { "invocationId", LDB_SYNTAX_SAMBA_GUID
},
1739 { "parentGUID", LDB_SYNTAX_SAMBA_GUID
},
1741 /* These NDR encoded things we want to be able to read with --show-binary */
1742 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD
},
1743 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY
},
1744 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
},
1745 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
}
1748 const struct ldb_schema_syntax
*ldb_samba_syntax_by_name(struct ldb_context
*ldb
, const char *name
)
1751 const struct ldb_schema_syntax
*s
= NULL
;
1753 for (j
=0; j
< ARRAY_SIZE(samba_syntaxes
); j
++) {
1754 if (strcmp(name
, samba_syntaxes
[j
].name
) == 0) {
1755 s
= &samba_syntaxes
[j
];
1762 const struct ldb_schema_syntax
*ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context
*ldb
, const char *name
)
1765 const struct ldb_schema_syntax
*s
= NULL
;
1767 for (j
=0; j
< ARRAY_SIZE(samba_attributes
); j
++) {
1768 if (strcmp(samba_attributes
[j
].name
, name
) == 0) {
1769 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[j
].syntax
);
1777 static const char *secret_attributes
[] = {DSDB_SECRET_ATTRIBUTES
, "secret",
1778 "priorSecret", NULL
};
1781 register the samba ldif handlers
1783 int ldb_register_samba_handlers(struct ldb_context
*ldb
)
1788 if (ldb_get_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED") != NULL
) {
1792 ret
= ldb_set_opaque(ldb
, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE
, discard_const_p(char *, secret_attributes
));
1793 if (ret
!= LDB_SUCCESS
) {
1797 for (i
=0; i
< ARRAY_SIZE(samba_attributes
); i
++) {
1798 const struct ldb_schema_syntax
*s
= NULL
;
1800 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1803 s
= ldb_standard_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1807 return LDB_ERR_OPERATIONS_ERROR
;
1810 ret
= ldb_schema_attribute_add_with_syntax(ldb
, samba_attributes
[i
].name
, LDB_ATTR_FLAG_FIXED
, s
);
1811 if (ret
!= LDB_SUCCESS
) {
1816 for (i
=0; i
< ARRAY_SIZE(samba_dn_syntax
); i
++) {
1817 ret
= ldb_dn_extended_add_syntax(ldb
, LDB_ATTR_FLAG_FIXED
, &samba_dn_syntax
[i
]);
1818 if (ret
!= LDB_SUCCESS
) {
1824 ret
= ldb_register_samba_matching_rules(ldb
);
1825 if (ret
!= LDB_SUCCESS
) {
1830 ret
= ldb_set_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1831 if (ret
!= LDB_SUCCESS
) {