2 ldb database library - ldif handlers for Samba
4 Copyright (C) Andrew Tridgell 2005
5 Copyright (C) Andrew Bartlett 2006-2009
6 Copyright (C) Matthias Dieter Wallnöfer 2009
7 ** NOTE! The following LGPL license applies to the ldb
8 ** library. This does NOT imply that all of Samba is released
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include <ldb_module.h>
28 #include "ldb_handlers.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "dsdb/common/util.h"
31 #include "librpc/gen_ndr/ndr_security.h"
32 #include "librpc/gen_ndr/ndr_misc.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "librpc/gen_ndr/ndr_dnsp.h"
35 #include "librpc/ndr/libndr.h"
36 #include "libcli/security/security.h"
37 #include "param/param.h"
38 #include "../lib/util/asn1.h"
41 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
43 If mask_errors is true, then function succeeds but out data
44 is set to "<Unable to decode binary data>" message
46 \return 0 on success; -1 on error
48 static int ldif_write_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
49 const struct ldb_val
*in
, struct ldb_val
*out
,
51 ndr_pull_flags_fn_t pull_fn
,
52 ndr_print_fn_t print_fn
,
56 enum ndr_err_code err
;
57 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
58 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
60 p
= talloc_size(mem_ctx
, struct_size
);
61 err
= ndr_pull_struct_blob(in
, mem_ctx
,
63 if (err
!= NDR_ERR_SUCCESS
) {
64 /* fail in not in mask_error mode */
69 out
->data
= (uint8_t *)talloc_strdup(mem_ctx
, "<Unable to decode binary data>");
70 out
->length
= strlen((const char *)out
->data
);
73 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
, print_fn
, "NDR", p
);
75 if (out
->data
== NULL
) {
76 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
78 out
->length
= strlen((char *)out
->data
);
83 convert a ldif formatted objectSid to a NDR formatted blob
85 static int ldif_read_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
86 const struct ldb_val
*in
, struct ldb_val
*out
)
89 enum ndr_err_code ndr_err
;
91 if (in
->length
> DOM_SID_STR_BUFLEN
) {
95 memcpy(p
, in
->data
, in
->length
);
98 ret
= dom_sid_parse(p
, &sid
);
103 *out
= data_blob_talloc(mem_ctx
, NULL
,
104 ndr_size_dom_sid(&sid
, 0));
105 if (out
->data
== NULL
) {
109 ndr_err
= ndr_push_struct_into_fixed_blob(out
, &sid
,
110 (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
111 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
119 convert a NDR formatted blob to a ldif formatted objectSid
121 int ldif_write_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
122 const struct ldb_val
*in
, struct ldb_val
*out
)
125 enum ndr_err_code ndr_err
;
127 ndr_err
= ndr_pull_struct_blob_all_noalloc(in
, &sid
,
128 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
129 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
132 *out
= data_blob_string_const(dom_sid_string(mem_ctx
, &sid
));
133 if (out
->data
== NULL
) {
139 bool ldif_comparision_objectSid_isString(const struct ldb_val
*v
)
145 if (strncmp("S-", (const char *)v
->data
, 2) != 0) return false;
151 compare two objectSids
153 static int ldif_comparison_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
154 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
156 if (ldif_comparision_objectSid_isString(v1
) && ldif_comparision_objectSid_isString(v2
)) {
157 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
158 } else if (ldif_comparision_objectSid_isString(v1
)
159 && !ldif_comparision_objectSid_isString(v2
)) {
162 if (ldif_read_objectSid(ldb
, mem_ctx
, v1
, &v
) != 0) {
163 /* Perhaps not a string after all */
164 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
166 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
169 } else if (!ldif_comparision_objectSid_isString(v1
)
170 && ldif_comparision_objectSid_isString(v2
)) {
173 if (ldif_read_objectSid(ldb
, mem_ctx
, v2
, &v
) != 0) {
174 /* Perhaps not a string after all */
175 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
177 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
181 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
185 canonicalise a objectSid
187 static int ldif_canonicalise_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
188 const struct ldb_val
*in
, struct ldb_val
*out
)
190 if (ldif_comparision_objectSid_isString(in
)) {
191 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) != 0) {
192 /* Perhaps not a string after all */
193 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
197 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
200 static int extended_dn_read_SID(struct ldb_context
*ldb
, void *mem_ctx
,
201 const struct ldb_val
*in
, struct ldb_val
*out
)
204 enum ndr_err_code ndr_err
;
205 if (ldif_comparision_objectSid_isString(in
)) {
206 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) == 0) {
211 /* Perhaps not a string after all */
212 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
218 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
219 (const char *)in
->data
, in
->length
);
221 /* Check it looks like a SID */
222 ndr_err
= ndr_pull_struct_blob_all_noalloc(out
, &sid
,
223 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
224 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
231 convert a ldif formatted objectGUID to a NDR formatted blob
233 static int ldif_read_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
234 const struct ldb_val
*in
, struct ldb_val
*out
)
239 status
= GUID_from_data_blob(in
, &guid
);
240 if (!NT_STATUS_IS_OK(status
)) {
244 status
= GUID_to_ndr_blob(&guid
, mem_ctx
, out
);
245 if (!NT_STATUS_IS_OK(status
)) {
252 convert a NDR formatted blob to a ldif formatted objectGUID
254 static int ldif_write_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
255 const struct ldb_val
*in
, struct ldb_val
*out
)
260 status
= GUID_from_ndr_blob(in
, &guid
);
261 if (!NT_STATUS_IS_OK(status
)) {
264 out
->data
= (uint8_t *)GUID_string(mem_ctx
, &guid
);
265 if (out
->data
== NULL
) {
268 out
->length
= strlen((const char *)out
->data
);
272 static bool ldif_comparision_objectGUID_isString(const struct ldb_val
*v
)
274 if (v
->length
!= 36 && v
->length
!= 38) return false;
276 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
280 static int extended_dn_read_GUID(struct ldb_context
*ldb
, void *mem_ctx
,
281 const struct ldb_val
*in
, struct ldb_val
*out
)
284 if (in
->length
== 36 && ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) == 0) {
288 /* Try as 'hex' form */
289 if (in
->length
!= 32) {
293 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
299 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
300 (const char *)in
->data
, in
->length
);
302 /* Check it looks like a GUID */
303 if ((*out
).length
!= 16) {
312 compare two objectGUIDs
314 static int ldif_comparison_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
315 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
317 if (ldif_comparision_objectGUID_isString(v1
) && ldif_comparision_objectGUID_isString(v2
)) {
318 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
319 } else if (ldif_comparision_objectGUID_isString(v1
)
320 && !ldif_comparision_objectGUID_isString(v2
)) {
323 if (ldif_read_objectGUID(ldb
, mem_ctx
, v1
, &v
) != 0) {
324 /* Perhaps it wasn't a valid string after all */
325 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
327 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
330 } else if (!ldif_comparision_objectGUID_isString(v1
)
331 && ldif_comparision_objectGUID_isString(v2
)) {
334 if (ldif_read_objectGUID(ldb
, mem_ctx
, v2
, &v
) != 0) {
335 /* Perhaps it wasn't a valid string after all */
336 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
338 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
342 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
346 canonicalise a objectGUID
348 static int ldif_canonicalise_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
349 const struct ldb_val
*in
, struct ldb_val
*out
)
351 if (ldif_comparision_objectGUID_isString(in
)) {
352 if (ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) != 0) {
353 /* Perhaps it wasn't a valid string after all */
354 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
358 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
363 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
365 static int ldif_read_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
366 const struct ldb_val
*in
, struct ldb_val
*out
)
368 struct security_descriptor
*sd
;
369 enum ndr_err_code ndr_err
;
371 sd
= talloc(mem_ctx
, struct security_descriptor
);
376 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
377 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
378 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
379 /* If this does not parse, then it is probably SDDL, and we should try it that way */
381 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
383 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
389 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, sd
,
390 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
392 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
400 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
402 static int ldif_write_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
403 const struct ldb_val
*in
, struct ldb_val
*out
)
405 struct security_descriptor
*sd
;
406 enum ndr_err_code ndr_err
;
408 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
409 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
410 sizeof(struct security_descriptor
),
411 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
,
412 (ndr_print_fn_t
)ndr_print_security_descriptor
,
417 sd
= talloc(mem_ctx
, struct security_descriptor
);
421 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
422 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
423 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
424 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
428 out
->data
= (uint8_t *)sddl_encode(mem_ctx
, sd
, samdb_domain_sid_cache_only(ldb
));
430 if (out
->data
== NULL
) {
433 out
->length
= strlen((const char *)out
->data
);
438 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
440 static int ldif_write_sddlSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
441 const struct ldb_val
*in
, struct ldb_val
*out
)
443 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
444 struct security_descriptor
*sd
;
445 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
447 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
448 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
,
449 (ndr_print_fn_t
)ndr_print_security_descriptor
,
451 out
->length
= strlen((const char *)out
->data
);
456 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
460 canonicalise an objectCategory. We use the long form as the canonical form:
461 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
463 Also any short name of an objectClass that points to a different
464 class (such as user) has the canonical form of the class it's
465 defaultObjectCategory points to (eg
466 cn=Person,cn=Schema,cn=Configuration,<basedn>)
469 static int ldif_canonicalise_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
470 const struct ldb_val
*in
, struct ldb_val
*out
)
472 struct ldb_dn
*dn1
= NULL
;
473 const struct dsdb_schema
*schema
= dsdb_get_schema(ldb
, NULL
);
474 const struct dsdb_class
*sclass
;
475 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
477 return LDB_ERR_OPERATIONS_ERROR
;
481 talloc_free(tmp_ctx
);
482 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
483 if (in
->data
&& !out
->data
) {
484 return LDB_ERR_OPERATIONS_ERROR
;
488 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, in
);
489 if ( ! ldb_dn_validate(dn1
)) {
490 const char *lDAPDisplayName
= talloc_strndup(tmp_ctx
, (char *)in
->data
, in
->length
);
491 sclass
= dsdb_class_by_lDAPDisplayName(schema
, lDAPDisplayName
);
493 struct ldb_dn
*dn
= ldb_dn_new(tmp_ctx
, ldb
,
494 sclass
->defaultObjectCategory
);
496 talloc_free(tmp_ctx
);
497 return LDB_ERR_OPERATIONS_ERROR
;
500 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn
));
501 talloc_free(tmp_ctx
);
504 return LDB_ERR_OPERATIONS_ERROR
;
508 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
509 talloc_free(tmp_ctx
);
511 if (in
->data
&& !out
->data
) {
512 return LDB_ERR_OPERATIONS_ERROR
;
517 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn1
));
518 talloc_free(tmp_ctx
);
521 return LDB_ERR_OPERATIONS_ERROR
;
526 static int ldif_comparison_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
527 const struct ldb_val
*v1
,
528 const struct ldb_val
*v2
)
530 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_objectCategory
,
535 convert a NDR formatted blob to a ldif formatted schemaInfo
537 static int ldif_write_schemaInfo(struct ldb_context
*ldb
, void *mem_ctx
,
538 const struct ldb_val
*in
, struct ldb_val
*out
)
540 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
541 sizeof(struct repsFromToBlob
),
542 (ndr_pull_flags_fn_t
)ndr_pull_schemaInfoBlob
,
543 (ndr_print_fn_t
)ndr_print_schemaInfoBlob
,
548 convert a ldif formatted prefixMap to a NDR formatted blob
550 static int ldif_read_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
551 const struct ldb_val
*in
, struct ldb_val
*out
)
553 struct prefixMapBlob
*blob
;
554 enum ndr_err_code ndr_err
;
555 char *string
, *line
, *p
, *oid
;
558 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
560 if (tmp_ctx
== NULL
) {
564 blob
= talloc_zero(tmp_ctx
, struct prefixMapBlob
);
566 talloc_free(tmp_ctx
);
570 /* use the switch value to detect if this is in the binary
573 if (in
->length
>= 4 && IVAL(in
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
574 ndr_err
= ndr_pull_struct_blob(in
, tmp_ctx
, blob
,
575 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
576 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
577 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
579 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
580 talloc_free(tmp_ctx
);
581 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
588 /* If this does not parse, then it is probably the text version, and we should try it that way */
589 blob
->version
= PREFIX_MAP_VERSION_DSDB
;
591 string
= talloc_strndup(mem_ctx
, (const char *)in
->data
, in
->length
);
592 if (string
== NULL
) {
598 while (line
&& line
[0]) {
605 p
=strchr(line
, '\n');
610 /* allow a trailing separator */
615 blob
->ctr
.dsdb
.mappings
= talloc_realloc(blob
,
616 blob
->ctr
.dsdb
.mappings
,
617 struct drsuapi_DsReplicaOIDMapping
,
618 blob
->ctr
.dsdb
.num_mappings
+1);
619 if (!blob
->ctr
.dsdb
.mappings
) {
620 talloc_free(tmp_ctx
);
624 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].id_prefix
=
625 strtoul_err(line
, &oid
, 10, &error
);
627 if (oid
[0] != ':' || error
!= 0) {
628 talloc_free(tmp_ctx
);
632 /* we know there must be at least ":" */
635 if (!ber_write_partial_OID_String(blob
->ctr
.dsdb
.mappings
, &oid_blob
, oid
)) {
636 talloc_free(tmp_ctx
);
639 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.length
= oid_blob
.length
;
640 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.binary_oid
= oid_blob
.data
;
642 blob
->ctr
.dsdb
.num_mappings
++;
644 /* Now look past the terminator we added above */
652 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
654 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
655 talloc_free(tmp_ctx
);
656 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
663 convert a NDR formatted blob to a ldif formatted prefixMap
665 static int ldif_write_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
666 const struct ldb_val
*in
, struct ldb_val
*out
)
668 struct prefixMapBlob
*blob
;
669 enum ndr_err_code ndr_err
;
673 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
675 /* try to decode the blob as S4 prefixMap */
676 err
= ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
677 sizeof(struct prefixMapBlob
),
678 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
,
679 (ndr_print_fn_t
)ndr_print_prefixMapBlob
,
684 /* try parsing it as Windows PrefixMap value */
685 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
686 sizeof(struct drsuapi_MSPrefixMap_Ctr
),
687 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_MSPrefixMap_Ctr
,
688 (ndr_print_fn_t
)ndr_print_drsuapi_MSPrefixMap_Ctr
,
692 blob
= talloc(mem_ctx
, struct prefixMapBlob
);
696 ndr_err
= ndr_pull_struct_blob_all(in
, blob
,
698 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
699 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
702 if (blob
->version
!= PREFIX_MAP_VERSION_DSDB
) {
705 string
= talloc_strdup(mem_ctx
, "");
706 if (string
== NULL
) {
710 for (i
=0; i
< blob
->ctr
.dsdb
.num_mappings
; i
++) {
712 char *partial_oid
= NULL
;
715 string
= talloc_asprintf_append(string
, ";");
718 oid_blob
= data_blob_const(blob
->ctr
.dsdb
.mappings
[i
].oid
.binary_oid
,
719 blob
->ctr
.dsdb
.mappings
[i
].oid
.length
);
720 if (!ber_read_partial_OID_String(blob
, oid_blob
, &partial_oid
)) {
721 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
722 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
));
725 string
= talloc_asprintf_append(string
, "%u:%s",
726 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
,
728 talloc_free(discard_const(partial_oid
));
729 if (string
== NULL
) {
735 *out
= data_blob_string_const(string
);
743 static bool ldif_comparision_prefixMap_isString(const struct ldb_val
*v
)
749 if (IVAL(v
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
757 canonicalise a prefixMap
759 static int ldif_canonicalise_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
760 const struct ldb_val
*in
, struct ldb_val
*out
)
762 if (ldif_comparision_prefixMap_isString(in
)) {
763 return ldif_read_prefixMap(ldb
, mem_ctx
, in
, out
);
765 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
768 static int ldif_comparison_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
769 const struct ldb_val
*v1
,
770 const struct ldb_val
*v2
)
772 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_prefixMap
,
776 /* length limited conversion of a ldb_val to a int32_t */
777 static int val_to_int32(const struct ldb_val
*in
, int32_t *v
)
782 /* make sure we don't read past the end of the data */
783 if (in
->length
> sizeof(buf
)-1) {
784 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
786 strncpy(buf
, (char *)in
->data
, in
->length
);
789 /* We've to use "strtoll" here to have the intended overflows.
790 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
791 *v
= (int32_t) strtoll(buf
, &end
, 0);
793 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
798 /* length limited conversion of a ldb_val to a int64_t */
799 static int val_to_int64(const struct ldb_val
*in
, int64_t *v
)
804 /* make sure we don't read past the end of the data */
805 if (in
->length
> sizeof(buf
)-1) {
806 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
808 strncpy(buf
, (char *)in
->data
, in
->length
);
811 *v
= (int64_t) strtoll(buf
, &end
, 0);
813 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
818 /* Canonicalisation of two 32-bit integers */
819 static int ldif_canonicalise_int32(struct ldb_context
*ldb
, void *mem_ctx
,
820 const struct ldb_val
*in
, struct ldb_val
*out
)
825 ret
= val_to_int32(in
, &i
);
826 if (ret
!= LDB_SUCCESS
) {
829 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%d", i
);
830 if (out
->data
== NULL
) {
832 return LDB_ERR_OPERATIONS_ERROR
;
834 out
->length
= strlen((char *)out
->data
);
838 /* Comparison of two 32-bit integers */
839 static int ldif_comparison_int32(struct ldb_context
*ldb
, void *mem_ctx
,
840 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
843 val_to_int32(v1
, &i1
);
844 val_to_int32(v2
, &i2
);
845 if (i1
== i2
) return 0;
846 return i1
> i2
? 1 : -1;
849 /* Canonicalisation of two 64-bit integers */
850 static int ldif_canonicalise_int64(struct ldb_context
*ldb
, void *mem_ctx
,
851 const struct ldb_val
*in
, struct ldb_val
*out
)
856 ret
= val_to_int64(in
, &i
);
857 if (ret
!= LDB_SUCCESS
) {
860 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%lld", (long long)i
);
861 if (out
->data
== NULL
) {
863 return LDB_ERR_OPERATIONS_ERROR
;
865 out
->length
= strlen((char *)out
->data
);
869 /* Comparison of two 64-bit integers */
870 static int ldif_comparison_int64(struct ldb_context
*ldb
, void *mem_ctx
,
871 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
874 val_to_int64(v1
, &i1
);
875 val_to_int64(v2
, &i2
);
876 if (i1
== i2
) return 0;
877 return i1
> i2
? 1 : -1;
881 convert a NDR formatted blob to a ldif formatted repsFromTo
883 static int ldif_write_repsFromTo(struct ldb_context
*ldb
, void *mem_ctx
,
884 const struct ldb_val
*in
, struct ldb_val
*out
)
886 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
887 sizeof(struct repsFromToBlob
),
888 (ndr_pull_flags_fn_t
)ndr_pull_repsFromToBlob
,
889 (ndr_print_fn_t
)ndr_print_repsFromToBlob
,
894 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
896 static int ldif_write_replPropertyMetaData(struct ldb_context
*ldb
, void *mem_ctx
,
897 const struct ldb_val
*in
, struct ldb_val
*out
)
899 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
900 sizeof(struct replPropertyMetaDataBlob
),
901 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaDataBlob
,
902 (ndr_print_fn_t
)ndr_print_replPropertyMetaDataBlob
,
907 convert a NDR formatted blob to a ldif formatted replUpToDateVector
909 static int ldif_write_replUpToDateVector(struct ldb_context
*ldb
, void *mem_ctx
,
910 const struct ldb_val
*in
, struct ldb_val
*out
)
912 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
913 sizeof(struct replUpToDateVectorBlob
),
914 (ndr_pull_flags_fn_t
)ndr_pull_replUpToDateVectorBlob
,
915 (ndr_print_fn_t
)ndr_print_replUpToDateVectorBlob
,
919 static int ldif_write_dn_binary_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
920 const struct ldb_val
*in
, struct ldb_val
*out
,
922 ndr_pull_flags_fn_t pull_fn
,
923 ndr_print_fn_t print_fn
,
927 enum ndr_err_code err
;
928 struct dsdb_dn
*dsdb_dn
= NULL
;
932 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
933 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
936 dsdb_dn
= dsdb_dn_parse(mem_ctx
, ldb
, in
, DSDB_SYNTAX_BINARY_DN
);
937 if (dsdb_dn
== NULL
) {
938 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
941 p
= talloc_size(dsdb_dn
, struct_size
);
943 TALLOC_FREE(dsdb_dn
);
944 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
947 err
= ndr_pull_struct_blob(&dsdb_dn
->extra_part
, p
, p
, pull_fn
);
948 if (err
!= NDR_ERR_SUCCESS
) {
949 /* fail in not in mask_error mode */
953 TALLOC_FREE(dsdb_dn
);
954 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
957 dn_str
= ldb_dn_get_extended_linearized(dsdb_dn
, dsdb_dn
->dn
, 1);
958 if (dn_str
== NULL
) {
959 TALLOC_FREE(dsdb_dn
);
960 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
963 str
= ndr_print_struct_string(mem_ctx
, print_fn
, dn_str
, p
);
964 TALLOC_FREE(dsdb_dn
);
966 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
969 *out
= data_blob_string_const(str
);
973 static int ldif_write_msDS_RevealedUsers(struct ldb_context
*ldb
, void *mem_ctx
,
974 const struct ldb_val
*in
, struct ldb_val
*out
)
976 return ldif_write_dn_binary_NDR(ldb
, mem_ctx
, in
, out
,
977 sizeof(struct replPropertyMetaData1
),
978 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaData1
,
979 (ndr_print_fn_t
)ndr_print_replPropertyMetaData1
,
984 convert a NDR formatted blob to a ldif formatted dnsRecord
986 static int ldif_write_dnsRecord(struct ldb_context
*ldb
, void *mem_ctx
,
987 const struct ldb_val
*in
, struct ldb_val
*out
)
989 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
990 sizeof(struct dnsp_DnssrvRpcRecord
),
991 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
,
992 (ndr_print_fn_t
)ndr_print_dnsp_DnssrvRpcRecord
,
997 convert a NDR formatted blob to a ldif formatted dnsProperty
999 static int ldif_write_dnsProperty(struct ldb_context
*ldb
, void *mem_ctx
,
1000 const struct ldb_val
*in
, struct ldb_val
*out
)
1002 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1003 sizeof(struct dnsp_DnsProperty
),
1004 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnsProperty
,
1005 (ndr_print_fn_t
)ndr_print_dnsp_DnsProperty
,
1010 convert a NDR formatted blob of a supplementalCredentials into text
1012 static int ldif_write_supplementalCredentialsBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1013 const struct ldb_val
*in
, struct ldb_val
*out
)
1015 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1016 sizeof(struct supplementalCredentialsBlob
),
1017 (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
,
1018 (ndr_print_fn_t
)ndr_print_supplementalCredentialsBlob
,
1023 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1025 static int ldif_write_trustAuthInOutBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1026 const struct ldb_val
*in
, struct ldb_val
*out
)
1028 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1029 sizeof(struct trustAuthInOutBlob
),
1030 (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
,
1031 (ndr_print_fn_t
)ndr_print_trustAuthInOutBlob
,
1036 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1038 static int ldif_write_ForestTrustInfo(struct ldb_context
*ldb
, void *mem_ctx
,
1039 const struct ldb_val
*in
, struct ldb_val
*out
)
1041 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1042 sizeof(struct ForestTrustInfo
),
1043 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
,
1044 (ndr_print_fn_t
)ndr_print_ForestTrustInfo
,
1048 convert a NDR formatted blob of a partialAttributeSet into text
1050 static int ldif_write_partialAttributeSet(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 partialAttributeSetBlob
),
1055 (ndr_pull_flags_fn_t
)ndr_pull_partialAttributeSetBlob
,
1056 (ndr_print_fn_t
)ndr_print_partialAttributeSetBlob
,
1061 static int extended_dn_write_hex(struct ldb_context
*ldb
, void *mem_ctx
,
1062 const struct ldb_val
*in
, struct ldb_val
*out
)
1064 *out
= data_blob_string_const(data_blob_hex_string_lower(mem_ctx
, in
));
1074 static int samba_ldb_dn_link_comparison(struct ldb_context
*ldb
, void *mem_ctx
,
1075 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1077 struct ldb_dn
*dn1
= NULL
, *dn2
= NULL
;
1080 if (dsdb_dn_is_deleted_val(v1
)) {
1081 /* If the DN is deleted, then we can't search for it */
1085 if (dsdb_dn_is_deleted_val(v2
)) {
1086 /* If the DN is deleted, then we can't search for it */
1090 dn1
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v1
);
1091 if ( ! ldb_dn_validate(dn1
)) return -1;
1093 dn2
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v2
);
1094 if ( ! ldb_dn_validate(dn2
)) {
1099 ret
= ldb_dn_compare(dn1
, dn2
);
1106 static int samba_ldb_dn_link_canonicalise(struct ldb_context
*ldb
, void *mem_ctx
,
1107 const struct ldb_val
*in
, struct ldb_val
*out
)
1115 dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, in
);
1116 if ( ! ldb_dn_validate(dn
)) {
1117 return LDB_ERR_INVALID_DN_SYNTAX
;
1120 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1121 * does not casually match a not deleted DN */
1122 if (dsdb_dn_is_deleted_val(in
)) {
1123 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
,
1125 dsdb_dn_val_rmd_flags(in
),
1126 ldb_dn_get_casefold(dn
));
1128 out
->data
= (uint8_t *)ldb_dn_alloc_casefold(mem_ctx
, dn
);
1131 if (out
->data
== NULL
) {
1134 out
->length
= strlen((char *)out
->data
);
1146 write a 64 bit 2-part range
1148 static int ldif_write_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1149 const struct ldb_val
*in
, struct ldb_val
*out
)
1153 ret
= val_to_int64(in
, &v
);
1154 if (ret
!= LDB_SUCCESS
) {
1157 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%lu-%lu",
1158 (unsigned long)(v
&0xFFFFFFFF),
1159 (unsigned long)(v
>>32));
1160 if (out
->data
== NULL
) {
1162 return LDB_ERR_OPERATIONS_ERROR
;
1164 out
->length
= strlen((char *)out
->data
);
1169 read a 64 bit 2-part range
1171 static int ldif_read_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1172 const struct ldb_val
*in
, struct ldb_val
*out
)
1174 unsigned long high
, low
;
1177 if (memchr(in
->data
, '-', in
->length
) == NULL
) {
1178 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1181 if (in
->length
> sizeof(buf
)-1) {
1182 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1184 strncpy(buf
, (const char *)in
->data
, in
->length
);
1185 buf
[in
->length
] = 0;
1187 if (sscanf(buf
, "%lu-%lu", &low
, &high
) != 2) {
1188 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1191 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%llu",
1192 (unsigned long long)(((uint64_t)high
)<<32) | (low
));
1194 if (out
->data
== NULL
) {
1196 return LDB_ERR_OPERATIONS_ERROR
;
1198 out
->length
= strlen((char *)out
->data
);
1203 when this operator_fn is set for a syntax, the backend calls is in
1204 preference to the comparison function. We are told the exact
1205 comparison operation that is needed, and we can return errors
1207 static int samba_syntax_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1208 const struct ldb_schema_attribute
*a
,
1209 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1211 switch (operation
) {
1215 case LDB_OP_SUBSTRING
:
1217 case LDB_OP_EXTENDED
:
1218 /* handled in the backends */
1219 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1221 case LDB_OP_GREATER
:
1223 case LDB_OP_EQUALITY
:
1225 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
1227 if (tmp_ctx
== NULL
) {
1228 return ldb_oom(ldb
);
1230 ret
= a
->syntax
->comparison_fn(ldb
, tmp_ctx
, v1
, v2
);
1231 talloc_free(tmp_ctx
);
1232 if (operation
== LDB_OP_GREATER
) {
1233 *matched
= (ret
>= 0);
1234 } else if (operation
== LDB_OP_LESS
) {
1235 *matched
= (ret
<= 0);
1237 *matched
= (ret
== 0);
1242 case LDB_OP_PRESENT
:
1247 /* we shouldn't get here */
1248 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1252 compare two binary objects. This is correct for sorting as the sort order is:
1259 rather than ldb_comparison_binary() which is:
1267 static int samba_ldb_comparison_binary(struct ldb_context
*ldb
, void *mem_ctx
,
1268 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1270 return data_blob_cmp(v1
, v2
);
1274 when this operator_fn is set for a syntax, the backend calls is in
1275 preference to the comparison function. We are told the exact
1276 comparison operation that is needed, and we can return errors.
1278 This mode optimises for ldb_comparison_binary() if we need equality,
1279 as this should be faster as it can do a length-check first.
1281 static int samba_syntax_binary_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1282 const struct ldb_schema_attribute
*a
,
1283 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1285 if (operation
== LDB_OP_EQUALITY
) {
1286 *matched
= (ldb_comparison_binary(ldb
, NULL
, v1
, v2
) == 0);
1289 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1293 see if two DNs match, comparing first by GUID, then by SID, and
1294 finally by string components
1296 static int samba_dn_extended_match(struct ldb_context
*ldb
,
1297 const struct ldb_val
*v1
,
1298 const struct ldb_val
*v2
,
1301 TALLOC_CTX
*tmp_ctx
;
1302 struct ldb_dn
*dn1
, *dn2
;
1303 const struct ldb_val
*guid1
, *guid2
, *sid1
, *sid2
;
1304 uint32_t rmd_flags1
, rmd_flags2
;
1306 tmp_ctx
= talloc_new(ldb
);
1308 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v1
);
1309 dn2
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v2
);
1311 /* couldn't parse as DN's */
1312 talloc_free(tmp_ctx
);
1317 rmd_flags1
= dsdb_dn_rmd_flags(dn1
);
1318 rmd_flags2
= dsdb_dn_rmd_flags(dn2
);
1320 if ((rmd_flags1
& DSDB_RMD_FLAG_DELETED
) !=
1321 (rmd_flags2
& DSDB_RMD_FLAG_DELETED
)) {
1322 /* only match if they have the same deletion status */
1323 talloc_free(tmp_ctx
);
1329 guid1
= ldb_dn_get_extended_component(dn1
, "GUID");
1330 guid2
= ldb_dn_get_extended_component(dn2
, "GUID");
1331 if (guid1
&& guid2
) {
1332 (*matched
) = (data_blob_cmp(guid1
, guid2
) == 0);
1333 talloc_free(tmp_ctx
);
1337 sid1
= ldb_dn_get_extended_component(dn1
, "SID");
1338 sid2
= ldb_dn_get_extended_component(dn2
, "SID");
1340 (*matched
) = (data_blob_cmp(sid1
, sid2
) == 0);
1341 talloc_free(tmp_ctx
);
1345 (*matched
) = (ldb_dn_compare(dn1
, dn2
) == 0);
1347 talloc_free(tmp_ctx
);
1352 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1354 static int samba_syntax_operator_dn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1355 const struct ldb_schema_attribute
*a
,
1356 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1358 if (operation
== LDB_OP_PRESENT
&& dsdb_dn_is_deleted_val(v1
)) {
1359 /* If the DN is deleted, then we can't search for it */
1361 /* should this be for equality too? */
1366 if (operation
== LDB_OP_EQUALITY
&&
1367 samba_dn_extended_match(ldb
, v1
, v2
, matched
) == LDB_SUCCESS
) {
1371 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1375 static const struct ldb_schema_syntax samba_syntaxes
[] = {
1377 .name
= LDB_SYNTAX_SAMBA_SID
,
1378 .ldif_read_fn
= ldif_read_objectSid
,
1379 .ldif_write_fn
= ldif_write_objectSid
,
1380 .canonicalise_fn
= ldif_canonicalise_objectSid
,
1381 .comparison_fn
= ldif_comparison_objectSid
,
1382 .operator_fn
= samba_syntax_operator_fn
1384 .name
= LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
,
1385 .ldif_read_fn
= ldif_read_ntSecurityDescriptor
,
1386 .ldif_write_fn
= ldif_write_ntSecurityDescriptor
,
1387 .canonicalise_fn
= ldb_handler_copy
,
1388 .comparison_fn
= samba_ldb_comparison_binary
,
1389 .operator_fn
= samba_syntax_binary_operator_fn
1391 .name
= LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
,
1392 .ldif_read_fn
= ldb_handler_copy
,
1393 .ldif_write_fn
= ldif_write_sddlSecurityDescriptor
,
1394 .canonicalise_fn
= ldb_handler_fold
,
1395 .comparison_fn
= ldb_comparison_fold
,
1396 .operator_fn
= samba_syntax_operator_fn
1398 .name
= LDB_SYNTAX_SAMBA_GUID
,
1399 .ldif_read_fn
= ldif_read_objectGUID
,
1400 .ldif_write_fn
= ldif_write_objectGUID
,
1401 .canonicalise_fn
= ldif_canonicalise_objectGUID
,
1402 .comparison_fn
= ldif_comparison_objectGUID
,
1403 .operator_fn
= samba_syntax_operator_fn
1405 .name
= LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
,
1406 .ldif_read_fn
= ldb_handler_copy
,
1407 .ldif_write_fn
= ldb_handler_copy
,
1408 .canonicalise_fn
= ldif_canonicalise_objectCategory
,
1409 .comparison_fn
= ldif_comparison_objectCategory
,
1410 .operator_fn
= samba_syntax_operator_fn
1412 .name
= LDB_SYNTAX_SAMBA_SCHEMAINFO
,
1413 .ldif_read_fn
= ldb_handler_copy
,
1414 .ldif_write_fn
= ldif_write_schemaInfo
,
1415 .canonicalise_fn
= ldb_handler_copy
,
1416 .comparison_fn
= samba_ldb_comparison_binary
,
1417 .operator_fn
= samba_syntax_binary_operator_fn
1419 .name
= LDB_SYNTAX_SAMBA_PREFIX_MAP
,
1420 .ldif_read_fn
= ldif_read_prefixMap
,
1421 .ldif_write_fn
= ldif_write_prefixMap
,
1422 .canonicalise_fn
= ldif_canonicalise_prefixMap
,
1423 .comparison_fn
= ldif_comparison_prefixMap
,
1424 .operator_fn
= samba_syntax_operator_fn
1426 .name
= LDB_SYNTAX_SAMBA_INT32
,
1427 .ldif_read_fn
= ldb_handler_copy
,
1428 .ldif_write_fn
= ldb_handler_copy
,
1429 .canonicalise_fn
= ldif_canonicalise_int32
,
1430 .comparison_fn
= ldif_comparison_int32
,
1431 .operator_fn
= samba_syntax_operator_fn
1433 .name
= LDB_SYNTAX_SAMBA_REPSFROMTO
,
1434 .ldif_read_fn
= ldb_handler_copy
,
1435 .ldif_write_fn
= ldif_write_repsFromTo
,
1436 .canonicalise_fn
= ldb_handler_copy
,
1437 .comparison_fn
= samba_ldb_comparison_binary
,
1438 .operator_fn
= samba_syntax_binary_operator_fn
1440 .name
= LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
,
1441 .ldif_read_fn
= ldb_handler_copy
,
1442 .ldif_write_fn
= ldif_write_replPropertyMetaData
,
1443 .canonicalise_fn
= ldb_handler_copy
,
1444 .comparison_fn
= samba_ldb_comparison_binary
,
1445 .operator_fn
= samba_syntax_binary_operator_fn
1447 .name
= LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
,
1448 .ldif_read_fn
= ldb_handler_copy
,
1449 .ldif_write_fn
= ldif_write_replUpToDateVector
,
1450 .canonicalise_fn
= ldb_handler_copy
,
1451 .comparison_fn
= samba_ldb_comparison_binary
,
1452 .operator_fn
= samba_syntax_binary_operator_fn
1454 .name
= LDB_SYNTAX_SAMBA_REVEALEDUSERS
,
1455 .ldif_read_fn
= ldb_handler_copy
,
1456 .ldif_write_fn
= ldif_write_msDS_RevealedUsers
,
1457 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1458 .comparison_fn
= dsdb_dn_binary_comparison
,
1459 .operator_fn
= samba_syntax_operator_fn
1461 .name
= LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
,
1462 .ldif_read_fn
= ldb_handler_copy
,
1463 .ldif_write_fn
= ldif_write_trustAuthInOutBlob
,
1464 .canonicalise_fn
= ldb_handler_copy
,
1465 .comparison_fn
= samba_ldb_comparison_binary
,
1466 .operator_fn
= samba_syntax_binary_operator_fn
1468 .name
= LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
,
1469 .ldif_read_fn
= ldb_handler_copy
,
1470 .ldif_write_fn
= ldif_write_ForestTrustInfo
,
1471 .canonicalise_fn
= ldb_handler_copy
,
1472 .comparison_fn
= samba_ldb_comparison_binary
,
1473 .operator_fn
= samba_syntax_binary_operator_fn
1475 .name
= DSDB_SYNTAX_BINARY_DN
,
1476 .ldif_read_fn
= ldb_handler_copy
,
1477 .ldif_write_fn
= ldb_handler_copy
,
1478 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1479 .comparison_fn
= dsdb_dn_binary_comparison
,
1480 .operator_fn
= samba_syntax_operator_fn
1482 .name
= DSDB_SYNTAX_STRING_DN
,
1483 .ldif_read_fn
= ldb_handler_copy
,
1484 .ldif_write_fn
= ldb_handler_copy
,
1485 .canonicalise_fn
= dsdb_dn_string_canonicalise
,
1486 .comparison_fn
= dsdb_dn_string_comparison
,
1487 .operator_fn
= samba_syntax_operator_fn
1489 .name
= LDB_SYNTAX_DN
,
1490 .ldif_read_fn
= ldb_handler_copy
,
1491 .ldif_write_fn
= ldb_handler_copy
,
1492 .canonicalise_fn
= samba_ldb_dn_link_canonicalise
,
1493 .comparison_fn
= samba_ldb_dn_link_comparison
,
1494 .operator_fn
= samba_syntax_operator_dn
1496 .name
= LDB_SYNTAX_SAMBA_RANGE64
,
1497 .ldif_read_fn
= ldif_read_range64
,
1498 .ldif_write_fn
= ldif_write_range64
,
1499 .canonicalise_fn
= ldif_canonicalise_int64
,
1500 .comparison_fn
= ldif_comparison_int64
,
1501 .operator_fn
= samba_syntax_operator_fn
1503 .name
= LDB_SYNTAX_SAMBA_DNSRECORD
,
1504 .ldif_read_fn
= ldb_handler_copy
,
1505 .ldif_write_fn
= ldif_write_dnsRecord
,
1506 .canonicalise_fn
= ldb_handler_copy
,
1507 .comparison_fn
= samba_ldb_comparison_binary
,
1508 .operator_fn
= samba_syntax_binary_operator_fn
1510 .name
= LDB_SYNTAX_SAMBA_DNSPROPERTY
,
1511 .ldif_read_fn
= ldb_handler_copy
,
1512 .ldif_write_fn
= ldif_write_dnsProperty
,
1513 .canonicalise_fn
= ldb_handler_copy
,
1514 .comparison_fn
= samba_ldb_comparison_binary
,
1515 .operator_fn
= samba_syntax_binary_operator_fn
1517 .name
= LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
,
1518 .ldif_read_fn
= ldb_handler_copy
,
1519 .ldif_write_fn
= ldif_write_supplementalCredentialsBlob
,
1520 .canonicalise_fn
= ldb_handler_copy
,
1521 .comparison_fn
= samba_ldb_comparison_binary
,
1522 .operator_fn
= samba_syntax_binary_operator_fn
1524 .name
= LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
,
1525 .ldif_read_fn
= ldb_handler_copy
,
1526 .ldif_write_fn
= ldif_write_partialAttributeSet
,
1527 .canonicalise_fn
= ldb_handler_copy
,
1528 .comparison_fn
= samba_ldb_comparison_binary
,
1529 .operator_fn
= samba_syntax_binary_operator_fn
1531 .name
= LDB_SYNTAX_SAMBA_OCTET_STRING
,
1532 .ldif_read_fn
= ldb_handler_copy
,
1533 .ldif_write_fn
= ldb_handler_copy
,
1534 .canonicalise_fn
= ldb_handler_copy
,
1535 .comparison_fn
= samba_ldb_comparison_binary
,
1536 .operator_fn
= samba_syntax_binary_operator_fn
1540 static const struct ldb_dn_extended_syntax samba_dn_syntax
[] = {
1543 .read_fn
= extended_dn_read_SID
,
1544 .write_clear_fn
= ldif_write_objectSid
,
1545 .write_hex_fn
= extended_dn_write_hex
1548 .read_fn
= extended_dn_read_GUID
,
1549 .write_clear_fn
= ldif_write_objectGUID
,
1550 .write_hex_fn
= extended_dn_write_hex
1553 .read_fn
= ldb_handler_copy
,
1554 .write_clear_fn
= ldb_handler_copy
,
1555 .write_hex_fn
= ldb_handler_copy
1557 .name
= "RMD_INVOCID",
1558 .read_fn
= extended_dn_read_GUID
,
1559 .write_clear_fn
= ldif_write_objectGUID
,
1560 .write_hex_fn
= extended_dn_write_hex
1562 .name
= "RMD_FLAGS",
1563 .read_fn
= ldb_handler_copy
,
1564 .write_clear_fn
= ldb_handler_copy
,
1565 .write_hex_fn
= ldb_handler_copy
1567 .name
= "RMD_ADDTIME",
1568 .read_fn
= ldb_handler_copy
,
1569 .write_clear_fn
= ldb_handler_copy
,
1570 .write_hex_fn
= ldb_handler_copy
1572 .name
= "RMD_CHANGETIME",
1573 .read_fn
= ldb_handler_copy
,
1574 .write_clear_fn
= ldb_handler_copy
,
1575 .write_hex_fn
= ldb_handler_copy
1577 .name
= "RMD_LOCAL_USN",
1578 .read_fn
= ldb_handler_copy
,
1579 .write_clear_fn
= ldb_handler_copy
,
1580 .write_hex_fn
= ldb_handler_copy
1582 .name
= "RMD_ORIGINATING_USN",
1583 .read_fn
= ldb_handler_copy
,
1584 .write_clear_fn
= ldb_handler_copy
,
1585 .write_hex_fn
= ldb_handler_copy
1587 .name
= "RMD_VERSION",
1588 .read_fn
= ldb_handler_copy
,
1589 .write_clear_fn
= ldb_handler_copy
,
1590 .write_hex_fn
= ldb_handler_copy
1594 /* TODO: Should be dynamic at some point */
1595 static const struct {
1598 } samba_attributes
[] = {
1599 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
},
1600 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32
},
1601 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
},
1602 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO
},
1603 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP
},
1604 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1605 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1606 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
},
1607 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
},
1608 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS
},
1609 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1610 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1611 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
},
1612 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1613 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1614 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64
},
1615 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
},
1618 * these are extracted by searching
1619 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1621 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1622 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1623 * hat can be used to identify the set of policies when applied to a resource.
1624 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1625 * server, we ignore it here.
1627 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID
},
1628 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID
},
1629 { "objectSid", LDB_SYNTAX_SAMBA_SID
},
1630 { "tokenGroups", LDB_SYNTAX_SAMBA_SID
},
1631 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID
},
1632 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID
},
1633 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID
},
1634 { "sIDHistory", LDB_SYNTAX_SAMBA_SID
},
1635 { "syncWithSID", LDB_SYNTAX_SAMBA_SID
},
1638 * these are extracted by searching
1639 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1641 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID
},
1642 { "categoryId", LDB_SYNTAX_SAMBA_GUID
},
1643 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID
},
1644 { "currMachineId", LDB_SYNTAX_SAMBA_GUID
},
1645 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID
},
1646 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID
},
1647 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID
},
1648 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID
},
1649 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID
},
1650 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID
},
1651 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID
},
1652 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID
},
1653 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID
},
1654 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID
},
1655 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID
},
1656 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID
},
1657 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID
},
1658 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID
},
1659 { "objectGUID", LDB_SYNTAX_SAMBA_GUID
},
1660 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID
},
1661 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID
},
1662 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID
},
1663 { "siteGUID", LDB_SYNTAX_SAMBA_GUID
},
1664 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1665 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1666 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1667 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID
},
1668 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID
},
1671 * these are known to be GUIDs
1673 { "invocationId", LDB_SYNTAX_SAMBA_GUID
},
1674 { "parentGUID", LDB_SYNTAX_SAMBA_GUID
},
1676 /* These NDR encoded things we want to be able to read with --show-binary */
1677 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD
},
1678 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY
},
1679 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
},
1680 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
}
1683 const struct ldb_schema_syntax
*ldb_samba_syntax_by_name(struct ldb_context
*ldb
, const char *name
)
1686 const struct ldb_schema_syntax
*s
= NULL
;
1688 for (j
=0; j
< ARRAY_SIZE(samba_syntaxes
); j
++) {
1689 if (strcmp(name
, samba_syntaxes
[j
].name
) == 0) {
1690 s
= &samba_syntaxes
[j
];
1697 const struct ldb_schema_syntax
*ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context
*ldb
, const char *name
)
1700 const struct ldb_schema_syntax
*s
= NULL
;
1702 for (j
=0; j
< ARRAY_SIZE(samba_attributes
); j
++) {
1703 if (strcmp(samba_attributes
[j
].name
, name
) == 0) {
1704 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[j
].syntax
);
1712 static const char *secret_attributes
[] = {DSDB_SECRET_ATTRIBUTES
, "secret",
1713 "priorSecret", NULL
};
1716 register the samba ldif handlers
1718 int ldb_register_samba_handlers(struct ldb_context
*ldb
)
1723 if (ldb_get_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED") != NULL
) {
1727 ret
= ldb_set_opaque(ldb
, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE
, discard_const_p(char *, secret_attributes
));
1728 if (ret
!= LDB_SUCCESS
) {
1732 for (i
=0; i
< ARRAY_SIZE(samba_attributes
); i
++) {
1733 const struct ldb_schema_syntax
*s
= NULL
;
1735 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1738 s
= ldb_standard_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1742 return LDB_ERR_OPERATIONS_ERROR
;
1745 ret
= ldb_schema_attribute_add_with_syntax(ldb
, samba_attributes
[i
].name
, LDB_ATTR_FLAG_FIXED
, s
);
1746 if (ret
!= LDB_SUCCESS
) {
1751 for (i
=0; i
< ARRAY_SIZE(samba_dn_syntax
); i
++) {
1752 ret
= ldb_dn_extended_add_syntax(ldb
, LDB_ATTR_FLAG_FIXED
, &samba_dn_syntax
[i
]);
1753 if (ret
!= LDB_SUCCESS
) {
1759 ret
= ldb_register_samba_matching_rules(ldb
);
1760 if (ret
!= LDB_SUCCESS
) {
1765 ret
= ldb_set_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1766 if (ret
!= LDB_SUCCESS
) {