2 ldb database library - ldif handlers for Samba
4 Copyright (C) Andrew Tridgell 2005
5 Copyright (C) Andrew Bartlett 2006-2009
6 Copyright (C) Matthias Dieter Wallnöfer 2009
7 ** NOTE! The following LGPL license applies to the ldb
8 ** library. This does NOT imply that all of Samba is released
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include <ldb_module.h>
28 #include "ldb_handlers.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "dsdb/common/util.h"
31 #include "librpc/gen_ndr/ndr_security.h"
32 #include "librpc/gen_ndr/ndr_misc.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "librpc/gen_ndr/ndr_dnsp.h"
35 #include "librpc/ndr/libndr.h"
36 #include "libcli/security/security.h"
37 #include "param/param.h"
38 #include "../lib/util/asn1.h"
39 #include "lib/util/smb_strtox.h"
42 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
44 If mask_errors is true, then function succeeds but out data
45 is set to "<Unable to decode binary data>" message
47 \return 0 on success; -1 on error
49 static int ldif_write_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
50 const struct ldb_val
*in
, struct ldb_val
*out
,
52 ndr_pull_flags_fn_t pull_fn
,
53 ndr_print_fn_t print_fn
,
57 enum ndr_err_code err
;
58 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
59 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
61 p
= talloc_size(mem_ctx
, struct_size
);
62 err
= ndr_pull_struct_blob(in
, mem_ctx
,
64 if (err
!= NDR_ERR_SUCCESS
) {
65 /* fail in not in mask_error mode */
70 out
->data
= (uint8_t *)talloc_strdup(mem_ctx
, "<Unable to decode binary data>");
71 out
->length
= strlen((const char *)out
->data
);
74 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
, print_fn
, "NDR", p
);
76 if (out
->data
== NULL
) {
77 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
79 out
->length
= strlen((char *)out
->data
);
84 convert a ldif formatted objectSid to a NDR formatted blob
86 static int ldif_read_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
87 const struct ldb_val
*in
, struct ldb_val
*out
)
90 enum ndr_err_code ndr_err
;
92 if (in
->length
> DOM_SID_STR_BUFLEN
) {
96 memcpy(p
, in
->data
, in
->length
);
99 ret
= dom_sid_parse(p
, &sid
);
104 *out
= data_blob_talloc(mem_ctx
, NULL
,
105 ndr_size_dom_sid(&sid
, 0));
106 if (out
->data
== NULL
) {
110 ndr_err
= ndr_push_struct_into_fixed_blob(out
, &sid
,
111 (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
112 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
120 convert a NDR formatted blob to a ldif formatted objectSid
122 int ldif_write_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
123 const struct ldb_val
*in
, struct ldb_val
*out
)
126 enum ndr_err_code ndr_err
;
128 ndr_err
= ndr_pull_struct_blob_all_noalloc(in
, &sid
,
129 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
130 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
133 *out
= data_blob_string_const(dom_sid_string(mem_ctx
, &sid
));
134 if (out
->data
== NULL
) {
140 bool ldif_comparision_objectSid_isString(const struct ldb_val
*v
)
146 if (strncmp("S-", (const char *)v
->data
, 2) != 0) return false;
152 compare two objectSids
154 static int ldif_comparison_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
155 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
157 if (ldif_comparision_objectSid_isString(v1
) && ldif_comparision_objectSid_isString(v2
)) {
158 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
159 } else if (ldif_comparision_objectSid_isString(v1
)
160 && !ldif_comparision_objectSid_isString(v2
)) {
163 if (ldif_read_objectSid(ldb
, mem_ctx
, v1
, &v
) != 0) {
164 /* Perhaps not a string after all */
165 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
167 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
170 } else if (!ldif_comparision_objectSid_isString(v1
)
171 && ldif_comparision_objectSid_isString(v2
)) {
174 if (ldif_read_objectSid(ldb
, mem_ctx
, v2
, &v
) != 0) {
175 /* Perhaps not a string after all */
176 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
178 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
182 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
186 canonicalise a objectSid
188 static int ldif_canonicalise_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
189 const struct ldb_val
*in
, struct ldb_val
*out
)
191 if (ldif_comparision_objectSid_isString(in
)) {
192 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) != 0) {
193 /* Perhaps not a string after all */
194 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
198 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
201 static int extended_dn_read_SID(struct ldb_context
*ldb
, void *mem_ctx
,
202 const struct ldb_val
*in
, struct ldb_val
*out
)
205 enum ndr_err_code ndr_err
;
206 if (ldif_comparision_objectSid_isString(in
)) {
207 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) == 0) {
212 /* Perhaps not a string after all */
213 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
219 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
220 (const char *)in
->data
, in
->length
);
222 /* Check it looks like a SID */
223 ndr_err
= ndr_pull_struct_blob_all_noalloc(out
, &sid
,
224 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
225 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
232 convert a ldif formatted objectGUID to a NDR formatted blob
234 static int ldif_read_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
235 const struct ldb_val
*in
, struct ldb_val
*out
)
240 status
= GUID_from_data_blob(in
, &guid
);
241 if (!NT_STATUS_IS_OK(status
)) {
245 status
= GUID_to_ndr_blob(&guid
, mem_ctx
, out
);
246 if (!NT_STATUS_IS_OK(status
)) {
253 convert a NDR formatted blob to a ldif formatted objectGUID
255 static int ldif_write_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
256 const struct ldb_val
*in
, struct ldb_val
*out
)
261 status
= GUID_from_ndr_blob(in
, &guid
);
262 if (!NT_STATUS_IS_OK(status
)) {
265 out
->data
= (uint8_t *)GUID_string(mem_ctx
, &guid
);
266 if (out
->data
== NULL
) {
269 out
->length
= strlen((const char *)out
->data
);
273 static bool ldif_comparision_objectGUID_isString(const struct ldb_val
*v
)
275 if (v
->length
!= 36 && v
->length
!= 38) return false;
277 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
281 static int extended_dn_read_GUID(struct ldb_context
*ldb
, void *mem_ctx
,
282 const struct ldb_val
*in
, struct ldb_val
*out
)
285 if (in
->length
== 36 && ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) == 0) {
289 /* Try as 'hex' form */
290 if (in
->length
!= 32) {
294 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
300 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
301 (const char *)in
->data
, in
->length
);
303 /* Check it looks like a GUID */
304 if ((*out
).length
!= 16) {
313 compare two objectGUIDs
315 static int ldif_comparison_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
316 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
318 if (ldif_comparision_objectGUID_isString(v1
) && ldif_comparision_objectGUID_isString(v2
)) {
319 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
320 } else if (ldif_comparision_objectGUID_isString(v1
)
321 && !ldif_comparision_objectGUID_isString(v2
)) {
324 if (ldif_read_objectGUID(ldb
, mem_ctx
, v1
, &v
) != 0) {
325 /* Perhaps it wasn't a valid string after all */
326 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
328 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
331 } else if (!ldif_comparision_objectGUID_isString(v1
)
332 && ldif_comparision_objectGUID_isString(v2
)) {
335 if (ldif_read_objectGUID(ldb
, mem_ctx
, v2
, &v
) != 0) {
336 /* Perhaps it wasn't a valid string after all */
337 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
339 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
343 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
347 canonicalise a objectGUID
349 static int ldif_canonicalise_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
350 const struct ldb_val
*in
, struct ldb_val
*out
)
352 if (ldif_comparision_objectGUID_isString(in
)) {
353 if (ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) != 0) {
354 /* Perhaps it wasn't a valid string after all */
355 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
359 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
364 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
366 static int ldif_read_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
367 const struct ldb_val
*in
, struct ldb_val
*out
)
369 struct security_descriptor
*sd
;
370 enum ndr_err_code ndr_err
;
372 if (in
->length
>= 2 && isupper(in
->data
[0]) && in
->data
[1] == ':') {
374 * If it starts with an upper case character followed by ':',
375 * we know it's not NDR, but most likely SDDL...
377 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
379 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
387 sd
= talloc(mem_ctx
, struct security_descriptor
);
392 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
393 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
394 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
400 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, sd
,
401 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
403 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
411 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
413 static int ldif_write_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
414 const struct ldb_val
*in
, struct ldb_val
*out
)
416 struct security_descriptor
*sd
;
417 enum ndr_err_code ndr_err
;
419 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
420 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
421 sizeof(struct security_descriptor
),
422 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
,
423 (ndr_print_fn_t
)ndr_print_security_descriptor
,
428 sd
= talloc(mem_ctx
, struct security_descriptor
);
432 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
433 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
434 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
435 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
439 out
->data
= (uint8_t *)sddl_encode(mem_ctx
, sd
, samdb_domain_sid_cache_only(ldb
));
441 if (out
->data
== NULL
) {
444 out
->length
= strlen((const char *)out
->data
);
449 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
451 static int ldif_write_sddlSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
452 const struct ldb_val
*in
, struct ldb_val
*out
)
454 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
455 struct security_descriptor
*sd
;
456 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
458 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
459 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
,
460 (ndr_print_fn_t
)ndr_print_security_descriptor
,
462 out
->length
= strlen((const char *)out
->data
);
467 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
471 canonicalise an objectCategory. We use the long form as the canonical form:
472 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
474 Also any short name of an objectClass that points to a different
475 class (such as user) has the canonical form of the class it's
476 defaultObjectCategory points to (eg
477 cn=Person,cn=Schema,cn=Configuration,<basedn>)
480 static int ldif_canonicalise_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
481 const struct ldb_val
*in
, struct ldb_val
*out
)
483 struct ldb_dn
*dn1
= NULL
;
484 const struct dsdb_schema
*schema
= dsdb_get_schema(ldb
, NULL
);
485 const struct dsdb_class
*sclass
;
486 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
488 return LDB_ERR_OPERATIONS_ERROR
;
492 talloc_free(tmp_ctx
);
493 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
494 if (in
->data
&& !out
->data
) {
495 return LDB_ERR_OPERATIONS_ERROR
;
499 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, in
);
500 if ( ! ldb_dn_validate(dn1
)) {
501 const char *lDAPDisplayName
= talloc_strndup(tmp_ctx
, (char *)in
->data
, in
->length
);
502 sclass
= dsdb_class_by_lDAPDisplayName(schema
, lDAPDisplayName
);
504 struct ldb_dn
*dn
= ldb_dn_new(tmp_ctx
, ldb
,
505 sclass
->defaultObjectCategory
);
507 talloc_free(tmp_ctx
);
508 return LDB_ERR_OPERATIONS_ERROR
;
511 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn
));
512 talloc_free(tmp_ctx
);
515 return LDB_ERR_OPERATIONS_ERROR
;
519 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
520 talloc_free(tmp_ctx
);
522 if (in
->data
&& !out
->data
) {
523 return LDB_ERR_OPERATIONS_ERROR
;
528 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn1
));
529 talloc_free(tmp_ctx
);
532 return LDB_ERR_OPERATIONS_ERROR
;
537 static int ldif_comparison_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
538 const struct ldb_val
*v1
,
539 const struct ldb_val
*v2
)
541 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_objectCategory
,
546 convert a NDR formatted blob to a ldif formatted schemaInfo
548 static int ldif_write_schemaInfo(struct ldb_context
*ldb
, void *mem_ctx
,
549 const struct ldb_val
*in
, struct ldb_val
*out
)
551 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
552 sizeof(struct repsFromToBlob
),
553 (ndr_pull_flags_fn_t
)ndr_pull_schemaInfoBlob
,
554 (ndr_print_fn_t
)ndr_print_schemaInfoBlob
,
559 convert a ldif formatted prefixMap to a NDR formatted blob
561 static int ldif_read_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
562 const struct ldb_val
*in
, struct ldb_val
*out
)
564 struct prefixMapBlob
*blob
;
565 enum ndr_err_code ndr_err
;
566 char *string
, *line
, *p
, *oid
;
569 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
571 if (tmp_ctx
== NULL
) {
575 blob
= talloc_zero(tmp_ctx
, struct prefixMapBlob
);
577 talloc_free(tmp_ctx
);
581 /* use the switch value to detect if this is in the binary
584 if (in
->length
>= 4 && IVAL(in
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
585 ndr_err
= ndr_pull_struct_blob(in
, tmp_ctx
, blob
,
586 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
587 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
588 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
590 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
591 talloc_free(tmp_ctx
);
592 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
599 /* If this does not parse, then it is probably the text version, and we should try it that way */
600 blob
->version
= PREFIX_MAP_VERSION_DSDB
;
602 string
= talloc_strndup(mem_ctx
, (const char *)in
->data
, in
->length
);
603 if (string
== NULL
) {
609 while (line
&& line
[0]) {
616 p
=strchr(line
, '\n');
621 /* allow a trailing separator */
626 blob
->ctr
.dsdb
.mappings
= talloc_realloc(blob
,
627 blob
->ctr
.dsdb
.mappings
,
628 struct drsuapi_DsReplicaOIDMapping
,
629 blob
->ctr
.dsdb
.num_mappings
+1);
630 if (!blob
->ctr
.dsdb
.mappings
) {
631 talloc_free(tmp_ctx
);
635 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].id_prefix
=
636 smb_strtoul(line
, &oid
, 10, &error
, SMB_STR_STANDARD
);
638 if (oid
[0] != ':' || error
!= 0) {
639 talloc_free(tmp_ctx
);
643 /* we know there must be at least ":" */
646 if (!ber_write_partial_OID_String(blob
->ctr
.dsdb
.mappings
, &oid_blob
, oid
)) {
647 talloc_free(tmp_ctx
);
650 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.length
= oid_blob
.length
;
651 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.binary_oid
= oid_blob
.data
;
653 blob
->ctr
.dsdb
.num_mappings
++;
655 /* Now look past the terminator we added above */
663 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
665 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
666 talloc_free(tmp_ctx
);
667 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
674 convert a NDR formatted blob to a ldif formatted prefixMap
676 static int ldif_write_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
677 const struct ldb_val
*in
, struct ldb_val
*out
)
679 struct prefixMapBlob
*blob
;
680 enum ndr_err_code ndr_err
;
684 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
686 /* try to decode the blob as S4 prefixMap */
687 err
= ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
688 sizeof(struct prefixMapBlob
),
689 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
,
690 (ndr_print_fn_t
)ndr_print_prefixMapBlob
,
695 /* try parsing it as Windows PrefixMap value */
696 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
697 sizeof(struct drsuapi_MSPrefixMap_Ctr
),
698 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_MSPrefixMap_Ctr
,
699 (ndr_print_fn_t
)ndr_print_drsuapi_MSPrefixMap_Ctr
,
703 blob
= talloc(mem_ctx
, struct prefixMapBlob
);
707 ndr_err
= ndr_pull_struct_blob_all(in
, blob
,
709 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
710 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
713 if (blob
->version
!= PREFIX_MAP_VERSION_DSDB
) {
716 string
= talloc_strdup(mem_ctx
, "");
717 if (string
== NULL
) {
721 for (i
=0; i
< blob
->ctr
.dsdb
.num_mappings
; i
++) {
723 char *partial_oid
= NULL
;
726 talloc_asprintf_addbuf(&string
, ";");
729 oid_blob
= data_blob_const(blob
->ctr
.dsdb
.mappings
[i
].oid
.binary_oid
,
730 blob
->ctr
.dsdb
.mappings
[i
].oid
.length
);
731 if (!ber_read_partial_OID_String(blob
, oid_blob
, &partial_oid
)) {
732 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
733 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
));
736 talloc_asprintf_addbuf(&string
, "%u:%s",
737 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
,
739 talloc_free(discard_const(partial_oid
));
743 *out
= data_blob_string_const(string
);
751 static bool ldif_comparision_prefixMap_isString(const struct ldb_val
*v
)
757 if (IVAL(v
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
765 canonicalise a prefixMap
767 static int ldif_canonicalise_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
768 const struct ldb_val
*in
, struct ldb_val
*out
)
770 if (ldif_comparision_prefixMap_isString(in
)) {
771 return ldif_read_prefixMap(ldb
, mem_ctx
, in
, out
);
773 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
776 static int ldif_comparison_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
777 const struct ldb_val
*v1
,
778 const struct ldb_val
*v2
)
780 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_prefixMap
,
784 /* length limited conversion of a ldb_val to a int32_t */
785 static int val_to_int32(const struct ldb_val
*in
, int32_t *v
)
790 /* make sure we don't read past the end of the data */
791 if (in
->length
> sizeof(buf
)-1) {
792 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
794 strncpy(buf
, (char *)in
->data
, in
->length
);
797 /* We've to use "strtoll" here to have the intended overflows.
798 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
799 *v
= (int32_t) strtoll(buf
, &end
, 0);
801 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
806 /* length limited conversion of a ldb_val to a int64_t */
807 static int val_to_int64(const struct ldb_val
*in
, int64_t *v
)
812 /* make sure we don't read past the end of the data */
813 if (in
->length
> sizeof(buf
)-1) {
814 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
816 strncpy(buf
, (char *)in
->data
, in
->length
);
819 *v
= (int64_t) strtoll(buf
, &end
, 0);
821 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
826 /* Canonicalisation of two 32-bit integers */
827 static int ldif_canonicalise_int32(struct ldb_context
*ldb
, void *mem_ctx
,
828 const struct ldb_val
*in
, struct ldb_val
*out
)
833 ret
= val_to_int32(in
, &i
);
834 if (ret
!= LDB_SUCCESS
) {
837 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%d", i
);
838 if (out
->data
== NULL
) {
840 return LDB_ERR_OPERATIONS_ERROR
;
842 out
->length
= strlen((char *)out
->data
);
847 * Lexicographically sorted representation for a 32-bit integer
849 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
852 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
853 * corresponding documentation for 64-bit integers.
855 * The same rules apply but use INT32_MIN and INT32_MAX.
857 * String representation padding is done to 10 characters.
859 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
862 static int ldif_index_format_int32(struct ldb_context
*ldb
,
864 const struct ldb_val
*in
,
872 ret
= val_to_int32(in
, &i
);
873 if (ret
!= LDB_SUCCESS
) {
879 * i is negative, so this is subtraction rather than
883 i
= INT32_MAX
+ i
+ 1;
890 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%c%010ld", prefix
, (long)i
);
891 if (out
->data
== NULL
) {
893 return LDB_ERR_OPERATIONS_ERROR
;
896 len
= talloc_array_length(out
->data
) - 1;
898 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
899 __location__
": expected index format str %s to"
900 " have length 11 but got %zu",
901 (char*)out
->data
, len
);
902 return LDB_ERR_OPERATIONS_ERROR
;
909 /* Comparison of two 32-bit integers */
910 static int ldif_comparison_int32(struct ldb_context
*ldb
, void *mem_ctx
,
911 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
914 val_to_int32(v1
, &i1
);
915 val_to_int32(v2
, &i2
);
916 if (i1
== i2
) return 0;
917 return i1
> i2
? 1 : -1;
920 /* Canonicalisation of two 64-bit integers */
921 static int ldif_canonicalise_int64(struct ldb_context
*ldb
, void *mem_ctx
,
922 const struct ldb_val
*in
, struct ldb_val
*out
)
927 ret
= val_to_int64(in
, &i
);
928 if (ret
!= LDB_SUCCESS
) {
931 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%lld", (long long)i
);
932 if (out
->data
== NULL
) {
934 return LDB_ERR_OPERATIONS_ERROR
;
936 out
->length
= strlen((char *)out
->data
);
940 /* Comparison of two 64-bit integers */
941 static int ldif_comparison_int64(struct ldb_context
*ldb
, void *mem_ctx
,
942 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
945 val_to_int64(v1
, &i1
);
946 val_to_int64(v2
, &i2
);
947 if (i1
== i2
) return 0;
948 return i1
> i2
? 1 : -1;
952 convert a NDR formatted blob to a ldif formatted repsFromTo
954 static int ldif_write_repsFromTo(struct ldb_context
*ldb
, void *mem_ctx
,
955 const struct ldb_val
*in
, struct ldb_val
*out
)
957 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
958 sizeof(struct repsFromToBlob
),
959 (ndr_pull_flags_fn_t
)ndr_pull_repsFromToBlob
,
960 (ndr_print_fn_t
)ndr_print_repsFromToBlob
,
965 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
967 static int ldif_write_replPropertyMetaData(struct ldb_context
*ldb
, void *mem_ctx
,
968 const struct ldb_val
*in
, struct ldb_val
*out
)
970 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
971 sizeof(struct replPropertyMetaDataBlob
),
972 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaDataBlob
,
973 (ndr_print_fn_t
)ndr_print_replPropertyMetaDataBlob
,
978 convert a NDR formatted blob to a ldif formatted replUpToDateVector
980 static int ldif_write_replUpToDateVector(struct ldb_context
*ldb
, void *mem_ctx
,
981 const struct ldb_val
*in
, struct ldb_val
*out
)
983 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
984 sizeof(struct replUpToDateVectorBlob
),
985 (ndr_pull_flags_fn_t
)ndr_pull_replUpToDateVectorBlob
,
986 (ndr_print_fn_t
)ndr_print_replUpToDateVectorBlob
,
990 static int ldif_write_dn_binary_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
991 const struct ldb_val
*in
, struct ldb_val
*out
,
993 ndr_pull_flags_fn_t pull_fn
,
994 ndr_print_fn_t print_fn
,
998 enum ndr_err_code err
;
999 struct dsdb_dn
*dsdb_dn
= NULL
;
1000 char *dn_str
= NULL
;
1003 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
1004 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1007 dsdb_dn
= dsdb_dn_parse(mem_ctx
, ldb
, in
, DSDB_SYNTAX_BINARY_DN
);
1008 if (dsdb_dn
== NULL
) {
1009 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1012 p
= talloc_size(dsdb_dn
, struct_size
);
1014 TALLOC_FREE(dsdb_dn
);
1015 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1018 err
= ndr_pull_struct_blob(&dsdb_dn
->extra_part
, p
, p
, pull_fn
);
1019 if (err
!= NDR_ERR_SUCCESS
) {
1020 /* fail in not in mask_error mode */
1024 TALLOC_FREE(dsdb_dn
);
1025 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1028 dn_str
= ldb_dn_get_extended_linearized(dsdb_dn
, dsdb_dn
->dn
, 1);
1029 if (dn_str
== NULL
) {
1030 TALLOC_FREE(dsdb_dn
);
1031 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1034 str
= ndr_print_struct_string(mem_ctx
, print_fn
, dn_str
, p
);
1035 TALLOC_FREE(dsdb_dn
);
1037 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1040 *out
= data_blob_string_const(str
);
1044 static int ldif_write_msDS_RevealedUsers(struct ldb_context
*ldb
, void *mem_ctx
,
1045 const struct ldb_val
*in
, struct ldb_val
*out
)
1047 return ldif_write_dn_binary_NDR(ldb
, mem_ctx
, in
, out
,
1048 sizeof(struct replPropertyMetaData1
),
1049 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaData1
,
1050 (ndr_print_fn_t
)ndr_print_replPropertyMetaData1
,
1055 convert a NDR formatted blob to a ldif formatted dnsRecord
1057 static int ldif_write_dnsRecord(struct ldb_context
*ldb
, void *mem_ctx
,
1058 const struct ldb_val
*in
, struct ldb_val
*out
)
1060 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1061 sizeof(struct dnsp_DnssrvRpcRecord
),
1062 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
,
1063 (ndr_print_fn_t
)ndr_print_dnsp_DnssrvRpcRecord
,
1068 convert a NDR formatted blob to a ldif formatted dnsProperty
1070 static int ldif_write_dnsProperty(struct ldb_context
*ldb
, void *mem_ctx
,
1071 const struct ldb_val
*in
, struct ldb_val
*out
)
1073 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1074 sizeof(struct dnsp_DnsProperty
),
1075 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnsProperty
,
1076 (ndr_print_fn_t
)ndr_print_dnsp_DnsProperty
,
1081 convert a NDR formatted blob of a supplementalCredentials into text
1083 static int ldif_write_supplementalCredentialsBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1084 const struct ldb_val
*in
, struct ldb_val
*out
)
1086 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1087 sizeof(struct supplementalCredentialsBlob
),
1088 (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
,
1089 (ndr_print_fn_t
)ndr_print_supplementalCredentialsBlob
,
1094 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1096 static int ldif_write_trustAuthInOutBlob(struct ldb_context
*ldb
, void *mem_ctx
,
1097 const struct ldb_val
*in
, struct ldb_val
*out
)
1099 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1100 sizeof(struct trustAuthInOutBlob
),
1101 (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
,
1102 (ndr_print_fn_t
)ndr_print_trustAuthInOutBlob
,
1107 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1109 static int ldif_write_ForestTrustInfo(struct ldb_context
*ldb
, void *mem_ctx
,
1110 const struct ldb_val
*in
, struct ldb_val
*out
)
1112 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1113 sizeof(struct ForestTrustInfo
),
1114 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
,
1115 (ndr_print_fn_t
)ndr_print_ForestTrustInfo
,
1119 convert a NDR formatted blob of a partialAttributeSet into text
1121 static int ldif_write_partialAttributeSet(struct ldb_context
*ldb
, void *mem_ctx
,
1122 const struct ldb_val
*in
, struct ldb_val
*out
)
1124 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1125 sizeof(struct partialAttributeSetBlob
),
1126 (ndr_pull_flags_fn_t
)ndr_pull_partialAttributeSetBlob
,
1127 (ndr_print_fn_t
)ndr_print_partialAttributeSetBlob
,
1132 static int extended_dn_write_hex(struct ldb_context
*ldb
, void *mem_ctx
,
1133 const struct ldb_val
*in
, struct ldb_val
*out
)
1135 *out
= data_blob_string_const(data_blob_hex_string_lower(mem_ctx
, in
));
1145 static int samba_ldb_dn_link_comparison(struct ldb_context
*ldb
, void *mem_ctx
,
1146 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1148 struct ldb_dn
*dn1
= NULL
, *dn2
= NULL
;
1151 if (dsdb_dn_is_deleted_val(v1
)) {
1152 /* If the DN is deleted, then we can't search for it */
1156 if (dsdb_dn_is_deleted_val(v2
)) {
1157 /* If the DN is deleted, then we can't search for it */
1161 dn1
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v1
);
1162 if ( ! ldb_dn_validate(dn1
)) return -1;
1164 dn2
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v2
);
1165 if ( ! ldb_dn_validate(dn2
)) {
1170 ret
= ldb_dn_compare(dn1
, dn2
);
1177 static int samba_ldb_dn_link_canonicalise(struct ldb_context
*ldb
, void *mem_ctx
,
1178 const struct ldb_val
*in
, struct ldb_val
*out
)
1186 dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, in
);
1187 if ( ! ldb_dn_validate(dn
)) {
1188 return LDB_ERR_INVALID_DN_SYNTAX
;
1191 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1192 * does not casually match a not deleted DN */
1193 if (dsdb_dn_is_deleted_val(in
)) {
1194 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
,
1196 dsdb_dn_val_rmd_flags(in
),
1197 ldb_dn_get_casefold(dn
));
1199 out
->data
= (uint8_t *)ldb_dn_alloc_casefold(mem_ctx
, dn
);
1202 if (out
->data
== NULL
) {
1205 out
->length
= strlen((char *)out
->data
);
1217 write a 64 bit 2-part range
1219 static int ldif_write_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1220 const struct ldb_val
*in
, struct ldb_val
*out
)
1224 ret
= val_to_int64(in
, &v
);
1225 if (ret
!= LDB_SUCCESS
) {
1228 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%lu-%lu",
1229 (unsigned long)(v
&0xFFFFFFFF),
1230 (unsigned long)(v
>>32));
1231 if (out
->data
== NULL
) {
1233 return LDB_ERR_OPERATIONS_ERROR
;
1235 out
->length
= strlen((char *)out
->data
);
1240 read a 64 bit 2-part range
1242 static int ldif_read_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1243 const struct ldb_val
*in
, struct ldb_val
*out
)
1245 unsigned long high
, low
;
1248 if (memchr(in
->data
, '-', in
->length
) == NULL
) {
1249 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1252 if (in
->length
> sizeof(buf
)-1) {
1253 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1255 strncpy(buf
, (const char *)in
->data
, in
->length
);
1256 buf
[in
->length
] = 0;
1258 if (sscanf(buf
, "%lu-%lu", &low
, &high
) != 2) {
1259 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1262 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%llu",
1263 (unsigned long long)(((uint64_t)high
)<<32) | (low
));
1265 if (out
->data
== NULL
) {
1267 return LDB_ERR_OPERATIONS_ERROR
;
1269 out
->length
= strlen((char *)out
->data
);
1274 when this operator_fn is set for a syntax, the backend calls is in
1275 preference to the comparison function. We are told the exact
1276 comparison operation that is needed, and we can return errors
1278 static int samba_syntax_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 switch (operation
) {
1286 case LDB_OP_SUBSTRING
:
1288 case LDB_OP_EXTENDED
:
1289 /* handled in the backends */
1290 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1292 case LDB_OP_GREATER
:
1294 case LDB_OP_EQUALITY
:
1296 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
1298 if (tmp_ctx
== NULL
) {
1299 return ldb_oom(ldb
);
1301 ret
= a
->syntax
->comparison_fn(ldb
, tmp_ctx
, v1
, v2
);
1302 talloc_free(tmp_ctx
);
1303 if (operation
== LDB_OP_GREATER
) {
1304 *matched
= (ret
>= 0);
1305 } else if (operation
== LDB_OP_LESS
) {
1306 *matched
= (ret
<= 0);
1308 *matched
= (ret
== 0);
1313 case LDB_OP_PRESENT
:
1318 /* we shouldn't get here */
1319 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1323 compare two binary objects. This is correct for sorting as the sort order is:
1330 rather than ldb_comparison_binary() which is:
1338 static int samba_ldb_comparison_binary(struct ldb_context
*ldb
, void *mem_ctx
,
1339 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1341 return data_blob_cmp(v1
, v2
);
1345 when this operator_fn is set for a syntax, the backend calls is in
1346 preference to the comparison function. We are told the exact
1347 comparison operation that is needed, and we can return errors.
1349 This mode optimises for ldb_comparison_binary() if we need equality,
1350 as this should be faster as it can do a length-check first.
1352 static int samba_syntax_binary_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1353 const struct ldb_schema_attribute
*a
,
1354 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1356 if (operation
== LDB_OP_EQUALITY
) {
1357 *matched
= (ldb_comparison_binary(ldb
, NULL
, v1
, v2
) == 0);
1360 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1364 see if two DNs match, comparing first by GUID, then by SID, and
1365 finally by string components
1367 static int samba_dn_extended_match(struct ldb_context
*ldb
,
1368 const struct ldb_val
*v1
,
1369 const struct ldb_val
*v2
,
1372 TALLOC_CTX
*tmp_ctx
;
1373 struct ldb_dn
*dn1
, *dn2
;
1374 const struct ldb_val
*guid1
, *guid2
, *sid1
, *sid2
;
1375 uint32_t rmd_flags1
, rmd_flags2
;
1377 tmp_ctx
= talloc_new(ldb
);
1379 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v1
);
1380 dn2
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v2
);
1382 /* couldn't parse as DN's */
1383 talloc_free(tmp_ctx
);
1388 rmd_flags1
= dsdb_dn_rmd_flags(dn1
);
1389 rmd_flags2
= dsdb_dn_rmd_flags(dn2
);
1391 if ((rmd_flags1
& DSDB_RMD_FLAG_DELETED
) !=
1392 (rmd_flags2
& DSDB_RMD_FLAG_DELETED
)) {
1393 /* only match if they have the same deletion status */
1394 talloc_free(tmp_ctx
);
1400 guid1
= ldb_dn_get_extended_component(dn1
, "GUID");
1401 guid2
= ldb_dn_get_extended_component(dn2
, "GUID");
1402 if (guid1
&& guid2
) {
1403 (*matched
) = (data_blob_cmp(guid1
, guid2
) == 0);
1404 talloc_free(tmp_ctx
);
1408 sid1
= ldb_dn_get_extended_component(dn1
, "SID");
1409 sid2
= ldb_dn_get_extended_component(dn2
, "SID");
1411 (*matched
) = (data_blob_cmp(sid1
, sid2
) == 0);
1412 talloc_free(tmp_ctx
);
1416 (*matched
) = (ldb_dn_compare(dn1
, dn2
) == 0);
1418 talloc_free(tmp_ctx
);
1423 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1425 static int samba_syntax_operator_dn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1426 const struct ldb_schema_attribute
*a
,
1427 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1429 if (operation
== LDB_OP_PRESENT
&& dsdb_dn_is_deleted_val(v1
)) {
1430 /* If the DN is deleted, then we can't search for it */
1432 /* should this be for equality too? */
1437 if (operation
== LDB_OP_EQUALITY
&&
1438 samba_dn_extended_match(ldb
, v1
, v2
, matched
) == LDB_SUCCESS
) {
1442 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1446 static const struct ldb_schema_syntax samba_syntaxes
[] = {
1448 .name
= LDB_SYNTAX_SAMBA_SID
,
1449 .ldif_read_fn
= ldif_read_objectSid
,
1450 .ldif_write_fn
= ldif_write_objectSid
,
1451 .canonicalise_fn
= ldif_canonicalise_objectSid
,
1452 .comparison_fn
= ldif_comparison_objectSid
,
1453 .operator_fn
= samba_syntax_operator_fn
1455 .name
= LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
,
1456 .ldif_read_fn
= ldif_read_ntSecurityDescriptor
,
1457 .ldif_write_fn
= ldif_write_ntSecurityDescriptor
,
1458 .canonicalise_fn
= ldb_handler_copy
,
1459 .comparison_fn
= samba_ldb_comparison_binary
,
1460 .operator_fn
= samba_syntax_binary_operator_fn
1462 .name
= LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
,
1463 .ldif_read_fn
= ldb_handler_copy
,
1464 .ldif_write_fn
= ldif_write_sddlSecurityDescriptor
,
1465 .canonicalise_fn
= ldb_handler_fold
,
1466 .comparison_fn
= ldb_comparison_fold
,
1467 .operator_fn
= samba_syntax_operator_fn
1469 .name
= LDB_SYNTAX_SAMBA_GUID
,
1470 .ldif_read_fn
= ldif_read_objectGUID
,
1471 .ldif_write_fn
= ldif_write_objectGUID
,
1472 .canonicalise_fn
= ldif_canonicalise_objectGUID
,
1473 .comparison_fn
= ldif_comparison_objectGUID
,
1474 .operator_fn
= samba_syntax_operator_fn
1476 .name
= LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
,
1477 .ldif_read_fn
= ldb_handler_copy
,
1478 .ldif_write_fn
= ldb_handler_copy
,
1479 .canonicalise_fn
= ldif_canonicalise_objectCategory
,
1480 .comparison_fn
= ldif_comparison_objectCategory
,
1481 .operator_fn
= samba_syntax_operator_fn
1483 .name
= LDB_SYNTAX_SAMBA_SCHEMAINFO
,
1484 .ldif_read_fn
= ldb_handler_copy
,
1485 .ldif_write_fn
= ldif_write_schemaInfo
,
1486 .canonicalise_fn
= ldb_handler_copy
,
1487 .comparison_fn
= samba_ldb_comparison_binary
,
1488 .operator_fn
= samba_syntax_binary_operator_fn
1490 .name
= LDB_SYNTAX_SAMBA_PREFIX_MAP
,
1491 .ldif_read_fn
= ldif_read_prefixMap
,
1492 .ldif_write_fn
= ldif_write_prefixMap
,
1493 .canonicalise_fn
= ldif_canonicalise_prefixMap
,
1494 .comparison_fn
= ldif_comparison_prefixMap
,
1495 .operator_fn
= samba_syntax_operator_fn
1497 .name
= LDB_SYNTAX_SAMBA_INT32
,
1498 .ldif_read_fn
= ldb_handler_copy
,
1499 .ldif_write_fn
= ldb_handler_copy
,
1500 .canonicalise_fn
= ldif_canonicalise_int32
,
1501 .index_format_fn
= ldif_index_format_int32
,
1502 .comparison_fn
= ldif_comparison_int32
,
1503 .operator_fn
= samba_syntax_operator_fn
1505 .name
= LDB_SYNTAX_SAMBA_REPSFROMTO
,
1506 .ldif_read_fn
= ldb_handler_copy
,
1507 .ldif_write_fn
= ldif_write_repsFromTo
,
1508 .canonicalise_fn
= ldb_handler_copy
,
1509 .comparison_fn
= samba_ldb_comparison_binary
,
1510 .operator_fn
= samba_syntax_binary_operator_fn
1512 .name
= LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
,
1513 .ldif_read_fn
= ldb_handler_copy
,
1514 .ldif_write_fn
= ldif_write_replPropertyMetaData
,
1515 .canonicalise_fn
= ldb_handler_copy
,
1516 .comparison_fn
= samba_ldb_comparison_binary
,
1517 .operator_fn
= samba_syntax_binary_operator_fn
1519 .name
= LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
,
1520 .ldif_read_fn
= ldb_handler_copy
,
1521 .ldif_write_fn
= ldif_write_replUpToDateVector
,
1522 .canonicalise_fn
= ldb_handler_copy
,
1523 .comparison_fn
= samba_ldb_comparison_binary
,
1524 .operator_fn
= samba_syntax_binary_operator_fn
1526 .name
= LDB_SYNTAX_SAMBA_REVEALEDUSERS
,
1527 .ldif_read_fn
= ldb_handler_copy
,
1528 .ldif_write_fn
= ldif_write_msDS_RevealedUsers
,
1529 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1530 .comparison_fn
= dsdb_dn_binary_comparison
,
1531 .operator_fn
= samba_syntax_operator_fn
1533 .name
= LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
,
1534 .ldif_read_fn
= ldb_handler_copy
,
1535 .ldif_write_fn
= ldif_write_trustAuthInOutBlob
,
1536 .canonicalise_fn
= ldb_handler_copy
,
1537 .comparison_fn
= samba_ldb_comparison_binary
,
1538 .operator_fn
= samba_syntax_binary_operator_fn
1540 .name
= LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
,
1541 .ldif_read_fn
= ldb_handler_copy
,
1542 .ldif_write_fn
= ldif_write_ForestTrustInfo
,
1543 .canonicalise_fn
= ldb_handler_copy
,
1544 .comparison_fn
= samba_ldb_comparison_binary
,
1545 .operator_fn
= samba_syntax_binary_operator_fn
1547 .name
= DSDB_SYNTAX_BINARY_DN
,
1548 .ldif_read_fn
= ldb_handler_copy
,
1549 .ldif_write_fn
= ldb_handler_copy
,
1550 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1551 .comparison_fn
= dsdb_dn_binary_comparison
,
1552 .operator_fn
= samba_syntax_operator_fn
1554 .name
= DSDB_SYNTAX_STRING_DN
,
1555 .ldif_read_fn
= ldb_handler_copy
,
1556 .ldif_write_fn
= ldb_handler_copy
,
1557 .canonicalise_fn
= dsdb_dn_string_canonicalise
,
1558 .comparison_fn
= dsdb_dn_string_comparison
,
1559 .operator_fn
= samba_syntax_operator_fn
1561 .name
= LDB_SYNTAX_DN
,
1562 .ldif_read_fn
= ldb_handler_copy
,
1563 .ldif_write_fn
= ldb_handler_copy
,
1564 .canonicalise_fn
= samba_ldb_dn_link_canonicalise
,
1565 .comparison_fn
= samba_ldb_dn_link_comparison
,
1566 .operator_fn
= samba_syntax_operator_dn
1568 .name
= LDB_SYNTAX_SAMBA_RANGE64
,
1569 .ldif_read_fn
= ldif_read_range64
,
1570 .ldif_write_fn
= ldif_write_range64
,
1571 .canonicalise_fn
= ldif_canonicalise_int64
,
1572 .comparison_fn
= ldif_comparison_int64
,
1573 .operator_fn
= samba_syntax_operator_fn
1575 .name
= LDB_SYNTAX_SAMBA_DNSRECORD
,
1576 .ldif_read_fn
= ldb_handler_copy
,
1577 .ldif_write_fn
= ldif_write_dnsRecord
,
1578 .canonicalise_fn
= ldb_handler_copy
,
1579 .comparison_fn
= samba_ldb_comparison_binary
,
1580 .operator_fn
= samba_syntax_binary_operator_fn
1582 .name
= LDB_SYNTAX_SAMBA_DNSPROPERTY
,
1583 .ldif_read_fn
= ldb_handler_copy
,
1584 .ldif_write_fn
= ldif_write_dnsProperty
,
1585 .canonicalise_fn
= ldb_handler_copy
,
1586 .comparison_fn
= samba_ldb_comparison_binary
,
1587 .operator_fn
= samba_syntax_binary_operator_fn
1589 .name
= LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
,
1590 .ldif_read_fn
= ldb_handler_copy
,
1591 .ldif_write_fn
= ldif_write_supplementalCredentialsBlob
,
1592 .canonicalise_fn
= ldb_handler_copy
,
1593 .comparison_fn
= samba_ldb_comparison_binary
,
1594 .operator_fn
= samba_syntax_binary_operator_fn
1596 .name
= LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
,
1597 .ldif_read_fn
= ldb_handler_copy
,
1598 .ldif_write_fn
= ldif_write_partialAttributeSet
,
1599 .canonicalise_fn
= ldb_handler_copy
,
1600 .comparison_fn
= samba_ldb_comparison_binary
,
1601 .operator_fn
= samba_syntax_binary_operator_fn
1603 .name
= LDB_SYNTAX_SAMBA_OCTET_STRING
,
1604 .ldif_read_fn
= ldb_handler_copy
,
1605 .ldif_write_fn
= ldb_handler_copy
,
1606 .canonicalise_fn
= ldb_handler_copy
,
1607 .comparison_fn
= samba_ldb_comparison_binary
,
1608 .operator_fn
= samba_syntax_binary_operator_fn
1612 static const struct ldb_dn_extended_syntax samba_dn_syntax
[] = {
1615 .read_fn
= extended_dn_read_SID
,
1616 .write_clear_fn
= ldif_write_objectSid
,
1617 .write_hex_fn
= extended_dn_write_hex
1620 .read_fn
= extended_dn_read_GUID
,
1621 .write_clear_fn
= ldif_write_objectGUID
,
1622 .write_hex_fn
= extended_dn_write_hex
1625 .read_fn
= ldb_handler_copy
,
1626 .write_clear_fn
= ldb_handler_copy
,
1627 .write_hex_fn
= ldb_handler_copy
1629 .name
= "RMD_INVOCID",
1630 .read_fn
= extended_dn_read_GUID
,
1631 .write_clear_fn
= ldif_write_objectGUID
,
1632 .write_hex_fn
= extended_dn_write_hex
1634 .name
= "RMD_FLAGS",
1635 .read_fn
= ldb_handler_copy
,
1636 .write_clear_fn
= ldb_handler_copy
,
1637 .write_hex_fn
= ldb_handler_copy
1639 .name
= "RMD_ADDTIME",
1640 .read_fn
= ldb_handler_copy
,
1641 .write_clear_fn
= ldb_handler_copy
,
1642 .write_hex_fn
= ldb_handler_copy
1644 .name
= "RMD_CHANGETIME",
1645 .read_fn
= ldb_handler_copy
,
1646 .write_clear_fn
= ldb_handler_copy
,
1647 .write_hex_fn
= ldb_handler_copy
1649 .name
= "RMD_LOCAL_USN",
1650 .read_fn
= ldb_handler_copy
,
1651 .write_clear_fn
= ldb_handler_copy
,
1652 .write_hex_fn
= ldb_handler_copy
1654 .name
= "RMD_ORIGINATING_USN",
1655 .read_fn
= ldb_handler_copy
,
1656 .write_clear_fn
= ldb_handler_copy
,
1657 .write_hex_fn
= ldb_handler_copy
1659 .name
= "RMD_VERSION",
1660 .read_fn
= ldb_handler_copy
,
1661 .write_clear_fn
= ldb_handler_copy
,
1662 .write_hex_fn
= ldb_handler_copy
1666 /* TODO: Should be dynamic at some point */
1667 static const struct {
1670 } samba_attributes
[] = {
1671 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
},
1672 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32
},
1673 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
},
1674 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO
},
1675 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP
},
1676 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1677 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1678 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
},
1679 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
},
1680 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS
},
1681 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1682 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1683 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
},
1684 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1685 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1686 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64
},
1687 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
},
1690 * these are extracted by searching
1691 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1693 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1694 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1695 * hat can be used to identify the set of policies when applied to a resource.
1696 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1697 * server, we ignore it here.
1699 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID
},
1700 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID
},
1701 { "objectSid", LDB_SYNTAX_SAMBA_SID
},
1702 { "tokenGroups", LDB_SYNTAX_SAMBA_SID
},
1703 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID
},
1704 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID
},
1705 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID
},
1706 { "sIDHistory", LDB_SYNTAX_SAMBA_SID
},
1707 { "syncWithSID", LDB_SYNTAX_SAMBA_SID
},
1710 * these are extracted by searching
1711 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1713 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID
},
1714 { "categoryId", LDB_SYNTAX_SAMBA_GUID
},
1715 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID
},
1716 { "currMachineId", LDB_SYNTAX_SAMBA_GUID
},
1717 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID
},
1718 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID
},
1719 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID
},
1720 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID
},
1721 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID
},
1722 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID
},
1723 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID
},
1724 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID
},
1725 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID
},
1726 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID
},
1727 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID
},
1728 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID
},
1729 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID
},
1730 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID
},
1731 { "objectGUID", LDB_SYNTAX_SAMBA_GUID
},
1732 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID
},
1733 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID
},
1734 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID
},
1735 { "siteGUID", LDB_SYNTAX_SAMBA_GUID
},
1736 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1737 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1738 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1739 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID
},
1740 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID
},
1743 * these are known to be GUIDs
1745 { "invocationId", LDB_SYNTAX_SAMBA_GUID
},
1746 { "parentGUID", LDB_SYNTAX_SAMBA_GUID
},
1748 /* These NDR encoded things we want to be able to read with --show-binary */
1749 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD
},
1750 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY
},
1751 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
},
1752 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
}
1755 const struct ldb_schema_syntax
*ldb_samba_syntax_by_name(struct ldb_context
*ldb
, const char *name
)
1758 const struct ldb_schema_syntax
*s
= NULL
;
1760 for (j
=0; j
< ARRAY_SIZE(samba_syntaxes
); j
++) {
1761 if (strcmp(name
, samba_syntaxes
[j
].name
) == 0) {
1762 s
= &samba_syntaxes
[j
];
1769 const struct ldb_schema_syntax
*ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context
*ldb
, const char *name
)
1772 const struct ldb_schema_syntax
*s
= NULL
;
1774 for (j
=0; j
< ARRAY_SIZE(samba_attributes
); j
++) {
1775 if (strcmp(samba_attributes
[j
].name
, name
) == 0) {
1776 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[j
].syntax
);
1784 static const char *secret_attributes
[] = {DSDB_SECRET_ATTRIBUTES
, "secret",
1785 "priorSecret", NULL
};
1788 register the samba ldif handlers
1790 int ldb_register_samba_handlers(struct ldb_context
*ldb
)
1795 if (ldb_get_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED") != NULL
) {
1799 ret
= ldb_set_opaque(ldb
, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE
, discard_const_p(char *, secret_attributes
));
1800 if (ret
!= LDB_SUCCESS
) {
1804 for (i
=0; i
< ARRAY_SIZE(samba_attributes
); i
++) {
1805 const struct ldb_schema_syntax
*s
= NULL
;
1807 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1810 s
= ldb_standard_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1814 return LDB_ERR_OPERATIONS_ERROR
;
1817 ret
= ldb_schema_attribute_add_with_syntax(ldb
, samba_attributes
[i
].name
, LDB_ATTR_FLAG_FIXED
, s
);
1818 if (ret
!= LDB_SUCCESS
) {
1823 for (i
=0; i
< ARRAY_SIZE(samba_dn_syntax
); i
++) {
1824 ret
= ldb_dn_extended_add_syntax(ldb
, LDB_ATTR_FLAG_FIXED
, &samba_dn_syntax
[i
]);
1825 if (ret
!= LDB_SUCCESS
) {
1831 ret
= ldb_register_samba_matching_rules(ldb
);
1832 if (ret
!= LDB_SUCCESS
) {
1837 ret
= ldb_set_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1838 if (ret
!= LDB_SUCCESS
) {