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
)) {
113 TALLOC_FREE(out
->data
);
121 convert a NDR formatted blob to a ldif formatted objectSid
123 int ldif_write_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
124 const struct ldb_val
*in
, struct ldb_val
*out
)
127 enum ndr_err_code ndr_err
;
129 ndr_err
= ndr_pull_struct_blob_all_noalloc(in
, &sid
,
130 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
131 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
134 *out
= data_blob_string_const(dom_sid_string(mem_ctx
, &sid
));
135 if (out
->data
== NULL
) {
141 bool ldif_comparision_objectSid_isString(const struct ldb_val
*v
)
147 if (strncmp("S-", (const char *)v
->data
, 2) != 0) return false;
153 compare two objectSids
155 If the SIDs seem to be strings, they are converted to binary form.
157 static int ldif_comparison_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
158 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
160 bool v1_is_string
= ldif_comparision_objectSid_isString(v1
);
161 bool v2_is_string
= ldif_comparision_objectSid_isString(v2
);
162 struct ldb_val parsed_1
= {};
163 struct ldb_val parsed_2
= {};
166 * If the ldb_vals look like SID strings (i.e. start with "S-"
167 * or "s-"), we try to parse them as such. If that fails, we
168 * assume they are binary SIDs, even though that's not really
169 * possible -- the first two bytes of a struct dom_sid are the
170 * version (1), and the number of sub-auths (<= 15), neither
171 * of which are close to 'S' or '-'.
174 int r
= ldif_read_objectSid(ldb
, mem_ctx
, v1
, &parsed_1
);
180 int r
= ldif_read_objectSid(ldb
, mem_ctx
, v2
, &parsed_2
);
186 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
189 TALLOC_FREE(parsed_1
.data
);
192 TALLOC_FREE(parsed_2
.data
);
198 canonicalise a objectSid
200 static int ldif_canonicalise_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
201 const struct ldb_val
*in
, struct ldb_val
*out
)
203 if (ldif_comparision_objectSid_isString(in
)) {
204 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) != 0) {
205 /* Perhaps not a string after all */
206 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
210 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
213 static int extended_dn_read_SID(struct ldb_context
*ldb
, void *mem_ctx
,
214 const struct ldb_val
*in
, struct ldb_val
*out
)
217 enum ndr_err_code ndr_err
;
218 if (ldif_comparision_objectSid_isString(in
)) {
219 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) == 0) {
224 /* Perhaps not a string after all */
225 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
231 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
232 (const char *)in
->data
, in
->length
);
234 /* Check it looks like a SID */
235 ndr_err
= ndr_pull_struct_blob_all_noalloc(out
, &sid
,
236 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
237 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
238 TALLOC_FREE(out
->data
);
245 convert a ldif formatted objectGUID to a NDR formatted blob
247 static int ldif_read_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
248 const struct ldb_val
*in
, struct ldb_val
*out
)
253 status
= GUID_from_data_blob(in
, &guid
);
254 if (!NT_STATUS_IS_OK(status
)) {
258 status
= GUID_to_ndr_blob(&guid
, mem_ctx
, out
);
259 if (!NT_STATUS_IS_OK(status
)) {
266 convert a NDR formatted blob to a ldif formatted objectGUID
268 static int ldif_write_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
269 const struct ldb_val
*in
, struct ldb_val
*out
)
274 status
= GUID_from_ndr_blob(in
, &guid
);
275 if (!NT_STATUS_IS_OK(status
)) {
278 out
->data
= (uint8_t *)GUID_string(mem_ctx
, &guid
);
279 if (out
->data
== NULL
) {
282 out
->length
= strlen((const char *)out
->data
);
286 static bool ldif_comparision_objectGUID_isString(const struct ldb_val
*v
)
288 if (v
->length
!= 36 && v
->length
!= 38) return false;
290 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
294 static int extended_dn_read_GUID(struct ldb_context
*ldb
, void *mem_ctx
,
295 const struct ldb_val
*in
, struct ldb_val
*out
)
298 if (in
->length
== 36 && ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) == 0) {
302 /* Try as 'hex' form */
303 if (in
->length
!= 32) {
307 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
313 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
314 (const char *)in
->data
, in
->length
);
316 /* Check it looks like a GUID */
317 if ((*out
).length
!= 16) {
326 compare two objectGUIDs
328 static int ldif_comparison_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
329 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
331 if (ldif_comparision_objectGUID_isString(v1
) && ldif_comparision_objectGUID_isString(v2
)) {
332 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
333 } else if (ldif_comparision_objectGUID_isString(v1
)
334 && !ldif_comparision_objectGUID_isString(v2
)) {
337 if (ldif_read_objectGUID(ldb
, mem_ctx
, v1
, &v
) != 0) {
338 /* Perhaps it wasn't a valid string after all */
339 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
341 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
344 } else if (!ldif_comparision_objectGUID_isString(v1
)
345 && ldif_comparision_objectGUID_isString(v2
)) {
348 if (ldif_read_objectGUID(ldb
, mem_ctx
, v2
, &v
) != 0) {
349 /* Perhaps it wasn't a valid string after all */
350 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
352 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
356 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
360 canonicalise a objectGUID
362 static int ldif_canonicalise_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
363 const struct ldb_val
*in
, struct ldb_val
*out
)
365 if (ldif_comparision_objectGUID_isString(in
)) {
366 if (ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) != 0) {
367 /* Perhaps it wasn't a valid string after all */
368 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
372 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
377 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
379 static int ldif_read_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
380 const struct ldb_val
*in
, struct ldb_val
*out
)
382 struct security_descriptor
*sd
;
383 enum ndr_err_code ndr_err
;
385 if (in
->length
>= 2 && isupper(in
->data
[0]) && in
->data
[1] == ':') {
387 * If it starts with an upper case character followed by ':',
388 * we know it's not NDR, but most likely SDDL...
390 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
392 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
400 sd
= talloc(mem_ctx
, struct security_descriptor
);
405 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
406 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
407 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
413 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, sd
,
414 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
416 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
424 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
426 static int ldif_write_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
427 const struct ldb_val
*in
, struct ldb_val
*out
)
429 struct security_descriptor
*sd
;
430 enum ndr_err_code ndr_err
;
432 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
433 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
434 sizeof(struct security_descriptor
),
435 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
,
436 (ndr_print_fn_t
)ndr_print_security_descriptor
,
441 sd
= talloc(mem_ctx
, struct security_descriptor
);
445 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
446 ndr_err
= ndr_pull_struct_blob(in
, sd
, sd
,
447 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
448 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
452 out
->data
= (uint8_t *)sddl_encode(mem_ctx
, sd
, samdb_domain_sid_cache_only(ldb
));
454 if (out
->data
== NULL
) {
457 out
->length
= strlen((const char *)out
->data
);
462 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
464 static int ldif_write_sddlSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
465 const struct ldb_val
*in
, struct ldb_val
*out
)
467 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
468 struct security_descriptor
*sd
;
469 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
471 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
472 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
,
473 (ndr_print_fn_t
)ndr_print_security_descriptor
,
475 out
->length
= strlen((const char *)out
->data
);
480 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
484 canonicalise an objectCategory. We use the long form as the canonical form:
485 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
487 Also any short name of an objectClass that points to a different
488 class (such as user) has the canonical form of the class it's
489 defaultObjectCategory points to (eg
490 cn=Person,cn=Schema,cn=Configuration,<basedn>)
493 static int ldif_canonicalise_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
494 const struct ldb_val
*in
, struct ldb_val
*out
)
496 struct ldb_dn
*dn1
= NULL
;
497 const struct dsdb_schema
*schema
= dsdb_get_schema(ldb
, NULL
);
498 const struct dsdb_class
*sclass
;
499 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
501 return LDB_ERR_OPERATIONS_ERROR
;
505 talloc_free(tmp_ctx
);
506 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
507 if (in
->data
&& !out
->data
) {
508 return LDB_ERR_OPERATIONS_ERROR
;
512 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, in
);
513 if ( ! ldb_dn_validate(dn1
)) {
514 const char *lDAPDisplayName
= talloc_strndup(tmp_ctx
, (char *)in
->data
, in
->length
);
515 sclass
= dsdb_class_by_lDAPDisplayName(schema
, lDAPDisplayName
);
517 struct ldb_dn
*dn
= ldb_dn_new(tmp_ctx
, ldb
,
518 sclass
->defaultObjectCategory
);
520 talloc_free(tmp_ctx
);
521 return LDB_ERR_OPERATIONS_ERROR
;
524 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn
));
525 talloc_free(tmp_ctx
);
528 return LDB_ERR_OPERATIONS_ERROR
;
532 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
533 talloc_free(tmp_ctx
);
535 if (in
->data
&& !out
->data
) {
536 return LDB_ERR_OPERATIONS_ERROR
;
541 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn1
));
542 talloc_free(tmp_ctx
);
545 return LDB_ERR_OPERATIONS_ERROR
;
550 static int ldif_comparison_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
551 const struct ldb_val
*v1
,
552 const struct ldb_val
*v2
)
554 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_objectCategory
,
559 convert a NDR formatted blob to a ldif formatted schemaInfo
561 static int ldif_write_schemaInfo(struct ldb_context
*ldb
, void *mem_ctx
,
562 const struct ldb_val
*in
, struct ldb_val
*out
)
564 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
565 sizeof(struct repsFromToBlob
),
566 (ndr_pull_flags_fn_t
)ndr_pull_schemaInfoBlob
,
567 (ndr_print_fn_t
)ndr_print_schemaInfoBlob
,
572 convert a ldif formatted prefixMap to a NDR formatted blob
574 static int ldif_read_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
575 const struct ldb_val
*in
, struct ldb_val
*out
)
577 struct prefixMapBlob
*blob
;
578 enum ndr_err_code ndr_err
;
579 char *string
, *line
, *p
, *oid
;
582 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
584 if (tmp_ctx
== NULL
) {
588 blob
= talloc_zero(tmp_ctx
, struct prefixMapBlob
);
590 talloc_free(tmp_ctx
);
594 /* use the switch value to detect if this is in the binary
597 if (in
->length
>= 4 && IVAL(in
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
598 ndr_err
= ndr_pull_struct_blob(in
, tmp_ctx
, blob
,
599 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
600 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
601 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
603 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
604 talloc_free(tmp_ctx
);
605 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
612 /* If this does not parse, then it is probably the text version, and we should try it that way */
613 blob
->version
= PREFIX_MAP_VERSION_DSDB
;
615 string
= talloc_strndup(mem_ctx
, (const char *)in
->data
, in
->length
);
616 if (string
== NULL
) {
622 while (line
&& line
[0]) {
629 p
=strchr(line
, '\n');
634 /* allow a trailing separator */
639 blob
->ctr
.dsdb
.mappings
= talloc_realloc(blob
,
640 blob
->ctr
.dsdb
.mappings
,
641 struct drsuapi_DsReplicaOIDMapping
,
642 blob
->ctr
.dsdb
.num_mappings
+1);
643 if (!blob
->ctr
.dsdb
.mappings
) {
644 talloc_free(tmp_ctx
);
648 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].id_prefix
=
649 smb_strtoul(line
, &oid
, 10, &error
, SMB_STR_STANDARD
);
651 if (oid
[0] != ':' || error
!= 0) {
652 talloc_free(tmp_ctx
);
656 /* we know there must be at least ":" */
659 if (!ber_write_partial_OID_String(blob
->ctr
.dsdb
.mappings
, &oid_blob
, oid
)) {
660 talloc_free(tmp_ctx
);
663 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.length
= oid_blob
.length
;
664 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.binary_oid
= oid_blob
.data
;
666 blob
->ctr
.dsdb
.num_mappings
++;
668 /* Now look past the terminator we added above */
676 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
678 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
679 talloc_free(tmp_ctx
);
680 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
687 convert a NDR formatted blob to a ldif formatted prefixMap
689 static int ldif_write_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
690 const struct ldb_val
*in
, struct ldb_val
*out
)
692 struct prefixMapBlob
*blob
;
693 enum ndr_err_code ndr_err
;
697 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
699 /* try to decode the blob as S4 prefixMap */
700 err
= ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
701 sizeof(struct prefixMapBlob
),
702 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
,
703 (ndr_print_fn_t
)ndr_print_prefixMapBlob
,
708 /* try parsing it as Windows PrefixMap value */
709 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
710 sizeof(struct drsuapi_MSPrefixMap_Ctr
),
711 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_MSPrefixMap_Ctr
,
712 (ndr_print_fn_t
)ndr_print_drsuapi_MSPrefixMap_Ctr
,
716 blob
= talloc(mem_ctx
, struct prefixMapBlob
);
720 ndr_err
= ndr_pull_struct_blob_all(in
, blob
,
722 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
723 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
726 if (blob
->version
!= PREFIX_MAP_VERSION_DSDB
) {
729 string
= talloc_strdup(mem_ctx
, "");
730 if (string
== NULL
) {
734 for (i
=0; i
< blob
->ctr
.dsdb
.num_mappings
; i
++) {
736 char *partial_oid
= NULL
;
739 talloc_asprintf_addbuf(&string
, ";");
742 oid_blob
= data_blob_const(blob
->ctr
.dsdb
.mappings
[i
].oid
.binary_oid
,
743 blob
->ctr
.dsdb
.mappings
[i
].oid
.length
);
744 if (!ber_read_partial_OID_String(blob
, oid_blob
, &partial_oid
)) {
745 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X\n",
746 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
));
749 talloc_asprintf_addbuf(&string
, "%u:%s",
750 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
,
752 talloc_free(discard_const(partial_oid
));
756 *out
= data_blob_string_const(string
);
764 static bool ldif_comparision_prefixMap_isString(const struct ldb_val
*v
)
770 if (IVAL(v
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
778 canonicalise a prefixMap
780 static int ldif_canonicalise_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
781 const struct ldb_val
*in
, struct ldb_val
*out
)
783 if (ldif_comparision_prefixMap_isString(in
)) {
784 return ldif_read_prefixMap(ldb
, mem_ctx
, in
, out
);
786 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
789 static int ldif_comparison_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
790 const struct ldb_val
*v1
,
791 const struct ldb_val
*v2
)
793 return ldb_any_comparison(ldb
, mem_ctx
, ldif_canonicalise_prefixMap
,
797 /* length limited conversion of a ldb_val to a int32_t */
798 static int val_to_int32(const struct ldb_val
*in
, int32_t *v
)
803 /* make sure we don't read past the end of the data */
804 if (in
->length
> sizeof(buf
)-1) {
805 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
807 strncpy(buf
, (char *)in
->data
, in
->length
);
810 /* We've to use "strtoll" here to have the intended overflows.
811 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
812 *v
= (int32_t) strtoll(buf
, &end
, 0);
814 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
819 /* length limited conversion of a ldb_val to a int64_t */
820 static int val_to_int64(const struct ldb_val
*in
, int64_t *v
)
825 /* make sure we don't read past the end of the data */
826 if (in
->length
> sizeof(buf
)-1) {
827 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
829 strncpy(buf
, (char *)in
->data
, in
->length
);
832 *v
= (int64_t) strtoll(buf
, &end
, 0);
834 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
839 /* Canonicalisation of two 32-bit integers */
840 static int ldif_canonicalise_int32(struct ldb_context
*ldb
, void *mem_ctx
,
841 const struct ldb_val
*in
, struct ldb_val
*out
)
846 ret
= val_to_int32(in
, &i
);
847 if (ret
!= LDB_SUCCESS
) {
850 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%d", i
);
851 if (out
->data
== NULL
) {
853 return LDB_ERR_OPERATIONS_ERROR
;
855 out
->length
= strlen((char *)out
->data
);
860 * Lexicographically sorted representation for a 32-bit integer
862 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
865 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
866 * corresponding documentation for 64-bit integers.
868 * The same rules apply but use INT32_MIN and INT32_MAX.
870 * String representation padding is done to 10 characters.
872 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
875 static int ldif_index_format_int32(struct ldb_context
*ldb
,
877 const struct ldb_val
*in
,
885 ret
= val_to_int32(in
, &i
);
886 if (ret
!= LDB_SUCCESS
) {
892 * i is negative, so this is subtraction rather than
896 i
= INT32_MAX
+ i
+ 1;
903 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%c%010ld", prefix
, (long)i
);
904 if (out
->data
== NULL
) {
906 return LDB_ERR_OPERATIONS_ERROR
;
909 len
= talloc_array_length(out
->data
) - 1;
911 ldb_debug(ldb
, LDB_DEBUG_ERROR
,
912 __location__
": expected index format str %s to"
913 " have length 11 but got %zu",
914 (char*)out
->data
, len
);
915 return LDB_ERR_OPERATIONS_ERROR
;
922 /* Comparison of two 32-bit integers */
923 static int ldif_comparison_int32(struct ldb_context
*ldb
, void *mem_ctx
,
924 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
927 val_to_int32(v1
, &i1
);
928 val_to_int32(v2
, &i2
);
929 if (i1
== i2
) return 0;
930 return i1
> i2
? 1 : -1;
933 /* Canonicalisation of two 64-bit integers */
934 static int ldif_canonicalise_int64(struct ldb_context
*ldb
, void *mem_ctx
,
935 const struct ldb_val
*in
, struct ldb_val
*out
)
940 ret
= val_to_int64(in
, &i
);
941 if (ret
!= LDB_SUCCESS
) {
944 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%lld", (long long)i
);
945 if (out
->data
== NULL
) {
947 return LDB_ERR_OPERATIONS_ERROR
;
949 out
->length
= strlen((char *)out
->data
);
953 /* Comparison of two 64-bit integers */
954 static int ldif_comparison_int64(struct ldb_context
*ldb
, void *mem_ctx
,
955 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
958 val_to_int64(v1
, &i1
);
959 val_to_int64(v2
, &i2
);
960 if (i1
== i2
) return 0;
961 return i1
> i2
? 1 : -1;
965 convert a NDR formatted blob to a ldif formatted repsFromTo
967 static int ldif_write_repsFromTo(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 repsFromToBlob
),
972 (ndr_pull_flags_fn_t
)ndr_pull_repsFromToBlob
,
973 (ndr_print_fn_t
)ndr_print_repsFromToBlob
,
978 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
980 static int ldif_write_replPropertyMetaData(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 replPropertyMetaDataBlob
),
985 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaDataBlob
,
986 (ndr_print_fn_t
)ndr_print_replPropertyMetaDataBlob
,
991 convert a NDR formatted blob to a ldif formatted replUpToDateVector
993 static int ldif_write_replUpToDateVector(struct ldb_context
*ldb
, void *mem_ctx
,
994 const struct ldb_val
*in
, struct ldb_val
*out
)
996 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
997 sizeof(struct replUpToDateVectorBlob
),
998 (ndr_pull_flags_fn_t
)ndr_pull_replUpToDateVectorBlob
,
999 (ndr_print_fn_t
)ndr_print_replUpToDateVectorBlob
,
1003 static int ldif_write_dn_binary_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
1004 const struct ldb_val
*in
, struct ldb_val
*out
,
1006 ndr_pull_flags_fn_t pull_fn
,
1007 ndr_print_fn_t print_fn
,
1011 enum ndr_err_code err
;
1012 struct dsdb_dn
*dsdb_dn
= NULL
;
1013 char *dn_str
= NULL
;
1016 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
1017 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1020 dsdb_dn
= dsdb_dn_parse(mem_ctx
, ldb
, in
, DSDB_SYNTAX_BINARY_DN
);
1021 if (dsdb_dn
== NULL
) {
1022 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1025 p
= talloc_size(dsdb_dn
, struct_size
);
1027 TALLOC_FREE(dsdb_dn
);
1028 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1031 err
= ndr_pull_struct_blob(&dsdb_dn
->extra_part
, p
, p
, pull_fn
);
1032 if (err
!= NDR_ERR_SUCCESS
) {
1033 /* fail in not in mask_error mode */
1037 TALLOC_FREE(dsdb_dn
);
1038 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1041 dn_str
= ldb_dn_get_extended_linearized(dsdb_dn
, dsdb_dn
->dn
, 1);
1042 if (dn_str
== NULL
) {
1043 TALLOC_FREE(dsdb_dn
);
1044 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1047 str
= ndr_print_struct_string(mem_ctx
, print_fn
, dn_str
, p
);
1048 TALLOC_FREE(dsdb_dn
);
1050 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1053 *out
= data_blob_string_const(str
);
1057 static int ldif_write_msDS_RevealedUsers(struct ldb_context
*ldb
, void *mem_ctx
,
1058 const struct ldb_val
*in
, struct ldb_val
*out
)
1060 return ldif_write_dn_binary_NDR(ldb
, mem_ctx
, in
, out
,
1061 sizeof(struct replPropertyMetaData1
),
1062 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaData1
,
1063 (ndr_print_fn_t
)ndr_print_replPropertyMetaData1
,
1068 convert a NDR formatted blob to a ldif formatted dnsRecord
1070 static int ldif_write_dnsRecord(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_DnssrvRpcRecord
),
1075 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
,
1076 (ndr_print_fn_t
)ndr_print_dnsp_DnssrvRpcRecord
,
1081 convert a NDR formatted blob to a ldif formatted dnsProperty
1083 static int ldif_write_dnsProperty(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 dnsp_DnsProperty
),
1088 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnsProperty
,
1089 (ndr_print_fn_t
)ndr_print_dnsp_DnsProperty
,
1094 convert a NDR formatted blob of a supplementalCredentials into text
1096 static int ldif_write_supplementalCredentialsBlob(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 supplementalCredentialsBlob
),
1101 (ndr_pull_flags_fn_t
)ndr_pull_supplementalCredentialsBlob
,
1102 (ndr_print_fn_t
)ndr_print_supplementalCredentialsBlob
,
1107 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1109 static int ldif_write_trustAuthInOutBlob(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 trustAuthInOutBlob
),
1114 (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
,
1115 (ndr_print_fn_t
)ndr_print_trustAuthInOutBlob
,
1120 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1122 static int ldif_write_ForestTrustInfo(struct ldb_context
*ldb
, void *mem_ctx
,
1123 const struct ldb_val
*in
, struct ldb_val
*out
)
1125 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1126 sizeof(struct ForestTrustInfo
),
1127 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
,
1128 (ndr_print_fn_t
)ndr_print_ForestTrustInfo
,
1132 convert a NDR formatted blob of a partialAttributeSet into text
1134 static int ldif_write_partialAttributeSet(struct ldb_context
*ldb
, void *mem_ctx
,
1135 const struct ldb_val
*in
, struct ldb_val
*out
)
1137 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
1138 sizeof(struct partialAttributeSetBlob
),
1139 (ndr_pull_flags_fn_t
)ndr_pull_partialAttributeSetBlob
,
1140 (ndr_print_fn_t
)ndr_print_partialAttributeSetBlob
,
1145 static int extended_dn_write_hex(struct ldb_context
*ldb
, void *mem_ctx
,
1146 const struct ldb_val
*in
, struct ldb_val
*out
)
1148 *out
= data_blob_string_const(data_blob_hex_string_lower(mem_ctx
, in
));
1158 static int samba_ldb_dn_link_comparison(struct ldb_context
*ldb
, void *mem_ctx
,
1159 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1161 struct ldb_dn
*dn1
= NULL
, *dn2
= NULL
;
1165 * In a sort context, Deleted DNs get shifted to the end.
1166 * They never match in an equality
1168 if (dsdb_dn_is_deleted_val(v1
)) {
1169 if (! dsdb_dn_is_deleted_val(v2
)) {
1173 * They are both deleted!
1175 * The soundest thing to do at this point is carry on
1176 * and compare the DNs normally. This matches the
1177 * behaviour of samba_dn_extended_match() below.
1179 } else if (dsdb_dn_is_deleted_val(v2
)) {
1183 dn1
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v1
);
1184 dn2
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v2
);
1186 if ( ! ldb_dn_validate(dn1
)) {
1188 if ( ! ldb_dn_validate(dn2
)) {
1196 if ( ! ldb_dn_validate(dn2
)) {
1202 ret
= ldb_dn_compare(dn1
, dn2
);
1209 static int samba_ldb_dn_link_canonicalise(struct ldb_context
*ldb
, void *mem_ctx
,
1210 const struct ldb_val
*in
, struct ldb_val
*out
)
1218 dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, in
);
1219 if ( ! ldb_dn_validate(dn
)) {
1220 return LDB_ERR_INVALID_DN_SYNTAX
;
1223 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1224 * does not casually match a not deleted DN */
1225 if (dsdb_dn_is_deleted_val(in
)) {
1226 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
,
1228 dsdb_dn_val_rmd_flags(in
),
1229 ldb_dn_get_casefold(dn
));
1231 out
->data
= (uint8_t *)ldb_dn_alloc_casefold(mem_ctx
, dn
);
1234 if (out
->data
== NULL
) {
1237 out
->length
= strlen((char *)out
->data
);
1249 write a 64 bit 2-part range
1251 static int ldif_write_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1252 const struct ldb_val
*in
, struct ldb_val
*out
)
1256 ret
= val_to_int64(in
, &v
);
1257 if (ret
!= LDB_SUCCESS
) {
1260 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%lu-%lu",
1261 (unsigned long)(v
&0xFFFFFFFF),
1262 (unsigned long)(v
>>32));
1263 if (out
->data
== NULL
) {
1265 return LDB_ERR_OPERATIONS_ERROR
;
1267 out
->length
= strlen((char *)out
->data
);
1272 read a 64 bit 2-part range
1274 static int ldif_read_range64(struct ldb_context
*ldb
, void *mem_ctx
,
1275 const struct ldb_val
*in
, struct ldb_val
*out
)
1277 unsigned long high
, low
;
1280 if (memchr(in
->data
, '-', in
->length
) == NULL
) {
1281 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
1284 if (in
->length
> sizeof(buf
)-1) {
1285 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1287 strncpy(buf
, (const char *)in
->data
, in
->length
);
1288 buf
[in
->length
] = 0;
1290 if (sscanf(buf
, "%lu-%lu", &low
, &high
) != 2) {
1291 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1294 out
->data
= (uint8_t *)talloc_asprintf(mem_ctx
, "%llu",
1295 (unsigned long long)(((uint64_t)high
)<<32) | (low
));
1297 if (out
->data
== NULL
) {
1299 return LDB_ERR_OPERATIONS_ERROR
;
1301 out
->length
= strlen((char *)out
->data
);
1306 when this operator_fn is set for a syntax, the backend calls is in
1307 preference to the comparison function. We are told the exact
1308 comparison operation that is needed, and we can return errors
1310 static int samba_syntax_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1311 const struct ldb_schema_attribute
*a
,
1312 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1314 switch (operation
) {
1318 case LDB_OP_SUBSTRING
:
1320 case LDB_OP_EXTENDED
:
1321 /* handled in the backends */
1322 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1324 case LDB_OP_GREATER
:
1326 case LDB_OP_EQUALITY
:
1328 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
1330 if (tmp_ctx
== NULL
) {
1331 return ldb_oom(ldb
);
1333 ret
= a
->syntax
->comparison_fn(ldb
, tmp_ctx
, v1
, v2
);
1334 talloc_free(tmp_ctx
);
1335 if (operation
== LDB_OP_GREATER
) {
1336 *matched
= (ret
>= 0);
1337 } else if (operation
== LDB_OP_LESS
) {
1338 *matched
= (ret
<= 0);
1340 *matched
= (ret
== 0);
1345 case LDB_OP_PRESENT
:
1350 /* we shouldn't get here */
1351 return LDB_ERR_INAPPROPRIATE_MATCHING
;
1355 compare two binary objects. This is correct for sorting as the sort order is:
1362 rather than ldb_comparison_binary() which is:
1370 static int samba_ldb_comparison_binary(struct ldb_context
*ldb
, void *mem_ctx
,
1371 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
1373 return data_blob_cmp(v1
, v2
);
1377 when this operator_fn is set for a syntax, the backend calls is in
1378 preference to the comparison function. We are told the exact
1379 comparison operation that is needed, and we can return errors.
1381 This mode optimises for ldb_comparison_binary() if we need equality,
1382 as this should be faster as it can do a length-check first.
1384 static int samba_syntax_binary_operator_fn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1385 const struct ldb_schema_attribute
*a
,
1386 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1388 if (operation
== LDB_OP_EQUALITY
) {
1389 *matched
= (ldb_comparison_binary(ldb
, NULL
, v1
, v2
) == 0);
1392 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1396 see if two DNs match, comparing first by GUID, then by SID, and
1397 finally by string components
1399 static int samba_dn_extended_match(struct ldb_context
*ldb
,
1400 const struct ldb_val
*v1
,
1401 const struct ldb_val
*v2
,
1404 TALLOC_CTX
*tmp_ctx
;
1405 struct ldb_dn
*dn1
, *dn2
;
1406 const struct ldb_val
*guid1
, *guid2
, *sid1
, *sid2
;
1407 uint32_t rmd_flags1
, rmd_flags2
;
1409 tmp_ctx
= talloc_new(ldb
);
1411 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v1
);
1412 dn2
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, v2
);
1414 /* couldn't parse as DN's */
1415 talloc_free(tmp_ctx
);
1420 rmd_flags1
= dsdb_dn_rmd_flags(dn1
);
1421 rmd_flags2
= dsdb_dn_rmd_flags(dn2
);
1423 if ((rmd_flags1
& DSDB_RMD_FLAG_DELETED
) !=
1424 (rmd_flags2
& DSDB_RMD_FLAG_DELETED
)) {
1425 /* only match if they have the same deletion status */
1426 talloc_free(tmp_ctx
);
1432 guid1
= ldb_dn_get_extended_component(dn1
, "GUID");
1433 guid2
= ldb_dn_get_extended_component(dn2
, "GUID");
1434 if (guid1
&& guid2
) {
1435 (*matched
) = (data_blob_cmp(guid1
, guid2
) == 0);
1436 talloc_free(tmp_ctx
);
1440 sid1
= ldb_dn_get_extended_component(dn1
, "SID");
1441 sid2
= ldb_dn_get_extended_component(dn2
, "SID");
1443 (*matched
) = (data_blob_cmp(sid1
, sid2
) == 0);
1444 talloc_free(tmp_ctx
);
1448 (*matched
) = (ldb_dn_compare(dn1
, dn2
) == 0);
1450 talloc_free(tmp_ctx
);
1455 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1457 static int samba_syntax_operator_dn(struct ldb_context
*ldb
, enum ldb_parse_op operation
,
1458 const struct ldb_schema_attribute
*a
,
1459 const struct ldb_val
*v1
, const struct ldb_val
*v2
, bool *matched
)
1461 if (operation
== LDB_OP_PRESENT
&& dsdb_dn_is_deleted_val(v1
)) {
1462 /* If the DN is deleted, then we can't search for it */
1464 /* should this be for equality too? */
1469 if (operation
== LDB_OP_EQUALITY
&&
1470 samba_dn_extended_match(ldb
, v1
, v2
, matched
) == LDB_SUCCESS
) {
1474 return samba_syntax_operator_fn(ldb
, operation
, a
, v1
, v2
, matched
);
1478 static const struct ldb_schema_syntax samba_syntaxes
[] = {
1480 .name
= LDB_SYNTAX_SAMBA_SID
,
1481 .ldif_read_fn
= ldif_read_objectSid
,
1482 .ldif_write_fn
= ldif_write_objectSid
,
1483 .canonicalise_fn
= ldif_canonicalise_objectSid
,
1484 .comparison_fn
= ldif_comparison_objectSid
,
1485 .operator_fn
= samba_syntax_operator_fn
1487 .name
= LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
,
1488 .ldif_read_fn
= ldif_read_ntSecurityDescriptor
,
1489 .ldif_write_fn
= ldif_write_ntSecurityDescriptor
,
1490 .canonicalise_fn
= ldb_handler_copy
,
1491 .comparison_fn
= samba_ldb_comparison_binary
,
1492 .operator_fn
= samba_syntax_binary_operator_fn
1494 .name
= LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
,
1495 .ldif_read_fn
= ldb_handler_copy
,
1496 .ldif_write_fn
= ldif_write_sddlSecurityDescriptor
,
1497 .canonicalise_fn
= ldb_handler_fold
,
1498 .comparison_fn
= ldb_comparison_fold
,
1499 .operator_fn
= samba_syntax_operator_fn
1501 .name
= LDB_SYNTAX_SAMBA_GUID
,
1502 .ldif_read_fn
= ldif_read_objectGUID
,
1503 .ldif_write_fn
= ldif_write_objectGUID
,
1504 .canonicalise_fn
= ldif_canonicalise_objectGUID
,
1505 .comparison_fn
= ldif_comparison_objectGUID
,
1506 .operator_fn
= samba_syntax_operator_fn
1508 .name
= LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
,
1509 .ldif_read_fn
= ldb_handler_copy
,
1510 .ldif_write_fn
= ldb_handler_copy
,
1511 .canonicalise_fn
= ldif_canonicalise_objectCategory
,
1512 .comparison_fn
= ldif_comparison_objectCategory
,
1513 .operator_fn
= samba_syntax_operator_fn
1515 .name
= LDB_SYNTAX_SAMBA_SCHEMAINFO
,
1516 .ldif_read_fn
= ldb_handler_copy
,
1517 .ldif_write_fn
= ldif_write_schemaInfo
,
1518 .canonicalise_fn
= ldb_handler_copy
,
1519 .comparison_fn
= samba_ldb_comparison_binary
,
1520 .operator_fn
= samba_syntax_binary_operator_fn
1522 .name
= LDB_SYNTAX_SAMBA_PREFIX_MAP
,
1523 .ldif_read_fn
= ldif_read_prefixMap
,
1524 .ldif_write_fn
= ldif_write_prefixMap
,
1525 .canonicalise_fn
= ldif_canonicalise_prefixMap
,
1526 .comparison_fn
= ldif_comparison_prefixMap
,
1527 .operator_fn
= samba_syntax_operator_fn
1529 .name
= LDB_SYNTAX_SAMBA_INT32
,
1530 .ldif_read_fn
= ldb_handler_copy
,
1531 .ldif_write_fn
= ldb_handler_copy
,
1532 .canonicalise_fn
= ldif_canonicalise_int32
,
1533 .index_format_fn
= ldif_index_format_int32
,
1534 .comparison_fn
= ldif_comparison_int32
,
1535 .operator_fn
= samba_syntax_operator_fn
1537 .name
= LDB_SYNTAX_SAMBA_REPSFROMTO
,
1538 .ldif_read_fn
= ldb_handler_copy
,
1539 .ldif_write_fn
= ldif_write_repsFromTo
,
1540 .canonicalise_fn
= ldb_handler_copy
,
1541 .comparison_fn
= samba_ldb_comparison_binary
,
1542 .operator_fn
= samba_syntax_binary_operator_fn
1544 .name
= LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
,
1545 .ldif_read_fn
= ldb_handler_copy
,
1546 .ldif_write_fn
= ldif_write_replPropertyMetaData
,
1547 .canonicalise_fn
= ldb_handler_copy
,
1548 .comparison_fn
= samba_ldb_comparison_binary
,
1549 .operator_fn
= samba_syntax_binary_operator_fn
1551 .name
= LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
,
1552 .ldif_read_fn
= ldb_handler_copy
,
1553 .ldif_write_fn
= ldif_write_replUpToDateVector
,
1554 .canonicalise_fn
= ldb_handler_copy
,
1555 .comparison_fn
= samba_ldb_comparison_binary
,
1556 .operator_fn
= samba_syntax_binary_operator_fn
1558 .name
= LDB_SYNTAX_SAMBA_REVEALEDUSERS
,
1559 .ldif_read_fn
= ldb_handler_copy
,
1560 .ldif_write_fn
= ldif_write_msDS_RevealedUsers
,
1561 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1562 .comparison_fn
= dsdb_dn_binary_comparison
,
1563 .operator_fn
= samba_syntax_operator_fn
1565 .name
= LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
,
1566 .ldif_read_fn
= ldb_handler_copy
,
1567 .ldif_write_fn
= ldif_write_trustAuthInOutBlob
,
1568 .canonicalise_fn
= ldb_handler_copy
,
1569 .comparison_fn
= samba_ldb_comparison_binary
,
1570 .operator_fn
= samba_syntax_binary_operator_fn
1572 .name
= LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
,
1573 .ldif_read_fn
= ldb_handler_copy
,
1574 .ldif_write_fn
= ldif_write_ForestTrustInfo
,
1575 .canonicalise_fn
= ldb_handler_copy
,
1576 .comparison_fn
= samba_ldb_comparison_binary
,
1577 .operator_fn
= samba_syntax_binary_operator_fn
1579 .name
= DSDB_SYNTAX_BINARY_DN
,
1580 .ldif_read_fn
= ldb_handler_copy
,
1581 .ldif_write_fn
= ldb_handler_copy
,
1582 .canonicalise_fn
= dsdb_dn_binary_canonicalise
,
1583 .comparison_fn
= dsdb_dn_binary_comparison
,
1584 .operator_fn
= samba_syntax_operator_fn
1586 .name
= DSDB_SYNTAX_STRING_DN
,
1587 .ldif_read_fn
= ldb_handler_copy
,
1588 .ldif_write_fn
= ldb_handler_copy
,
1589 .canonicalise_fn
= dsdb_dn_string_canonicalise
,
1590 .comparison_fn
= dsdb_dn_string_comparison
,
1591 .operator_fn
= samba_syntax_operator_fn
1593 .name
= LDB_SYNTAX_DN
,
1594 .ldif_read_fn
= ldb_handler_copy
,
1595 .ldif_write_fn
= ldb_handler_copy
,
1596 .canonicalise_fn
= samba_ldb_dn_link_canonicalise
,
1597 .comparison_fn
= samba_ldb_dn_link_comparison
,
1598 .operator_fn
= samba_syntax_operator_dn
1600 .name
= LDB_SYNTAX_SAMBA_RANGE64
,
1601 .ldif_read_fn
= ldif_read_range64
,
1602 .ldif_write_fn
= ldif_write_range64
,
1603 .canonicalise_fn
= ldif_canonicalise_int64
,
1604 .comparison_fn
= ldif_comparison_int64
,
1605 .operator_fn
= samba_syntax_operator_fn
1607 .name
= LDB_SYNTAX_SAMBA_DNSRECORD
,
1608 .ldif_read_fn
= ldb_handler_copy
,
1609 .ldif_write_fn
= ldif_write_dnsRecord
,
1610 .canonicalise_fn
= ldb_handler_copy
,
1611 .comparison_fn
= samba_ldb_comparison_binary
,
1612 .operator_fn
= samba_syntax_binary_operator_fn
1614 .name
= LDB_SYNTAX_SAMBA_DNSPROPERTY
,
1615 .ldif_read_fn
= ldb_handler_copy
,
1616 .ldif_write_fn
= ldif_write_dnsProperty
,
1617 .canonicalise_fn
= ldb_handler_copy
,
1618 .comparison_fn
= samba_ldb_comparison_binary
,
1619 .operator_fn
= samba_syntax_binary_operator_fn
1621 .name
= LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
,
1622 .ldif_read_fn
= ldb_handler_copy
,
1623 .ldif_write_fn
= ldif_write_supplementalCredentialsBlob
,
1624 .canonicalise_fn
= ldb_handler_copy
,
1625 .comparison_fn
= samba_ldb_comparison_binary
,
1626 .operator_fn
= samba_syntax_binary_operator_fn
1628 .name
= LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
,
1629 .ldif_read_fn
= ldb_handler_copy
,
1630 .ldif_write_fn
= ldif_write_partialAttributeSet
,
1631 .canonicalise_fn
= ldb_handler_copy
,
1632 .comparison_fn
= samba_ldb_comparison_binary
,
1633 .operator_fn
= samba_syntax_binary_operator_fn
1635 .name
= LDB_SYNTAX_SAMBA_OCTET_STRING
,
1636 .ldif_read_fn
= ldb_handler_copy
,
1637 .ldif_write_fn
= ldb_handler_copy
,
1638 .canonicalise_fn
= ldb_handler_copy
,
1639 .comparison_fn
= samba_ldb_comparison_binary
,
1640 .operator_fn
= samba_syntax_binary_operator_fn
1644 static const struct ldb_dn_extended_syntax samba_dn_syntax
[] = {
1647 .read_fn
= extended_dn_read_SID
,
1648 .write_clear_fn
= ldif_write_objectSid
,
1649 .write_hex_fn
= extended_dn_write_hex
1652 .read_fn
= extended_dn_read_GUID
,
1653 .write_clear_fn
= ldif_write_objectGUID
,
1654 .write_hex_fn
= extended_dn_write_hex
1657 .read_fn
= ldb_handler_copy
,
1658 .write_clear_fn
= ldb_handler_copy
,
1659 .write_hex_fn
= ldb_handler_copy
1661 .name
= "RMD_INVOCID",
1662 .read_fn
= extended_dn_read_GUID
,
1663 .write_clear_fn
= ldif_write_objectGUID
,
1664 .write_hex_fn
= extended_dn_write_hex
1666 .name
= "RMD_FLAGS",
1667 .read_fn
= ldb_handler_copy
,
1668 .write_clear_fn
= ldb_handler_copy
,
1669 .write_hex_fn
= ldb_handler_copy
1671 .name
= "RMD_ADDTIME",
1672 .read_fn
= ldb_handler_copy
,
1673 .write_clear_fn
= ldb_handler_copy
,
1674 .write_hex_fn
= ldb_handler_copy
1676 .name
= "RMD_CHANGETIME",
1677 .read_fn
= ldb_handler_copy
,
1678 .write_clear_fn
= ldb_handler_copy
,
1679 .write_hex_fn
= ldb_handler_copy
1681 .name
= "RMD_LOCAL_USN",
1682 .read_fn
= ldb_handler_copy
,
1683 .write_clear_fn
= ldb_handler_copy
,
1684 .write_hex_fn
= ldb_handler_copy
1686 .name
= "RMD_ORIGINATING_USN",
1687 .read_fn
= ldb_handler_copy
,
1688 .write_clear_fn
= ldb_handler_copy
,
1689 .write_hex_fn
= ldb_handler_copy
1691 .name
= "RMD_VERSION",
1692 .read_fn
= ldb_handler_copy
,
1693 .write_clear_fn
= ldb_handler_copy
,
1694 .write_hex_fn
= ldb_handler_copy
1698 /* TODO: Should be dynamic at some point */
1699 static const struct {
1702 } samba_attributes
[] = {
1703 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
},
1704 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32
},
1705 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
},
1706 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO
},
1707 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP
},
1708 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1709 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO
},
1710 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
},
1711 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
},
1712 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS
},
1713 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1714 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB
},
1715 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO
},
1716 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1717 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64
},
1718 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64
},
1719 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR
},
1722 * these are extracted by searching
1723 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1725 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1726 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1727 * hat can be used to identify the set of policies when applied to a resource.
1728 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1729 * server, we ignore it here.
1731 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID
},
1732 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID
},
1733 { "objectSid", LDB_SYNTAX_SAMBA_SID
},
1734 { "tokenGroups", LDB_SYNTAX_SAMBA_SID
},
1735 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID
},
1736 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID
},
1737 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID
},
1738 { "sIDHistory", LDB_SYNTAX_SAMBA_SID
},
1739 { "syncWithSID", LDB_SYNTAX_SAMBA_SID
},
1742 * these are extracted by searching
1743 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1745 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID
},
1746 { "categoryId", LDB_SYNTAX_SAMBA_GUID
},
1747 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID
},
1748 { "currMachineId", LDB_SYNTAX_SAMBA_GUID
},
1749 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID
},
1750 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID
},
1751 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID
},
1752 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID
},
1753 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID
},
1754 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID
},
1755 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID
},
1756 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID
},
1757 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID
},
1758 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID
},
1759 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID
},
1760 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID
},
1761 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID
},
1762 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID
},
1763 { "objectGUID", LDB_SYNTAX_SAMBA_GUID
},
1764 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID
},
1765 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID
},
1766 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID
},
1767 { "siteGUID", LDB_SYNTAX_SAMBA_GUID
},
1768 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1769 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1770 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID
},
1771 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID
},
1772 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID
},
1775 * these are known to be GUIDs
1777 { "invocationId", LDB_SYNTAX_SAMBA_GUID
},
1778 { "parentGUID", LDB_SYNTAX_SAMBA_GUID
},
1780 /* These NDR encoded things we want to be able to read with --show-binary */
1781 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD
},
1782 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY
},
1783 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS
},
1784 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET
}
1787 const struct ldb_schema_syntax
*ldb_samba_syntax_by_name(struct ldb_context
*ldb
, const char *name
)
1790 const struct ldb_schema_syntax
*s
= NULL
;
1792 for (j
=0; j
< ARRAY_SIZE(samba_syntaxes
); j
++) {
1793 if (strcmp(name
, samba_syntaxes
[j
].name
) == 0) {
1794 s
= &samba_syntaxes
[j
];
1801 const struct ldb_schema_syntax
*ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context
*ldb
, const char *name
)
1804 const struct ldb_schema_syntax
*s
= NULL
;
1806 for (j
=0; j
< ARRAY_SIZE(samba_attributes
); j
++) {
1807 if (strcmp(samba_attributes
[j
].name
, name
) == 0) {
1808 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[j
].syntax
);
1816 static const char *secret_attributes
[] = {DSDB_SECRET_ATTRIBUTES
, "secret",
1817 "priorSecret", NULL
};
1820 register the samba ldif handlers
1822 int ldb_register_samba_handlers(struct ldb_context
*ldb
)
1827 if (ldb_get_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED") != NULL
) {
1831 ret
= ldb_set_opaque(ldb
, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE
, discard_const_p(char *, secret_attributes
));
1832 if (ret
!= LDB_SUCCESS
) {
1836 for (i
=0; i
< ARRAY_SIZE(samba_attributes
); i
++) {
1837 const struct ldb_schema_syntax
*s
= NULL
;
1839 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1842 s
= ldb_standard_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
1846 return LDB_ERR_OPERATIONS_ERROR
;
1849 ret
= ldb_schema_attribute_add_with_syntax(ldb
, samba_attributes
[i
].name
, LDB_ATTR_FLAG_FIXED
, s
);
1850 if (ret
!= LDB_SUCCESS
) {
1855 for (i
=0; i
< ARRAY_SIZE(samba_dn_syntax
); i
++) {
1856 ret
= ldb_dn_extended_add_syntax(ldb
, LDB_ATTR_FLAG_FIXED
, &samba_dn_syntax
[i
]);
1857 if (ret
!= LDB_SUCCESS
) {
1863 ret
= ldb_register_samba_matching_rules(ldb
);
1864 if (ret
!= LDB_SUCCESS
) {
1869 ret
= ldb_set_opaque(ldb
, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1870 if (ret
!= LDB_SUCCESS
) {