lib/ldb-samba: We can confirm a GUID is a GUID by length
[Samba.git] / lib / ldb-samba / ldif_handlers.c
blobc0972a4a6a75ade4fe0d97c0984e5c4b77233e60
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 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
113 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
114 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
115 return -1;
117 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
118 if (out->data == NULL) {
119 return -1;
121 return 0;
124 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
126 if (v->length < 3) {
127 return false;
130 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
132 return true;
136 compare two objectSids
138 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
139 const struct ldb_val *v1, const struct ldb_val *v2)
141 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
142 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
143 } else if (ldif_comparision_objectSid_isString(v1)
144 && !ldif_comparision_objectSid_isString(v2)) {
145 struct ldb_val v;
146 int ret;
147 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
148 /* Perhaps not a string after all */
149 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
151 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
152 talloc_free(v.data);
153 return ret;
154 } else if (!ldif_comparision_objectSid_isString(v1)
155 && ldif_comparision_objectSid_isString(v2)) {
156 struct ldb_val v;
157 int ret;
158 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
159 /* Perhaps not a string after all */
160 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
162 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
163 talloc_free(v.data);
164 return ret;
166 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
170 canonicalise a objectSid
172 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
173 const struct ldb_val *in, struct ldb_val *out)
175 if (ldif_comparision_objectSid_isString(in)) {
176 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
177 /* Perhaps not a string after all */
178 return ldb_handler_copy(ldb, mem_ctx, in, out);
180 return 0;
182 return ldb_handler_copy(ldb, mem_ctx, in, out);
185 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
186 const struct ldb_val *in, struct ldb_val *out)
188 struct dom_sid sid;
189 enum ndr_err_code ndr_err;
190 if (ldif_comparision_objectSid_isString(in)) {
191 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
192 return 0;
196 /* Perhaps not a string after all */
197 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
199 if (!out->data) {
200 return -1;
203 (*out).length = strhex_to_str((char *)out->data, out->length,
204 (const char *)in->data, in->length);
206 /* Check it looks like a SID */
207 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
208 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
209 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
210 return -1;
212 return 0;
216 convert a ldif formatted objectGUID to a NDR formatted blob
218 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
219 const struct ldb_val *in, struct ldb_val *out)
221 struct GUID guid;
222 NTSTATUS status;
224 status = GUID_from_data_blob(in, &guid);
225 if (!NT_STATUS_IS_OK(status)) {
226 return -1;
229 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
230 if (!NT_STATUS_IS_OK(status)) {
231 return -1;
233 return 0;
237 convert a NDR formatted blob to a ldif formatted objectGUID
239 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
240 const struct ldb_val *in, struct ldb_val *out)
242 struct GUID guid;
243 NTSTATUS status;
245 status = GUID_from_ndr_blob(in, &guid);
246 if (!NT_STATUS_IS_OK(status)) {
247 return -1;
249 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
250 if (out->data == NULL) {
251 return -1;
253 out->length = strlen((const char *)out->data);
254 return 0;
257 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
259 if (v->length != 36 && v->length != 38) return false;
261 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
262 return true;
265 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
266 const struct ldb_val *in, struct ldb_val *out)
269 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
270 return 0;
273 /* Try as 'hex' form */
274 if (in->length != 32) {
275 return -1;
278 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
280 if (!out->data) {
281 return -1;
284 (*out).length = strhex_to_str((char *)out->data, out->length,
285 (const char *)in->data, in->length);
287 /* Check it looks like a GUID */
288 if ((*out).length != 16) {
289 data_blob_free(out);
290 return -1;
293 return 0;
297 compare two objectGUIDs
299 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
300 const struct ldb_val *v1, const struct ldb_val *v2)
302 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
303 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
304 } else if (ldif_comparision_objectGUID_isString(v1)
305 && !ldif_comparision_objectGUID_isString(v2)) {
306 struct ldb_val v;
307 int ret;
308 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
309 /* Perhaps it wasn't a valid string after all */
310 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
312 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
313 talloc_free(v.data);
314 return ret;
315 } else if (!ldif_comparision_objectGUID_isString(v1)
316 && ldif_comparision_objectGUID_isString(v2)) {
317 struct ldb_val v;
318 int ret;
319 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
320 /* Perhaps it wasn't a valid string after all */
321 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
323 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
324 talloc_free(v.data);
325 return ret;
327 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
331 canonicalise a objectGUID
333 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
334 const struct ldb_val *in, struct ldb_val *out)
336 if (ldif_comparision_objectGUID_isString(in)) {
337 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
338 /* Perhaps it wasn't a valid string after all */
339 return ldb_handler_copy(ldb, mem_ctx, in, out);
341 return 0;
343 return ldb_handler_copy(ldb, mem_ctx, in, out);
348 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
350 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
351 const struct ldb_val *in, struct ldb_val *out)
353 struct security_descriptor *sd;
354 enum ndr_err_code ndr_err;
356 sd = talloc(mem_ctx, struct security_descriptor);
357 if (sd == NULL) {
358 return -1;
361 ndr_err = ndr_pull_struct_blob(in, sd, sd,
362 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
363 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
364 /* If this does not parse, then it is probably SDDL, and we should try it that way */
366 const struct dom_sid *sid = samdb_domain_sid(ldb);
367 talloc_free(sd);
368 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
369 if (sd == NULL) {
370 return -1;
374 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
375 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
376 talloc_free(sd);
377 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
378 return -1;
381 return 0;
385 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
387 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
388 const struct ldb_val *in, struct ldb_val *out)
390 struct security_descriptor *sd;
391 enum ndr_err_code ndr_err;
393 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
394 return ldif_write_NDR(ldb, mem_ctx, in, out,
395 sizeof(struct security_descriptor),
396 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
397 (ndr_print_fn_t)ndr_print_security_descriptor,
398 true);
402 sd = talloc(mem_ctx, struct security_descriptor);
403 if (sd == NULL) {
404 return -1;
406 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
407 ndr_err = ndr_pull_struct_blob(in, sd, sd,
408 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
409 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
410 talloc_free(sd);
411 return -1;
413 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
414 talloc_free(sd);
415 if (out->data == NULL) {
416 return -1;
418 out->length = strlen((const char *)out->data);
419 return 0;
423 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
425 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
426 const struct ldb_val *in, struct ldb_val *out)
428 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
429 struct security_descriptor *sd;
430 const struct dom_sid *sid = samdb_domain_sid(ldb);
432 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
433 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
434 (ndr_print_fn_t)ndr_print_security_descriptor,
435 "SDDL", sd);
436 out->length = strlen((const char *)out->data);
437 talloc_free(sd);
438 return 0;
441 return ldb_handler_copy(ldb, mem_ctx, in, out);
445 canonicalise an objectCategory. We use the long form as the canonical form:
446 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
448 Also any short name of an objectClass that points to a different
449 class (such as user) has the canonical form of the class it's
450 defaultObjectCategory points to (eg
451 cn=Person,cn=Schema,cn=Configuration,<basedn>)
454 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
455 const struct ldb_val *in, struct ldb_val *out)
457 struct ldb_dn *dn1 = NULL;
458 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
459 const struct dsdb_class *sclass;
460 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
461 if (!tmp_ctx) {
462 return LDB_ERR_OPERATIONS_ERROR;
465 if (!schema) {
466 talloc_free(tmp_ctx);
467 *out = data_blob_talloc(mem_ctx, in->data, in->length);
468 if (in->data && !out->data) {
469 return LDB_ERR_OPERATIONS_ERROR;
471 return LDB_SUCCESS;
473 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
474 if ( ! ldb_dn_validate(dn1)) {
475 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
476 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
477 if (sclass) {
478 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
479 sclass->defaultObjectCategory);
480 if (dn == NULL) {
481 talloc_free(tmp_ctx);
482 return LDB_ERR_OPERATIONS_ERROR;
485 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
486 talloc_free(tmp_ctx);
488 if (!out->data) {
489 return LDB_ERR_OPERATIONS_ERROR;
491 return LDB_SUCCESS;
492 } else {
493 *out = data_blob_talloc(mem_ctx, in->data, in->length);
494 talloc_free(tmp_ctx);
496 if (in->data && !out->data) {
497 return LDB_ERR_OPERATIONS_ERROR;
499 return LDB_SUCCESS;
502 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
503 talloc_free(tmp_ctx);
505 if (!out->data) {
506 return LDB_ERR_OPERATIONS_ERROR;
508 return LDB_SUCCESS;
511 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
512 const struct ldb_val *v1,
513 const struct ldb_val *v2)
515 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
516 v1, v2);
520 convert a NDR formatted blob to a ldif formatted schemaInfo
522 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
523 const struct ldb_val *in, struct ldb_val *out)
525 return ldif_write_NDR(ldb, mem_ctx, in, out,
526 sizeof(struct repsFromToBlob),
527 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
528 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
529 true);
533 convert a ldif formatted prefixMap to a NDR formatted blob
535 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
536 const struct ldb_val *in, struct ldb_val *out)
538 struct prefixMapBlob *blob;
539 enum ndr_err_code ndr_err;
540 char *string, *line, *p, *oid;
541 DATA_BLOB oid_blob;
543 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
545 if (tmp_ctx == NULL) {
546 return -1;
549 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
550 if (blob == NULL) {
551 talloc_free(tmp_ctx);
552 return -1;
555 /* use the switch value to detect if this is in the binary
556 * format
558 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
559 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
560 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
561 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
562 ndr_err = ndr_push_struct_blob(out, mem_ctx,
563 blob,
564 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
565 talloc_free(tmp_ctx);
566 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
567 return -1;
569 return 0;
573 /* If this does not parse, then it is probably the text version, and we should try it that way */
574 blob->version = PREFIX_MAP_VERSION_DSDB;
576 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
577 if (string == NULL) {
578 talloc_free(blob);
579 return -1;
582 line = string;
583 while (line && line[0]) {
584 p=strchr(line, ';');
585 if (p) {
586 p[0] = '\0';
587 } else {
588 p=strchr(line, '\n');
589 if (p) {
590 p[0] = '\0';
593 /* allow a trailing separator */
594 if (line == p) {
595 break;
598 blob->ctr.dsdb.mappings = talloc_realloc(blob,
599 blob->ctr.dsdb.mappings,
600 struct drsuapi_DsReplicaOIDMapping,
601 blob->ctr.dsdb.num_mappings+1);
602 if (!blob->ctr.dsdb.mappings) {
603 talloc_free(tmp_ctx);
604 return -1;
607 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
609 if (oid[0] != ':') {
610 talloc_free(tmp_ctx);
611 return -1;
614 /* we know there must be at least ":" */
615 oid++;
617 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
618 talloc_free(tmp_ctx);
619 return -1;
621 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
622 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
624 blob->ctr.dsdb.num_mappings++;
626 /* Now look past the terminator we added above */
627 if (p) {
628 line = p + 1;
629 } else {
630 line = NULL;
634 ndr_err = ndr_push_struct_blob(out, mem_ctx,
635 blob,
636 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
637 talloc_free(tmp_ctx);
638 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
639 return -1;
641 return 0;
645 convert a NDR formatted blob to a ldif formatted prefixMap
647 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
648 const struct ldb_val *in, struct ldb_val *out)
650 struct prefixMapBlob *blob;
651 enum ndr_err_code ndr_err;
652 char *string;
653 uint32_t i;
655 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
656 int err;
657 /* try to decode the blob as S4 prefixMap */
658 err = ldif_write_NDR(ldb, mem_ctx, in, out,
659 sizeof(struct prefixMapBlob),
660 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
661 (ndr_print_fn_t)ndr_print_prefixMapBlob,
662 false);
663 if (0 == err) {
664 return err;
666 /* try parsing it as Windows PrefixMap value */
667 return ldif_write_NDR(ldb, mem_ctx, in, out,
668 sizeof(struct drsuapi_MSPrefixMap_Ctr),
669 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
670 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
671 true);
674 blob = talloc(mem_ctx, struct prefixMapBlob);
675 if (blob == NULL) {
676 return -1;
678 ndr_err = ndr_pull_struct_blob_all(in, blob,
679 blob,
680 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
681 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
682 goto failed;
684 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
685 goto failed;
687 string = talloc_strdup(mem_ctx, "");
688 if (string == NULL) {
689 goto failed;
692 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
693 DATA_BLOB oid_blob;
694 char *partial_oid = NULL;
696 if (i > 0) {
697 string = talloc_asprintf_append(string, ";");
700 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
701 blob->ctr.dsdb.mappings[i].oid.length);
702 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
703 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
704 blob->ctr.dsdb.mappings[i].id_prefix));
705 goto failed;
707 string = talloc_asprintf_append(string, "%u:%s",
708 blob->ctr.dsdb.mappings[i].id_prefix,
709 partial_oid);
710 talloc_free(discard_const(partial_oid));
711 if (string == NULL) {
712 goto failed;
716 talloc_free(blob);
717 *out = data_blob_string_const(string);
718 return 0;
720 failed:
721 talloc_free(blob);
722 return -1;
725 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
727 if (v->length < 4) {
728 return true;
731 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
732 return false;
735 return true;
739 canonicalise a prefixMap
741 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
742 const struct ldb_val *in, struct ldb_val *out)
744 if (ldif_comparision_prefixMap_isString(in)) {
745 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
747 return ldb_handler_copy(ldb, mem_ctx, in, out);
750 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
751 const struct ldb_val *v1,
752 const struct ldb_val *v2)
754 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
755 v1, v2);
758 /* length limited conversion of a ldb_val to a int32_t */
759 static int val_to_int32(const struct ldb_val *in, int32_t *v)
761 char *end;
762 char buf[64];
764 /* make sure we don't read past the end of the data */
765 if (in->length > sizeof(buf)-1) {
766 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
768 strncpy(buf, (char *)in->data, in->length);
769 buf[in->length] = 0;
771 /* We've to use "strtoll" here to have the intended overflows.
772 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
773 *v = (int32_t) strtoll(buf, &end, 0);
774 if (*end != 0) {
775 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
777 return LDB_SUCCESS;
780 /* length limited conversion of a ldb_val to a int64_t */
781 static int val_to_int64(const struct ldb_val *in, int64_t *v)
783 char *end;
784 char buf[64];
786 /* make sure we don't read past the end of the data */
787 if (in->length > sizeof(buf)-1) {
788 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
790 strncpy(buf, (char *)in->data, in->length);
791 buf[in->length] = 0;
793 *v = (int64_t) strtoll(buf, &end, 0);
794 if (*end != 0) {
795 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
797 return LDB_SUCCESS;
800 /* Canonicalisation of two 32-bit integers */
801 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
802 const struct ldb_val *in, struct ldb_val *out)
804 int32_t i;
805 int ret;
807 ret = val_to_int32(in, &i);
808 if (ret != LDB_SUCCESS) {
809 return ret;
811 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
812 if (out->data == NULL) {
813 ldb_oom(ldb);
814 return LDB_ERR_OPERATIONS_ERROR;
816 out->length = strlen((char *)out->data);
817 return 0;
820 /* Comparison of two 32-bit integers */
821 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
822 const struct ldb_val *v1, const struct ldb_val *v2)
824 int32_t i1=0, i2=0;
825 val_to_int32(v1, &i1);
826 val_to_int32(v2, &i2);
827 if (i1 == i2) return 0;
828 return i1 > i2? 1 : -1;
831 /* Canonicalisation of two 64-bit integers */
832 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
833 const struct ldb_val *in, struct ldb_val *out)
835 int64_t i;
836 int ret;
838 ret = val_to_int64(in, &i);
839 if (ret != LDB_SUCCESS) {
840 return ret;
842 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
843 if (out->data == NULL) {
844 ldb_oom(ldb);
845 return LDB_ERR_OPERATIONS_ERROR;
847 out->length = strlen((char *)out->data);
848 return 0;
851 /* Comparison of two 64-bit integers */
852 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
853 const struct ldb_val *v1, const struct ldb_val *v2)
855 int64_t i1=0, i2=0;
856 val_to_int64(v1, &i1);
857 val_to_int64(v2, &i2);
858 if (i1 == i2) return 0;
859 return i1 > i2? 1 : -1;
863 convert a NDR formatted blob to a ldif formatted repsFromTo
865 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
866 const struct ldb_val *in, struct ldb_val *out)
868 return ldif_write_NDR(ldb, mem_ctx, in, out,
869 sizeof(struct repsFromToBlob),
870 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
871 (ndr_print_fn_t)ndr_print_repsFromToBlob,
872 true);
876 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
878 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
879 const struct ldb_val *in, struct ldb_val *out)
881 return ldif_write_NDR(ldb, mem_ctx, in, out,
882 sizeof(struct replPropertyMetaDataBlob),
883 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
884 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
885 true);
889 convert a NDR formatted blob to a ldif formatted replUpToDateVector
891 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
892 const struct ldb_val *in, struct ldb_val *out)
894 return ldif_write_NDR(ldb, mem_ctx, in, out,
895 sizeof(struct replUpToDateVectorBlob),
896 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
897 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
898 true);
901 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
902 const struct ldb_val *in, struct ldb_val *out,
903 size_t struct_size,
904 ndr_pull_flags_fn_t pull_fn,
905 ndr_print_fn_t print_fn,
906 bool mask_errors)
908 uint8_t *p = NULL;
909 enum ndr_err_code err;
910 struct dsdb_dn *dsdb_dn = NULL;
911 char *dn_str = NULL;
912 char *str = NULL;
914 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
915 return ldb_handler_copy(ldb, mem_ctx, in, out);
918 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
919 if (dsdb_dn == NULL) {
920 return ldb_handler_copy(ldb, mem_ctx, in, out);
923 p = talloc_size(dsdb_dn, struct_size);
924 if (p == NULL) {
925 TALLOC_FREE(dsdb_dn);
926 return ldb_handler_copy(ldb, mem_ctx, in, out);
929 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
930 if (err != NDR_ERR_SUCCESS) {
931 /* fail in not in mask_error mode */
932 if (!mask_errors) {
933 return -1;
935 TALLOC_FREE(dsdb_dn);
936 return ldb_handler_copy(ldb, mem_ctx, in, out);
939 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
940 if (dn_str == NULL) {
941 TALLOC_FREE(dsdb_dn);
942 return ldb_handler_copy(ldb, mem_ctx, in, out);
945 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
946 TALLOC_FREE(dsdb_dn);
947 if (str == NULL) {
948 return ldb_handler_copy(ldb, mem_ctx, in, out);
951 *out = data_blob_string_const(str);
952 return 0;
955 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
956 const struct ldb_val *in, struct ldb_val *out)
958 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
959 sizeof(struct replPropertyMetaData1),
960 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
961 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
962 true);
966 convert a NDR formatted blob to a ldif formatted dnsRecord
968 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
969 const struct ldb_val *in, struct ldb_val *out)
971 return ldif_write_NDR(ldb, mem_ctx, in, out,
972 sizeof(struct dnsp_DnssrvRpcRecord),
973 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
974 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
975 true);
979 convert a NDR formatted blob to a ldif formatted dnsProperty
981 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
982 const struct ldb_val *in, struct ldb_val *out)
984 return ldif_write_NDR(ldb, mem_ctx, in, out,
985 sizeof(struct dnsp_DnsProperty),
986 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
987 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
988 true);
992 convert a NDR formatted blob of a supplementalCredentials into text
994 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
995 const struct ldb_val *in, struct ldb_val *out)
997 return ldif_write_NDR(ldb, mem_ctx, in, out,
998 sizeof(struct supplementalCredentialsBlob),
999 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1000 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1001 true);
1005 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1007 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1008 const struct ldb_val *in, struct ldb_val *out)
1010 return ldif_write_NDR(ldb, mem_ctx, in, out,
1011 sizeof(struct trustAuthInOutBlob),
1012 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1013 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1014 true);
1018 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1020 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1021 const struct ldb_val *in, struct ldb_val *out)
1023 return ldif_write_NDR(ldb, mem_ctx, in, out,
1024 sizeof(struct ForestTrustInfo),
1025 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1026 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1027 true);
1030 convert a NDR formatted blob of a partialAttributeSet into text
1032 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1033 const struct ldb_val *in, struct ldb_val *out)
1035 return ldif_write_NDR(ldb, mem_ctx, in, out,
1036 sizeof(struct partialAttributeSetBlob),
1037 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1038 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1039 true);
1043 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1044 const struct ldb_val *in, struct ldb_val *out)
1046 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1047 if (!out->data) {
1048 return -1;
1050 return 0;
1054 compare two dns
1056 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1057 const struct ldb_val *v1, const struct ldb_val *v2)
1059 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1060 int ret;
1062 if (dsdb_dn_is_deleted_val(v1)) {
1063 /* If the DN is deleted, then we can't search for it */
1064 return -1;
1067 if (dsdb_dn_is_deleted_val(v2)) {
1068 /* If the DN is deleted, then we can't search for it */
1069 return -1;
1072 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1073 if ( ! ldb_dn_validate(dn1)) return -1;
1075 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1076 if ( ! ldb_dn_validate(dn2)) {
1077 talloc_free(dn1);
1078 return -1;
1081 ret = ldb_dn_compare(dn1, dn2);
1083 talloc_free(dn1);
1084 talloc_free(dn2);
1085 return ret;
1088 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1089 const struct ldb_val *in, struct ldb_val *out)
1091 struct ldb_dn *dn;
1092 int ret = -1;
1094 out->length = 0;
1095 out->data = NULL;
1097 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1098 if ( ! ldb_dn_validate(dn)) {
1099 return LDB_ERR_INVALID_DN_SYNTAX;
1102 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1103 * does not casually match a not deleted DN */
1104 if (dsdb_dn_is_deleted_val(in)) {
1105 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1106 "<RMD_FLAGS=%u>%s",
1107 dsdb_dn_val_rmd_flags(in),
1108 ldb_dn_get_casefold(dn));
1109 } else {
1110 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1113 if (out->data == NULL) {
1114 goto done;
1116 out->length = strlen((char *)out->data);
1118 ret = 0;
1120 done:
1121 talloc_free(dn);
1123 return ret;
1128 write a 64 bit 2-part range
1130 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1131 const struct ldb_val *in, struct ldb_val *out)
1133 int64_t v;
1134 int ret;
1135 ret = val_to_int64(in, &v);
1136 if (ret != LDB_SUCCESS) {
1137 return ret;
1139 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1140 (unsigned long)(v&0xFFFFFFFF),
1141 (unsigned long)(v>>32));
1142 if (out->data == NULL) {
1143 ldb_oom(ldb);
1144 return LDB_ERR_OPERATIONS_ERROR;
1146 out->length = strlen((char *)out->data);
1147 return LDB_SUCCESS;
1151 read a 64 bit 2-part range
1153 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1154 const struct ldb_val *in, struct ldb_val *out)
1156 unsigned long high, low;
1157 char buf[64];
1159 if (memchr(in->data, '-', in->length) == NULL) {
1160 return ldb_handler_copy(ldb, mem_ctx, in, out);
1163 if (in->length > sizeof(buf)-1) {
1164 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1166 strncpy(buf, (const char *)in->data, in->length);
1167 buf[in->length] = 0;
1169 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1170 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1173 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1174 (unsigned long long)(((uint64_t)high)<<32) | (low));
1176 if (out->data == NULL) {
1177 ldb_oom(ldb);
1178 return LDB_ERR_OPERATIONS_ERROR;
1180 out->length = strlen((char *)out->data);
1181 return LDB_SUCCESS;
1185 when this operator_fn is set for a syntax, the backend calls is in
1186 preference to the comparison function. We are told the exact
1187 comparison operation that is needed, and we can return errors
1189 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1190 const struct ldb_schema_attribute *a,
1191 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1193 switch (operation) {
1194 case LDB_OP_AND:
1195 case LDB_OP_OR:
1196 case LDB_OP_NOT:
1197 case LDB_OP_SUBSTRING:
1198 case LDB_OP_APPROX:
1199 case LDB_OP_EXTENDED:
1200 /* handled in the backends */
1201 return LDB_ERR_INAPPROPRIATE_MATCHING;
1203 case LDB_OP_GREATER:
1204 case LDB_OP_LESS:
1205 case LDB_OP_EQUALITY:
1207 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1208 int ret;
1209 if (tmp_ctx == NULL) {
1210 return ldb_oom(ldb);
1212 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1213 talloc_free(tmp_ctx);
1214 if (operation == LDB_OP_GREATER) {
1215 *matched = (ret >= 0);
1216 } else if (operation == LDB_OP_LESS) {
1217 *matched = (ret <= 0);
1218 } else {
1219 *matched = (ret == 0);
1221 return LDB_SUCCESS;
1224 case LDB_OP_PRESENT:
1225 *matched = true;
1226 return LDB_SUCCESS;
1229 /* we shouldn't get here */
1230 return LDB_ERR_INAPPROPRIATE_MATCHING;
1234 compare two binary objects. This is correct for sorting as the sort order is:
1241 rather than ldb_comparison_binary() which is:
1249 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1250 const struct ldb_val *v1, const struct ldb_val *v2)
1252 return data_blob_cmp(v1, v2);
1256 when this operator_fn is set for a syntax, the backend calls is in
1257 preference to the comparison function. We are told the exact
1258 comparison operation that is needed, and we can return errors.
1260 This mode optimises for ldb_comparison_binary() if we need equality,
1261 as this should be faster as it can do a length-check first.
1263 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1264 const struct ldb_schema_attribute *a,
1265 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1267 if (operation == LDB_OP_EQUALITY) {
1268 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1269 return LDB_SUCCESS;
1271 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1275 see if two DNs match, comparing first by GUID, then by SID, and
1276 finally by string components
1278 static int samba_dn_extended_match(struct ldb_context *ldb,
1279 const struct ldb_val *v1,
1280 const struct ldb_val *v2,
1281 bool *matched)
1283 TALLOC_CTX *tmp_ctx;
1284 struct ldb_dn *dn1, *dn2;
1285 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1286 uint32_t rmd_flags1, rmd_flags2;
1288 tmp_ctx = talloc_new(ldb);
1290 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1291 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1292 if (!dn1 || !dn2) {
1293 /* couldn't parse as DN's */
1294 talloc_free(tmp_ctx);
1295 (*matched) = false;
1296 return LDB_SUCCESS;
1299 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1300 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1302 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1303 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1304 /* only match if they have the same deletion status */
1305 talloc_free(tmp_ctx);
1306 (*matched) = false;
1307 return LDB_SUCCESS;
1311 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1312 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1313 if (guid1 && guid2) {
1314 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1315 talloc_free(tmp_ctx);
1316 return LDB_SUCCESS;
1319 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1320 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1321 if (sid1 && sid2) {
1322 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1323 talloc_free(tmp_ctx);
1324 return LDB_SUCCESS;
1327 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1329 talloc_free(tmp_ctx);
1330 return LDB_SUCCESS;
1334 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1336 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1337 const struct ldb_schema_attribute *a,
1338 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1340 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1341 /* If the DN is deleted, then we can't search for it */
1343 /* should this be for equality too? */
1344 *matched = false;
1345 return LDB_SUCCESS;
1348 if (operation == LDB_OP_EQUALITY &&
1349 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1350 return LDB_SUCCESS;
1353 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1357 static const struct ldb_schema_syntax samba_syntaxes[] = {
1359 .name = LDB_SYNTAX_SAMBA_SID,
1360 .ldif_read_fn = ldif_read_objectSid,
1361 .ldif_write_fn = ldif_write_objectSid,
1362 .canonicalise_fn = ldif_canonicalise_objectSid,
1363 .comparison_fn = ldif_comparison_objectSid,
1364 .operator_fn = samba_syntax_operator_fn
1366 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1367 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1368 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1369 .canonicalise_fn = ldb_handler_copy,
1370 .comparison_fn = samba_ldb_comparison_binary,
1371 .operator_fn = samba_syntax_binary_operator_fn
1373 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1374 .ldif_read_fn = ldb_handler_copy,
1375 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1376 .canonicalise_fn = ldb_handler_fold,
1377 .comparison_fn = ldb_comparison_fold,
1378 .operator_fn = samba_syntax_operator_fn
1380 .name = LDB_SYNTAX_SAMBA_GUID,
1381 .ldif_read_fn = ldif_read_objectGUID,
1382 .ldif_write_fn = ldif_write_objectGUID,
1383 .canonicalise_fn = ldif_canonicalise_objectGUID,
1384 .comparison_fn = ldif_comparison_objectGUID,
1385 .operator_fn = samba_syntax_operator_fn
1387 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1388 .ldif_read_fn = ldb_handler_copy,
1389 .ldif_write_fn = ldb_handler_copy,
1390 .canonicalise_fn = ldif_canonicalise_objectCategory,
1391 .comparison_fn = ldif_comparison_objectCategory,
1392 .operator_fn = samba_syntax_operator_fn
1394 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1395 .ldif_read_fn = ldb_handler_copy,
1396 .ldif_write_fn = ldif_write_schemaInfo,
1397 .canonicalise_fn = ldb_handler_copy,
1398 .comparison_fn = samba_ldb_comparison_binary,
1399 .operator_fn = samba_syntax_binary_operator_fn
1401 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1402 .ldif_read_fn = ldif_read_prefixMap,
1403 .ldif_write_fn = ldif_write_prefixMap,
1404 .canonicalise_fn = ldif_canonicalise_prefixMap,
1405 .comparison_fn = ldif_comparison_prefixMap,
1406 .operator_fn = samba_syntax_operator_fn
1408 .name = LDB_SYNTAX_SAMBA_INT32,
1409 .ldif_read_fn = ldb_handler_copy,
1410 .ldif_write_fn = ldb_handler_copy,
1411 .canonicalise_fn = ldif_canonicalise_int32,
1412 .comparison_fn = ldif_comparison_int32,
1413 .operator_fn = samba_syntax_operator_fn
1415 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1416 .ldif_read_fn = ldb_handler_copy,
1417 .ldif_write_fn = ldif_write_repsFromTo,
1418 .canonicalise_fn = ldb_handler_copy,
1419 .comparison_fn = samba_ldb_comparison_binary,
1420 .operator_fn = samba_syntax_binary_operator_fn
1422 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1423 .ldif_read_fn = ldb_handler_copy,
1424 .ldif_write_fn = ldif_write_replPropertyMetaData,
1425 .canonicalise_fn = ldb_handler_copy,
1426 .comparison_fn = samba_ldb_comparison_binary,
1427 .operator_fn = samba_syntax_binary_operator_fn
1429 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1430 .ldif_read_fn = ldb_handler_copy,
1431 .ldif_write_fn = ldif_write_replUpToDateVector,
1432 .canonicalise_fn = ldb_handler_copy,
1433 .comparison_fn = samba_ldb_comparison_binary,
1434 .operator_fn = samba_syntax_binary_operator_fn
1436 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1437 .ldif_read_fn = ldb_handler_copy,
1438 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1439 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1440 .comparison_fn = dsdb_dn_binary_comparison,
1441 .operator_fn = samba_syntax_operator_fn
1443 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1444 .ldif_read_fn = ldb_handler_copy,
1445 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1446 .canonicalise_fn = ldb_handler_copy,
1447 .comparison_fn = samba_ldb_comparison_binary,
1448 .operator_fn = samba_syntax_binary_operator_fn
1450 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1451 .ldif_read_fn = ldb_handler_copy,
1452 .ldif_write_fn = ldif_write_ForestTrustInfo,
1453 .canonicalise_fn = ldb_handler_copy,
1454 .comparison_fn = samba_ldb_comparison_binary,
1455 .operator_fn = samba_syntax_binary_operator_fn
1457 .name = DSDB_SYNTAX_BINARY_DN,
1458 .ldif_read_fn = ldb_handler_copy,
1459 .ldif_write_fn = ldb_handler_copy,
1460 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1461 .comparison_fn = dsdb_dn_binary_comparison,
1462 .operator_fn = samba_syntax_operator_fn
1464 .name = DSDB_SYNTAX_STRING_DN,
1465 .ldif_read_fn = ldb_handler_copy,
1466 .ldif_write_fn = ldb_handler_copy,
1467 .canonicalise_fn = dsdb_dn_string_canonicalise,
1468 .comparison_fn = dsdb_dn_string_comparison,
1469 .operator_fn = samba_syntax_operator_fn
1471 .name = LDB_SYNTAX_DN,
1472 .ldif_read_fn = ldb_handler_copy,
1473 .ldif_write_fn = ldb_handler_copy,
1474 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1475 .comparison_fn = samba_ldb_dn_link_comparison,
1476 .operator_fn = samba_syntax_operator_dn
1478 .name = LDB_SYNTAX_SAMBA_RANGE64,
1479 .ldif_read_fn = ldif_read_range64,
1480 .ldif_write_fn = ldif_write_range64,
1481 .canonicalise_fn = ldif_canonicalise_int64,
1482 .comparison_fn = ldif_comparison_int64,
1483 .operator_fn = samba_syntax_operator_fn
1485 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1486 .ldif_read_fn = ldb_handler_copy,
1487 .ldif_write_fn = ldif_write_dnsRecord,
1488 .canonicalise_fn = ldb_handler_copy,
1489 .comparison_fn = samba_ldb_comparison_binary,
1490 .operator_fn = samba_syntax_binary_operator_fn
1492 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1493 .ldif_read_fn = ldb_handler_copy,
1494 .ldif_write_fn = ldif_write_dnsProperty,
1495 .canonicalise_fn = ldb_handler_copy,
1496 .comparison_fn = samba_ldb_comparison_binary,
1497 .operator_fn = samba_syntax_binary_operator_fn
1499 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1500 .ldif_read_fn = ldb_handler_copy,
1501 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1502 .canonicalise_fn = ldb_handler_copy,
1503 .comparison_fn = samba_ldb_comparison_binary,
1504 .operator_fn = samba_syntax_binary_operator_fn
1506 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1507 .ldif_read_fn = ldb_handler_copy,
1508 .ldif_write_fn = ldif_write_partialAttributeSet,
1509 .canonicalise_fn = ldb_handler_copy,
1510 .comparison_fn = samba_ldb_comparison_binary,
1511 .operator_fn = samba_syntax_binary_operator_fn
1513 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1514 .ldif_read_fn = ldb_handler_copy,
1515 .ldif_write_fn = ldb_handler_copy,
1516 .canonicalise_fn = ldb_handler_copy,
1517 .comparison_fn = samba_ldb_comparison_binary,
1518 .operator_fn = samba_syntax_binary_operator_fn
1522 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1524 .name = "SID",
1525 .read_fn = extended_dn_read_SID,
1526 .write_clear_fn = ldif_write_objectSid,
1527 .write_hex_fn = extended_dn_write_hex
1529 .name = "GUID",
1530 .read_fn = extended_dn_read_GUID,
1531 .write_clear_fn = ldif_write_objectGUID,
1532 .write_hex_fn = extended_dn_write_hex
1534 .name = "WKGUID",
1535 .read_fn = ldb_handler_copy,
1536 .write_clear_fn = ldb_handler_copy,
1537 .write_hex_fn = ldb_handler_copy
1539 .name = "RMD_INVOCID",
1540 .read_fn = extended_dn_read_GUID,
1541 .write_clear_fn = ldif_write_objectGUID,
1542 .write_hex_fn = extended_dn_write_hex
1544 .name = "RMD_FLAGS",
1545 .read_fn = ldb_handler_copy,
1546 .write_clear_fn = ldb_handler_copy,
1547 .write_hex_fn = ldb_handler_copy
1549 .name = "RMD_ADDTIME",
1550 .read_fn = ldb_handler_copy,
1551 .write_clear_fn = ldb_handler_copy,
1552 .write_hex_fn = ldb_handler_copy
1554 .name = "RMD_CHANGETIME",
1555 .read_fn = ldb_handler_copy,
1556 .write_clear_fn = ldb_handler_copy,
1557 .write_hex_fn = ldb_handler_copy
1559 .name = "RMD_LOCAL_USN",
1560 .read_fn = ldb_handler_copy,
1561 .write_clear_fn = ldb_handler_copy,
1562 .write_hex_fn = ldb_handler_copy
1564 .name = "RMD_ORIGINATING_USN",
1565 .read_fn = ldb_handler_copy,
1566 .write_clear_fn = ldb_handler_copy,
1567 .write_hex_fn = ldb_handler_copy
1569 .name = "RMD_VERSION",
1570 .read_fn = ldb_handler_copy,
1571 .write_clear_fn = ldb_handler_copy,
1572 .write_hex_fn = ldb_handler_copy
1576 /* TODO: Should be dynamic at some point */
1577 static const struct {
1578 const char *name;
1579 const char *syntax;
1580 } samba_attributes[] = {
1581 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1582 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1583 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1584 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1585 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1586 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1587 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1588 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1589 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1590 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1591 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1592 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1593 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1594 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1595 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1596 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1597 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1600 * these are extracted by searching
1601 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1603 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1604 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1605 * hat can be used to identify the set of policies when applied to a resource.
1606 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1607 * server, we ignore it here.
1609 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1610 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1611 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1612 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1613 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1614 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1615 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1616 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1617 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1620 * these are extracted by searching
1621 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1623 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1624 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1625 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1626 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1627 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1628 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1629 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1630 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1631 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1632 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1633 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1634 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1635 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1636 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1637 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1638 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1639 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1640 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1641 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1642 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1643 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1644 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1645 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1646 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1647 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1648 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1649 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1650 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1653 * these are known to be GUIDs
1655 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1656 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1658 /* These NDR encoded things we want to be able to read with --show-binary */
1659 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1660 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1661 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1662 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1665 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1667 unsigned int j;
1668 const struct ldb_schema_syntax *s = NULL;
1670 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1671 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1672 s = &samba_syntaxes[j];
1673 break;
1676 return s;
1679 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1681 unsigned int j;
1682 const struct ldb_schema_syntax *s = NULL;
1684 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1685 if (strcmp(samba_attributes[j].name, name) == 0) {
1686 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1687 break;
1691 return s;
1694 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret", NULL};
1697 register the samba ldif handlers
1699 int ldb_register_samba_handlers(struct ldb_context *ldb)
1701 unsigned int i;
1702 int ret;
1704 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1705 return LDB_SUCCESS;
1708 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1709 if (ret != LDB_SUCCESS) {
1710 return ret;
1713 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1714 const struct ldb_schema_syntax *s = NULL;
1716 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1718 if (!s) {
1719 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1722 if (!s) {
1723 return LDB_ERR_OPERATIONS_ERROR;
1726 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1727 if (ret != LDB_SUCCESS) {
1728 return ret;
1732 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1733 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1734 if (ret != LDB_SUCCESS) {
1735 return ret;
1740 ret = ldb_register_samba_matching_rules(ldb);
1741 if (ret != LDB_SUCCESS) {
1742 talloc_free(ldb);
1743 return LDB_SUCCESS;
1746 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1747 if (ret != LDB_SUCCESS) {
1748 return ret;
1751 return LDB_SUCCESS;