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