pidl/NDR/Parser: declare all union helper variables in ParseUnionPull()
[Samba.git] / lib / ldb-samba / ldif_handlers.c
blobaf66623efaf4c098f0a4819169382d9d94010a4b
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 "librpc/gen_ndr/ndr_security.h"
31 #include "librpc/gen_ndr/ndr_misc.h"
32 #include "librpc/gen_ndr/ndr_drsblobs.h"
33 #include "librpc/gen_ndr/ndr_dnsp.h"
34 #include "librpc/ndr/libndr.h"
35 #include "libcli/security/security.h"
36 #include "param/param.h"
37 #include "../lib/util/asn1.h"
40 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
42 If mask_errors is true, then function succeeds but out data
43 is set to "<Unable to decode binary data>" message
45 \return 0 on success; -1 on error
47 static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
48 const struct ldb_val *in, struct ldb_val *out,
49 size_t struct_size,
50 ndr_pull_flags_fn_t pull_fn,
51 ndr_print_fn_t print_fn,
52 bool mask_errors)
54 uint8_t *p;
55 enum ndr_err_code err;
56 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
57 return ldb_handler_copy(ldb, mem_ctx, in, out);
59 p = talloc_size(mem_ctx, struct_size);
60 err = ndr_pull_struct_blob(in, mem_ctx,
61 p, pull_fn);
62 if (err != NDR_ERR_SUCCESS) {
63 /* fail in not in mask_error mode */
64 if (!mask_errors) {
65 return -1;
67 talloc_free(p);
68 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
69 out->length = strlen((const char *)out->data);
70 return 0;
72 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
73 talloc_free(p);
74 if (out->data == NULL) {
75 return ldb_handler_copy(ldb, mem_ctx, in, out);
77 out->length = strlen((char *)out->data);
78 return 0;
82 convert a ldif formatted objectSid to a NDR formatted blob
84 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
85 const struct ldb_val *in, struct ldb_val *out)
87 enum ndr_err_code ndr_err;
88 struct dom_sid *sid;
89 sid = dom_sid_parse_length(mem_ctx, in);
90 if (sid == NULL) {
91 return -1;
93 ndr_err = ndr_push_struct_blob(out, mem_ctx, sid,
94 (ndr_push_flags_fn_t)ndr_push_dom_sid);
95 talloc_free(sid);
96 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
97 return -1;
99 return 0;
103 convert a NDR formatted blob to a ldif formatted objectSid
105 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
106 const struct ldb_val *in, struct ldb_val *out)
108 struct dom_sid *sid;
109 enum ndr_err_code ndr_err;
111 sid = talloc(mem_ctx, struct dom_sid);
112 if (sid == NULL) {
113 return -1;
115 ndr_err = ndr_pull_struct_blob_all(in, sid, sid,
116 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
117 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
118 talloc_free(sid);
119 return -1;
121 *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
122 talloc_free(sid);
123 if (out->data == NULL) {
124 return -1;
126 return 0;
129 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
131 if (v->length < 3) {
132 return false;
135 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
137 return true;
141 compare two objectSids
143 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
144 const struct ldb_val *v1, const struct ldb_val *v2)
146 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
147 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
148 } else if (ldif_comparision_objectSid_isString(v1)
149 && !ldif_comparision_objectSid_isString(v2)) {
150 struct ldb_val v;
151 int ret;
152 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
153 /* Perhaps not a string after all */
154 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
156 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
157 talloc_free(v.data);
158 return ret;
159 } else if (!ldif_comparision_objectSid_isString(v1)
160 && ldif_comparision_objectSid_isString(v2)) {
161 struct ldb_val v;
162 int ret;
163 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
164 /* Perhaps not a string after all */
165 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
167 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
168 talloc_free(v.data);
169 return ret;
171 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
175 canonicalise a objectSid
177 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
178 const struct ldb_val *in, struct ldb_val *out)
180 if (ldif_comparision_objectSid_isString(in)) {
181 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
182 /* Perhaps not a string after all */
183 return ldb_handler_copy(ldb, mem_ctx, in, out);
185 return 0;
187 return ldb_handler_copy(ldb, mem_ctx, in, out);
190 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
191 const struct ldb_val *in, struct ldb_val *out)
193 struct dom_sid sid;
194 enum ndr_err_code ndr_err;
195 if (ldif_comparision_objectSid_isString(in)) {
196 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
197 return 0;
201 /* Perhaps not a string after all */
202 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
204 if (!out->data) {
205 return -1;
208 (*out).length = strhex_to_str((char *)out->data, out->length,
209 (const char *)in->data, in->length);
211 /* Check it looks like a SID */
212 ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, &sid,
213 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
214 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
215 return -1;
217 return 0;
221 convert a ldif formatted objectGUID to a NDR formatted blob
223 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
224 const struct ldb_val *in, struct ldb_val *out)
226 struct GUID guid;
227 NTSTATUS status;
229 status = GUID_from_data_blob(in, &guid);
230 if (!NT_STATUS_IS_OK(status)) {
231 return -1;
234 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
235 if (!NT_STATUS_IS_OK(status)) {
236 return -1;
238 return 0;
242 convert a NDR formatted blob to a ldif formatted objectGUID
244 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
245 const struct ldb_val *in, struct ldb_val *out)
247 struct GUID guid;
248 NTSTATUS status;
250 status = GUID_from_ndr_blob(in, &guid);
251 if (!NT_STATUS_IS_OK(status)) {
252 return -1;
254 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
255 if (out->data == NULL) {
256 return -1;
258 out->length = strlen((const char *)out->data);
259 return 0;
262 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
264 if (v->length != 36 && v->length != 38) return false;
266 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
267 return true;
270 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
271 const struct ldb_val *in, struct ldb_val *out)
273 struct GUID guid;
274 NTSTATUS status;
276 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
277 return 0;
280 /* Try as 'hex' form */
281 if (in->length != 32) {
282 return -1;
285 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
287 if (!out->data) {
288 return -1;
291 (*out).length = strhex_to_str((char *)out->data, out->length,
292 (const char *)in->data, in->length);
294 /* Check it looks like a GUID */
295 status = GUID_from_ndr_blob(out, &guid);
296 if (!NT_STATUS_IS_OK(status)) {
297 data_blob_free(out);
298 return -1;
300 return 0;
304 compare two objectGUIDs
306 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
307 const struct ldb_val *v1, const struct ldb_val *v2)
309 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
310 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
311 } else if (ldif_comparision_objectGUID_isString(v1)
312 && !ldif_comparision_objectGUID_isString(v2)) {
313 struct ldb_val v;
314 int ret;
315 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
316 /* Perhaps it wasn't a valid string after all */
317 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
319 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
320 talloc_free(v.data);
321 return ret;
322 } else if (!ldif_comparision_objectGUID_isString(v1)
323 && ldif_comparision_objectGUID_isString(v2)) {
324 struct ldb_val v;
325 int ret;
326 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
327 /* Perhaps it wasn't a valid string after all */
328 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
330 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
331 talloc_free(v.data);
332 return ret;
334 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
338 canonicalise a objectGUID
340 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
341 const struct ldb_val *in, struct ldb_val *out)
343 if (ldif_comparision_objectGUID_isString(in)) {
344 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
345 /* Perhaps it wasn't a valid string after all */
346 return ldb_handler_copy(ldb, mem_ctx, in, out);
348 return 0;
350 return ldb_handler_copy(ldb, mem_ctx, in, out);
355 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
357 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
358 const struct ldb_val *in, struct ldb_val *out)
360 struct security_descriptor *sd;
361 enum ndr_err_code ndr_err;
363 sd = talloc(mem_ctx, struct security_descriptor);
364 if (sd == NULL) {
365 return -1;
368 ndr_err = ndr_pull_struct_blob(in, sd, sd,
369 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
370 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
371 /* If this does not parse, then it is probably SDDL, and we should try it that way */
373 const struct dom_sid *sid = samdb_domain_sid(ldb);
374 talloc_free(sd);
375 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
376 if (sd == NULL) {
377 return -1;
381 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
382 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
383 talloc_free(sd);
384 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
385 return -1;
388 return 0;
392 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
394 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
395 const struct ldb_val *in, struct ldb_val *out)
397 struct security_descriptor *sd;
398 enum ndr_err_code ndr_err;
400 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
401 return ldif_write_NDR(ldb, mem_ctx, in, out,
402 sizeof(struct security_descriptor),
403 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
404 (ndr_print_fn_t)ndr_print_security_descriptor,
405 true);
409 sd = talloc(mem_ctx, struct security_descriptor);
410 if (sd == NULL) {
411 return -1;
413 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
414 ndr_err = ndr_pull_struct_blob(in, sd, sd,
415 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
416 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
417 talloc_free(sd);
418 return -1;
420 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
421 talloc_free(sd);
422 if (out->data == NULL) {
423 return -1;
425 out->length = strlen((const char *)out->data);
426 return 0;
430 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
432 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
433 const struct ldb_val *in, struct ldb_val *out)
435 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
436 struct security_descriptor *sd;
437 const struct dom_sid *sid = samdb_domain_sid(ldb);
439 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
440 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
441 (ndr_print_fn_t)ndr_print_security_descriptor,
442 "SDDL", sd);
443 out->length = strlen((const char *)out->data);
444 talloc_free(sd);
445 return 0;
448 return ldb_handler_copy(ldb, mem_ctx, in, out);
452 canonicalise an objectCategory. We use the long form as the canonical form:
453 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
455 Also any short name of an objectClass that points to a different
456 class (such as user) has the canonical form of the class it's
457 defaultObjectCategory points to (eg
458 cn=Person,cn=Schema,cn=Configuration,<basedn>)
461 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
462 const struct ldb_val *in, struct ldb_val *out)
464 struct ldb_dn *dn1 = NULL;
465 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
466 const struct dsdb_class *sclass;
467 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
468 if (!tmp_ctx) {
469 return LDB_ERR_OPERATIONS_ERROR;
472 if (!schema) {
473 talloc_free(tmp_ctx);
474 *out = data_blob_talloc(mem_ctx, in->data, in->length);
475 if (in->data && !out->data) {
476 return LDB_ERR_OPERATIONS_ERROR;
478 return LDB_SUCCESS;
480 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
481 if ( ! ldb_dn_validate(dn1)) {
482 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
483 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
484 if (sclass) {
485 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
486 sclass->defaultObjectCategory);
487 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
488 talloc_free(tmp_ctx);
490 if (!out->data) {
491 return LDB_ERR_OPERATIONS_ERROR;
493 return LDB_SUCCESS;
494 } else {
495 *out = data_blob_talloc(mem_ctx, in->data, in->length);
496 talloc_free(tmp_ctx);
498 if (in->data && !out->data) {
499 return LDB_ERR_OPERATIONS_ERROR;
501 return LDB_SUCCESS;
504 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
505 talloc_free(tmp_ctx);
507 if (!out->data) {
508 return LDB_ERR_OPERATIONS_ERROR;
510 return LDB_SUCCESS;
513 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
514 const struct ldb_val *v1,
515 const struct ldb_val *v2)
517 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
518 v1, v2);
522 convert a NDR formatted blob to a ldif formatted schemaInfo
524 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
525 const struct ldb_val *in, struct ldb_val *out)
527 return ldif_write_NDR(ldb, mem_ctx, in, out,
528 sizeof(struct repsFromToBlob),
529 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
530 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
531 true);
535 convert a ldif formatted prefixMap to a NDR formatted blob
537 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
538 const struct ldb_val *in, struct ldb_val *out)
540 struct prefixMapBlob *blob;
541 enum ndr_err_code ndr_err;
542 char *string, *line, *p, *oid;
543 DATA_BLOB oid_blob;
545 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
547 if (tmp_ctx == NULL) {
548 return -1;
551 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
552 if (blob == NULL) {
553 talloc_free(tmp_ctx);
554 return -1;
557 /* use the switch value to detect if this is in the binary
558 * format
560 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
561 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
562 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
563 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
564 ndr_err = ndr_push_struct_blob(out, mem_ctx,
565 blob,
566 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
567 talloc_free(tmp_ctx);
568 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
569 return -1;
571 return 0;
575 /* If this does not parse, then it is probably the text version, and we should try it that way */
576 blob->version = PREFIX_MAP_VERSION_DSDB;
578 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
579 if (string == NULL) {
580 talloc_free(blob);
581 return -1;
584 line = string;
585 while (line && line[0]) {
586 p=strchr(line, ';');
587 if (p) {
588 p[0] = '\0';
589 } else {
590 p=strchr(line, '\n');
591 if (p) {
592 p[0] = '\0';
595 /* allow a trailing separator */
596 if (line == p) {
597 break;
600 blob->ctr.dsdb.mappings = talloc_realloc(blob,
601 blob->ctr.dsdb.mappings,
602 struct drsuapi_DsReplicaOIDMapping,
603 blob->ctr.dsdb.num_mappings+1);
604 if (!blob->ctr.dsdb.mappings) {
605 talloc_free(tmp_ctx);
606 return -1;
609 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
611 if (oid[0] != ':') {
612 talloc_free(tmp_ctx);
613 return -1;
616 /* we know there must be at least ":" */
617 oid++;
619 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
620 talloc_free(tmp_ctx);
621 return -1;
623 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
624 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
626 blob->ctr.dsdb.num_mappings++;
628 /* Now look past the terminator we added above */
629 if (p) {
630 line = p + 1;
631 } else {
632 line = NULL;
636 ndr_err = ndr_push_struct_blob(out, mem_ctx,
637 blob,
638 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
639 talloc_free(tmp_ctx);
640 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
641 return -1;
643 return 0;
647 convert a NDR formatted blob to a ldif formatted prefixMap
649 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
650 const struct ldb_val *in, struct ldb_val *out)
652 struct prefixMapBlob *blob;
653 enum ndr_err_code ndr_err;
654 char *string;
655 uint32_t i;
657 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
658 int err;
659 /* try to decode the blob as S4 prefixMap */
660 err = ldif_write_NDR(ldb, mem_ctx, in, out,
661 sizeof(struct prefixMapBlob),
662 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
663 (ndr_print_fn_t)ndr_print_prefixMapBlob,
664 false);
665 if (0 == err) {
666 return err;
668 /* try parsing it as Windows PrefixMap value */
669 return ldif_write_NDR(ldb, mem_ctx, in, out,
670 sizeof(struct drsuapi_MSPrefixMap_Ctr),
671 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
672 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
673 true);
676 blob = talloc(mem_ctx, struct prefixMapBlob);
677 if (blob == NULL) {
678 return -1;
680 ndr_err = ndr_pull_struct_blob_all(in, blob,
681 blob,
682 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
683 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
684 goto failed;
686 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
687 goto failed;
689 string = talloc_strdup(mem_ctx, "");
690 if (string == NULL) {
691 goto failed;
694 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
695 DATA_BLOB oid_blob;
696 char *partial_oid = NULL;
698 if (i > 0) {
699 string = talloc_asprintf_append(string, ";");
702 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
703 blob->ctr.dsdb.mappings[i].oid.length);
704 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
705 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
706 blob->ctr.dsdb.mappings[i].id_prefix));
707 goto failed;
709 string = talloc_asprintf_append(string, "%u:%s",
710 blob->ctr.dsdb.mappings[i].id_prefix,
711 partial_oid);
712 talloc_free(discard_const(partial_oid));
713 if (string == NULL) {
714 goto failed;
718 talloc_free(blob);
719 *out = data_blob_string_const(string);
720 return 0;
722 failed:
723 talloc_free(blob);
724 return -1;
727 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
729 if (v->length < 4) {
730 return true;
733 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
734 return false;
737 return true;
741 canonicalise a prefixMap
743 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
744 const struct ldb_val *in, struct ldb_val *out)
746 if (ldif_comparision_prefixMap_isString(in)) {
747 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
749 return ldb_handler_copy(ldb, mem_ctx, in, out);
752 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
753 const struct ldb_val *v1,
754 const struct ldb_val *v2)
756 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
757 v1, v2);
760 /* length limited conversion of a ldb_val to a int32_t */
761 static int val_to_int32(const struct ldb_val *in, int32_t *v)
763 char *end;
764 char buf[64];
766 /* make sure we don't read past the end of the data */
767 if (in->length > sizeof(buf)-1) {
768 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
770 strncpy(buf, (char *)in->data, in->length);
771 buf[in->length] = 0;
773 /* We've to use "strtoll" here to have the intended overflows.
774 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
775 *v = (int32_t) strtoll(buf, &end, 0);
776 if (*end != 0) {
777 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
779 return LDB_SUCCESS;
782 /* length limited conversion of a ldb_val to a int64_t */
783 static int val_to_int64(const struct ldb_val *in, int64_t *v)
785 char *end;
786 char buf[64];
788 /* make sure we don't read past the end of the data */
789 if (in->length > sizeof(buf)-1) {
790 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
792 strncpy(buf, (char *)in->data, in->length);
793 buf[in->length] = 0;
795 *v = (int64_t) strtoll(buf, &end, 0);
796 if (*end != 0) {
797 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
799 return LDB_SUCCESS;
802 /* Canonicalisation of two 32-bit integers */
803 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
804 const struct ldb_val *in, struct ldb_val *out)
806 int32_t i;
807 int ret;
809 ret = val_to_int32(in, &i);
810 if (ret != LDB_SUCCESS) {
811 return ret;
813 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
814 if (out->data == NULL) {
815 ldb_oom(ldb);
816 return LDB_ERR_OPERATIONS_ERROR;
818 out->length = strlen((char *)out->data);
819 return 0;
822 /* Comparison of two 32-bit integers */
823 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
824 const struct ldb_val *v1, const struct ldb_val *v2)
826 int32_t i1=0, i2=0;
827 val_to_int32(v1, &i1);
828 val_to_int32(v2, &i2);
829 if (i1 == i2) return 0;
830 return i1 > i2? 1 : -1;
833 /* Canonicalisation of two 64-bit integers */
834 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
835 const struct ldb_val *in, struct ldb_val *out)
837 int64_t i;
838 int ret;
840 ret = val_to_int64(in, &i);
841 if (ret != LDB_SUCCESS) {
842 return ret;
844 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
845 if (out->data == NULL) {
846 ldb_oom(ldb);
847 return LDB_ERR_OPERATIONS_ERROR;
849 out->length = strlen((char *)out->data);
850 return 0;
853 /* Comparison of two 64-bit integers */
854 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
855 const struct ldb_val *v1, const struct ldb_val *v2)
857 int64_t i1=0, i2=0;
858 val_to_int64(v1, &i1);
859 val_to_int64(v2, &i2);
860 if (i1 == i2) return 0;
861 return i1 > i2? 1 : -1;
865 convert a NDR formatted blob to a ldif formatted repsFromTo
867 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
868 const struct ldb_val *in, struct ldb_val *out)
870 return ldif_write_NDR(ldb, mem_ctx, in, out,
871 sizeof(struct repsFromToBlob),
872 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
873 (ndr_print_fn_t)ndr_print_repsFromToBlob,
874 true);
878 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
880 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
881 const struct ldb_val *in, struct ldb_val *out)
883 return ldif_write_NDR(ldb, mem_ctx, in, out,
884 sizeof(struct replPropertyMetaDataBlob),
885 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
886 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
887 true);
891 convert a NDR formatted blob to a ldif formatted replUpToDateVector
893 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
894 const struct ldb_val *in, struct ldb_val *out)
896 return ldif_write_NDR(ldb, mem_ctx, in, out,
897 sizeof(struct replUpToDateVectorBlob),
898 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
899 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
900 true);
905 convert a NDR formatted blob to a ldif formatted dnsRecord
907 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
908 const struct ldb_val *in, struct ldb_val *out)
910 return ldif_write_NDR(ldb, mem_ctx, in, out,
911 sizeof(struct dnsp_DnssrvRpcRecord),
912 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
913 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
914 true);
918 convert a NDR formatted blob to a ldif formatted dnsProperty
920 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
921 const struct ldb_val *in, struct ldb_val *out)
923 return ldif_write_NDR(ldb, mem_ctx, in, out,
924 sizeof(struct dnsp_DnsProperty),
925 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
926 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
927 true);
931 convert a NDR formatted blob of a supplementalCredentials into text
933 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
934 const struct ldb_val *in, struct ldb_val *out)
936 return ldif_write_NDR(ldb, mem_ctx, in, out,
937 sizeof(struct supplementalCredentialsBlob),
938 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
939 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
940 true);
944 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
946 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
947 const struct ldb_val *in, struct ldb_val *out)
949 return ldif_write_NDR(ldb, mem_ctx, in, out,
950 sizeof(struct trustAuthInOutBlob),
951 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
952 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
953 true);
957 convert a NDR formatted blob of a partialAttributeSet into text
959 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
960 const struct ldb_val *in, struct ldb_val *out)
962 return ldif_write_NDR(ldb, mem_ctx, in, out,
963 sizeof(struct partialAttributeSetBlob),
964 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
965 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
966 true);
970 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
971 const struct ldb_val *in, struct ldb_val *out)
973 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
974 if (!out->data) {
975 return -1;
977 return 0;
981 compare two dns
983 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
984 const struct ldb_val *v1, const struct ldb_val *v2)
986 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
987 int ret;
989 if (dsdb_dn_is_deleted_val(v1)) {
990 /* If the DN is deleted, then we can't search for it */
991 return -1;
994 if (dsdb_dn_is_deleted_val(v2)) {
995 /* If the DN is deleted, then we can't search for it */
996 return -1;
999 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1000 if ( ! ldb_dn_validate(dn1)) return -1;
1002 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1003 if ( ! ldb_dn_validate(dn2)) {
1004 talloc_free(dn1);
1005 return -1;
1008 ret = ldb_dn_compare(dn1, dn2);
1010 talloc_free(dn1);
1011 talloc_free(dn2);
1012 return ret;
1015 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1016 const struct ldb_val *in, struct ldb_val *out)
1018 struct ldb_dn *dn;
1019 int ret = -1;
1021 out->length = 0;
1022 out->data = NULL;
1024 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1025 if ( ! ldb_dn_validate(dn)) {
1026 return LDB_ERR_INVALID_DN_SYNTAX;
1029 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1030 * does not casually match a not deleted DN */
1031 if (dsdb_dn_is_deleted_val(in)) {
1032 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1033 "<RMD_FLAGS=%u>%s",
1034 dsdb_dn_val_rmd_flags(in),
1035 ldb_dn_get_casefold(dn));
1036 } else {
1037 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1040 if (out->data == NULL) {
1041 goto done;
1043 out->length = strlen((char *)out->data);
1045 ret = 0;
1047 done:
1048 talloc_free(dn);
1050 return ret;
1055 write a 64 bit 2-part range
1057 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1058 const struct ldb_val *in, struct ldb_val *out)
1060 int64_t v;
1061 int ret;
1062 ret = val_to_int64(in, &v);
1063 if (ret != LDB_SUCCESS) {
1064 return ret;
1066 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1067 (unsigned long)(v&0xFFFFFFFF),
1068 (unsigned long)(v>>32));
1069 if (out->data == NULL) {
1070 ldb_oom(ldb);
1071 return LDB_ERR_OPERATIONS_ERROR;
1073 out->length = strlen((char *)out->data);
1074 return LDB_SUCCESS;
1078 read a 64 bit 2-part range
1080 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1081 const struct ldb_val *in, struct ldb_val *out)
1083 unsigned long high, low;
1084 char buf[64];
1086 if (memchr(in->data, '-', in->length) == NULL) {
1087 return ldb_handler_copy(ldb, mem_ctx, in, out);
1090 if (in->length > sizeof(buf)-1) {
1091 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1093 strncpy(buf, (const char *)in->data, in->length);
1094 buf[in->length] = 0;
1096 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1097 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1100 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1101 (unsigned long long)(((uint64_t)high)<<32) | (low));
1103 if (out->data == NULL) {
1104 ldb_oom(ldb);
1105 return LDB_ERR_OPERATIONS_ERROR;
1107 out->length = strlen((char *)out->data);
1108 return LDB_SUCCESS;
1112 when this operator_fn is set for a syntax, the backend calls is in
1113 preference to the comparison function. We are told the exact
1114 comparison operation that is needed, and we can return errors
1116 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1117 const struct ldb_schema_attribute *a,
1118 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1120 switch (operation) {
1121 case LDB_OP_AND:
1122 case LDB_OP_OR:
1123 case LDB_OP_NOT:
1124 case LDB_OP_SUBSTRING:
1125 case LDB_OP_APPROX:
1126 case LDB_OP_EXTENDED:
1127 /* handled in the backends */
1128 return LDB_ERR_INAPPROPRIATE_MATCHING;
1130 case LDB_OP_GREATER:
1131 case LDB_OP_LESS:
1132 case LDB_OP_EQUALITY:
1134 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1135 int ret;
1136 if (tmp_ctx == NULL) {
1137 return ldb_oom(ldb);
1139 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1140 talloc_free(tmp_ctx);
1141 if (operation == LDB_OP_GREATER) {
1142 *matched = (ret > 0);
1143 } else if (operation == LDB_OP_LESS) {
1144 *matched = (ret < 0);
1145 } else {
1146 *matched = (ret == 0);
1148 return LDB_SUCCESS;
1151 case LDB_OP_PRESENT:
1152 *matched = true;
1153 return LDB_SUCCESS;
1156 /* we shouldn't get here */
1157 return LDB_ERR_INAPPROPRIATE_MATCHING;
1161 see if two DNs match, comparing first by GUID, then by SID, and
1162 finally by string components
1164 static int samba_dn_extended_match(struct ldb_context *ldb,
1165 const struct ldb_val *v1,
1166 const struct ldb_val *v2,
1167 bool *matched)
1169 TALLOC_CTX *tmp_ctx;
1170 struct ldb_dn *dn1, *dn2;
1171 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1172 uint32_t rmd_flags1, rmd_flags2;
1174 tmp_ctx = talloc_new(ldb);
1176 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1177 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1178 if (!dn1 || !dn2) {
1179 /* couldn't parse as DN's */
1180 talloc_free(tmp_ctx);
1181 (*matched) = false;
1182 return LDB_SUCCESS;
1185 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1186 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1188 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1189 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1190 /* only match if they have the same deletion status */
1191 talloc_free(tmp_ctx);
1192 (*matched) = false;
1193 return LDB_SUCCESS;
1197 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1198 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1199 if (guid1 && guid2) {
1200 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1201 talloc_free(tmp_ctx);
1202 return LDB_SUCCESS;
1205 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1206 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1207 if (sid1 && sid2) {
1208 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1209 talloc_free(tmp_ctx);
1210 return LDB_SUCCESS;
1213 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1215 talloc_free(tmp_ctx);
1216 return LDB_SUCCESS;
1220 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1222 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1223 const struct ldb_schema_attribute *a,
1224 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1226 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1227 /* If the DN is deleted, then we can't search for it */
1229 /* should this be for equality too? */
1230 *matched = false;
1231 return LDB_SUCCESS;
1234 if (operation == LDB_OP_EQUALITY &&
1235 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1236 return LDB_SUCCESS;
1239 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1243 static const struct ldb_schema_syntax samba_syntaxes[] = {
1245 .name = LDB_SYNTAX_SAMBA_SID,
1246 .ldif_read_fn = ldif_read_objectSid,
1247 .ldif_write_fn = ldif_write_objectSid,
1248 .canonicalise_fn = ldif_canonicalise_objectSid,
1249 .comparison_fn = ldif_comparison_objectSid,
1250 .operator_fn = samba_syntax_operator_fn
1252 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1253 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1254 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1255 .canonicalise_fn = ldb_handler_copy,
1256 .comparison_fn = ldb_comparison_binary,
1257 .operator_fn = samba_syntax_operator_fn
1259 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1260 .ldif_read_fn = ldb_handler_copy,
1261 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1262 .canonicalise_fn = ldb_handler_fold,
1263 .comparison_fn = ldb_comparison_fold,
1264 .operator_fn = samba_syntax_operator_fn
1266 .name = LDB_SYNTAX_SAMBA_GUID,
1267 .ldif_read_fn = ldif_read_objectGUID,
1268 .ldif_write_fn = ldif_write_objectGUID,
1269 .canonicalise_fn = ldif_canonicalise_objectGUID,
1270 .comparison_fn = ldif_comparison_objectGUID,
1271 .operator_fn = samba_syntax_operator_fn
1273 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1274 .ldif_read_fn = ldb_handler_copy,
1275 .ldif_write_fn = ldb_handler_copy,
1276 .canonicalise_fn = ldif_canonicalise_objectCategory,
1277 .comparison_fn = ldif_comparison_objectCategory,
1278 .operator_fn = samba_syntax_operator_fn
1280 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1281 .ldif_read_fn = ldb_handler_copy,
1282 .ldif_write_fn = ldif_write_schemaInfo,
1283 .canonicalise_fn = ldb_handler_copy,
1284 .comparison_fn = ldb_comparison_binary,
1285 .operator_fn = samba_syntax_operator_fn
1287 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1288 .ldif_read_fn = ldif_read_prefixMap,
1289 .ldif_write_fn = ldif_write_prefixMap,
1290 .canonicalise_fn = ldif_canonicalise_prefixMap,
1291 .comparison_fn = ldif_comparison_prefixMap,
1292 .operator_fn = samba_syntax_operator_fn
1294 .name = LDB_SYNTAX_SAMBA_INT32,
1295 .ldif_read_fn = ldb_handler_copy,
1296 .ldif_write_fn = ldb_handler_copy,
1297 .canonicalise_fn = ldif_canonicalise_int32,
1298 .comparison_fn = ldif_comparison_int32,
1299 .operator_fn = samba_syntax_operator_fn
1301 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1302 .ldif_read_fn = ldb_handler_copy,
1303 .ldif_write_fn = ldif_write_repsFromTo,
1304 .canonicalise_fn = ldb_handler_copy,
1305 .comparison_fn = ldb_comparison_binary,
1306 .operator_fn = samba_syntax_operator_fn
1308 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1309 .ldif_read_fn = ldb_handler_copy,
1310 .ldif_write_fn = ldif_write_replPropertyMetaData,
1311 .canonicalise_fn = ldb_handler_copy,
1312 .comparison_fn = ldb_comparison_binary,
1313 .operator_fn = samba_syntax_operator_fn
1315 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1316 .ldif_read_fn = ldb_handler_copy,
1317 .ldif_write_fn = ldif_write_replUpToDateVector,
1318 .canonicalise_fn = ldb_handler_copy,
1319 .comparison_fn = ldb_comparison_binary,
1320 .operator_fn = samba_syntax_operator_fn
1322 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1323 .ldif_read_fn = ldb_handler_copy,
1324 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1325 .canonicalise_fn = ldb_handler_copy,
1326 .comparison_fn = ldb_comparison_binary,
1327 .operator_fn = samba_syntax_operator_fn
1329 .name = DSDB_SYNTAX_BINARY_DN,
1330 .ldif_read_fn = ldb_handler_copy,
1331 .ldif_write_fn = ldb_handler_copy,
1332 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1333 .comparison_fn = dsdb_dn_binary_comparison,
1334 .operator_fn = samba_syntax_operator_fn
1336 .name = DSDB_SYNTAX_STRING_DN,
1337 .ldif_read_fn = ldb_handler_copy,
1338 .ldif_write_fn = ldb_handler_copy,
1339 .canonicalise_fn = dsdb_dn_string_canonicalise,
1340 .comparison_fn = dsdb_dn_string_comparison,
1341 .operator_fn = samba_syntax_operator_fn
1343 .name = LDB_SYNTAX_DN,
1344 .ldif_read_fn = ldb_handler_copy,
1345 .ldif_write_fn = ldb_handler_copy,
1346 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1347 .comparison_fn = samba_ldb_dn_link_comparison,
1348 .operator_fn = samba_syntax_operator_dn
1350 .name = LDB_SYNTAX_SAMBA_RANGE64,
1351 .ldif_read_fn = ldif_read_range64,
1352 .ldif_write_fn = ldif_write_range64,
1353 .canonicalise_fn = ldif_canonicalise_int64,
1354 .comparison_fn = ldif_comparison_int64,
1355 .operator_fn = samba_syntax_operator_fn
1357 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1358 .ldif_read_fn = ldb_handler_copy,
1359 .ldif_write_fn = ldif_write_dnsRecord,
1360 .canonicalise_fn = ldb_handler_copy,
1361 .comparison_fn = ldb_comparison_binary,
1362 .operator_fn = samba_syntax_operator_fn
1364 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1365 .ldif_read_fn = ldb_handler_copy,
1366 .ldif_write_fn = ldif_write_dnsProperty,
1367 .canonicalise_fn = ldb_handler_copy,
1368 .comparison_fn = ldb_comparison_binary,
1369 .operator_fn = samba_syntax_operator_fn
1371 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1372 .ldif_read_fn = ldb_handler_copy,
1373 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1374 .canonicalise_fn = ldb_handler_copy,
1375 .comparison_fn = ldb_comparison_binary,
1376 .operator_fn = samba_syntax_operator_fn
1378 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1379 .ldif_read_fn = ldb_handler_copy,
1380 .ldif_write_fn = ldif_write_partialAttributeSet,
1381 .canonicalise_fn = ldb_handler_copy,
1382 .comparison_fn = ldb_comparison_binary,
1383 .operator_fn = samba_syntax_operator_fn
1387 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1389 .name = "SID",
1390 .read_fn = extended_dn_read_SID,
1391 .write_clear_fn = ldif_write_objectSid,
1392 .write_hex_fn = extended_dn_write_hex
1394 .name = "GUID",
1395 .read_fn = extended_dn_read_GUID,
1396 .write_clear_fn = ldif_write_objectGUID,
1397 .write_hex_fn = extended_dn_write_hex
1399 .name = "WKGUID",
1400 .read_fn = ldb_handler_copy,
1401 .write_clear_fn = ldb_handler_copy,
1402 .write_hex_fn = ldb_handler_copy
1404 .name = "RMD_INVOCID",
1405 .read_fn = extended_dn_read_GUID,
1406 .write_clear_fn = ldif_write_objectGUID,
1407 .write_hex_fn = extended_dn_write_hex
1409 .name = "RMD_FLAGS",
1410 .read_fn = ldb_handler_copy,
1411 .write_clear_fn = ldb_handler_copy,
1412 .write_hex_fn = ldb_handler_copy
1414 .name = "RMD_ADDTIME",
1415 .read_fn = ldb_handler_copy,
1416 .write_clear_fn = ldb_handler_copy,
1417 .write_hex_fn = ldb_handler_copy
1419 .name = "RMD_CHANGETIME",
1420 .read_fn = ldb_handler_copy,
1421 .write_clear_fn = ldb_handler_copy,
1422 .write_hex_fn = ldb_handler_copy
1424 .name = "RMD_LOCAL_USN",
1425 .read_fn = ldb_handler_copy,
1426 .write_clear_fn = ldb_handler_copy,
1427 .write_hex_fn = ldb_handler_copy
1429 .name = "RMD_ORIGINATING_USN",
1430 .read_fn = ldb_handler_copy,
1431 .write_clear_fn = ldb_handler_copy,
1432 .write_hex_fn = ldb_handler_copy
1434 .name = "RMD_VERSION",
1435 .read_fn = ldb_handler_copy,
1436 .write_clear_fn = ldb_handler_copy,
1437 .write_hex_fn = ldb_handler_copy
1441 /* TODO: Should be dynamic at some point */
1442 static const struct {
1443 const char *name;
1444 const char *syntax;
1445 } samba_attributes[] = {
1446 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1447 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1448 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1449 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1450 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1451 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1452 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1453 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1454 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1455 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1456 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1457 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1458 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1459 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1460 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1461 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1462 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1463 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1466 * these are extracted by searching
1467 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1469 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1470 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1471 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1472 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1473 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1474 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1475 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1476 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1477 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1478 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1479 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1480 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1481 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1482 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1483 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1484 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1485 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1486 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1487 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1488 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1489 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1490 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1491 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1492 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1495 * these are known to be GUIDs
1497 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1498 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1499 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1501 /* These NDR encoded things we want to be able to read with --show-binary */
1502 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1503 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1504 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1505 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1508 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1510 unsigned int j;
1511 const struct ldb_schema_syntax *s = NULL;
1513 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1514 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1515 s = &samba_syntaxes[j];
1516 break;
1519 return s;
1522 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1524 unsigned int j;
1525 const struct ldb_schema_syntax *s = NULL;
1527 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1528 if (strcmp(samba_attributes[j].name, name) == 0) {
1529 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1530 break;
1534 return s;
1538 register the samba ldif handlers
1540 int ldb_register_samba_handlers(struct ldb_context *ldb)
1542 unsigned int i;
1543 int ret;
1545 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1546 return LDB_SUCCESS;
1549 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1550 const struct ldb_schema_syntax *s = NULL;
1552 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1554 if (!s) {
1555 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1558 if (!s) {
1559 return LDB_ERR_OPERATIONS_ERROR;
1562 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1563 if (ret != LDB_SUCCESS) {
1564 return ret;
1568 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1569 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1570 if (ret != LDB_SUCCESS) {
1571 return ret;
1576 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1577 if (ret != LDB_SUCCESS) {
1578 return ret;
1581 return LDB_SUCCESS;