build: Fix quota tests, including move of sysquotas.c to the top level
[Samba/bjacke.git] / lib / ldb-samba / ldif_handlers.c
blobc7385f654a850e31fa9f5f9155e56e2ff63ff09d
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(mem_ctx, ldb,
487 sclass->defaultObjectCategory);
488 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
489 talloc_free(tmp_ctx);
491 if (!out->data) {
492 return LDB_ERR_OPERATIONS_ERROR;
494 return LDB_SUCCESS;
495 } else {
496 *out = data_blob_talloc(mem_ctx, in->data, in->length);
497 talloc_free(tmp_ctx);
499 if (in->data && !out->data) {
500 return LDB_ERR_OPERATIONS_ERROR;
502 return LDB_SUCCESS;
505 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
506 talloc_free(tmp_ctx);
508 if (!out->data) {
509 return LDB_ERR_OPERATIONS_ERROR;
511 return LDB_SUCCESS;
514 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
515 const struct ldb_val *v1,
516 const struct ldb_val *v2)
518 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
519 v1, v2);
523 convert a NDR formatted blob to a ldif formatted schemaInfo
525 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
526 const struct ldb_val *in, struct ldb_val *out)
528 return ldif_write_NDR(ldb, mem_ctx, in, out,
529 sizeof(struct repsFromToBlob),
530 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
531 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
532 true);
536 convert a ldif formatted prefixMap to a NDR formatted blob
538 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
539 const struct ldb_val *in, struct ldb_val *out)
541 struct prefixMapBlob *blob;
542 enum ndr_err_code ndr_err;
543 char *string, *line, *p, *oid;
544 DATA_BLOB oid_blob;
546 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
548 if (tmp_ctx == NULL) {
549 return -1;
552 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
553 if (blob == NULL) {
554 talloc_free(tmp_ctx);
555 return -1;
558 /* use the switch value to detect if this is in the binary
559 * format
561 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
562 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
563 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
564 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
565 ndr_err = ndr_push_struct_blob(out, mem_ctx,
566 blob,
567 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
568 talloc_free(tmp_ctx);
569 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
570 return -1;
572 return 0;
576 /* If this does not parse, then it is probably the text version, and we should try it that way */
577 blob->version = PREFIX_MAP_VERSION_DSDB;
579 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
580 if (string == NULL) {
581 talloc_free(blob);
582 return -1;
585 line = string;
586 while (line && line[0]) {
587 p=strchr(line, ';');
588 if (p) {
589 p[0] = '\0';
590 } else {
591 p=strchr(line, '\n');
592 if (p) {
593 p[0] = '\0';
596 /* allow a trailing separator */
597 if (line == p) {
598 break;
601 blob->ctr.dsdb.mappings = talloc_realloc(blob,
602 blob->ctr.dsdb.mappings,
603 struct drsuapi_DsReplicaOIDMapping,
604 blob->ctr.dsdb.num_mappings+1);
605 if (!blob->ctr.dsdb.mappings) {
606 talloc_free(tmp_ctx);
607 return -1;
610 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
612 if (oid[0] != ':') {
613 talloc_free(tmp_ctx);
614 return -1;
617 /* we know there must be at least ":" */
618 oid++;
620 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
621 talloc_free(tmp_ctx);
622 return -1;
624 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
625 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
627 blob->ctr.dsdb.num_mappings++;
629 /* Now look past the terminator we added above */
630 if (p) {
631 line = p + 1;
632 } else {
633 line = NULL;
637 ndr_err = ndr_push_struct_blob(out, mem_ctx,
638 blob,
639 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
640 talloc_free(tmp_ctx);
641 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
642 return -1;
644 return 0;
648 convert a NDR formatted blob to a ldif formatted prefixMap
650 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
651 const struct ldb_val *in, struct ldb_val *out)
653 struct prefixMapBlob *blob;
654 enum ndr_err_code ndr_err;
655 char *string;
656 uint32_t i;
658 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
659 int err;
660 /* try to decode the blob as S4 prefixMap */
661 err = ldif_write_NDR(ldb, mem_ctx, in, out,
662 sizeof(struct prefixMapBlob),
663 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
664 (ndr_print_fn_t)ndr_print_prefixMapBlob,
665 false);
666 if (0 == err) {
667 return err;
669 /* try parsing it as Windows PrefixMap value */
670 return ldif_write_NDR(ldb, mem_ctx, in, out,
671 sizeof(struct drsuapi_MSPrefixMap_Ctr),
672 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
673 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
674 true);
677 blob = talloc(mem_ctx, struct prefixMapBlob);
678 if (blob == NULL) {
679 return -1;
681 ndr_err = ndr_pull_struct_blob_all(in, blob,
682 blob,
683 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
684 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
685 goto failed;
687 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
688 goto failed;
690 string = talloc_strdup(mem_ctx, "");
691 if (string == NULL) {
692 goto failed;
695 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
696 DATA_BLOB oid_blob;
697 char *partial_oid = NULL;
699 if (i > 0) {
700 string = talloc_asprintf_append(string, ";");
703 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
704 blob->ctr.dsdb.mappings[i].oid.length);
705 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
706 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
707 blob->ctr.dsdb.mappings[i].id_prefix));
708 goto failed;
710 string = talloc_asprintf_append(string, "%u:%s",
711 blob->ctr.dsdb.mappings[i].id_prefix,
712 partial_oid);
713 talloc_free(discard_const(partial_oid));
714 if (string == NULL) {
715 goto failed;
719 talloc_free(blob);
720 *out = data_blob_string_const(string);
721 return 0;
723 failed:
724 talloc_free(blob);
725 return -1;
728 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
730 if (v->length < 4) {
731 return true;
734 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
735 return false;
738 return true;
742 canonicalise a prefixMap
744 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
745 const struct ldb_val *in, struct ldb_val *out)
747 if (ldif_comparision_prefixMap_isString(in)) {
748 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
750 return ldb_handler_copy(ldb, mem_ctx, in, out);
753 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
754 const struct ldb_val *v1,
755 const struct ldb_val *v2)
757 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
758 v1, v2);
761 /* length limited conversion of a ldb_val to a int32_t */
762 static int val_to_int32(const struct ldb_val *in, int32_t *v)
764 char *end;
765 char buf[64];
767 /* make sure we don't read past the end of the data */
768 if (in->length > sizeof(buf)-1) {
769 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
771 strncpy(buf, (char *)in->data, in->length);
772 buf[in->length] = 0;
774 /* We've to use "strtoll" here to have the intended overflows.
775 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
776 *v = (int32_t) strtoll(buf, &end, 0);
777 if (*end != 0) {
778 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
780 return LDB_SUCCESS;
783 /* length limited conversion of a ldb_val to a int64_t */
784 static int val_to_int64(const struct ldb_val *in, int64_t *v)
786 char *end;
787 char buf[64];
789 /* make sure we don't read past the end of the data */
790 if (in->length > sizeof(buf)-1) {
791 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
793 strncpy(buf, (char *)in->data, in->length);
794 buf[in->length] = 0;
796 *v = (int64_t) strtoll(buf, &end, 0);
797 if (*end != 0) {
798 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
800 return LDB_SUCCESS;
803 /* Canonicalisation of two 32-bit integers */
804 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
805 const struct ldb_val *in, struct ldb_val *out)
807 int32_t i;
808 int ret;
810 ret = val_to_int32(in, &i);
811 if (ret != LDB_SUCCESS) {
812 return ret;
814 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
815 if (out->data == NULL) {
816 ldb_oom(ldb);
817 return LDB_ERR_OPERATIONS_ERROR;
819 out->length = strlen((char *)out->data);
820 return 0;
823 /* Comparison of two 32-bit integers */
824 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
825 const struct ldb_val *v1, const struct ldb_val *v2)
827 int32_t i1=0, i2=0;
828 val_to_int32(v1, &i1);
829 val_to_int32(v2, &i2);
830 if (i1 == i2) return 0;
831 return i1 > i2? 1 : -1;
834 /* Canonicalisation of two 64-bit integers */
835 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
836 const struct ldb_val *in, struct ldb_val *out)
838 int64_t i;
839 int ret;
841 ret = val_to_int64(in, &i);
842 if (ret != LDB_SUCCESS) {
843 return ret;
845 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
846 if (out->data == NULL) {
847 ldb_oom(ldb);
848 return LDB_ERR_OPERATIONS_ERROR;
850 out->length = strlen((char *)out->data);
851 return 0;
854 /* Comparison of two 64-bit integers */
855 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
856 const struct ldb_val *v1, const struct ldb_val *v2)
858 int64_t i1=0, i2=0;
859 val_to_int64(v1, &i1);
860 val_to_int64(v2, &i2);
861 if (i1 == i2) return 0;
862 return i1 > i2? 1 : -1;
866 convert a NDR formatted blob to a ldif formatted repsFromTo
868 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
869 const struct ldb_val *in, struct ldb_val *out)
871 return ldif_write_NDR(ldb, mem_ctx, in, out,
872 sizeof(struct repsFromToBlob),
873 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
874 (ndr_print_fn_t)ndr_print_repsFromToBlob,
875 true);
879 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
881 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
882 const struct ldb_val *in, struct ldb_val *out)
884 return ldif_write_NDR(ldb, mem_ctx, in, out,
885 sizeof(struct replPropertyMetaDataBlob),
886 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
887 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
888 true);
892 convert a NDR formatted blob to a ldif formatted replUpToDateVector
894 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
895 const struct ldb_val *in, struct ldb_val *out)
897 return ldif_write_NDR(ldb, mem_ctx, in, out,
898 sizeof(struct replUpToDateVectorBlob),
899 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
900 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
901 true);
906 convert a NDR formatted blob to a ldif formatted dnsRecord
908 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
909 const struct ldb_val *in, struct ldb_val *out)
911 return ldif_write_NDR(ldb, mem_ctx, in, out,
912 sizeof(struct dnsp_DnssrvRpcRecord),
913 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
914 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
915 true);
919 convert a NDR formatted blob to a ldif formatted dnsProperty
921 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
922 const struct ldb_val *in, struct ldb_val *out)
924 return ldif_write_NDR(ldb, mem_ctx, in, out,
925 sizeof(struct dnsp_DnsProperty),
926 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
927 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
928 true);
932 convert a NDR formatted blob of a supplementalCredentials into text
934 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
935 const struct ldb_val *in, struct ldb_val *out)
937 return ldif_write_NDR(ldb, mem_ctx, in, out,
938 sizeof(struct supplementalCredentialsBlob),
939 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
940 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
941 true);
945 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
947 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
948 const struct ldb_val *in, struct ldb_val *out)
950 return ldif_write_NDR(ldb, mem_ctx, in, out,
951 sizeof(struct trustAuthInOutBlob),
952 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
953 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
954 true);
958 convert a NDR formatted blob of a partialAttributeSet into text
960 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
961 const struct ldb_val *in, struct ldb_val *out)
963 return ldif_write_NDR(ldb, mem_ctx, in, out,
964 sizeof(struct partialAttributeSetBlob),
965 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
966 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
967 true);
971 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
972 const struct ldb_val *in, struct ldb_val *out)
974 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
975 if (!out->data) {
976 return -1;
978 return 0;
982 compare two dns
984 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
985 const struct ldb_val *v1, const struct ldb_val *v2)
987 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
988 int ret;
990 if (dsdb_dn_is_deleted_val(v1)) {
991 /* If the DN is deleted, then we can't search for it */
992 return -1;
995 if (dsdb_dn_is_deleted_val(v2)) {
996 /* If the DN is deleted, then we can't search for it */
997 return -1;
1000 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1001 if ( ! ldb_dn_validate(dn1)) return -1;
1003 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1004 if ( ! ldb_dn_validate(dn2)) {
1005 talloc_free(dn1);
1006 return -1;
1009 ret = ldb_dn_compare(dn1, dn2);
1011 talloc_free(dn1);
1012 talloc_free(dn2);
1013 return ret;
1016 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1017 const struct ldb_val *in, struct ldb_val *out)
1019 struct ldb_dn *dn;
1020 int ret = -1;
1022 out->length = 0;
1023 out->data = NULL;
1025 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1026 if ( ! ldb_dn_validate(dn)) {
1027 return LDB_ERR_INVALID_DN_SYNTAX;
1030 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1031 * does not casually match a not deleted DN */
1032 if (dsdb_dn_is_deleted_val(in)) {
1033 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1034 "<RMD_FLAGS=%u>%s",
1035 dsdb_dn_val_rmd_flags(in),
1036 ldb_dn_get_casefold(dn));
1037 } else {
1038 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1041 if (out->data == NULL) {
1042 goto done;
1044 out->length = strlen((char *)out->data);
1046 ret = 0;
1048 done:
1049 talloc_free(dn);
1051 return ret;
1056 write a 64 bit 2-part range
1058 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1059 const struct ldb_val *in, struct ldb_val *out)
1061 int64_t v;
1062 int ret;
1063 ret = val_to_int64(in, &v);
1064 if (ret != LDB_SUCCESS) {
1065 return ret;
1067 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1068 (unsigned long)(v&0xFFFFFFFF),
1069 (unsigned long)(v>>32));
1070 if (out->data == NULL) {
1071 ldb_oom(ldb);
1072 return LDB_ERR_OPERATIONS_ERROR;
1074 out->length = strlen((char *)out->data);
1075 return LDB_SUCCESS;
1079 read a 64 bit 2-part range
1081 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1082 const struct ldb_val *in, struct ldb_val *out)
1084 unsigned long high, low;
1085 char buf[64];
1087 if (memchr(in->data, '-', in->length) == NULL) {
1088 return ldb_handler_copy(ldb, mem_ctx, in, out);
1091 if (in->length > sizeof(buf)-1) {
1092 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1094 strncpy(buf, (const char *)in->data, in->length);
1095 buf[in->length] = 0;
1097 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1098 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1101 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1102 (unsigned long long)(((uint64_t)high)<<32) | (low));
1104 if (out->data == NULL) {
1105 ldb_oom(ldb);
1106 return LDB_ERR_OPERATIONS_ERROR;
1108 out->length = strlen((char *)out->data);
1109 return LDB_SUCCESS;
1113 when this operator_fn is set for a syntax, the backend calls is in
1114 preference to the comparison function. We are told the exact
1115 comparison operation that is needed, and we can return errors
1117 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1118 const struct ldb_schema_attribute *a,
1119 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1121 switch (operation) {
1122 case LDB_OP_AND:
1123 case LDB_OP_OR:
1124 case LDB_OP_NOT:
1125 case LDB_OP_SUBSTRING:
1126 case LDB_OP_APPROX:
1127 case LDB_OP_EXTENDED:
1128 /* handled in the backends */
1129 return LDB_ERR_INAPPROPRIATE_MATCHING;
1131 case LDB_OP_GREATER:
1132 case LDB_OP_LESS:
1133 case LDB_OP_EQUALITY:
1135 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1136 int ret;
1137 if (tmp_ctx == NULL) {
1138 return ldb_oom(ldb);
1140 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1141 talloc_free(tmp_ctx);
1142 if (operation == LDB_OP_GREATER) {
1143 *matched = (ret >= 0);
1144 } else if (operation == LDB_OP_LESS) {
1145 *matched = (ret <= 0);
1146 } else {
1147 *matched = (ret == 0);
1149 return LDB_SUCCESS;
1152 case LDB_OP_PRESENT:
1153 *matched = true;
1154 return LDB_SUCCESS;
1157 /* we shouldn't get here */
1158 return LDB_ERR_INAPPROPRIATE_MATCHING;
1162 see if two DNs match, comparing first by GUID, then by SID, and
1163 finally by string components
1165 static int samba_dn_extended_match(struct ldb_context *ldb,
1166 const struct ldb_val *v1,
1167 const struct ldb_val *v2,
1168 bool *matched)
1170 TALLOC_CTX *tmp_ctx;
1171 struct ldb_dn *dn1, *dn2;
1172 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1173 uint32_t rmd_flags1, rmd_flags2;
1175 tmp_ctx = talloc_new(ldb);
1177 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1178 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1179 if (!dn1 || !dn2) {
1180 /* couldn't parse as DN's */
1181 talloc_free(tmp_ctx);
1182 (*matched) = false;
1183 return LDB_SUCCESS;
1186 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1187 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1189 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1190 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1191 /* only match if they have the same deletion status */
1192 talloc_free(tmp_ctx);
1193 (*matched) = false;
1194 return LDB_SUCCESS;
1198 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1199 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1200 if (guid1 && guid2) {
1201 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1202 talloc_free(tmp_ctx);
1203 return LDB_SUCCESS;
1206 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1207 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1208 if (sid1 && sid2) {
1209 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1210 talloc_free(tmp_ctx);
1211 return LDB_SUCCESS;
1214 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1216 talloc_free(tmp_ctx);
1217 return LDB_SUCCESS;
1221 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1223 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1224 const struct ldb_schema_attribute *a,
1225 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1227 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1228 /* If the DN is deleted, then we can't search for it */
1230 /* should this be for equality too? */
1231 *matched = false;
1232 return LDB_SUCCESS;
1235 if (operation == LDB_OP_EQUALITY &&
1236 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1237 return LDB_SUCCESS;
1240 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1244 static const struct ldb_schema_syntax samba_syntaxes[] = {
1246 .name = LDB_SYNTAX_SAMBA_SID,
1247 .ldif_read_fn = ldif_read_objectSid,
1248 .ldif_write_fn = ldif_write_objectSid,
1249 .canonicalise_fn = ldif_canonicalise_objectSid,
1250 .comparison_fn = ldif_comparison_objectSid,
1251 .operator_fn = samba_syntax_operator_fn
1253 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1254 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1255 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1256 .canonicalise_fn = ldb_handler_copy,
1257 .comparison_fn = ldb_comparison_binary,
1258 .operator_fn = samba_syntax_operator_fn
1260 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1261 .ldif_read_fn = ldb_handler_copy,
1262 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1263 .canonicalise_fn = ldb_handler_fold,
1264 .comparison_fn = ldb_comparison_fold,
1265 .operator_fn = samba_syntax_operator_fn
1267 .name = LDB_SYNTAX_SAMBA_GUID,
1268 .ldif_read_fn = ldif_read_objectGUID,
1269 .ldif_write_fn = ldif_write_objectGUID,
1270 .canonicalise_fn = ldif_canonicalise_objectGUID,
1271 .comparison_fn = ldif_comparison_objectGUID,
1272 .operator_fn = samba_syntax_operator_fn
1274 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1275 .ldif_read_fn = ldb_handler_copy,
1276 .ldif_write_fn = ldb_handler_copy,
1277 .canonicalise_fn = ldif_canonicalise_objectCategory,
1278 .comparison_fn = ldif_comparison_objectCategory,
1279 .operator_fn = samba_syntax_operator_fn
1281 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1282 .ldif_read_fn = ldb_handler_copy,
1283 .ldif_write_fn = ldif_write_schemaInfo,
1284 .canonicalise_fn = ldb_handler_copy,
1285 .comparison_fn = ldb_comparison_binary,
1286 .operator_fn = samba_syntax_operator_fn
1288 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1289 .ldif_read_fn = ldif_read_prefixMap,
1290 .ldif_write_fn = ldif_write_prefixMap,
1291 .canonicalise_fn = ldif_canonicalise_prefixMap,
1292 .comparison_fn = ldif_comparison_prefixMap,
1293 .operator_fn = samba_syntax_operator_fn
1295 .name = LDB_SYNTAX_SAMBA_INT32,
1296 .ldif_read_fn = ldb_handler_copy,
1297 .ldif_write_fn = ldb_handler_copy,
1298 .canonicalise_fn = ldif_canonicalise_int32,
1299 .comparison_fn = ldif_comparison_int32,
1300 .operator_fn = samba_syntax_operator_fn
1302 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1303 .ldif_read_fn = ldb_handler_copy,
1304 .ldif_write_fn = ldif_write_repsFromTo,
1305 .canonicalise_fn = ldb_handler_copy,
1306 .comparison_fn = ldb_comparison_binary,
1307 .operator_fn = samba_syntax_operator_fn
1309 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1310 .ldif_read_fn = ldb_handler_copy,
1311 .ldif_write_fn = ldif_write_replPropertyMetaData,
1312 .canonicalise_fn = ldb_handler_copy,
1313 .comparison_fn = ldb_comparison_binary,
1314 .operator_fn = samba_syntax_operator_fn
1316 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1317 .ldif_read_fn = ldb_handler_copy,
1318 .ldif_write_fn = ldif_write_replUpToDateVector,
1319 .canonicalise_fn = ldb_handler_copy,
1320 .comparison_fn = ldb_comparison_binary,
1321 .operator_fn = samba_syntax_operator_fn
1323 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1324 .ldif_read_fn = ldb_handler_copy,
1325 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1326 .canonicalise_fn = ldb_handler_copy,
1327 .comparison_fn = ldb_comparison_binary,
1328 .operator_fn = samba_syntax_operator_fn
1330 .name = DSDB_SYNTAX_BINARY_DN,
1331 .ldif_read_fn = ldb_handler_copy,
1332 .ldif_write_fn = ldb_handler_copy,
1333 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1334 .comparison_fn = dsdb_dn_binary_comparison,
1335 .operator_fn = samba_syntax_operator_fn
1337 .name = DSDB_SYNTAX_STRING_DN,
1338 .ldif_read_fn = ldb_handler_copy,
1339 .ldif_write_fn = ldb_handler_copy,
1340 .canonicalise_fn = dsdb_dn_string_canonicalise,
1341 .comparison_fn = dsdb_dn_string_comparison,
1342 .operator_fn = samba_syntax_operator_fn
1344 .name = LDB_SYNTAX_DN,
1345 .ldif_read_fn = ldb_handler_copy,
1346 .ldif_write_fn = ldb_handler_copy,
1347 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1348 .comparison_fn = samba_ldb_dn_link_comparison,
1349 .operator_fn = samba_syntax_operator_dn
1351 .name = LDB_SYNTAX_SAMBA_RANGE64,
1352 .ldif_read_fn = ldif_read_range64,
1353 .ldif_write_fn = ldif_write_range64,
1354 .canonicalise_fn = ldif_canonicalise_int64,
1355 .comparison_fn = ldif_comparison_int64,
1356 .operator_fn = samba_syntax_operator_fn
1358 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1359 .ldif_read_fn = ldb_handler_copy,
1360 .ldif_write_fn = ldif_write_dnsRecord,
1361 .canonicalise_fn = ldb_handler_copy,
1362 .comparison_fn = ldb_comparison_binary,
1363 .operator_fn = samba_syntax_operator_fn
1365 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1366 .ldif_read_fn = ldb_handler_copy,
1367 .ldif_write_fn = ldif_write_dnsProperty,
1368 .canonicalise_fn = ldb_handler_copy,
1369 .comparison_fn = ldb_comparison_binary,
1370 .operator_fn = samba_syntax_operator_fn
1372 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1373 .ldif_read_fn = ldb_handler_copy,
1374 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1375 .canonicalise_fn = ldb_handler_copy,
1376 .comparison_fn = ldb_comparison_binary,
1377 .operator_fn = samba_syntax_operator_fn
1379 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1380 .ldif_read_fn = ldb_handler_copy,
1381 .ldif_write_fn = ldif_write_partialAttributeSet,
1382 .canonicalise_fn = ldb_handler_copy,
1383 .comparison_fn = ldb_comparison_binary,
1384 .operator_fn = samba_syntax_operator_fn
1388 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1390 .name = "SID",
1391 .read_fn = extended_dn_read_SID,
1392 .write_clear_fn = ldif_write_objectSid,
1393 .write_hex_fn = extended_dn_write_hex
1395 .name = "GUID",
1396 .read_fn = extended_dn_read_GUID,
1397 .write_clear_fn = ldif_write_objectGUID,
1398 .write_hex_fn = extended_dn_write_hex
1400 .name = "WKGUID",
1401 .read_fn = ldb_handler_copy,
1402 .write_clear_fn = ldb_handler_copy,
1403 .write_hex_fn = ldb_handler_copy
1405 .name = "RMD_INVOCID",
1406 .read_fn = extended_dn_read_GUID,
1407 .write_clear_fn = ldif_write_objectGUID,
1408 .write_hex_fn = extended_dn_write_hex
1410 .name = "RMD_FLAGS",
1411 .read_fn = ldb_handler_copy,
1412 .write_clear_fn = ldb_handler_copy,
1413 .write_hex_fn = ldb_handler_copy
1415 .name = "RMD_ADDTIME",
1416 .read_fn = ldb_handler_copy,
1417 .write_clear_fn = ldb_handler_copy,
1418 .write_hex_fn = ldb_handler_copy
1420 .name = "RMD_CHANGETIME",
1421 .read_fn = ldb_handler_copy,
1422 .write_clear_fn = ldb_handler_copy,
1423 .write_hex_fn = ldb_handler_copy
1425 .name = "RMD_LOCAL_USN",
1426 .read_fn = ldb_handler_copy,
1427 .write_clear_fn = ldb_handler_copy,
1428 .write_hex_fn = ldb_handler_copy
1430 .name = "RMD_ORIGINATING_USN",
1431 .read_fn = ldb_handler_copy,
1432 .write_clear_fn = ldb_handler_copy,
1433 .write_hex_fn = ldb_handler_copy
1435 .name = "RMD_VERSION",
1436 .read_fn = ldb_handler_copy,
1437 .write_clear_fn = ldb_handler_copy,
1438 .write_hex_fn = ldb_handler_copy
1442 /* TODO: Should be dynamic at some point */
1443 static const struct {
1444 const char *name;
1445 const char *syntax;
1446 } samba_attributes[] = {
1447 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1448 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1449 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1450 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1451 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1452 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1453 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1454 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1455 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1456 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1457 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1458 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1459 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1460 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1461 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1462 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1463 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1464 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1467 * these are extracted by searching
1468 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1470 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1471 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1472 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1473 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1474 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1475 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1476 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1477 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1478 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1479 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1480 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1481 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1482 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1483 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1484 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1485 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1486 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1487 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1488 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1489 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1490 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1491 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1492 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1493 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1496 * these are known to be GUIDs
1498 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1499 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1500 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1502 /* These NDR encoded things we want to be able to read with --show-binary */
1503 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1504 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1505 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1506 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1509 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1511 unsigned int j;
1512 const struct ldb_schema_syntax *s = NULL;
1514 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1515 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1516 s = &samba_syntaxes[j];
1517 break;
1520 return s;
1523 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1525 unsigned int j;
1526 const struct ldb_schema_syntax *s = NULL;
1528 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1529 if (strcmp(samba_attributes[j].name, name) == 0) {
1530 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1531 break;
1535 return s;
1538 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, NULL};
1541 register the samba ldif handlers
1543 int ldb_register_samba_handlers(struct ldb_context *ldb)
1545 unsigned int i;
1546 int ret;
1548 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1549 return LDB_SUCCESS;
1552 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1553 if (ret != LDB_SUCCESS) {
1554 return ret;
1557 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1558 const struct ldb_schema_syntax *s = NULL;
1560 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1562 if (!s) {
1563 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1566 if (!s) {
1567 return LDB_ERR_OPERATIONS_ERROR;
1570 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1571 if (ret != LDB_SUCCESS) {
1572 return ret;
1576 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1577 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1578 if (ret != LDB_SUCCESS) {
1579 return ret;
1584 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1585 if (ret != LDB_SUCCESS) {
1586 return ret;
1589 return LDB_SUCCESS;