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
)
88 enum ndr_err_code ndr_err
;
90 sid
= dom_sid_parse_length(mem_ctx
, in
);
94 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, sid
,
95 (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
97 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
104 convert a NDR formatted blob to a ldif formatted objectSid
106 int ldif_write_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
107 const struct ldb_val
*in
, struct ldb_val
*out
)
110 enum ndr_err_code ndr_err
;
112 sid
= talloc(mem_ctx
, struct dom_sid
);
116 ndr_err
= ndr_pull_struct_blob_all(in
, sid
, sid
,
117 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
118 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
122 *out
= data_blob_string_const(dom_sid_string(mem_ctx
, sid
));
124 if (out
->data
== NULL
) {
130 bool ldif_comparision_objectSid_isString(const struct ldb_val
*v
)
136 if (strncmp("S-", (const char *)v
->data
, 2) != 0) return false;
142 compare two objectSids
144 static int ldif_comparison_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
145 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
147 if (ldif_comparision_objectSid_isString(v1
) && ldif_comparision_objectSid_isString(v2
)) {
148 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
149 } else if (ldif_comparision_objectSid_isString(v1
)
150 && !ldif_comparision_objectSid_isString(v2
)) {
153 if (ldif_read_objectSid(ldb
, mem_ctx
, v1
, &v
) != 0) {
154 /* Perhaps not a string after all */
155 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
157 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
160 } else if (!ldif_comparision_objectSid_isString(v1
)
161 && ldif_comparision_objectSid_isString(v2
)) {
164 if (ldif_read_objectSid(ldb
, mem_ctx
, v2
, &v
) != 0) {
165 /* Perhaps not a string after all */
166 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
168 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
172 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
176 canonicalise a objectSid
178 static int ldif_canonicalise_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
179 const struct ldb_val
*in
, struct ldb_val
*out
)
181 if (ldif_comparision_objectSid_isString(in
)) {
182 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) != 0) {
183 /* Perhaps not a string after all */
184 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
188 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
191 static int extended_dn_read_SID(struct ldb_context
*ldb
, void *mem_ctx
,
192 const struct ldb_val
*in
, struct ldb_val
*out
)
195 enum ndr_err_code ndr_err
;
196 if (ldif_comparision_objectSid_isString(in
)) {
197 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) == 0) {
202 /* Perhaps not a string after all */
203 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
209 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
210 (const char *)in
->data
, in
->length
);
212 /* Check it looks like a SID */
213 ndr_err
= ndr_pull_struct_blob_all(out
, mem_ctx
, &sid
,
214 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
215 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
222 convert a ldif formatted objectGUID to a NDR formatted blob
224 static int ldif_read_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
225 const struct ldb_val
*in
, struct ldb_val
*out
)
230 status
= GUID_from_data_blob(in
, &guid
);
231 if (!NT_STATUS_IS_OK(status
)) {
235 status
= GUID_to_ndr_blob(&guid
, mem_ctx
, out
);
236 if (!NT_STATUS_IS_OK(status
)) {
243 convert a NDR formatted blob to a ldif formatted objectGUID
245 static int ldif_write_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
246 const struct ldb_val
*in
, struct ldb_val
*out
)
251 status
= GUID_from_ndr_blob(in
, &guid
);
252 if (!NT_STATUS_IS_OK(status
)) {
255 out
->data
= (uint8_t *)GUID_string(mem_ctx
, &guid
);
256 if (out
->data
== NULL
) {
259 out
->length
= strlen((const char *)out
->data
);
263 static bool ldif_comparision_objectGUID_isString(const struct ldb_val
*v
)
265 if (v
->length
!= 36 && v
->length
!= 38) return false;
267 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
271 static int extended_dn_read_GUID(struct ldb_context
*ldb
, void *mem_ctx
,
272 const struct ldb_val
*in
, struct ldb_val
*out
)
277 if (in
->length
== 36 && ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) == 0) {
281 /* Try as 'hex' form */
282 if (in
->length
!= 32) {
286 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
292 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
293 (const char *)in
->data
, in
->length
);
295 /* Check it looks like a GUID */
296 status
= GUID_from_ndr_blob(out
, &guid
);
297 if (!NT_STATUS_IS_OK(status
)) {
305 compare two objectGUIDs
307 static int ldif_comparison_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
308 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
310 if (ldif_comparision_objectGUID_isString(v1
) && ldif_comparision_objectGUID_isString(v2
)) {
311 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
312 } else if (ldif_comparision_objectGUID_isString(v1
)
313 && !ldif_comparision_objectGUID_isString(v2
)) {
316 if (ldif_read_objectGUID(ldb
, mem_ctx
, v1
, &v
) != 0) {
317 /* Perhaps it wasn't a valid string after all */
318 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
320 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
323 } else if (!ldif_comparision_objectGUID_isString(v1
)
324 && ldif_comparision_objectGUID_isString(v2
)) {
327 if (ldif_read_objectGUID(ldb
, mem_ctx
, v2
, &v
) != 0) {
328 /* Perhaps it wasn't a valid string after all */
329 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
331 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
335 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
339 canonicalise a objectGUID
341 static int ldif_canonicalise_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
342 const struct ldb_val
*in
, struct ldb_val
*out
)
344 if (ldif_comparision_objectGUID_isString(in
)) {
345 if (ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) != 0) {
346 /* Perhaps it wasn't a valid string after all */
347 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
351 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
356 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
358 static int ldif_read_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
359 const struct ldb_val
*in
, struct ldb_val
*out
)
361 struct security_descriptor
*sd
;
362 enum ndr_err_code ndr_err
;
364 sd
= talloc(mem_ctx
, struct security_descriptor
);
369 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
370 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
371 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
372 /* If this does not parse, then it is probably SDDL, and we should try it that way */
374 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
376 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
382 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, sd
,
383 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
385 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
393 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
395 static int ldif_write_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
396 const struct ldb_val
*in
, struct ldb_val
*out
)
398 struct security_descriptor
*sd
;
399 enum ndr_err_code ndr_err
;
401 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
402 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
403 sizeof(struct security_descriptor
),
404 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
,
405 (ndr_print_fn_t
)ndr_print_security_descriptor
,
410 sd
= talloc(mem_ctx
, struct security_descriptor
);
414 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
415 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
416 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
417 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
421 out
->data
= (uint8_t *)sddl_encode(mem_ctx
, sd
, samdb_domain_sid_cache_only(ldb
));
423 if (out
->data
== NULL
) {
426 out
->length
= strlen((const char *)out
->data
);
431 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
433 static int ldif_write_sddlSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
434 const struct ldb_val
*in
, struct ldb_val
*out
)
436 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
437 struct security_descriptor
*sd
;
438 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
440 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
441 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
,
442 (ndr_print_fn_t
)ndr_print_security_descriptor
,
444 out
->length
= strlen((const char *)out
->data
);
449 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
453 canonicalise an objectCategory. We use the long form as the canonical form:
454 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
456 Also any short name of an objectClass that points to a different
457 class (such as user) has the canonical form of the class it's
458 defaultObjectCategory points to (eg
459 cn=Person,cn=Schema,cn=Configuration,<basedn>)
462 static int ldif_canonicalise_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
463 const struct ldb_val
*in
, struct ldb_val
*out
)
465 struct ldb_dn
*dn1
= NULL
;
466 const struct dsdb_schema
*schema
= dsdb_get_schema(ldb
, NULL
);
467 const struct dsdb_class
*sclass
;
468 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
470 return LDB_ERR_OPERATIONS_ERROR
;
474 talloc_free(tmp_ctx
);
475 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
476 if (in
->data
&& !out
->data
) {
477 return LDB_ERR_OPERATIONS_ERROR
;
481 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, in
);
482 if ( ! ldb_dn_validate(dn1
)) {
483 const char *lDAPDisplayName
= talloc_strndup(tmp_ctx
, (char *)in
->data
, in
->length
);
484 sclass
= dsdb_class_by_lDAPDisplayName(schema
, lDAPDisplayName
);
486 struct ldb_dn
*dn
= ldb_dn_new(tmp_ctx
, ldb
,
487 sclass
->defaultObjectCategory
);
489 talloc_free(tmp_ctx
);
490 return LDB_ERR_OPERATIONS_ERROR
;
493 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn
));
494 talloc_free(tmp_ctx
);
497 return LDB_ERR_OPERATIONS_ERROR
;
501 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
502 talloc_free(tmp_ctx
);
504 if (in
->data
&& !out
->data
) {
505 return LDB_ERR_OPERATIONS_ERROR
;
510 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn1
));
511 talloc_free(tmp_ctx
);
514 return LDB_ERR_OPERATIONS_ERROR
;
519 static int ldif_comparison_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
520 const struct ldb_val
*v1
,
521 const struct ldb_val
*v2
)
523 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_objectCategory
,
528 convert a NDR formatted blob to a ldif formatted schemaInfo
530 static int ldif_write_schemaInfo(struct ldb_context
*ldb
, void *mem_ctx
,
531 const struct ldb_val
*in
, struct ldb_val
*out
)
533 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
534 sizeof(struct repsFromToBlob
),
535 (ndr_pull_flags_fn_t
)ndr_pull_schemaInfoBlob
,
536 (ndr_print_fn_t
)ndr_print_schemaInfoBlob
,
541 convert a ldif formatted prefixMap to a NDR formatted blob
543 static int ldif_read_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
544 const struct ldb_val
*in
, struct ldb_val
*out
)
546 struct prefixMapBlob
*blob
;
547 enum ndr_err_code ndr_err
;
548 char *string
, *line
, *p
, *oid
;
551 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
553 if (tmp_ctx
== NULL
) {
557 blob
= talloc_zero(tmp_ctx
, struct prefixMapBlob
);
559 talloc_free(tmp_ctx
);
563 /* use the switch value to detect if this is in the binary
566 if (in
->length
>= 4 && IVAL(in
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
567 ndr_err
= ndr_pull_struct_blob(in
, tmp_ctx
, blob
,
568 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
569 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
570 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
572 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
573 talloc_free(tmp_ctx
);
574 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
581 /* If this does not parse, then it is probably the text version, and we should try it that way */
582 blob
->version
= PREFIX_MAP_VERSION_DSDB
;
584 string
= talloc_strndup(mem_ctx
, (const char *)in
->data
, in
->length
);
585 if (string
== NULL
) {
591 while (line
&& line
[0]) {
596 p
=strchr(line
, '\n');
601 /* allow a trailing separator */
606 blob
->ctr
.dsdb
.mappings
= talloc_realloc(blob
,
607 blob
->ctr
.dsdb
.mappings
,
608 struct drsuapi_DsReplicaOIDMapping
,
609 blob
->ctr
.dsdb
.num_mappings
+1);
610 if (!blob
->ctr
.dsdb
.mappings
) {
611 talloc_free(tmp_ctx
);
615 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].id_prefix
= strtoul(line
, &oid
, 10);
618 talloc_free(tmp_ctx
);
622 /* we know there must be at least ":" */
625 if (!ber_write_partial_OID_String(blob
->ctr
.dsdb
.mappings
, &oid_blob
, oid
)) {
626 talloc_free(tmp_ctx
);
629 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.length
= oid_blob
.length
;
630 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.binary_oid
= oid_blob
.data
;
632 blob
->ctr
.dsdb
.num_mappings
++;
634 /* Now look past the terminator we added above */
642 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
644 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
645 talloc_free(tmp_ctx
);
646 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
653 convert a NDR formatted blob to a ldif formatted prefixMap
655 static int ldif_write_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
656 const struct ldb_val
*in
, struct ldb_val
*out
)
658 struct prefixMapBlob
*blob
;
659 enum ndr_err_code ndr_err
;
663 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
665 /* try to decode the blob as S4 prefixMap */
666 err
= ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
667 sizeof(struct prefixMapBlob
),
668 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
,
669 (ndr_print_fn_t
)ndr_print_prefixMapBlob
,
674 /* try parsing it as Windows PrefixMap value */
675 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
676 sizeof(struct drsuapi_MSPrefixMap_Ctr
),
677 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_MSPrefixMap_Ctr
,
678 (ndr_print_fn_t
)ndr_print_drsuapi_MSPrefixMap_Ctr
,
682 blob
= talloc(mem_ctx
, struct prefixMapBlob
);
686 ndr_err
= ndr_pull_struct_blob_all(in
, blob
,
688 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
689 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
692 if (blob
->version
!= PREFIX_MAP_VERSION_DSDB
) {
695 string
= talloc_strdup(mem_ctx
, "");
696 if (string
== NULL
) {
700 for (i
=0; i
< blob
->ctr
.dsdb
.num_mappings
; i
++) {
702 char *partial_oid
= NULL
;
705 string
= talloc_asprintf_append(string
, ";");
708 oid_blob
= data_blob_const(blob
->ctr
.dsdb
.mappings
[i
].oid
.binary_oid
,
709 blob
->ctr
.dsdb
.mappings
[i
].oid
.length
);
710 if (!ber_read_partial_OID_String(blob
, oid_blob
, &partial_oid
)) {
711 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
712 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
));
715 string
= talloc_asprintf_append(string
, "%u:%s",
716 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
,
718 talloc_free(discard_const(partial_oid
));
719 if (string
== NULL
) {
725 *out
= data_blob_string_const(string
);
733 static bool ldif_comparision_prefixMap_isString(const struct ldb_val
*v
)
739 if (IVAL(v
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
747 canonicalise a prefixMap
749 static int ldif_canonicalise_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
750 const struct ldb_val
*in
, struct ldb_val
*out
)
752 if (ldif_comparision_prefixMap_isString(in
)) {
753 return ldif_read_prefixMap(ldb
, mem_ctx
, in
, out
);
755 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
758 static int ldif_comparison_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
759 const struct ldb_val
*v1
,
760 const struct ldb_val
*v2
)
762 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_prefixMap
,
766 /* length limited conversion of a ldb_val to a int32_t */
767 static int val_to_int32(const struct ldb_val
*in
, int32_t *v
)
772 /* make sure we don't read past the end of the data */
773 if (in
->length
> sizeof(buf
)-1) {
774 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
776 strncpy(buf
, (char *)in
->data
, in
->length
);
779 /* We've to use "strtoll" here to have the intended overflows.
780 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
781 *v
= (int32_t) strtoll(buf
, &end
, 0);
783 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
788 /* length limited conversion of a ldb_val to a int64_t */
789 static int val_to_int64(const struct ldb_val
*in
, int64_t *v
)
794 /* make sure we don't read past the end of the data */
795 if (in
->length
> sizeof(buf
)-1) {
796 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
798 strncpy(buf
, (char *)in
->data
, in
->length
);
801 *v
= (int64_t) strtoll(buf
, &end
, 0);
803 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
808 /* Canonicalisation of two 32-bit integers */
809 static int ldif_canonicalise_int32(struct ldb_context
*ldb
, void *mem_ctx
,
810 const struct ldb_val
*in
, struct ldb_val
*out
)
815 ret
= val_to_int32(in
, &i
);
816 if (ret
!= LDB_SUCCESS
) {
819 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%d", i
);
820 if (out
->data
== NULL
) {
822 return LDB_ERR_OPERATIONS_ERROR
;
824 out
->length
= strlen((char *)out
->data
);
828 /* Comparison of two 32-bit integers */
829 static int ldif_comparison_int32(struct ldb_context
*ldb
, void *mem_ctx
,
830 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
833 val_to_int32(v1
, &i1
);
834 val_to_int32(v2
, &i2
);
835 if (i1
== i2
) return 0;
836 return i1
> i2
? 1 : -1;
839 /* Canonicalisation of two 64-bit integers */
840 static int ldif_canonicalise_int64(struct ldb_context
*ldb
, void *mem_ctx
,
841 const struct ldb_val
*in
, struct ldb_val
*out
)
846 ret
= val_to_int64(in
, &i
);
847 if (ret
!= LDB_SUCCESS
) {
850 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%lld", (long long)i
);
851 if (out
->data
== NULL
) {
853 return LDB_ERR_OPERATIONS_ERROR
;
855 out
->length
= strlen((char *)out
->data
);
859 /* Comparison of two 64-bit integers */
860 static int ldif_comparison_int64(struct ldb_context
*ldb
, void *mem_ctx
,
861 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
864 val_to_int64(v1
, &i1
);
865 val_to_int64(v2
, &i2
);
866 if (i1
== i2
) return 0;
867 return i1
> i2
? 1 : -1;
871 convert a NDR formatted blob to a ldif formatted repsFromTo
873 static int ldif_write_repsFromTo(struct ldb_context
*ldb
, void *mem_ctx
,
874 const struct ldb_val
*in
, struct ldb_val
*out
)
876 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
877 sizeof(struct repsFromToBlob
),
878 (ndr_pull_flags_fn_t
)ndr_pull_repsFromToBlob
,
879 (ndr_print_fn_t
)ndr_print_repsFromToBlob
,
884 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
886 static int ldif_write_replPropertyMetaData(struct ldb_context
*ldb
, void *mem_ctx
,
887 const struct ldb_val
*in
, struct ldb_val
*out
)
889 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
890 sizeof(struct replPropertyMetaDataBlob
),
891 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaDataBlob
,
892 (ndr_print_fn_t
)ndr_print_replPropertyMetaDataBlob
,
897 convert a NDR formatted blob to a ldif formatted replUpToDateVector
899 static int ldif_write_replUpToDateVector(struct ldb_context
*ldb
, void *mem_ctx
,
900 const struct ldb_val
*in
, struct ldb_val
*out
)
902 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
903 sizeof(struct replUpToDateVectorBlob
),
904 (ndr_pull_flags_fn_t
)ndr_pull_replUpToDateVectorBlob
,
905 (ndr_print_fn_t
)ndr_print_replUpToDateVectorBlob
,
909 static int ldif_write_dn_binary_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
910 const struct ldb_val
*in
, struct ldb_val
*out
,
912 ndr_pull_flags_fn_t pull_fn
,
913 ndr_print_fn_t print_fn
,
917 enum ndr_err_code err
;
918 struct dsdb_dn
*dsdb_dn
= NULL
;
922 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
923 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
926 dsdb_dn
= dsdb_dn_parse(mem_ctx
, ldb
, in
, DSDB_SYNTAX_BINARY_DN
);
927 if (dsdb_dn
== NULL
) {
928 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
931 p
= talloc_size(dsdb_dn
, struct_size
);
933 TALLOC_FREE(dsdb_dn
);
934 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
937 err
= ndr_pull_struct_blob(&dsdb_dn
->extra_part
, p
, p
, pull_fn
);
938 if (err
!= NDR_ERR_SUCCESS
) {
939 /* fail in not in mask_error mode */
943 TALLOC_FREE(dsdb_dn
);
944 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
947 dn_str
= ldb_dn_get_extended_linearized(dsdb_dn
, dsdb_dn
->dn
, 1);
948 if (dn_str
== NULL
) {
949 TALLOC_FREE(dsdb_dn
);
950 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
953 str
= ndr_print_struct_string(mem_ctx
, print_fn
, dn_str
, p
);
954 TALLOC_FREE(dsdb_dn
);
956 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
959 *out
= data_blob_string_const(str
);
963 static int ldif_write_msDS_RevealedUsers(struct ldb_context
*ldb
, void *mem_ctx
,
964 const struct ldb_val
*in
, struct ldb_val
*out
)
966 return ldif_write_dn_binary_NDR(ldb
, mem_ctx
, in
, out
,
967 sizeof(struct replPropertyMetaData1
),
968 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaData1
,
969 (ndr_print_fn_t
)ndr_print_replPropertyMetaData1
,
974 convert a NDR formatted blob to a ldif formatted dnsRecord
976 static int ldif_write_dnsRecord(struct ldb_context
*ldb
, void *mem_ctx
,
977 const struct ldb_val
*in
, struct ldb_val
*out
)
979 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
980 sizeof(struct dnsp_DnssrvRpcRecord
),
981 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
,
982 (ndr_print_fn_t
)ndr_print_dnsp_DnssrvRpcRecord
,
987 convert a NDR formatted blob to a ldif formatted dnsProperty
989 static int ldif_write_dnsProperty(struct ldb_context
*ldb
, void *mem_ctx
,
990 const struct ldb_val
*in
, struct ldb_val
*out
)
992 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
993 sizeof(struct dnsp_DnsProperty
),
994 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnsProperty
,
995 (ndr_print_fn_t
)ndr_print_dnsp_DnsProperty
,
1000 convert a NDR formatted blob of a supplementalCredentials into text
1002 static int ldif_write_supplementalCredentialsBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1003 const struct ldb_val
*in
, struct ldb_val
*out
)
1005 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1006 sizeof(struct supplementalCredentialsBlob
),
1007 (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
,
1008 (ndr_print_fn_t
)ndr_print_supplementalCredentialsBlob
,
1013 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1015 static int ldif_write_trustAuthInOutBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1016 const struct ldb_val
*in
, struct ldb_val
*out
)
1018 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1019 sizeof(struct trustAuthInOutBlob
),
1020 (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
,
1021 (ndr_print_fn_t
)ndr_print_trustAuthInOutBlob
,
1026 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1028 static int ldif_write_ForestTrustInfo(struct ldb_context
*ldb
, void *mem_ctx
,
1029 const struct ldb_val
*in
, struct ldb_val
*out
)
1031 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1032 sizeof(struct ForestTrustInfo
),
1033 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
,
1034 (ndr_print_fn_t
)ndr_print_ForestTrustInfo
,
1038 convert a NDR formatted blob of a partialAttributeSet into text
1040 static int ldif_write_partialAttributeSet(struct ldb_context
*ldb
, void *mem_ctx
,
1041 const struct ldb_val
*in
, struct ldb_val
*out
)
1043 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1044 sizeof(struct partialAttributeSetBlob
),
1045 (ndr_pull_flags_fn_t
)ndr_pull_partialAttributeSetBlob
,
1046 (ndr_print_fn_t
)ndr_print_partialAttributeSetBlob
,
1051 static int extended_dn_write_hex(struct ldb_context
*ldb
, void *mem_ctx
,
1052 const struct ldb_val
*in
, struct ldb_val
*out
)
1054 *out
= data_blob_string_const(data_blob_hex_string_lower(mem_ctx
, in
));
1064 static int samba_ldb_dn_link_comparison(struct ldb_context
*ldb
, void *mem_ctx
,
1065 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1067 struct ldb_dn
*dn1
= NULL
, *dn2
= NULL
;
1070 if (dsdb_dn_is_deleted_val(v1
)) {
1071 /* If the DN is deleted, then we can't search for it */
1075 if (dsdb_dn_is_deleted_val(v2
)) {
1076 /* If the DN is deleted, then we can't search for it */
1080 dn1
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v1
);
1081 if ( ! ldb_dn_validate(dn1
)) return -1;
1083 dn2
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v2
);
1084 if ( ! ldb_dn_validate(dn2
)) {
1089 ret
= ldb_dn_compare(dn1
, dn2
);
1096 static int samba_ldb_dn_link_canonicalise(struct ldb_context
*ldb
, void *mem_ctx
,
1097 const struct ldb_val
*in
, struct ldb_val
*out
)
1105 dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, in
);
1106 if ( ! ldb_dn_validate(dn
)) {
1107 return LDB_ERR_INVALID_DN_SYNTAX
;
1110 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1111 * does not casually match a not deleted DN */
1112 if (dsdb_dn_is_deleted_val(in
)) {
1113 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
,
1115 dsdb_dn_val_rmd_flags(in
),
1116 ldb_dn_get_casefold(dn
));
1118 out
->data
= (uint8_t *)ldb_dn_alloc_casefold(mem_ctx
, dn
);
1121 if (out
->data
== NULL
) {
1124 out
->length
= strlen((char *)out
->data
);
1136 write a 64 bit 2-part range
1138 static int ldif_write_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1139 const struct ldb_val
*in
, struct ldb_val
*out
)
1143 ret
= val_to_int64(in
, &v
);
1144 if (ret
!= LDB_SUCCESS
) {
1147 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%lu-%lu",
1148 (unsigned long)(v
&0xFFFFFFFF),
1149 (unsigned long)(v
>>32));
1150 if (out
->data
== NULL
) {
1152 return LDB_ERR_OPERATIONS_ERROR
;
1154 out
->length
= strlen((char *)out
->data
);
1159 read a 64 bit 2-part range
1161 static int ldif_read_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1162 const struct ldb_val
*in
, struct ldb_val
*out
)
1164 unsigned long high
, low
;
1167 if (memchr(in
->data
, '-', in
->length
) == NULL
) {
1168 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1171 if (in
->length
> sizeof(buf
)-1) {
1172 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1174 strncpy(buf
, (const char *)in
->data
, in
->length
);
1175 buf
[in
->length
] = 0;
1177 if (sscanf(buf
, "%lu-%lu", &low
, &high
) != 2) {
1178 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1181 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%llu",
1182 (unsigned long long)(((uint64_t)high
)<<32) | (low
));
1184 if (out
->data
== NULL
) {
1186 return LDB_ERR_OPERATIONS_ERROR
;
1188 out
->length
= strlen((char *)out
->data
);
1193 when this operator_fn is set for a syntax, the backend calls is in
1194 preference to the comparison function. We are told the exact
1195 comparison operation that is needed, and we can return errors
1197 static int samba_syntax_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1198 const struct ldb_schema_attribute
*a
,
1199 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1201 switch (operation
) {
1205 case LDB_OP_SUBSTRING
:
1207 case LDB_OP_EXTENDED
:
1208 /* handled in the backends */
1209 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1211 case LDB_OP_GREATER
:
1213 case LDB_OP_EQUALITY
:
1215 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
1217 if (tmp_ctx
== NULL
) {
1218 return ldb_oom(ldb
);
1220 ret
= a
->syntax
->comparison_fn(ldb
, tmp_ctx
, v1
, v2
);
1221 talloc_free(tmp_ctx
);
1222 if (operation
== LDB_OP_GREATER
) {
1223 *matched
= (ret
>= 0);
1224 } else if (operation
== LDB_OP_LESS
) {
1225 *matched
= (ret
<= 0);
1227 *matched
= (ret
== 0);
1232 case LDB_OP_PRESENT
:
1237 /* we shouldn't get here */
1238 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1242 see if two DNs match, comparing first by GUID, then by SID, and
1243 finally by string components
1245 static int samba_dn_extended_match(struct ldb_context
*ldb
,
1246 const struct ldb_val
*v1
,
1247 const struct ldb_val
*v2
,
1250 TALLOC_CTX
*tmp_ctx
;
1251 struct ldb_dn
*dn1
, *dn2
;
1252 const struct ldb_val
*guid1
, *guid2
, *sid1
, *sid2
;
1253 uint32_t rmd_flags1
, rmd_flags2
;
1255 tmp_ctx
= talloc_new(ldb
);
1257 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v1
);
1258 dn2
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v2
);
1260 /* couldn't parse as DN's */
1261 talloc_free(tmp_ctx
);
1266 rmd_flags1
= dsdb_dn_rmd_flags(dn1
);
1267 rmd_flags2
= dsdb_dn_rmd_flags(dn2
);
1269 if ((rmd_flags1
& DSDB_RMD_FLAG_DELETED
) !=
1270 (rmd_flags2
& DSDB_RMD_FLAG_DELETED
)) {
1271 /* only match if they have the same deletion status */
1272 talloc_free(tmp_ctx
);
1278 guid1
= ldb_dn_get_extended_component(dn1
, "GUID");
1279 guid2
= ldb_dn_get_extended_component(dn2
, "GUID");
1280 if (guid1
&& guid2
) {
1281 (*matched
) = (data_blob_cmp(guid1
, guid2
) == 0);
1282 talloc_free(tmp_ctx
);
1286 sid1
= ldb_dn_get_extended_component(dn1
, "SID");
1287 sid2
= ldb_dn_get_extended_component(dn2
, "SID");
1289 (*matched
) = (data_blob_cmp(sid1
, sid2
) == 0);
1290 talloc_free(tmp_ctx
);
1294 (*matched
) = (ldb_dn_compare(dn1
, dn2
) == 0);
1296 talloc_free(tmp_ctx
);
1301 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1303 static int samba_syntax_operator_dn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1304 const struct ldb_schema_attribute
*a
,
1305 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1307 if (operation
== LDB_OP_PRESENT
&& dsdb_dn_is_deleted_val(v1
)) {
1308 /* If the DN is deleted, then we can't search for it */
1310 /* should this be for equality too? */
1315 if (operation
== LDB_OP_EQUALITY
&&
1316 samba_dn_extended_match(ldb
, v1
, v2
, matched
) == LDB_SUCCESS
) {
1320 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1324 static const struct ldb_schema_syntax samba_syntaxes
[] = {
1326 .name
= LDB_SYNTAX_SAMBA_SID
,
1327 .ldif_read_fn
= ldif_read_objectSid
,
1328 .ldif_write_fn
= ldif_write_objectSid
,
1329 .canonicalise_fn
= ldif_canonicalise_objectSid
,
1330 .comparison_fn
= ldif_comparison_objectSid
,
1331 .operator_fn
= samba_syntax_operator_fn
1333 .name
= LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
,
1334 .ldif_read_fn
= ldif_read_ntSecurityDescriptor
,
1335 .ldif_write_fn
= ldif_write_ntSecurityDescriptor
,
1336 .canonicalise_fn
= ldb_handler_copy
,
1337 .comparison_fn
= ldb_comparison_binary
,
1338 .operator_fn
= samba_syntax_operator_fn
1340 .name
= LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
,
1341 .ldif_read_fn
= ldb_handler_copy
,
1342 .ldif_write_fn
= ldif_write_sddlSecurityDescriptor
,
1343 .canonicalise_fn
= ldb_handler_fold
,
1344 .comparison_fn
= ldb_comparison_fold
,
1345 .operator_fn
= samba_syntax_operator_fn
1347 .name
= LDB_SYNTAX_SAMBA_GUID
,
1348 .ldif_read_fn
= ldif_read_objectGUID
,
1349 .ldif_write_fn
= ldif_write_objectGUID
,
1350 .canonicalise_fn
= ldif_canonicalise_objectGUID
,
1351 .comparison_fn
= ldif_comparison_objectGUID
,
1352 .operator_fn
= samba_syntax_operator_fn
1354 .name
= LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
,
1355 .ldif_read_fn
= ldb_handler_copy
,
1356 .ldif_write_fn
= ldb_handler_copy
,
1357 .canonicalise_fn
= ldif_canonicalise_objectCategory
,
1358 .comparison_fn
= ldif_comparison_objectCategory
,
1359 .operator_fn
= samba_syntax_operator_fn
1361 .name
= LDB_SYNTAX_SAMBA_SCHEMAINFO
,
1362 .ldif_read_fn
= ldb_handler_copy
,
1363 .ldif_write_fn
= ldif_write_schemaInfo
,
1364 .canonicalise_fn
= ldb_handler_copy
,
1365 .comparison_fn
= ldb_comparison_binary
,
1366 .operator_fn
= samba_syntax_operator_fn
1368 .name
= LDB_SYNTAX_SAMBA_PREFIX_MAP
,
1369 .ldif_read_fn
= ldif_read_prefixMap
,
1370 .ldif_write_fn
= ldif_write_prefixMap
,
1371 .canonicalise_fn
= ldif_canonicalise_prefixMap
,
1372 .comparison_fn
= ldif_comparison_prefixMap
,
1373 .operator_fn
= samba_syntax_operator_fn
1375 .name
= LDB_SYNTAX_SAMBA_INT32
,
1376 .ldif_read_fn
= ldb_handler_copy
,
1377 .ldif_write_fn
= ldb_handler_copy
,
1378 .canonicalise_fn
= ldif_canonicalise_int32
,
1379 .comparison_fn
= ldif_comparison_int32
,
1380 .operator_fn
= samba_syntax_operator_fn
1382 .name
= LDB_SYNTAX_SAMBA_REPSFROMTO
,
1383 .ldif_read_fn
= ldb_handler_copy
,
1384 .ldif_write_fn
= ldif_write_repsFromTo
,
1385 .canonicalise_fn
= ldb_handler_copy
,
1386 .comparison_fn
= ldb_comparison_binary
,
1387 .operator_fn
= samba_syntax_operator_fn
1389 .name
= LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
,
1390 .ldif_read_fn
= ldb_handler_copy
,
1391 .ldif_write_fn
= ldif_write_replPropertyMetaData
,
1392 .canonicalise_fn
= ldb_handler_copy
,
1393 .comparison_fn
= ldb_comparison_binary
,
1394 .operator_fn
= samba_syntax_operator_fn
1396 .name
= LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
,
1397 .ldif_read_fn
= ldb_handler_copy
,
1398 .ldif_write_fn
= ldif_write_replUpToDateVector
,
1399 .canonicalise_fn
= ldb_handler_copy
,
1400 .comparison_fn
= ldb_comparison_binary
,
1401 .operator_fn
= samba_syntax_operator_fn
1403 .name
= LDB_SYNTAX_SAMBA_REVEALEDUSERS
,
1404 .ldif_read_fn
= ldb_handler_copy
,
1405 .ldif_write_fn
= ldif_write_msDS_RevealedUsers
,
1406 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1407 .comparison_fn
= dsdb_dn_binary_comparison
,
1408 .operator_fn
= samba_syntax_operator_fn
1410 .name
= LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
,
1411 .ldif_read_fn
= ldb_handler_copy
,
1412 .ldif_write_fn
= ldif_write_trustAuthInOutBlob
,
1413 .canonicalise_fn
= ldb_handler_copy
,
1414 .comparison_fn
= ldb_comparison_binary
,
1415 .operator_fn
= samba_syntax_operator_fn
1417 .name
= LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
,
1418 .ldif_read_fn
= ldb_handler_copy
,
1419 .ldif_write_fn
= ldif_write_ForestTrustInfo
,
1420 .canonicalise_fn
= ldb_handler_copy
,
1421 .comparison_fn
= ldb_comparison_binary
,
1422 .operator_fn
= samba_syntax_operator_fn
1424 .name
= DSDB_SYNTAX_BINARY_DN
,
1425 .ldif_read_fn
= ldb_handler_copy
,
1426 .ldif_write_fn
= ldb_handler_copy
,
1427 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1428 .comparison_fn
= dsdb_dn_binary_comparison
,
1429 .operator_fn
= samba_syntax_operator_fn
1431 .name
= DSDB_SYNTAX_STRING_DN
,
1432 .ldif_read_fn
= ldb_handler_copy
,
1433 .ldif_write_fn
= ldb_handler_copy
,
1434 .canonicalise_fn
= dsdb_dn_string_canonicalise
,
1435 .comparison_fn
= dsdb_dn_string_comparison
,
1436 .operator_fn
= samba_syntax_operator_fn
1438 .name
= LDB_SYNTAX_DN
,
1439 .ldif_read_fn
= ldb_handler_copy
,
1440 .ldif_write_fn
= ldb_handler_copy
,
1441 .canonicalise_fn
= samba_ldb_dn_link_canonicalise
,
1442 .comparison_fn
= samba_ldb_dn_link_comparison
,
1443 .operator_fn
= samba_syntax_operator_dn
1445 .name
= LDB_SYNTAX_SAMBA_RANGE64
,
1446 .ldif_read_fn
= ldif_read_range64
,
1447 .ldif_write_fn
= ldif_write_range64
,
1448 .canonicalise_fn
= ldif_canonicalise_int64
,
1449 .comparison_fn
= ldif_comparison_int64
,
1450 .operator_fn
= samba_syntax_operator_fn
1452 .name
= LDB_SYNTAX_SAMBA_DNSRECORD
,
1453 .ldif_read_fn
= ldb_handler_copy
,
1454 .ldif_write_fn
= ldif_write_dnsRecord
,
1455 .canonicalise_fn
= ldb_handler_copy
,
1456 .comparison_fn
= ldb_comparison_binary
,
1457 .operator_fn
= samba_syntax_operator_fn
1459 .name
= LDB_SYNTAX_SAMBA_DNSPROPERTY
,
1460 .ldif_read_fn
= ldb_handler_copy
,
1461 .ldif_write_fn
= ldif_write_dnsProperty
,
1462 .canonicalise_fn
= ldb_handler_copy
,
1463 .comparison_fn
= ldb_comparison_binary
,
1464 .operator_fn
= samba_syntax_operator_fn
1466 .name
= LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
,
1467 .ldif_read_fn
= ldb_handler_copy
,
1468 .ldif_write_fn
= ldif_write_supplementalCredentialsBlob
,
1469 .canonicalise_fn
= ldb_handler_copy
,
1470 .comparison_fn
= ldb_comparison_binary
,
1471 .operator_fn
= samba_syntax_operator_fn
1473 .name
= LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
,
1474 .ldif_read_fn
= ldb_handler_copy
,
1475 .ldif_write_fn
= ldif_write_partialAttributeSet
,
1476 .canonicalise_fn
= ldb_handler_copy
,
1477 .comparison_fn
= ldb_comparison_binary
,
1478 .operator_fn
= samba_syntax_operator_fn
1482 static const struct ldb_dn_extended_syntax samba_dn_syntax
[] = {
1485 .read_fn
= extended_dn_read_SID
,
1486 .write_clear_fn
= ldif_write_objectSid
,
1487 .write_hex_fn
= extended_dn_write_hex
1490 .read_fn
= extended_dn_read_GUID
,
1491 .write_clear_fn
= ldif_write_objectGUID
,
1492 .write_hex_fn
= extended_dn_write_hex
1495 .read_fn
= ldb_handler_copy
,
1496 .write_clear_fn
= ldb_handler_copy
,
1497 .write_hex_fn
= ldb_handler_copy
1499 .name
= "RMD_INVOCID",
1500 .read_fn
= extended_dn_read_GUID
,
1501 .write_clear_fn
= ldif_write_objectGUID
,
1502 .write_hex_fn
= extended_dn_write_hex
1504 .name
= "RMD_FLAGS",
1505 .read_fn
= ldb_handler_copy
,
1506 .write_clear_fn
= ldb_handler_copy
,
1507 .write_hex_fn
= ldb_handler_copy
1509 .name
= "RMD_ADDTIME",
1510 .read_fn
= ldb_handler_copy
,
1511 .write_clear_fn
= ldb_handler_copy
,
1512 .write_hex_fn
= ldb_handler_copy
1514 .name
= "RMD_CHANGETIME",
1515 .read_fn
= ldb_handler_copy
,
1516 .write_clear_fn
= ldb_handler_copy
,
1517 .write_hex_fn
= ldb_handler_copy
1519 .name
= "RMD_LOCAL_USN",
1520 .read_fn
= ldb_handler_copy
,
1521 .write_clear_fn
= ldb_handler_copy
,
1522 .write_hex_fn
= ldb_handler_copy
1524 .name
= "RMD_ORIGINATING_USN",
1525 .read_fn
= ldb_handler_copy
,
1526 .write_clear_fn
= ldb_handler_copy
,
1527 .write_hex_fn
= ldb_handler_copy
1529 .name
= "RMD_VERSION",
1530 .read_fn
= ldb_handler_copy
,
1531 .write_clear_fn
= ldb_handler_copy
,
1532 .write_hex_fn
= ldb_handler_copy
1536 /* TODO: Should be dynamic at some point */
1537 static const struct {
1540 } samba_attributes
[] = {
1541 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
},
1542 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32
},
1543 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
},
1544 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO
},
1545 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP
},
1546 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1547 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1548 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
},
1549 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
},
1550 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS
},
1551 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1552 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1553 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
},
1554 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1555 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1556 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64
},
1557 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
},
1560 * these are extracted by searching
1561 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1563 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1564 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1565 * hat can be used to identify the set of policies when applied to a resource.
1566 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1567 * server, we ignore it here.
1569 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID
},
1570 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID
},
1571 { "objectSid", LDB_SYNTAX_SAMBA_SID
},
1572 { "tokenGroups", LDB_SYNTAX_SAMBA_SID
},
1573 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID
},
1574 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID
},
1575 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID
},
1576 { "sIDHistory", LDB_SYNTAX_SAMBA_SID
},
1577 { "syncWithSID", LDB_SYNTAX_SAMBA_SID
},
1580 * these are extracted by searching
1581 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1583 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID
},
1584 { "categoryId", LDB_SYNTAX_SAMBA_GUID
},
1585 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID
},
1586 { "currMachineId", LDB_SYNTAX_SAMBA_GUID
},
1587 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID
},
1588 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID
},
1589 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID
},
1590 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID
},
1591 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID
},
1592 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID
},
1593 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID
},
1594 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID
},
1595 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID
},
1596 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID
},
1597 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID
},
1598 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID
},
1599 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID
},
1600 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID
},
1601 { "objectGUID", LDB_SYNTAX_SAMBA_GUID
},
1602 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID
},
1603 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID
},
1604 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID
},
1605 { "siteGUID", LDB_SYNTAX_SAMBA_GUID
},
1606 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1607 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1608 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1609 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID
},
1610 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID
},
1613 * these are known to be GUIDs
1615 { "invocationId", LDB_SYNTAX_SAMBA_GUID
},
1616 { "parentGUID", LDB_SYNTAX_SAMBA_GUID
},
1618 /* These NDR encoded things we want to be able to read with --show-binary */
1619 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD
},
1620 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY
},
1621 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
},
1622 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
}
1625 const struct ldb_schema_syntax
*ldb_samba_syntax_by_name(struct ldb_context
*ldb
, const char *name
)
1628 const struct ldb_schema_syntax
*s
= NULL
;
1630 for (j
=0; j
< ARRAY_SIZE(samba_syntaxes
); j
++) {
1631 if (strcmp(name
, samba_syntaxes
[j
].name
) == 0) {
1632 s
= &samba_syntaxes
[j
];
1639 const struct ldb_schema_syntax
*ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context
*ldb
, const char *name
)
1642 const struct ldb_schema_syntax
*s
= NULL
;
1644 for (j
=0; j
< ARRAY_SIZE(samba_attributes
); j
++) {
1645 if (strcmp(samba_attributes
[j
].name
, name
) == 0) {
1646 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[j
].syntax
);
1654 static const char *secret_attributes
[] = {DSDB_SECRET_ATTRIBUTES
, NULL
};
1657 register the samba ldif handlers
1659 int ldb_register_samba_handlers(struct ldb_context
*ldb
)
1664 if (ldb_get_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED") != NULL
) {
1668 ret
= ldb_set_opaque(ldb
, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE
, discard_const_p(char *, secret_attributes
));
1669 if (ret
!= LDB_SUCCESS
) {
1673 for (i
=0; i
< ARRAY_SIZE(samba_attributes
); i
++) {
1674 const struct ldb_schema_syntax
*s
= NULL
;
1676 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1679 s
= ldb_standard_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1683 return LDB_ERR_OPERATIONS_ERROR
;
1686 ret
= ldb_schema_attribute_add_with_syntax(ldb
, samba_attributes
[i
].name
, LDB_ATTR_FLAG_FIXED
, s
);
1687 if (ret
!= LDB_SUCCESS
) {
1692 for (i
=0; i
< ARRAY_SIZE(samba_dn_syntax
); i
++) {
1693 ret
= ldb_dn_extended_add_syntax(ldb
, LDB_ATTR_FLAG_FIXED
, &samba_dn_syntax
[i
]);
1694 if (ret
!= LDB_SUCCESS
) {
1700 ret
= ldb_register_samba_matching_rules(ldb
);
1701 if (ret
!= LDB_SUCCESS
) {
1706 ret
= ldb_set_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1707 if (ret
!= LDB_SUCCESS
) {