2 ldb database library - ldif handlers for Samba
4 Copyright (C) Andrew Tridgell 2005
5 Copyright (C) Andrew Bartlett 2006-2007
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/>.
26 #include "lib/ldb/include/ldb.h"
27 #include "lib/ldb/include/ldb_module.h"
28 #include "ldb_handlers.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "librpc/gen_ndr/ndr_misc.h"
32 #include "librpc/gen_ndr/ndr_drsblobs.h"
33 #include "librpc/ndr/libndr.h"
34 #include "libcli/security/security.h"
35 #include "param/param.h"
36 #include "../lib/util/asn1.h"
39 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
41 static int ldif_write_NDR(struct ldb_context
*ldb
, void *mem_ctx
,
42 const struct ldb_val
*in
, struct ldb_val
*out
,
44 ndr_pull_flags_fn_t pull_fn
,
45 ndr_print_fn_t print_fn
)
48 enum ndr_err_code err
;
49 if (!(ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
)) {
50 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
52 p
= talloc_size(mem_ctx
, struct_size
);
53 err
= ndr_pull_struct_blob(in
, mem_ctx
,
54 lp_iconv_convenience(ldb_get_opaque(ldb
, "loadparm")),
56 if (err
!= NDR_ERR_SUCCESS
) {
58 out
->data
= (uint8_t *)talloc_strdup(mem_ctx
, "<Unable to decode binary data>");
59 out
->length
= strlen((const char *)out
->data
);
62 out
->data
= (uint8_t *)ndr_print_struct_string(mem_ctx
, print_fn
, "NDR", p
);
64 if (out
->data
== NULL
) {
65 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
67 out
->length
= strlen((char *)out
->data
);
72 convert a ldif formatted objectSid to a NDR formatted blob
74 static int ldif_read_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
75 const struct ldb_val
*in
, struct ldb_val
*out
)
77 enum ndr_err_code ndr_err
;
79 sid
= dom_sid_parse_length(mem_ctx
, in
);
83 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, NULL
, sid
,
84 (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
86 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
93 convert a NDR formatted blob to a ldif formatted objectSid
95 int ldif_write_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
96 const struct ldb_val
*in
, struct ldb_val
*out
)
99 enum ndr_err_code ndr_err
;
101 sid
= talloc(mem_ctx
, struct dom_sid
);
105 ndr_err
= ndr_pull_struct_blob_all(in
, sid
, NULL
, sid
,
106 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
107 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
111 *out
= data_blob_string_const(dom_sid_string(mem_ctx
, sid
));
113 if (out
->data
== NULL
) {
119 bool ldif_comparision_objectSid_isString(const struct ldb_val
*v
)
125 if (strncmp("S-", (const char *)v
->data
, 2) != 0) return false;
131 compare two objectSids
133 static int ldif_comparison_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
134 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
136 if (ldif_comparision_objectSid_isString(v1
) && ldif_comparision_objectSid_isString(v2
)) {
137 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
138 } else if (ldif_comparision_objectSid_isString(v1
)
139 && !ldif_comparision_objectSid_isString(v2
)) {
142 if (ldif_read_objectSid(ldb
, mem_ctx
, v1
, &v
) != 0) {
143 /* Perhaps not a string after all */
144 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
146 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
149 } else if (!ldif_comparision_objectSid_isString(v1
)
150 && ldif_comparision_objectSid_isString(v2
)) {
153 if (ldif_read_objectSid(ldb
, mem_ctx
, v2
, &v
) != 0) {
154 /* Perhaps not a string after all */
155 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
157 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
161 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
165 canonicalise a objectSid
167 static int ldif_canonicalise_objectSid(struct ldb_context
*ldb
, void *mem_ctx
,
168 const struct ldb_val
*in
, struct ldb_val
*out
)
170 if (ldif_comparision_objectSid_isString(in
)) {
171 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) != 0) {
172 /* Perhaps not a string after all */
173 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
177 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
180 static int extended_dn_read_SID(struct ldb_context
*ldb
, void *mem_ctx
,
181 const struct ldb_val
*in
, struct ldb_val
*out
)
184 enum ndr_err_code ndr_err
;
185 if (ldif_comparision_objectSid_isString(in
)) {
186 if (ldif_read_objectSid(ldb
, mem_ctx
, in
, out
) == 0) {
191 /* Perhaps not a string after all */
192 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
198 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
199 (const char *)in
->data
, in
->length
);
201 /* Check it looks like a SID */
202 ndr_err
= ndr_pull_struct_blob_all(out
, mem_ctx
, NULL
, &sid
,
203 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
204 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
211 convert a ldif formatted objectGUID to a NDR formatted blob
213 static int ldif_read_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
214 const struct ldb_val
*in
, struct ldb_val
*out
)
218 enum ndr_err_code ndr_err
;
220 status
= GUID_from_data_blob(in
, &guid
);
221 if (!NT_STATUS_IS_OK(status
)) {
225 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, NULL
, &guid
,
226 (ndr_push_flags_fn_t
)ndr_push_GUID
);
227 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
234 convert a NDR formatted blob to a ldif formatted objectGUID
236 static int ldif_write_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
237 const struct ldb_val
*in
, struct ldb_val
*out
)
240 enum ndr_err_code ndr_err
;
241 ndr_err
= ndr_pull_struct_blob_all(in
, mem_ctx
, NULL
, &guid
,
242 (ndr_pull_flags_fn_t
)ndr_pull_GUID
);
243 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
246 out
->data
= (uint8_t *)GUID_string(mem_ctx
, &guid
);
247 if (out
->data
== NULL
) {
250 out
->length
= strlen((const char *)out
->data
);
254 static bool ldif_comparision_objectGUID_isString(const struct ldb_val
*v
)
256 if (v
->length
!= 36 && v
->length
!= 38) return false;
258 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
262 static int extended_dn_read_GUID(struct ldb_context
*ldb
, void *mem_ctx
,
263 const struct ldb_val
*in
, struct ldb_val
*out
)
266 enum ndr_err_code ndr_err
;
267 if (in
->length
== 36 && ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) == 0) {
271 /* Try as 'hex' form */
272 if (in
->length
!= 32) {
276 *out
= data_blob_talloc(mem_ctx
, NULL
, in
->length
/2+1);
282 (*out
).length
= strhex_to_str((char *)out
->data
, out
->length
,
283 (const char *)in
->data
, in
->length
);
285 /* Check it looks like a GUID */
286 ndr_err
= ndr_pull_struct_blob_all(out
, mem_ctx
, NULL
, &guid
,
287 (ndr_pull_flags_fn_t
)ndr_pull_GUID
);
288 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
295 compare two objectGUIDs
297 static int ldif_comparison_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
298 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
300 if (ldif_comparision_objectGUID_isString(v1
) && ldif_comparision_objectGUID_isString(v2
)) {
301 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
302 } else if (ldif_comparision_objectGUID_isString(v1
)
303 && !ldif_comparision_objectGUID_isString(v2
)) {
306 if (ldif_read_objectGUID(ldb
, mem_ctx
, v1
, &v
) != 0) {
307 /* Perhaps it wasn't a valid string after all */
308 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
310 ret
= ldb_comparison_binary(ldb
, mem_ctx
, &v
, v2
);
313 } else if (!ldif_comparision_objectGUID_isString(v1
)
314 && ldif_comparision_objectGUID_isString(v2
)) {
317 if (ldif_read_objectGUID(ldb
, mem_ctx
, v2
, &v
) != 0) {
318 /* Perhaps it wasn't a valid string after all */
319 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
321 ret
= ldb_comparison_binary(ldb
, mem_ctx
, v1
, &v
);
325 return ldb_comparison_binary(ldb
, mem_ctx
, v1
, v2
);
329 canonicalise a objectGUID
331 static int ldif_canonicalise_objectGUID(struct ldb_context
*ldb
, void *mem_ctx
,
332 const struct ldb_val
*in
, struct ldb_val
*out
)
334 if (ldif_comparision_objectGUID_isString(in
)) {
335 if (ldif_read_objectGUID(ldb
, mem_ctx
, in
, out
) != 0) {
336 /* Perhaps it wasn't a valid string after all */
337 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
341 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
346 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
348 static int ldif_read_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
349 const struct ldb_val
*in
, struct ldb_val
*out
)
351 struct security_descriptor
*sd
;
352 enum ndr_err_code ndr_err
;
354 sd
= talloc(mem_ctx
, struct security_descriptor
);
359 ndr_err
= ndr_pull_struct_blob(in
, sd
, NULL
, sd
,
360 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
361 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
362 /* If this does not parse, then it is probably SDDL, and we should try it that way */
364 const struct dom_sid
*sid
= samdb_domain_sid(ldb
);
366 sd
= sddl_decode(mem_ctx
, (const char *)in
->data
, sid
);
372 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
, NULL
, sd
,
373 (ndr_push_flags_fn_t
)ndr_push_security_descriptor
);
375 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
383 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
385 static int ldif_write_ntSecurityDescriptor(struct ldb_context
*ldb
, void *mem_ctx
,
386 const struct ldb_val
*in
, struct ldb_val
*out
)
388 struct security_descriptor
*sd
;
389 enum ndr_err_code ndr_err
;
391 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
392 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
393 sizeof(struct security_descriptor
),
394 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
,
395 (ndr_print_fn_t
)ndr_print_security_descriptor
);
399 sd
= talloc(mem_ctx
, struct security_descriptor
);
403 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
404 ndr_err
= ndr_pull_struct_blob(in
, sd
, NULL
, sd
,
405 (ndr_pull_flags_fn_t
)ndr_pull_security_descriptor
);
406 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
410 out
->data
= (uint8_t *)sddl_encode(mem_ctx
, sd
, NULL
);
412 if (out
->data
== NULL
) {
415 out
->length
= strlen((const char *)out
->data
);
420 canonicalise an objectCategory. We use the short form as the cannoical form:
421 cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
424 static int ldif_canonicalise_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
425 const struct ldb_val
*in
, struct ldb_val
*out
)
427 struct ldb_dn
*dn1
= NULL
;
428 const struct dsdb_schema
*schema
= dsdb_get_schema(ldb
);
429 const struct dsdb_class
*sclass
;
430 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
432 return LDB_ERR_OPERATIONS_ERROR
;
436 talloc_free(tmp_ctx
);
437 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
438 if (in
->data
&& !out
->data
) {
439 return LDB_ERR_OPERATIONS_ERROR
;
443 dn1
= ldb_dn_from_ldb_val(tmp_ctx
, ldb
, in
);
444 if ( ! ldb_dn_validate(dn1
)) {
445 const char *lDAPDisplayName
= talloc_strndup(tmp_ctx
, (char *)in
->data
, in
->length
);
446 sclass
= dsdb_class_by_lDAPDisplayName(schema
, lDAPDisplayName
);
448 struct ldb_dn
*dn
= ldb_dn_new(mem_ctx
, ldb
,
449 sclass
->defaultObjectCategory
);
450 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn
));
451 talloc_free(tmp_ctx
);
454 return LDB_ERR_OPERATIONS_ERROR
;
458 *out
= data_blob_talloc(mem_ctx
, in
->data
, in
->length
);
459 talloc_free(tmp_ctx
);
461 if (in
->data
&& !out
->data
) {
462 return LDB_ERR_OPERATIONS_ERROR
;
467 *out
= data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx
, dn1
));
468 talloc_free(tmp_ctx
);
471 return LDB_ERR_OPERATIONS_ERROR
;
476 static int ldif_comparison_objectCategory(struct ldb_context
*ldb
, void *mem_ctx
,
477 const struct ldb_val
*v1
,
478 const struct ldb_val
*v2
)
482 struct ldb_val v1_canon
, v2_canon
;
483 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
485 /* I could try and bail if tmp_ctx was NULL, but what return
488 * It seems easier to continue on the NULL context
490 ret1
= ldif_canonicalise_objectCategory(ldb
, tmp_ctx
, v1
, &v1_canon
);
491 ret2
= ldif_canonicalise_objectCategory(ldb
, tmp_ctx
, v2
, &v2_canon
);
493 if (ret1
== LDB_SUCCESS
&& ret2
== LDB_SUCCESS
) {
494 ret
= data_blob_cmp(&v1_canon
, &v2_canon
);
496 ret
= data_blob_cmp(v1
, v2
);
498 talloc_free(tmp_ctx
);
503 convert a ldif formatted prefixMap to a NDR formatted blob
505 static int ldif_read_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
506 const struct ldb_val
*in
, struct ldb_val
*out
)
508 struct prefixMapBlob
*blob
;
509 enum ndr_err_code ndr_err
;
510 char *string
, *line
, *p
, *oid
;
513 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
515 if (tmp_ctx
== NULL
) {
519 blob
= talloc_zero(tmp_ctx
, struct prefixMapBlob
);
525 blob
->version
= PREFIX_MAP_VERSION_DSDB
;
527 string
= talloc_strndup(mem_ctx
, (const char *)in
->data
, in
->length
);
528 if (string
== NULL
) {
534 while (line
&& line
[0]) {
539 p
=strchr(line
, '\n');
544 /* allow a traling seperator */
549 blob
->ctr
.dsdb
.mappings
= talloc_realloc(blob
,
550 blob
->ctr
.dsdb
.mappings
,
551 struct drsuapi_DsReplicaOIDMapping
,
552 blob
->ctr
.dsdb
.num_mappings
+1);
553 if (!blob
->ctr
.dsdb
.mappings
) {
554 talloc_free(tmp_ctx
);
558 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].id_prefix
= strtoul(line
, &oid
, 10);
561 talloc_free(tmp_ctx
);
565 /* we know there must be at least ":" */
568 if (!ber_write_partial_OID_String(blob
->ctr
.dsdb
.mappings
, &oid_blob
, oid
)) {
569 talloc_free(tmp_ctx
);
572 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.length
= oid_blob
.length
;
573 blob
->ctr
.dsdb
.mappings
[blob
->ctr
.dsdb
.num_mappings
].oid
.binary_oid
= oid_blob
.data
;
575 blob
->ctr
.dsdb
.num_mappings
++;
577 /* Now look past the terminator we added above */
585 ndr_err
= ndr_push_struct_blob(out
, mem_ctx
,
586 lp_iconv_convenience(ldb_get_opaque(ldb
, "loadparm")),
588 (ndr_push_flags_fn_t
)ndr_push_prefixMapBlob
);
589 talloc_free(tmp_ctx
);
590 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
597 convert a NDR formatted blob to a ldif formatted prefixMap
599 static int ldif_write_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
600 const struct ldb_val
*in
, struct ldb_val
*out
)
602 struct prefixMapBlob
*blob
;
603 enum ndr_err_code ndr_err
;
607 if (ldb_get_flags(ldb
) & LDB_FLG_SHOW_BINARY
) {
608 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
609 sizeof(struct prefixMapBlob
),
610 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
,
611 (ndr_print_fn_t
)ndr_print_prefixMapBlob
);
615 blob
= talloc(mem_ctx
, struct prefixMapBlob
);
619 ndr_err
= ndr_pull_struct_blob_all(in
, blob
,
620 lp_iconv_convenience(ldb_get_opaque(ldb
, "loadparm")),
622 (ndr_pull_flags_fn_t
)ndr_pull_prefixMapBlob
);
623 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
626 if (blob
->version
!= PREFIX_MAP_VERSION_DSDB
) {
629 string
= talloc_strdup(mem_ctx
, "");
630 if (string
== NULL
) {
634 for (i
=0; i
< blob
->ctr
.dsdb
.num_mappings
; i
++) {
636 const char *partial_oid
= NULL
;
639 string
= talloc_asprintf_append(string
, ";");
642 oid_blob
= data_blob_const(blob
->ctr
.dsdb
.mappings
[i
].oid
.binary_oid
,
643 blob
->ctr
.dsdb
.mappings
[i
].oid
.length
);
644 if (!ber_read_partial_OID_String(blob
, oid_blob
, &partial_oid
)) {
645 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
646 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
));
649 string
= talloc_asprintf_append(string
, "%u:%s",
650 blob
->ctr
.dsdb
.mappings
[i
].id_prefix
,
652 talloc_free(discard_const(partial_oid
));
653 if (string
== NULL
) {
659 *out
= data_blob_string_const(string
);
667 static bool ldif_comparision_prefixMap_isString(const struct ldb_val
*v
)
673 if (IVAL(v
->data
, 0) == PREFIX_MAP_VERSION_DSDB
) {
681 canonicalise a prefixMap
683 static int ldif_canonicalise_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
684 const struct ldb_val
*in
, struct ldb_val
*out
)
686 if (ldif_comparision_prefixMap_isString(in
)) {
687 return ldif_read_prefixMap(ldb
, mem_ctx
, in
, out
);
689 return ldb_handler_copy(ldb
, mem_ctx
, in
, out
);
692 static int ldif_comparison_prefixMap(struct ldb_context
*ldb
, void *mem_ctx
,
693 const struct ldb_val
*v1
,
694 const struct ldb_val
*v2
)
698 struct ldb_val v1_canon
, v2_canon
;
699 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
701 /* I could try and bail if tmp_ctx was NULL, but what return
704 * It seems easier to continue on the NULL context
706 ret1
= ldif_canonicalise_prefixMap(ldb
, tmp_ctx
, v1
, &v1_canon
);
707 ret2
= ldif_canonicalise_prefixMap(ldb
, tmp_ctx
, v2
, &v2_canon
);
709 if (ret1
== LDB_SUCCESS
&& ret2
== LDB_SUCCESS
) {
710 ret
= data_blob_cmp(&v1_canon
, &v2_canon
);
712 ret
= data_blob_cmp(v1
, v2
);
714 talloc_free(tmp_ctx
);
718 /* Canonicalisation of two 32-bit integers */
719 static int ldif_canonicalise_int32(struct ldb_context
*ldb
, void *mem_ctx
,
720 const struct ldb_val
*in
, struct ldb_val
*out
)
723 /* We've to use "strtoll" here to have the intended overflows.
724 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
725 int32_t i
= (int32_t) strtoll((char *)in
->data
, &end
, 0);
729 out
->data
= (uint8_t *) talloc_asprintf(mem_ctx
, "%d", i
);
730 if (out
->data
== NULL
) {
733 out
->length
= strlen((char *)out
->data
);
737 /* Comparison of two 32-bit integers */
738 static int ldif_comparison_int32(struct ldb_context
*ldb
, void *mem_ctx
,
739 const struct ldb_val
*v1
, const struct ldb_val
*v2
)
741 /* We've to use "strtoll" here to have the intended overflows.
742 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
743 return (int32_t) strtoll((char *)v1
->data
, NULL
, 0)
744 - (int32_t) strtoll((char *)v2
->data
, NULL
, 0);
748 convert a NDR formatted blob to a ldif formatted repsFromTo
750 static int ldif_write_repsFromTo(struct ldb_context
*ldb
, void *mem_ctx
,
751 const struct ldb_val
*in
, struct ldb_val
*out
)
753 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
754 sizeof(struct repsFromToBlob
),
755 (ndr_pull_flags_fn_t
)ndr_pull_repsFromToBlob
,
756 (ndr_print_fn_t
)ndr_print_repsFromToBlob
);
760 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
762 static int ldif_write_replPropertyMetaData(struct ldb_context
*ldb
, void *mem_ctx
,
763 const struct ldb_val
*in
, struct ldb_val
*out
)
765 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
766 sizeof(struct replPropertyMetaDataBlob
),
767 (ndr_pull_flags_fn_t
)ndr_pull_replPropertyMetaDataBlob
,
768 (ndr_print_fn_t
)ndr_print_replPropertyMetaDataBlob
);
772 convert a NDR formatted blob to a ldif formatted replUpToDateVector
774 static int ldif_write_replUpToDateVector(struct ldb_context
*ldb
, void *mem_ctx
,
775 const struct ldb_val
*in
, struct ldb_val
*out
)
777 return ldif_write_NDR(ldb
, mem_ctx
, in
, out
,
778 sizeof(struct replUpToDateVectorBlob
),
779 (ndr_pull_flags_fn_t
)ndr_pull_replUpToDateVectorBlob
,
780 (ndr_print_fn_t
)ndr_print_replUpToDateVectorBlob
);
784 static int extended_dn_write_hex(struct ldb_context
*ldb
, void *mem_ctx
,
785 const struct ldb_val
*in
, struct ldb_val
*out
)
787 *out
= data_blob_string_const(data_blob_hex_string_lower(mem_ctx
, in
));
794 static const struct ldb_schema_syntax samba_syntaxes
[] = {
796 .name
= LDB_SYNTAX_SAMBA_SID
,
797 .ldif_read_fn
= ldif_read_objectSid
,
798 .ldif_write_fn
= ldif_write_objectSid
,
799 .canonicalise_fn
= ldif_canonicalise_objectSid
,
800 .comparison_fn
= ldif_comparison_objectSid
802 .name
= LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
,
803 .ldif_read_fn
= ldif_read_ntSecurityDescriptor
,
804 .ldif_write_fn
= ldif_write_ntSecurityDescriptor
,
805 .canonicalise_fn
= ldb_handler_copy
,
806 .comparison_fn
= ldb_comparison_binary
808 .name
= LDB_SYNTAX_SAMBA_GUID
,
809 .ldif_read_fn
= ldif_read_objectGUID
,
810 .ldif_write_fn
= ldif_write_objectGUID
,
811 .canonicalise_fn
= ldif_canonicalise_objectGUID
,
812 .comparison_fn
= ldif_comparison_objectGUID
814 .name
= LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
,
815 .ldif_read_fn
= ldb_handler_copy
,
816 .ldif_write_fn
= ldb_handler_copy
,
817 .canonicalise_fn
= ldif_canonicalise_objectCategory
,
818 .comparison_fn
= ldif_comparison_objectCategory
820 .name
= LDB_SYNTAX_SAMBA_PREFIX_MAP
,
821 .ldif_read_fn
= ldif_read_prefixMap
,
822 .ldif_write_fn
= ldif_write_prefixMap
,
823 .canonicalise_fn
= ldif_canonicalise_prefixMap
,
824 .comparison_fn
= ldif_comparison_prefixMap
826 .name
= LDB_SYNTAX_SAMBA_INT32
,
827 .ldif_read_fn
= ldb_handler_copy
,
828 .ldif_write_fn
= ldb_handler_copy
,
829 .canonicalise_fn
= ldif_canonicalise_int32
,
830 .comparison_fn
= ldif_comparison_int32
832 .name
= LDB_SYNTAX_SAMBA_REPSFROMTO
,
833 .ldif_read_fn
= ldb_handler_copy
,
834 .ldif_write_fn
= ldif_write_repsFromTo
,
835 .canonicalise_fn
= ldb_handler_copy
,
836 .comparison_fn
= ldb_comparison_binary
838 .name
= LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
,
839 .ldif_read_fn
= ldb_handler_copy
,
840 .ldif_write_fn
= ldif_write_replPropertyMetaData
,
841 .canonicalise_fn
= ldb_handler_copy
,
842 .comparison_fn
= ldb_comparison_binary
844 .name
= LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
,
845 .ldif_read_fn
= ldb_handler_copy
,
846 .ldif_write_fn
= ldif_write_replUpToDateVector
,
847 .canonicalise_fn
= ldb_handler_copy
,
848 .comparison_fn
= ldb_comparison_binary
852 static const struct ldb_dn_extended_syntax samba_dn_syntax
[] = {
855 .read_fn
= extended_dn_read_SID
,
856 .write_clear_fn
= ldif_write_objectSid
,
857 .write_hex_fn
= extended_dn_write_hex
860 .read_fn
= extended_dn_read_GUID
,
861 .write_clear_fn
= ldif_write_objectGUID
,
862 .write_hex_fn
= extended_dn_write_hex
865 .read_fn
= ldb_handler_copy
,
866 .write_clear_fn
= ldb_handler_copy
,
867 .write_hex_fn
= ldb_handler_copy
871 /* TODO: Should be dynamic at some point */
872 static const struct {
875 } samba_attributes
[] = {
876 { "objectSid", LDB_SYNTAX_SAMBA_SID
},
877 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID
},
878 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR
},
879 { "objectGUID", LDB_SYNTAX_SAMBA_GUID
},
880 { "invocationId", LDB_SYNTAX_SAMBA_GUID
},
881 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID
},
882 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID
},
883 { "parentGUID", LDB_SYNTAX_SAMBA_GUID
},
884 { "siteGUID", LDB_SYNTAX_SAMBA_GUID
},
885 { "pKTGUID", LDB_SYNTAX_SAMBA_GUID
},
886 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID
},
887 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID
},
888 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID
},
889 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY
},
890 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP
},
891 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO
},
892 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO
},
893 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA
},
894 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR
},
897 const struct ldb_schema_syntax
*ldb_samba_syntax_by_name(struct ldb_context
*ldb
, const char *name
)
900 const struct ldb_schema_syntax
*s
= NULL
;
902 for (j
=0; j
< ARRAY_SIZE(samba_syntaxes
); j
++) {
903 if (strcmp(name
, samba_syntaxes
[j
].name
) == 0) {
904 s
= &samba_syntaxes
[j
];
911 const struct ldb_schema_syntax
*ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context
*ldb
, const char *name
)
914 const struct ldb_schema_syntax
*s
= NULL
;
916 for (j
=0; j
< ARRAY_SIZE(samba_attributes
); j
++) {
917 if (strcmp(samba_attributes
[j
].name
, name
) == 0) {
918 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[j
].syntax
);
927 register the samba ldif handlers
929 int ldb_register_samba_handlers(struct ldb_context
*ldb
)
933 for (i
=0; i
< ARRAY_SIZE(samba_attributes
); i
++) {
935 const struct ldb_schema_syntax
*s
= NULL
;
937 s
= ldb_samba_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
940 s
= ldb_standard_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
947 ret
= ldb_schema_attribute_add_with_syntax(ldb
, samba_attributes
[i
].name
, LDB_ATTR_FLAG_FIXED
, s
);
948 if (ret
!= LDB_SUCCESS
) {
953 for (i
=0; i
< ARRAY_SIZE(samba_dn_syntax
); i
++) {
955 ret
= ldb_dn_extended_add_syntax(ldb
, LDB_ATTR_FLAG_FIXED
, &samba_dn_syntax
[i
]);
956 if (ret
!= LDB_SUCCESS
) {