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]) {
603 p
=strchr(line
, '\n');
608 /* allow a trailing separator */
613 blob
->ctr
.dsdb
.mappings
= talloc_realloc(blob
,
614 blob
->ctr
.dsdb
.mappings
,
615 struct drsuapi_DsReplicaOIDMapping
,
616 blob
->ctr
.dsdb
.num_mappings
+1);
617 if (!blob
->ctr
.dsdb
.mappings
) {
618 talloc_free(tmp_ctx
);
622 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].id_prefix
= strtoul(line
, &oid
, 10);
625 talloc_free(tmp_ctx
);
629 /* we know there must be at least ":" */
632 if (!ber_write_partial_OID_String(blob
->ctr
.dsdb
.mappings
, &oid_blob
, oid
)) {
633 talloc_free(tmp_ctx
);
636 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.length
= oid_blob
.length
;
637 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.binary_oid
= oid_blob
.data
;
639 blob
->ctr
.dsdb
.num_mappings
++;
641 /* Now look past the terminator we added above */
649 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
651 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
652 talloc_free(tmp_ctx
);
653 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
660 convert a NDR formatted blob to a ldif formatted prefixMap
662 static int ldif_write_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
663 const struct ldb_val
*in
, struct ldb_val
*out
)
665 struct prefixMapBlob
*blob
;
666 enum ndr_err_code ndr_err
;
670 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
672 /* try to decode the blob as S4 prefixMap */
673 err
= ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
674 sizeof(struct prefixMapBlob
),
675 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
,
676 (ndr_print_fn_t
)ndr_print_prefixMapBlob
,
681 /* try parsing it as Windows PrefixMap value */
682 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
683 sizeof(struct drsuapi_MSPrefixMap_Ctr
),
684 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_MSPrefixMap_Ctr
,
685 (ndr_print_fn_t
)ndr_print_drsuapi_MSPrefixMap_Ctr
,
689 blob
= talloc(mem_ctx
, struct prefixMapBlob
);
693 ndr_err
= ndr_pull_struct_blob_all(in
, blob
,
695 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
696 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
699 if (blob
->version
!= PREFIX_MAP_VERSION_DSDB
) {
702 string
= talloc_strdup(mem_ctx
, "");
703 if (string
== NULL
) {
707 for (i
=0; i
< blob
->ctr
.dsdb
.num_mappings
; i
++) {
709 char *partial_oid
= NULL
;
712 string
= talloc_asprintf_append(string
, ";");
715 oid_blob
= data_blob_const(blob
->ctr
.dsdb
.mappings
[i
].oid
.binary_oid
,
716 blob
->ctr
.dsdb
.mappings
[i
].oid
.length
);
717 if (!ber_read_partial_OID_String(blob
, oid_blob
, &partial_oid
)) {
718 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
719 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
));
722 string
= talloc_asprintf_append(string
, "%u:%s",
723 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
,
725 talloc_free(discard_const(partial_oid
));
726 if (string
== NULL
) {
732 *out
= data_blob_string_const(string
);
740 static bool ldif_comparision_prefixMap_isString(const struct ldb_val
*v
)
746 if (IVAL(v
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
754 canonicalise a prefixMap
756 static int ldif_canonicalise_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
757 const struct ldb_val
*in
, struct ldb_val
*out
)
759 if (ldif_comparision_prefixMap_isString(in
)) {
760 return ldif_read_prefixMap(ldb
, mem_ctx
, in
, out
);
762 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
765 static int ldif_comparison_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
766 const struct ldb_val
*v1
,
767 const struct ldb_val
*v2
)
769 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_prefixMap
,
773 /* length limited conversion of a ldb_val to a int32_t */
774 static int val_to_int32(const struct ldb_val
*in
, int32_t *v
)
779 /* make sure we don't read past the end of the data */
780 if (in
->length
> sizeof(buf
)-1) {
781 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
783 strncpy(buf
, (char *)in
->data
, in
->length
);
786 /* We've to use "strtoll" here to have the intended overflows.
787 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
788 *v
= (int32_t) strtoll(buf
, &end
, 0);
790 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
795 /* length limited conversion of a ldb_val to a int64_t */
796 static int val_to_int64(const struct ldb_val
*in
, int64_t *v
)
801 /* make sure we don't read past the end of the data */
802 if (in
->length
> sizeof(buf
)-1) {
803 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
805 strncpy(buf
, (char *)in
->data
, in
->length
);
808 *v
= (int64_t) strtoll(buf
, &end
, 0);
810 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
815 /* Canonicalisation of two 32-bit integers */
816 static int ldif_canonicalise_int32(struct ldb_context
*ldb
, void *mem_ctx
,
817 const struct ldb_val
*in
, struct ldb_val
*out
)
822 ret
= val_to_int32(in
, &i
);
823 if (ret
!= LDB_SUCCESS
) {
826 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%d", i
);
827 if (out
->data
== NULL
) {
829 return LDB_ERR_OPERATIONS_ERROR
;
831 out
->length
= strlen((char *)out
->data
);
835 /* Comparison of two 32-bit integers */
836 static int ldif_comparison_int32(struct ldb_context
*ldb
, void *mem_ctx
,
837 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
840 val_to_int32(v1
, &i1
);
841 val_to_int32(v2
, &i2
);
842 if (i1
== i2
) return 0;
843 return i1
> i2
? 1 : -1;
846 /* Canonicalisation of two 64-bit integers */
847 static int ldif_canonicalise_int64(struct ldb_context
*ldb
, void *mem_ctx
,
848 const struct ldb_val
*in
, struct ldb_val
*out
)
853 ret
= val_to_int64(in
, &i
);
854 if (ret
!= LDB_SUCCESS
) {
857 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%lld", (long long)i
);
858 if (out
->data
== NULL
) {
860 return LDB_ERR_OPERATIONS_ERROR
;
862 out
->length
= strlen((char *)out
->data
);
866 /* Comparison of two 64-bit integers */
867 static int ldif_comparison_int64(struct ldb_context
*ldb
, void *mem_ctx
,
868 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
871 val_to_int64(v1
, &i1
);
872 val_to_int64(v2
, &i2
);
873 if (i1
== i2
) return 0;
874 return i1
> i2
? 1 : -1;
878 convert a NDR formatted blob to a ldif formatted repsFromTo
880 static int ldif_write_repsFromTo(struct ldb_context
*ldb
, void *mem_ctx
,
881 const struct ldb_val
*in
, struct ldb_val
*out
)
883 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
884 sizeof(struct repsFromToBlob
),
885 (ndr_pull_flags_fn_t
)ndr_pull_repsFromToBlob
,
886 (ndr_print_fn_t
)ndr_print_repsFromToBlob
,
891 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
893 static int ldif_write_replPropertyMetaData(struct ldb_context
*ldb
, void *mem_ctx
,
894 const struct ldb_val
*in
, struct ldb_val
*out
)
896 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
897 sizeof(struct replPropertyMetaDataBlob
),
898 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaDataBlob
,
899 (ndr_print_fn_t
)ndr_print_replPropertyMetaDataBlob
,
904 convert a NDR formatted blob to a ldif formatted replUpToDateVector
906 static int ldif_write_replUpToDateVector(struct ldb_context
*ldb
, void *mem_ctx
,
907 const struct ldb_val
*in
, struct ldb_val
*out
)
909 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
910 sizeof(struct replUpToDateVectorBlob
),
911 (ndr_pull_flags_fn_t
)ndr_pull_replUpToDateVectorBlob
,
912 (ndr_print_fn_t
)ndr_print_replUpToDateVectorBlob
,
916 static int ldif_write_dn_binary_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
917 const struct ldb_val
*in
, struct ldb_val
*out
,
919 ndr_pull_flags_fn_t pull_fn
,
920 ndr_print_fn_t print_fn
,
924 enum ndr_err_code err
;
925 struct dsdb_dn
*dsdb_dn
= NULL
;
929 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
930 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
933 dsdb_dn
= dsdb_dn_parse(mem_ctx
, ldb
, in
, DSDB_SYNTAX_BINARY_DN
);
934 if (dsdb_dn
== NULL
) {
935 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
938 p
= talloc_size(dsdb_dn
, struct_size
);
940 TALLOC_FREE(dsdb_dn
);
941 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
944 err
= ndr_pull_struct_blob(&dsdb_dn
->extra_part
, p
, p
, pull_fn
);
945 if (err
!= NDR_ERR_SUCCESS
) {
946 /* fail in not in mask_error mode */
950 TALLOC_FREE(dsdb_dn
);
951 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
954 dn_str
= ldb_dn_get_extended_linearized(dsdb_dn
, dsdb_dn
->dn
, 1);
955 if (dn_str
== NULL
) {
956 TALLOC_FREE(dsdb_dn
);
957 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
960 str
= ndr_print_struct_string(mem_ctx
, print_fn
, dn_str
, p
);
961 TALLOC_FREE(dsdb_dn
);
963 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
966 *out
= data_blob_string_const(str
);
970 static int ldif_write_msDS_RevealedUsers(struct ldb_context
*ldb
, void *mem_ctx
,
971 const struct ldb_val
*in
, struct ldb_val
*out
)
973 return ldif_write_dn_binary_NDR(ldb
, mem_ctx
, in
, out
,
974 sizeof(struct replPropertyMetaData1
),
975 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaData1
,
976 (ndr_print_fn_t
)ndr_print_replPropertyMetaData1
,
981 convert a NDR formatted blob to a ldif formatted dnsRecord
983 static int ldif_write_dnsRecord(struct ldb_context
*ldb
, void *mem_ctx
,
984 const struct ldb_val
*in
, struct ldb_val
*out
)
986 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
987 sizeof(struct dnsp_DnssrvRpcRecord
),
988 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
,
989 (ndr_print_fn_t
)ndr_print_dnsp_DnssrvRpcRecord
,
994 convert a NDR formatted blob to a ldif formatted dnsProperty
996 static int ldif_write_dnsProperty(struct ldb_context
*ldb
, void *mem_ctx
,
997 const struct ldb_val
*in
, struct ldb_val
*out
)
999 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1000 sizeof(struct dnsp_DnsProperty
),
1001 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnsProperty
,
1002 (ndr_print_fn_t
)ndr_print_dnsp_DnsProperty
,
1007 convert a NDR formatted blob of a supplementalCredentials into text
1009 static int ldif_write_supplementalCredentialsBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1010 const struct ldb_val
*in
, struct ldb_val
*out
)
1012 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1013 sizeof(struct supplementalCredentialsBlob
),
1014 (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
,
1015 (ndr_print_fn_t
)ndr_print_supplementalCredentialsBlob
,
1020 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1022 static int ldif_write_trustAuthInOutBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1023 const struct ldb_val
*in
, struct ldb_val
*out
)
1025 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1026 sizeof(struct trustAuthInOutBlob
),
1027 (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
,
1028 (ndr_print_fn_t
)ndr_print_trustAuthInOutBlob
,
1033 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1035 static int ldif_write_ForestTrustInfo(struct ldb_context
*ldb
, void *mem_ctx
,
1036 const struct ldb_val
*in
, struct ldb_val
*out
)
1038 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1039 sizeof(struct ForestTrustInfo
),
1040 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
,
1041 (ndr_print_fn_t
)ndr_print_ForestTrustInfo
,
1045 convert a NDR formatted blob of a partialAttributeSet into text
1047 static int ldif_write_partialAttributeSet(struct ldb_context
*ldb
, void *mem_ctx
,
1048 const struct ldb_val
*in
, struct ldb_val
*out
)
1050 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1051 sizeof(struct partialAttributeSetBlob
),
1052 (ndr_pull_flags_fn_t
)ndr_pull_partialAttributeSetBlob
,
1053 (ndr_print_fn_t
)ndr_print_partialAttributeSetBlob
,
1058 static int extended_dn_write_hex(struct ldb_context
*ldb
, void *mem_ctx
,
1059 const struct ldb_val
*in
, struct ldb_val
*out
)
1061 *out
= data_blob_string_const(data_blob_hex_string_lower(mem_ctx
, in
));
1071 static int samba_ldb_dn_link_comparison(struct ldb_context
*ldb
, void *mem_ctx
,
1072 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1074 struct ldb_dn
*dn1
= NULL
, *dn2
= NULL
;
1077 if (dsdb_dn_is_deleted_val(v1
)) {
1078 /* If the DN is deleted, then we can't search for it */
1082 if (dsdb_dn_is_deleted_val(v2
)) {
1083 /* If the DN is deleted, then we can't search for it */
1087 dn1
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v1
);
1088 if ( ! ldb_dn_validate(dn1
)) return -1;
1090 dn2
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v2
);
1091 if ( ! ldb_dn_validate(dn2
)) {
1096 ret
= ldb_dn_compare(dn1
, dn2
);
1103 static int samba_ldb_dn_link_canonicalise(struct ldb_context
*ldb
, void *mem_ctx
,
1104 const struct ldb_val
*in
, struct ldb_val
*out
)
1112 dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, in
);
1113 if ( ! ldb_dn_validate(dn
)) {
1114 return LDB_ERR_INVALID_DN_SYNTAX
;
1117 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1118 * does not casually match a not deleted DN */
1119 if (dsdb_dn_is_deleted_val(in
)) {
1120 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
,
1122 dsdb_dn_val_rmd_flags(in
),
1123 ldb_dn_get_casefold(dn
));
1125 out
->data
= (uint8_t *)ldb_dn_alloc_casefold(mem_ctx
, dn
);
1128 if (out
->data
== NULL
) {
1131 out
->length
= strlen((char *)out
->data
);
1143 write a 64 bit 2-part range
1145 static int ldif_write_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1146 const struct ldb_val
*in
, struct ldb_val
*out
)
1150 ret
= val_to_int64(in
, &v
);
1151 if (ret
!= LDB_SUCCESS
) {
1154 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%lu-%lu",
1155 (unsigned long)(v
&0xFFFFFFFF),
1156 (unsigned long)(v
>>32));
1157 if (out
->data
== NULL
) {
1159 return LDB_ERR_OPERATIONS_ERROR
;
1161 out
->length
= strlen((char *)out
->data
);
1166 read a 64 bit 2-part range
1168 static int ldif_read_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1169 const struct ldb_val
*in
, struct ldb_val
*out
)
1171 unsigned long high
, low
;
1174 if (memchr(in
->data
, '-', in
->length
) == NULL
) {
1175 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1178 if (in
->length
> sizeof(buf
)-1) {
1179 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1181 strncpy(buf
, (const char *)in
->data
, in
->length
);
1182 buf
[in
->length
] = 0;
1184 if (sscanf(buf
, "%lu-%lu", &low
, &high
) != 2) {
1185 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1188 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%llu",
1189 (unsigned long long)(((uint64_t)high
)<<32) | (low
));
1191 if (out
->data
== NULL
) {
1193 return LDB_ERR_OPERATIONS_ERROR
;
1195 out
->length
= strlen((char *)out
->data
);
1200 when this operator_fn is set for a syntax, the backend calls is in
1201 preference to the comparison function. We are told the exact
1202 comparison operation that is needed, and we can return errors
1204 static int samba_syntax_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1205 const struct ldb_schema_attribute
*a
,
1206 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1208 switch (operation
) {
1212 case LDB_OP_SUBSTRING
:
1214 case LDB_OP_EXTENDED
:
1215 /* handled in the backends */
1216 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1218 case LDB_OP_GREATER
:
1220 case LDB_OP_EQUALITY
:
1222 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
1224 if (tmp_ctx
== NULL
) {
1225 return ldb_oom(ldb
);
1227 ret
= a
->syntax
->comparison_fn(ldb
, tmp_ctx
, v1
, v2
);
1228 talloc_free(tmp_ctx
);
1229 if (operation
== LDB_OP_GREATER
) {
1230 *matched
= (ret
>= 0);
1231 } else if (operation
== LDB_OP_LESS
) {
1232 *matched
= (ret
<= 0);
1234 *matched
= (ret
== 0);
1239 case LDB_OP_PRESENT
:
1244 /* we shouldn't get here */
1245 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1249 compare two binary objects. This is correct for sorting as the sort order is:
1256 rather than ldb_comparison_binary() which is:
1264 static int samba_ldb_comparison_binary(struct ldb_context
*ldb
, void *mem_ctx
,
1265 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1267 return data_blob_cmp(v1
, v2
);
1271 when this operator_fn is set for a syntax, the backend calls is in
1272 preference to the comparison function. We are told the exact
1273 comparison operation that is needed, and we can return errors.
1275 This mode optimises for ldb_comparison_binary() if we need equality,
1276 as this should be faster as it can do a length-check first.
1278 static int samba_syntax_binary_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1279 const struct ldb_schema_attribute
*a
,
1280 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1282 if (operation
== LDB_OP_EQUALITY
) {
1283 *matched
= (ldb_comparison_binary(ldb
, NULL
, v1
, v2
) == 0);
1286 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1290 see if two DNs match, comparing first by GUID, then by SID, and
1291 finally by string components
1293 static int samba_dn_extended_match(struct ldb_context
*ldb
,
1294 const struct ldb_val
*v1
,
1295 const struct ldb_val
*v2
,
1298 TALLOC_CTX
*tmp_ctx
;
1299 struct ldb_dn
*dn1
, *dn2
;
1300 const struct ldb_val
*guid1
, *guid2
, *sid1
, *sid2
;
1301 uint32_t rmd_flags1
, rmd_flags2
;
1303 tmp_ctx
= talloc_new(ldb
);
1305 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v1
);
1306 dn2
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v2
);
1308 /* couldn't parse as DN's */
1309 talloc_free(tmp_ctx
);
1314 rmd_flags1
= dsdb_dn_rmd_flags(dn1
);
1315 rmd_flags2
= dsdb_dn_rmd_flags(dn2
);
1317 if ((rmd_flags1
& DSDB_RMD_FLAG_DELETED
) !=
1318 (rmd_flags2
& DSDB_RMD_FLAG_DELETED
)) {
1319 /* only match if they have the same deletion status */
1320 talloc_free(tmp_ctx
);
1326 guid1
= ldb_dn_get_extended_component(dn1
, "GUID");
1327 guid2
= ldb_dn_get_extended_component(dn2
, "GUID");
1328 if (guid1
&& guid2
) {
1329 (*matched
) = (data_blob_cmp(guid1
, guid2
) == 0);
1330 talloc_free(tmp_ctx
);
1334 sid1
= ldb_dn_get_extended_component(dn1
, "SID");
1335 sid2
= ldb_dn_get_extended_component(dn2
, "SID");
1337 (*matched
) = (data_blob_cmp(sid1
, sid2
) == 0);
1338 talloc_free(tmp_ctx
);
1342 (*matched
) = (ldb_dn_compare(dn1
, dn2
) == 0);
1344 talloc_free(tmp_ctx
);
1349 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1351 static int samba_syntax_operator_dn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1352 const struct ldb_schema_attribute
*a
,
1353 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1355 if (operation
== LDB_OP_PRESENT
&& dsdb_dn_is_deleted_val(v1
)) {
1356 /* If the DN is deleted, then we can't search for it */
1358 /* should this be for equality too? */
1363 if (operation
== LDB_OP_EQUALITY
&&
1364 samba_dn_extended_match(ldb
, v1
, v2
, matched
) == LDB_SUCCESS
) {
1368 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1372 static const struct ldb_schema_syntax samba_syntaxes
[] = {
1374 .name
= LDB_SYNTAX_SAMBA_SID
,
1375 .ldif_read_fn
= ldif_read_objectSid
,
1376 .ldif_write_fn
= ldif_write_objectSid
,
1377 .canonicalise_fn
= ldif_canonicalise_objectSid
,
1378 .comparison_fn
= ldif_comparison_objectSid
,
1379 .operator_fn
= samba_syntax_operator_fn
1381 .name
= LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
,
1382 .ldif_read_fn
= ldif_read_ntSecurityDescriptor
,
1383 .ldif_write_fn
= ldif_write_ntSecurityDescriptor
,
1384 .canonicalise_fn
= ldb_handler_copy
,
1385 .comparison_fn
= samba_ldb_comparison_binary
,
1386 .operator_fn
= samba_syntax_binary_operator_fn
1388 .name
= LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
,
1389 .ldif_read_fn
= ldb_handler_copy
,
1390 .ldif_write_fn
= ldif_write_sddlSecurityDescriptor
,
1391 .canonicalise_fn
= ldb_handler_fold
,
1392 .comparison_fn
= ldb_comparison_fold
,
1393 .operator_fn
= samba_syntax_operator_fn
1395 .name
= LDB_SYNTAX_SAMBA_GUID
,
1396 .ldif_read_fn
= ldif_read_objectGUID
,
1397 .ldif_write_fn
= ldif_write_objectGUID
,
1398 .canonicalise_fn
= ldif_canonicalise_objectGUID
,
1399 .comparison_fn
= ldif_comparison_objectGUID
,
1400 .operator_fn
= samba_syntax_operator_fn
1402 .name
= LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
,
1403 .ldif_read_fn
= ldb_handler_copy
,
1404 .ldif_write_fn
= ldb_handler_copy
,
1405 .canonicalise_fn
= ldif_canonicalise_objectCategory
,
1406 .comparison_fn
= ldif_comparison_objectCategory
,
1407 .operator_fn
= samba_syntax_operator_fn
1409 .name
= LDB_SYNTAX_SAMBA_SCHEMAINFO
,
1410 .ldif_read_fn
= ldb_handler_copy
,
1411 .ldif_write_fn
= ldif_write_schemaInfo
,
1412 .canonicalise_fn
= ldb_handler_copy
,
1413 .comparison_fn
= samba_ldb_comparison_binary
,
1414 .operator_fn
= samba_syntax_binary_operator_fn
1416 .name
= LDB_SYNTAX_SAMBA_PREFIX_MAP
,
1417 .ldif_read_fn
= ldif_read_prefixMap
,
1418 .ldif_write_fn
= ldif_write_prefixMap
,
1419 .canonicalise_fn
= ldif_canonicalise_prefixMap
,
1420 .comparison_fn
= ldif_comparison_prefixMap
,
1421 .operator_fn
= samba_syntax_operator_fn
1423 .name
= LDB_SYNTAX_SAMBA_INT32
,
1424 .ldif_read_fn
= ldb_handler_copy
,
1425 .ldif_write_fn
= ldb_handler_copy
,
1426 .canonicalise_fn
= ldif_canonicalise_int32
,
1427 .comparison_fn
= ldif_comparison_int32
,
1428 .operator_fn
= samba_syntax_operator_fn
1430 .name
= LDB_SYNTAX_SAMBA_REPSFROMTO
,
1431 .ldif_read_fn
= ldb_handler_copy
,
1432 .ldif_write_fn
= ldif_write_repsFromTo
,
1433 .canonicalise_fn
= ldb_handler_copy
,
1434 .comparison_fn
= samba_ldb_comparison_binary
,
1435 .operator_fn
= samba_syntax_binary_operator_fn
1437 .name
= LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
,
1438 .ldif_read_fn
= ldb_handler_copy
,
1439 .ldif_write_fn
= ldif_write_replPropertyMetaData
,
1440 .canonicalise_fn
= ldb_handler_copy
,
1441 .comparison_fn
= samba_ldb_comparison_binary
,
1442 .operator_fn
= samba_syntax_binary_operator_fn
1444 .name
= LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
,
1445 .ldif_read_fn
= ldb_handler_copy
,
1446 .ldif_write_fn
= ldif_write_replUpToDateVector
,
1447 .canonicalise_fn
= ldb_handler_copy
,
1448 .comparison_fn
= samba_ldb_comparison_binary
,
1449 .operator_fn
= samba_syntax_binary_operator_fn
1451 .name
= LDB_SYNTAX_SAMBA_REVEALEDUSERS
,
1452 .ldif_read_fn
= ldb_handler_copy
,
1453 .ldif_write_fn
= ldif_write_msDS_RevealedUsers
,
1454 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1455 .comparison_fn
= dsdb_dn_binary_comparison
,
1456 .operator_fn
= samba_syntax_operator_fn
1458 .name
= LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
,
1459 .ldif_read_fn
= ldb_handler_copy
,
1460 .ldif_write_fn
= ldif_write_trustAuthInOutBlob
,
1461 .canonicalise_fn
= ldb_handler_copy
,
1462 .comparison_fn
= samba_ldb_comparison_binary
,
1463 .operator_fn
= samba_syntax_binary_operator_fn
1465 .name
= LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
,
1466 .ldif_read_fn
= ldb_handler_copy
,
1467 .ldif_write_fn
= ldif_write_ForestTrustInfo
,
1468 .canonicalise_fn
= ldb_handler_copy
,
1469 .comparison_fn
= samba_ldb_comparison_binary
,
1470 .operator_fn
= samba_syntax_binary_operator_fn
1472 .name
= DSDB_SYNTAX_BINARY_DN
,
1473 .ldif_read_fn
= ldb_handler_copy
,
1474 .ldif_write_fn
= ldb_handler_copy
,
1475 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1476 .comparison_fn
= dsdb_dn_binary_comparison
,
1477 .operator_fn
= samba_syntax_operator_fn
1479 .name
= DSDB_SYNTAX_STRING_DN
,
1480 .ldif_read_fn
= ldb_handler_copy
,
1481 .ldif_write_fn
= ldb_handler_copy
,
1482 .canonicalise_fn
= dsdb_dn_string_canonicalise
,
1483 .comparison_fn
= dsdb_dn_string_comparison
,
1484 .operator_fn
= samba_syntax_operator_fn
1486 .name
= LDB_SYNTAX_DN
,
1487 .ldif_read_fn
= ldb_handler_copy
,
1488 .ldif_write_fn
= ldb_handler_copy
,
1489 .canonicalise_fn
= samba_ldb_dn_link_canonicalise
,
1490 .comparison_fn
= samba_ldb_dn_link_comparison
,
1491 .operator_fn
= samba_syntax_operator_dn
1493 .name
= LDB_SYNTAX_SAMBA_RANGE64
,
1494 .ldif_read_fn
= ldif_read_range64
,
1495 .ldif_write_fn
= ldif_write_range64
,
1496 .canonicalise_fn
= ldif_canonicalise_int64
,
1497 .comparison_fn
= ldif_comparison_int64
,
1498 .operator_fn
= samba_syntax_operator_fn
1500 .name
= LDB_SYNTAX_SAMBA_DNSRECORD
,
1501 .ldif_read_fn
= ldb_handler_copy
,
1502 .ldif_write_fn
= ldif_write_dnsRecord
,
1503 .canonicalise_fn
= ldb_handler_copy
,
1504 .comparison_fn
= samba_ldb_comparison_binary
,
1505 .operator_fn
= samba_syntax_binary_operator_fn
1507 .name
= LDB_SYNTAX_SAMBA_DNSPROPERTY
,
1508 .ldif_read_fn
= ldb_handler_copy
,
1509 .ldif_write_fn
= ldif_write_dnsProperty
,
1510 .canonicalise_fn
= ldb_handler_copy
,
1511 .comparison_fn
= samba_ldb_comparison_binary
,
1512 .operator_fn
= samba_syntax_binary_operator_fn
1514 .name
= LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
,
1515 .ldif_read_fn
= ldb_handler_copy
,
1516 .ldif_write_fn
= ldif_write_supplementalCredentialsBlob
,
1517 .canonicalise_fn
= ldb_handler_copy
,
1518 .comparison_fn
= samba_ldb_comparison_binary
,
1519 .operator_fn
= samba_syntax_binary_operator_fn
1521 .name
= LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
,
1522 .ldif_read_fn
= ldb_handler_copy
,
1523 .ldif_write_fn
= ldif_write_partialAttributeSet
,
1524 .canonicalise_fn
= ldb_handler_copy
,
1525 .comparison_fn
= samba_ldb_comparison_binary
,
1526 .operator_fn
= samba_syntax_binary_operator_fn
1528 .name
= LDB_SYNTAX_SAMBA_OCTET_STRING
,
1529 .ldif_read_fn
= ldb_handler_copy
,
1530 .ldif_write_fn
= ldb_handler_copy
,
1531 .canonicalise_fn
= ldb_handler_copy
,
1532 .comparison_fn
= samba_ldb_comparison_binary
,
1533 .operator_fn
= samba_syntax_binary_operator_fn
1537 static const struct ldb_dn_extended_syntax samba_dn_syntax
[] = {
1540 .read_fn
= extended_dn_read_SID
,
1541 .write_clear_fn
= ldif_write_objectSid
,
1542 .write_hex_fn
= extended_dn_write_hex
1545 .read_fn
= extended_dn_read_GUID
,
1546 .write_clear_fn
= ldif_write_objectGUID
,
1547 .write_hex_fn
= extended_dn_write_hex
1550 .read_fn
= ldb_handler_copy
,
1551 .write_clear_fn
= ldb_handler_copy
,
1552 .write_hex_fn
= ldb_handler_copy
1554 .name
= "RMD_INVOCID",
1555 .read_fn
= extended_dn_read_GUID
,
1556 .write_clear_fn
= ldif_write_objectGUID
,
1557 .write_hex_fn
= extended_dn_write_hex
1559 .name
= "RMD_FLAGS",
1560 .read_fn
= ldb_handler_copy
,
1561 .write_clear_fn
= ldb_handler_copy
,
1562 .write_hex_fn
= ldb_handler_copy
1564 .name
= "RMD_ADDTIME",
1565 .read_fn
= ldb_handler_copy
,
1566 .write_clear_fn
= ldb_handler_copy
,
1567 .write_hex_fn
= ldb_handler_copy
1569 .name
= "RMD_CHANGETIME",
1570 .read_fn
= ldb_handler_copy
,
1571 .write_clear_fn
= ldb_handler_copy
,
1572 .write_hex_fn
= ldb_handler_copy
1574 .name
= "RMD_LOCAL_USN",
1575 .read_fn
= ldb_handler_copy
,
1576 .write_clear_fn
= ldb_handler_copy
,
1577 .write_hex_fn
= ldb_handler_copy
1579 .name
= "RMD_ORIGINATING_USN",
1580 .read_fn
= ldb_handler_copy
,
1581 .write_clear_fn
= ldb_handler_copy
,
1582 .write_hex_fn
= ldb_handler_copy
1584 .name
= "RMD_VERSION",
1585 .read_fn
= ldb_handler_copy
,
1586 .write_clear_fn
= ldb_handler_copy
,
1587 .write_hex_fn
= ldb_handler_copy
1591 /* TODO: Should be dynamic at some point */
1592 static const struct {
1595 } samba_attributes
[] = {
1596 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
},
1597 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32
},
1598 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
},
1599 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO
},
1600 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP
},
1601 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1602 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1603 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
},
1604 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
},
1605 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS
},
1606 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1607 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1608 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
},
1609 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1610 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1611 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64
},
1612 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
},
1615 * these are extracted by searching
1616 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1618 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1619 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1620 * hat can be used to identify the set of policies when applied to a resource.
1621 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1622 * server, we ignore it here.
1624 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID
},
1625 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID
},
1626 { "objectSid", LDB_SYNTAX_SAMBA_SID
},
1627 { "tokenGroups", LDB_SYNTAX_SAMBA_SID
},
1628 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID
},
1629 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID
},
1630 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID
},
1631 { "sIDHistory", LDB_SYNTAX_SAMBA_SID
},
1632 { "syncWithSID", LDB_SYNTAX_SAMBA_SID
},
1635 * these are extracted by searching
1636 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1638 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID
},
1639 { "categoryId", LDB_SYNTAX_SAMBA_GUID
},
1640 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID
},
1641 { "currMachineId", LDB_SYNTAX_SAMBA_GUID
},
1642 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID
},
1643 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID
},
1644 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID
},
1645 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID
},
1646 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID
},
1647 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID
},
1648 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID
},
1649 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID
},
1650 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID
},
1651 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID
},
1652 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID
},
1653 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID
},
1654 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID
},
1655 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID
},
1656 { "objectGUID", LDB_SYNTAX_SAMBA_GUID
},
1657 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID
},
1658 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID
},
1659 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID
},
1660 { "siteGUID", LDB_SYNTAX_SAMBA_GUID
},
1661 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1662 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1663 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1664 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID
},
1665 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID
},
1668 * these are known to be GUIDs
1670 { "invocationId", LDB_SYNTAX_SAMBA_GUID
},
1671 { "parentGUID", LDB_SYNTAX_SAMBA_GUID
},
1673 /* These NDR encoded things we want to be able to read with --show-binary */
1674 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD
},
1675 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY
},
1676 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
},
1677 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
}
1680 const struct ldb_schema_syntax
*ldb_samba_syntax_by_name(struct ldb_context
*ldb
, const char *name
)
1683 const struct ldb_schema_syntax
*s
= NULL
;
1685 for (j
=0; j
< ARRAY_SIZE(samba_syntaxes
); j
++) {
1686 if (strcmp(name
, samba_syntaxes
[j
].name
) == 0) {
1687 s
= &samba_syntaxes
[j
];
1694 const struct ldb_schema_syntax
*ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context
*ldb
, const char *name
)
1697 const struct ldb_schema_syntax
*s
= NULL
;
1699 for (j
=0; j
< ARRAY_SIZE(samba_attributes
); j
++) {
1700 if (strcmp(samba_attributes
[j
].name
, name
) == 0) {
1701 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[j
].syntax
);
1709 static const char *secret_attributes
[] = {DSDB_SECRET_ATTRIBUTES
, "secret", NULL
};
1712 register the samba ldif handlers
1714 int ldb_register_samba_handlers(struct ldb_context
*ldb
)
1719 if (ldb_get_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED") != NULL
) {
1723 ret
= ldb_set_opaque(ldb
, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE
, discard_const_p(char *, secret_attributes
));
1724 if (ret
!= LDB_SUCCESS
) {
1728 for (i
=0; i
< ARRAY_SIZE(samba_attributes
); i
++) {
1729 const struct ldb_schema_syntax
*s
= NULL
;
1731 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1734 s
= ldb_standard_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1738 return LDB_ERR_OPERATIONS_ERROR
;
1741 ret
= ldb_schema_attribute_add_with_syntax(ldb
, samba_attributes
[i
].name
, LDB_ATTR_FLAG_FIXED
, s
);
1742 if (ret
!= LDB_SUCCESS
) {
1747 for (i
=0; i
< ARRAY_SIZE(samba_dn_syntax
); i
++) {
1748 ret
= ldb_dn_extended_add_syntax(ldb
, LDB_ATTR_FLAG_FIXED
, &samba_dn_syntax
[i
]);
1749 if (ret
!= LDB_SUCCESS
) {
1755 ret
= ldb_register_samba_matching_rules(ldb
);
1756 if (ret
!= LDB_SUCCESS
) {
1761 ret
= ldb_set_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1762 if (ret
!= LDB_SUCCESS
) {