ldb-samba: Implement transitive extended matching
[Samba.git] / lib / ldb-samba / ldif_handlers.c
blobea62bf9ff43acab75de4edeae31566b5900b5d6a
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);
911 convert a NDR formatted blob to a ldif formatted dnsRecord
913 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
914 const struct ldb_val *in, struct ldb_val *out)
916 return ldif_write_NDR(ldb, mem_ctx, in, out,
917 sizeof(struct dnsp_DnssrvRpcRecord),
918 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
919 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
920 true);
924 convert a NDR formatted blob to a ldif formatted dnsProperty
926 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
927 const struct ldb_val *in, struct ldb_val *out)
929 return ldif_write_NDR(ldb, mem_ctx, in, out,
930 sizeof(struct dnsp_DnsProperty),
931 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
932 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
933 true);
937 convert a NDR formatted blob of a supplementalCredentials into text
939 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
940 const struct ldb_val *in, struct ldb_val *out)
942 return ldif_write_NDR(ldb, mem_ctx, in, out,
943 sizeof(struct supplementalCredentialsBlob),
944 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
945 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
946 true);
950 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
952 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
953 const struct ldb_val *in, struct ldb_val *out)
955 return ldif_write_NDR(ldb, mem_ctx, in, out,
956 sizeof(struct trustAuthInOutBlob),
957 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
958 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
959 true);
963 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
965 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
966 const struct ldb_val *in, struct ldb_val *out)
968 return ldif_write_NDR(ldb, mem_ctx, in, out,
969 sizeof(struct ForestTrustInfo),
970 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
971 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
972 true);
975 convert a NDR formatted blob of a partialAttributeSet into text
977 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
978 const struct ldb_val *in, struct ldb_val *out)
980 return ldif_write_NDR(ldb, mem_ctx, in, out,
981 sizeof(struct partialAttributeSetBlob),
982 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
983 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
984 true);
988 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
989 const struct ldb_val *in, struct ldb_val *out)
991 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
992 if (!out->data) {
993 return -1;
995 return 0;
999 compare two dns
1001 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1002 const struct ldb_val *v1, const struct ldb_val *v2)
1004 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1005 int ret;
1007 if (dsdb_dn_is_deleted_val(v1)) {
1008 /* If the DN is deleted, then we can't search for it */
1009 return -1;
1012 if (dsdb_dn_is_deleted_val(v2)) {
1013 /* If the DN is deleted, then we can't search for it */
1014 return -1;
1017 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1018 if ( ! ldb_dn_validate(dn1)) return -1;
1020 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1021 if ( ! ldb_dn_validate(dn2)) {
1022 talloc_free(dn1);
1023 return -1;
1026 ret = ldb_dn_compare(dn1, dn2);
1028 talloc_free(dn1);
1029 talloc_free(dn2);
1030 return ret;
1033 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1034 const struct ldb_val *in, struct ldb_val *out)
1036 struct ldb_dn *dn;
1037 int ret = -1;
1039 out->length = 0;
1040 out->data = NULL;
1042 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1043 if ( ! ldb_dn_validate(dn)) {
1044 return LDB_ERR_INVALID_DN_SYNTAX;
1047 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1048 * does not casually match a not deleted DN */
1049 if (dsdb_dn_is_deleted_val(in)) {
1050 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1051 "<RMD_FLAGS=%u>%s",
1052 dsdb_dn_val_rmd_flags(in),
1053 ldb_dn_get_casefold(dn));
1054 } else {
1055 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1058 if (out->data == NULL) {
1059 goto done;
1061 out->length = strlen((char *)out->data);
1063 ret = 0;
1065 done:
1066 talloc_free(dn);
1068 return ret;
1073 write a 64 bit 2-part range
1075 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1076 const struct ldb_val *in, struct ldb_val *out)
1078 int64_t v;
1079 int ret;
1080 ret = val_to_int64(in, &v);
1081 if (ret != LDB_SUCCESS) {
1082 return ret;
1084 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1085 (unsigned long)(v&0xFFFFFFFF),
1086 (unsigned long)(v>>32));
1087 if (out->data == NULL) {
1088 ldb_oom(ldb);
1089 return LDB_ERR_OPERATIONS_ERROR;
1091 out->length = strlen((char *)out->data);
1092 return LDB_SUCCESS;
1096 read a 64 bit 2-part range
1098 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1099 const struct ldb_val *in, struct ldb_val *out)
1101 unsigned long high, low;
1102 char buf[64];
1104 if (memchr(in->data, '-', in->length) == NULL) {
1105 return ldb_handler_copy(ldb, mem_ctx, in, out);
1108 if (in->length > sizeof(buf)-1) {
1109 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1111 strncpy(buf, (const char *)in->data, in->length);
1112 buf[in->length] = 0;
1114 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1115 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1118 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1119 (unsigned long long)(((uint64_t)high)<<32) | (low));
1121 if (out->data == NULL) {
1122 ldb_oom(ldb);
1123 return LDB_ERR_OPERATIONS_ERROR;
1125 out->length = strlen((char *)out->data);
1126 return LDB_SUCCESS;
1130 when this operator_fn is set for a syntax, the backend calls is in
1131 preference to the comparison function. We are told the exact
1132 comparison operation that is needed, and we can return errors
1134 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1135 const struct ldb_schema_attribute *a,
1136 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1138 switch (operation) {
1139 case LDB_OP_AND:
1140 case LDB_OP_OR:
1141 case LDB_OP_NOT:
1142 case LDB_OP_SUBSTRING:
1143 case LDB_OP_APPROX:
1144 case LDB_OP_EXTENDED:
1145 /* handled in the backends */
1146 return LDB_ERR_INAPPROPRIATE_MATCHING;
1148 case LDB_OP_GREATER:
1149 case LDB_OP_LESS:
1150 case LDB_OP_EQUALITY:
1152 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1153 int ret;
1154 if (tmp_ctx == NULL) {
1155 return ldb_oom(ldb);
1157 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1158 talloc_free(tmp_ctx);
1159 if (operation == LDB_OP_GREATER) {
1160 *matched = (ret >= 0);
1161 } else if (operation == LDB_OP_LESS) {
1162 *matched = (ret <= 0);
1163 } else {
1164 *matched = (ret == 0);
1166 return LDB_SUCCESS;
1169 case LDB_OP_PRESENT:
1170 *matched = true;
1171 return LDB_SUCCESS;
1174 /* we shouldn't get here */
1175 return LDB_ERR_INAPPROPRIATE_MATCHING;
1179 see if two DNs match, comparing first by GUID, then by SID, and
1180 finally by string components
1182 static int samba_dn_extended_match(struct ldb_context *ldb,
1183 const struct ldb_val *v1,
1184 const struct ldb_val *v2,
1185 bool *matched)
1187 TALLOC_CTX *tmp_ctx;
1188 struct ldb_dn *dn1, *dn2;
1189 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1190 uint32_t rmd_flags1, rmd_flags2;
1192 tmp_ctx = talloc_new(ldb);
1194 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1195 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1196 if (!dn1 || !dn2) {
1197 /* couldn't parse as DN's */
1198 talloc_free(tmp_ctx);
1199 (*matched) = false;
1200 return LDB_SUCCESS;
1203 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1204 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1206 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1207 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1208 /* only match if they have the same deletion status */
1209 talloc_free(tmp_ctx);
1210 (*matched) = false;
1211 return LDB_SUCCESS;
1215 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1216 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1217 if (guid1 && guid2) {
1218 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1219 talloc_free(tmp_ctx);
1220 return LDB_SUCCESS;
1223 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1224 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1225 if (sid1 && sid2) {
1226 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1227 talloc_free(tmp_ctx);
1228 return LDB_SUCCESS;
1231 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1233 talloc_free(tmp_ctx);
1234 return LDB_SUCCESS;
1238 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1240 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1241 const struct ldb_schema_attribute *a,
1242 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1244 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1245 /* If the DN is deleted, then we can't search for it */
1247 /* should this be for equality too? */
1248 *matched = false;
1249 return LDB_SUCCESS;
1252 if (operation == LDB_OP_EQUALITY &&
1253 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1254 return LDB_SUCCESS;
1257 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1261 static const struct ldb_schema_syntax samba_syntaxes[] = {
1263 .name = LDB_SYNTAX_SAMBA_SID,
1264 .ldif_read_fn = ldif_read_objectSid,
1265 .ldif_write_fn = ldif_write_objectSid,
1266 .canonicalise_fn = ldif_canonicalise_objectSid,
1267 .comparison_fn = ldif_comparison_objectSid,
1268 .operator_fn = samba_syntax_operator_fn
1270 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1271 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1272 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1273 .canonicalise_fn = ldb_handler_copy,
1274 .comparison_fn = ldb_comparison_binary,
1275 .operator_fn = samba_syntax_operator_fn
1277 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1278 .ldif_read_fn = ldb_handler_copy,
1279 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1280 .canonicalise_fn = ldb_handler_fold,
1281 .comparison_fn = ldb_comparison_fold,
1282 .operator_fn = samba_syntax_operator_fn
1284 .name = LDB_SYNTAX_SAMBA_GUID,
1285 .ldif_read_fn = ldif_read_objectGUID,
1286 .ldif_write_fn = ldif_write_objectGUID,
1287 .canonicalise_fn = ldif_canonicalise_objectGUID,
1288 .comparison_fn = ldif_comparison_objectGUID,
1289 .operator_fn = samba_syntax_operator_fn
1291 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1292 .ldif_read_fn = ldb_handler_copy,
1293 .ldif_write_fn = ldb_handler_copy,
1294 .canonicalise_fn = ldif_canonicalise_objectCategory,
1295 .comparison_fn = ldif_comparison_objectCategory,
1296 .operator_fn = samba_syntax_operator_fn
1298 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1299 .ldif_read_fn = ldb_handler_copy,
1300 .ldif_write_fn = ldif_write_schemaInfo,
1301 .canonicalise_fn = ldb_handler_copy,
1302 .comparison_fn = ldb_comparison_binary,
1303 .operator_fn = samba_syntax_operator_fn
1305 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1306 .ldif_read_fn = ldif_read_prefixMap,
1307 .ldif_write_fn = ldif_write_prefixMap,
1308 .canonicalise_fn = ldif_canonicalise_prefixMap,
1309 .comparison_fn = ldif_comparison_prefixMap,
1310 .operator_fn = samba_syntax_operator_fn
1312 .name = LDB_SYNTAX_SAMBA_INT32,
1313 .ldif_read_fn = ldb_handler_copy,
1314 .ldif_write_fn = ldb_handler_copy,
1315 .canonicalise_fn = ldif_canonicalise_int32,
1316 .comparison_fn = ldif_comparison_int32,
1317 .operator_fn = samba_syntax_operator_fn
1319 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1320 .ldif_read_fn = ldb_handler_copy,
1321 .ldif_write_fn = ldif_write_repsFromTo,
1322 .canonicalise_fn = ldb_handler_copy,
1323 .comparison_fn = ldb_comparison_binary,
1324 .operator_fn = samba_syntax_operator_fn
1326 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1327 .ldif_read_fn = ldb_handler_copy,
1328 .ldif_write_fn = ldif_write_replPropertyMetaData,
1329 .canonicalise_fn = ldb_handler_copy,
1330 .comparison_fn = ldb_comparison_binary,
1331 .operator_fn = samba_syntax_operator_fn
1333 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1334 .ldif_read_fn = ldb_handler_copy,
1335 .ldif_write_fn = ldif_write_replUpToDateVector,
1336 .canonicalise_fn = ldb_handler_copy,
1337 .comparison_fn = ldb_comparison_binary,
1338 .operator_fn = samba_syntax_operator_fn
1340 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1341 .ldif_read_fn = ldb_handler_copy,
1342 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1343 .canonicalise_fn = ldb_handler_copy,
1344 .comparison_fn = ldb_comparison_binary,
1345 .operator_fn = samba_syntax_operator_fn
1347 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1348 .ldif_read_fn = ldb_handler_copy,
1349 .ldif_write_fn = ldif_write_ForestTrustInfo,
1350 .canonicalise_fn = ldb_handler_copy,
1351 .comparison_fn = ldb_comparison_binary,
1352 .operator_fn = samba_syntax_operator_fn
1354 .name = DSDB_SYNTAX_BINARY_DN,
1355 .ldif_read_fn = ldb_handler_copy,
1356 .ldif_write_fn = ldb_handler_copy,
1357 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1358 .comparison_fn = dsdb_dn_binary_comparison,
1359 .operator_fn = samba_syntax_operator_fn
1361 .name = DSDB_SYNTAX_STRING_DN,
1362 .ldif_read_fn = ldb_handler_copy,
1363 .ldif_write_fn = ldb_handler_copy,
1364 .canonicalise_fn = dsdb_dn_string_canonicalise,
1365 .comparison_fn = dsdb_dn_string_comparison,
1366 .operator_fn = samba_syntax_operator_fn
1368 .name = LDB_SYNTAX_DN,
1369 .ldif_read_fn = ldb_handler_copy,
1370 .ldif_write_fn = ldb_handler_copy,
1371 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1372 .comparison_fn = samba_ldb_dn_link_comparison,
1373 .operator_fn = samba_syntax_operator_dn
1375 .name = LDB_SYNTAX_SAMBA_RANGE64,
1376 .ldif_read_fn = ldif_read_range64,
1377 .ldif_write_fn = ldif_write_range64,
1378 .canonicalise_fn = ldif_canonicalise_int64,
1379 .comparison_fn = ldif_comparison_int64,
1380 .operator_fn = samba_syntax_operator_fn
1382 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1383 .ldif_read_fn = ldb_handler_copy,
1384 .ldif_write_fn = ldif_write_dnsRecord,
1385 .canonicalise_fn = ldb_handler_copy,
1386 .comparison_fn = ldb_comparison_binary,
1387 .operator_fn = samba_syntax_operator_fn
1389 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1390 .ldif_read_fn = ldb_handler_copy,
1391 .ldif_write_fn = ldif_write_dnsProperty,
1392 .canonicalise_fn = ldb_handler_copy,
1393 .comparison_fn = ldb_comparison_binary,
1394 .operator_fn = samba_syntax_operator_fn
1396 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1397 .ldif_read_fn = ldb_handler_copy,
1398 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1399 .canonicalise_fn = ldb_handler_copy,
1400 .comparison_fn = ldb_comparison_binary,
1401 .operator_fn = samba_syntax_operator_fn
1403 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1404 .ldif_read_fn = ldb_handler_copy,
1405 .ldif_write_fn = ldif_write_partialAttributeSet,
1406 .canonicalise_fn = ldb_handler_copy,
1407 .comparison_fn = ldb_comparison_binary,
1408 .operator_fn = samba_syntax_operator_fn
1412 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1414 .name = "SID",
1415 .read_fn = extended_dn_read_SID,
1416 .write_clear_fn = ldif_write_objectSid,
1417 .write_hex_fn = extended_dn_write_hex
1419 .name = "GUID",
1420 .read_fn = extended_dn_read_GUID,
1421 .write_clear_fn = ldif_write_objectGUID,
1422 .write_hex_fn = extended_dn_write_hex
1424 .name = "WKGUID",
1425 .read_fn = ldb_handler_copy,
1426 .write_clear_fn = ldb_handler_copy,
1427 .write_hex_fn = ldb_handler_copy
1429 .name = "RMD_INVOCID",
1430 .read_fn = extended_dn_read_GUID,
1431 .write_clear_fn = ldif_write_objectGUID,
1432 .write_hex_fn = extended_dn_write_hex
1434 .name = "RMD_FLAGS",
1435 .read_fn = ldb_handler_copy,
1436 .write_clear_fn = ldb_handler_copy,
1437 .write_hex_fn = ldb_handler_copy
1439 .name = "RMD_ADDTIME",
1440 .read_fn = ldb_handler_copy,
1441 .write_clear_fn = ldb_handler_copy,
1442 .write_hex_fn = ldb_handler_copy
1444 .name = "RMD_CHANGETIME",
1445 .read_fn = ldb_handler_copy,
1446 .write_clear_fn = ldb_handler_copy,
1447 .write_hex_fn = ldb_handler_copy
1449 .name = "RMD_LOCAL_USN",
1450 .read_fn = ldb_handler_copy,
1451 .write_clear_fn = ldb_handler_copy,
1452 .write_hex_fn = ldb_handler_copy
1454 .name = "RMD_ORIGINATING_USN",
1455 .read_fn = ldb_handler_copy,
1456 .write_clear_fn = ldb_handler_copy,
1457 .write_hex_fn = ldb_handler_copy
1459 .name = "RMD_VERSION",
1460 .read_fn = ldb_handler_copy,
1461 .write_clear_fn = ldb_handler_copy,
1462 .write_hex_fn = ldb_handler_copy
1466 /* TODO: Should be dynamic at some point */
1467 static const struct {
1468 const char *name;
1469 const char *syntax;
1470 } samba_attributes[] = {
1471 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1472 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1473 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1474 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1475 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1476 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1477 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1478 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1479 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1480 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1481 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1482 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1483 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1484 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1485 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1486 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1489 * these are extracted by searching
1490 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1492 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1493 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1494 * hat can be used to identify the set of policies when applied to a resource.
1495 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1496 * server, we ignore it here.
1498 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1499 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1500 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1501 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1502 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1503 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1504 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1505 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1506 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1509 * these are extracted by searching
1510 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1512 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1513 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1514 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1515 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1516 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1517 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1518 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1519 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1520 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1521 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1522 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1523 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1524 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1525 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1526 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1527 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1528 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1529 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1530 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1531 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1532 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1533 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1534 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1535 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1536 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1537 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1538 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1539 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1542 * these are known to be GUIDs
1544 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1545 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1547 /* These NDR encoded things we want to be able to read with --show-binary */
1548 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1549 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1550 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1551 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1554 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1556 unsigned int j;
1557 const struct ldb_schema_syntax *s = NULL;
1559 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1560 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1561 s = &samba_syntaxes[j];
1562 break;
1565 return s;
1568 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1570 unsigned int j;
1571 const struct ldb_schema_syntax *s = NULL;
1573 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1574 if (strcmp(samba_attributes[j].name, name) == 0) {
1575 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1576 break;
1580 return s;
1583 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, NULL};
1586 register the samba ldif handlers
1588 int ldb_register_samba_handlers(struct ldb_context *ldb)
1590 unsigned int i;
1591 int ret;
1593 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1594 return LDB_SUCCESS;
1597 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1598 if (ret != LDB_SUCCESS) {
1599 return ret;
1602 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1603 const struct ldb_schema_syntax *s = NULL;
1605 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1607 if (!s) {
1608 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1611 if (!s) {
1612 return LDB_ERR_OPERATIONS_ERROR;
1615 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1616 if (ret != LDB_SUCCESS) {
1617 return ret;
1621 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1622 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1623 if (ret != LDB_SUCCESS) {
1624 return ret;
1629 ret = ldb_register_samba_matching_rules(ldb);
1630 if (ret != LDB_SUCCESS) {
1631 talloc_free(ldb);
1632 return LDB_SUCCESS;
1635 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1636 if (ret != LDB_SUCCESS) {
1637 return ret;
1640 return LDB_SUCCESS;