talloc: version 2.1.13
[Samba.git] / lib / ldb-samba / ldif_handlers.c
blob591bd1ee217b9d3d0168327e239240f95b932384
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 bool ret;
89 enum ndr_err_code ndr_err;
90 struct dom_sid sid;
91 if (in->length > DOM_SID_STR_BUFLEN) {
92 return -1;
93 } else {
94 char p[in->length+1];
95 memcpy(p, in->data, in->length);
96 p[in->length] = '\0';
98 ret = dom_sid_parse(p, &sid);
99 if (ret == false) {
100 return -1;
103 *out = data_blob_talloc(mem_ctx, NULL,
104 ndr_size_dom_sid(&sid, 0));
105 if (out->data == NULL) {
106 return -1;
109 ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
110 (ndr_push_flags_fn_t)ndr_push_dom_sid);
111 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
112 return -1;
115 return 0;
119 convert a NDR formatted blob to a ldif formatted objectSid
121 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
122 const struct ldb_val *in, struct ldb_val *out)
124 struct dom_sid sid;
125 enum ndr_err_code ndr_err;
127 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
128 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
129 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
130 return -1;
132 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
133 if (out->data == NULL) {
134 return -1;
136 return 0;
139 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
141 if (v->length < 3) {
142 return false;
145 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
147 return true;
151 compare two objectSids
153 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
154 const struct ldb_val *v1, const struct ldb_val *v2)
156 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
157 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
158 } else if (ldif_comparision_objectSid_isString(v1)
159 && !ldif_comparision_objectSid_isString(v2)) {
160 struct ldb_val v;
161 int ret;
162 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
163 /* Perhaps not a string after all */
164 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
166 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
167 talloc_free(v.data);
168 return ret;
169 } else if (!ldif_comparision_objectSid_isString(v1)
170 && ldif_comparision_objectSid_isString(v2)) {
171 struct ldb_val v;
172 int ret;
173 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
174 /* Perhaps not a string after all */
175 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
177 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
178 talloc_free(v.data);
179 return ret;
181 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
185 canonicalise a objectSid
187 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
188 const struct ldb_val *in, struct ldb_val *out)
190 if (ldif_comparision_objectSid_isString(in)) {
191 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
192 /* Perhaps not a string after all */
193 return ldb_handler_copy(ldb, mem_ctx, in, out);
195 return 0;
197 return ldb_handler_copy(ldb, mem_ctx, in, out);
200 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
201 const struct ldb_val *in, struct ldb_val *out)
203 struct dom_sid sid;
204 enum ndr_err_code ndr_err;
205 if (ldif_comparision_objectSid_isString(in)) {
206 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
207 return 0;
211 /* Perhaps not a string after all */
212 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
214 if (!out->data) {
215 return -1;
218 (*out).length = strhex_to_str((char *)out->data, out->length,
219 (const char *)in->data, in->length);
221 /* Check it looks like a SID */
222 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
223 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
224 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
225 return -1;
227 return 0;
231 convert a ldif formatted objectGUID to a NDR formatted blob
233 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
234 const struct ldb_val *in, struct ldb_val *out)
236 struct GUID guid;
237 NTSTATUS status;
239 status = GUID_from_data_blob(in, &guid);
240 if (!NT_STATUS_IS_OK(status)) {
241 return -1;
244 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
245 if (!NT_STATUS_IS_OK(status)) {
246 return -1;
248 return 0;
252 convert a NDR formatted blob to a ldif formatted objectGUID
254 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
255 const struct ldb_val *in, struct ldb_val *out)
257 struct GUID guid;
258 NTSTATUS status;
260 status = GUID_from_ndr_blob(in, &guid);
261 if (!NT_STATUS_IS_OK(status)) {
262 return -1;
264 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
265 if (out->data == NULL) {
266 return -1;
268 out->length = strlen((const char *)out->data);
269 return 0;
272 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
274 if (v->length != 36 && v->length != 38) return false;
276 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
277 return true;
280 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
281 const struct ldb_val *in, struct ldb_val *out)
284 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
285 return 0;
288 /* Try as 'hex' form */
289 if (in->length != 32) {
290 return -1;
293 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
295 if (!out->data) {
296 return -1;
299 (*out).length = strhex_to_str((char *)out->data, out->length,
300 (const char *)in->data, in->length);
302 /* Check it looks like a GUID */
303 if ((*out).length != 16) {
304 data_blob_free(out);
305 return -1;
308 return 0;
312 compare two objectGUIDs
314 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
315 const struct ldb_val *v1, const struct ldb_val *v2)
317 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
318 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
319 } else if (ldif_comparision_objectGUID_isString(v1)
320 && !ldif_comparision_objectGUID_isString(v2)) {
321 struct ldb_val v;
322 int ret;
323 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
324 /* Perhaps it wasn't a valid string after all */
325 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
327 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
328 talloc_free(v.data);
329 return ret;
330 } else if (!ldif_comparision_objectGUID_isString(v1)
331 && ldif_comparision_objectGUID_isString(v2)) {
332 struct ldb_val v;
333 int ret;
334 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
335 /* Perhaps it wasn't a valid string after all */
336 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
338 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
339 talloc_free(v.data);
340 return ret;
342 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
346 canonicalise a objectGUID
348 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
349 const struct ldb_val *in, struct ldb_val *out)
351 if (ldif_comparision_objectGUID_isString(in)) {
352 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
353 /* Perhaps it wasn't a valid string after all */
354 return ldb_handler_copy(ldb, mem_ctx, in, out);
356 return 0;
358 return ldb_handler_copy(ldb, mem_ctx, in, out);
363 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
365 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
366 const struct ldb_val *in, struct ldb_val *out)
368 struct security_descriptor *sd;
369 enum ndr_err_code ndr_err;
371 sd = talloc(mem_ctx, struct security_descriptor);
372 if (sd == NULL) {
373 return -1;
376 ndr_err = ndr_pull_struct_blob(in, sd, sd,
377 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
378 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
379 /* If this does not parse, then it is probably SDDL, and we should try it that way */
381 const struct dom_sid *sid = samdb_domain_sid(ldb);
382 talloc_free(sd);
383 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
384 if (sd == NULL) {
385 return -1;
389 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
390 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
391 talloc_free(sd);
392 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
393 return -1;
396 return 0;
400 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
402 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
403 const struct ldb_val *in, struct ldb_val *out)
405 struct security_descriptor *sd;
406 enum ndr_err_code ndr_err;
408 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
409 return ldif_write_NDR(ldb, mem_ctx, in, out,
410 sizeof(struct security_descriptor),
411 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
412 (ndr_print_fn_t)ndr_print_security_descriptor,
413 true);
417 sd = talloc(mem_ctx, struct security_descriptor);
418 if (sd == NULL) {
419 return -1;
421 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
422 ndr_err = ndr_pull_struct_blob(in, sd, sd,
423 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
424 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
425 talloc_free(sd);
426 return -1;
428 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
429 talloc_free(sd);
430 if (out->data == NULL) {
431 return -1;
433 out->length = strlen((const char *)out->data);
434 return 0;
438 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
440 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
441 const struct ldb_val *in, struct ldb_val *out)
443 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
444 struct security_descriptor *sd;
445 const struct dom_sid *sid = samdb_domain_sid(ldb);
447 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
448 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
449 (ndr_print_fn_t)ndr_print_security_descriptor,
450 "SDDL", sd);
451 out->length = strlen((const char *)out->data);
452 talloc_free(sd);
453 return 0;
456 return ldb_handler_copy(ldb, mem_ctx, in, out);
460 canonicalise an objectCategory. We use the long form as the canonical form:
461 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
463 Also any short name of an objectClass that points to a different
464 class (such as user) has the canonical form of the class it's
465 defaultObjectCategory points to (eg
466 cn=Person,cn=Schema,cn=Configuration,<basedn>)
469 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
470 const struct ldb_val *in, struct ldb_val *out)
472 struct ldb_dn *dn1 = NULL;
473 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
474 const struct dsdb_class *sclass;
475 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
476 if (!tmp_ctx) {
477 return LDB_ERR_OPERATIONS_ERROR;
480 if (!schema) {
481 talloc_free(tmp_ctx);
482 *out = data_blob_talloc(mem_ctx, in->data, in->length);
483 if (in->data && !out->data) {
484 return LDB_ERR_OPERATIONS_ERROR;
486 return LDB_SUCCESS;
488 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
489 if ( ! ldb_dn_validate(dn1)) {
490 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
491 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
492 if (sclass) {
493 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
494 sclass->defaultObjectCategory);
495 if (dn == NULL) {
496 talloc_free(tmp_ctx);
497 return LDB_ERR_OPERATIONS_ERROR;
500 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
501 talloc_free(tmp_ctx);
503 if (!out->data) {
504 return LDB_ERR_OPERATIONS_ERROR;
506 return LDB_SUCCESS;
507 } else {
508 *out = data_blob_talloc(mem_ctx, in->data, in->length);
509 talloc_free(tmp_ctx);
511 if (in->data && !out->data) {
512 return LDB_ERR_OPERATIONS_ERROR;
514 return LDB_SUCCESS;
517 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
518 talloc_free(tmp_ctx);
520 if (!out->data) {
521 return LDB_ERR_OPERATIONS_ERROR;
523 return LDB_SUCCESS;
526 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
527 const struct ldb_val *v1,
528 const struct ldb_val *v2)
530 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
531 v1, v2);
535 convert a NDR formatted blob to a ldif formatted schemaInfo
537 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
538 const struct ldb_val *in, struct ldb_val *out)
540 return ldif_write_NDR(ldb, mem_ctx, in, out,
541 sizeof(struct repsFromToBlob),
542 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
543 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
544 true);
548 convert a ldif formatted prefixMap to a NDR formatted blob
550 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
551 const struct ldb_val *in, struct ldb_val *out)
553 struct prefixMapBlob *blob;
554 enum ndr_err_code ndr_err;
555 char *string, *line, *p, *oid;
556 DATA_BLOB oid_blob;
558 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
560 if (tmp_ctx == NULL) {
561 return -1;
564 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
565 if (blob == NULL) {
566 talloc_free(tmp_ctx);
567 return -1;
570 /* use the switch value to detect if this is in the binary
571 * format
573 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
574 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
575 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
576 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
577 ndr_err = ndr_push_struct_blob(out, mem_ctx,
578 blob,
579 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
580 talloc_free(tmp_ctx);
581 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
582 return -1;
584 return 0;
588 /* If this does not parse, then it is probably the text version, and we should try it that way */
589 blob->version = PREFIX_MAP_VERSION_DSDB;
591 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
592 if (string == NULL) {
593 talloc_free(blob);
594 return -1;
597 line = string;
598 while (line && line[0]) {
599 p=strchr(line, ';');
600 if (p) {
601 p[0] = '\0';
602 } else {
603 p=strchr(line, '\n');
604 if (p) {
605 p[0] = '\0';
608 /* allow a trailing separator */
609 if (line == p) {
610 break;
613 blob->ctr.dsdb.mappings = talloc_realloc(blob,
614 blob->ctr.dsdb.mappings,
615 struct drsuapi_DsReplicaOIDMapping,
616 blob->ctr.dsdb.num_mappings+1);
617 if (!blob->ctr.dsdb.mappings) {
618 talloc_free(tmp_ctx);
619 return -1;
622 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
624 if (oid[0] != ':') {
625 talloc_free(tmp_ctx);
626 return -1;
629 /* we know there must be at least ":" */
630 oid++;
632 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
633 talloc_free(tmp_ctx);
634 return -1;
636 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
637 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
639 blob->ctr.dsdb.num_mappings++;
641 /* Now look past the terminator we added above */
642 if (p) {
643 line = p + 1;
644 } else {
645 line = NULL;
649 ndr_err = ndr_push_struct_blob(out, mem_ctx,
650 blob,
651 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
652 talloc_free(tmp_ctx);
653 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
654 return -1;
656 return 0;
660 convert a NDR formatted blob to a ldif formatted prefixMap
662 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
663 const struct ldb_val *in, struct ldb_val *out)
665 struct prefixMapBlob *blob;
666 enum ndr_err_code ndr_err;
667 char *string;
668 uint32_t i;
670 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
671 int err;
672 /* try to decode the blob as S4 prefixMap */
673 err = ldif_write_NDR(ldb, mem_ctx, in, out,
674 sizeof(struct prefixMapBlob),
675 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
676 (ndr_print_fn_t)ndr_print_prefixMapBlob,
677 false);
678 if (0 == err) {
679 return err;
681 /* try parsing it as Windows PrefixMap value */
682 return ldif_write_NDR(ldb, mem_ctx, in, out,
683 sizeof(struct drsuapi_MSPrefixMap_Ctr),
684 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
685 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
686 true);
689 blob = talloc(mem_ctx, struct prefixMapBlob);
690 if (blob == NULL) {
691 return -1;
693 ndr_err = ndr_pull_struct_blob_all(in, blob,
694 blob,
695 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
696 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
697 goto failed;
699 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
700 goto failed;
702 string = talloc_strdup(mem_ctx, "");
703 if (string == NULL) {
704 goto failed;
707 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
708 DATA_BLOB oid_blob;
709 char *partial_oid = NULL;
711 if (i > 0) {
712 string = talloc_asprintf_append(string, ";");
715 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
716 blob->ctr.dsdb.mappings[i].oid.length);
717 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
718 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
719 blob->ctr.dsdb.mappings[i].id_prefix));
720 goto failed;
722 string = talloc_asprintf_append(string, "%u:%s",
723 blob->ctr.dsdb.mappings[i].id_prefix,
724 partial_oid);
725 talloc_free(discard_const(partial_oid));
726 if (string == NULL) {
727 goto failed;
731 talloc_free(blob);
732 *out = data_blob_string_const(string);
733 return 0;
735 failed:
736 talloc_free(blob);
737 return -1;
740 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
742 if (v->length < 4) {
743 return true;
746 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
747 return false;
750 return true;
754 canonicalise a prefixMap
756 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
757 const struct ldb_val *in, struct ldb_val *out)
759 if (ldif_comparision_prefixMap_isString(in)) {
760 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
762 return ldb_handler_copy(ldb, mem_ctx, in, out);
765 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
766 const struct ldb_val *v1,
767 const struct ldb_val *v2)
769 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
770 v1, v2);
773 /* length limited conversion of a ldb_val to a int32_t */
774 static int val_to_int32(const struct ldb_val *in, int32_t *v)
776 char *end;
777 char buf[64];
779 /* make sure we don't read past the end of the data */
780 if (in->length > sizeof(buf)-1) {
781 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
783 strncpy(buf, (char *)in->data, in->length);
784 buf[in->length] = 0;
786 /* We've to use "strtoll" here to have the intended overflows.
787 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
788 *v = (int32_t) strtoll(buf, &end, 0);
789 if (*end != 0) {
790 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
792 return LDB_SUCCESS;
795 /* length limited conversion of a ldb_val to a int64_t */
796 static int val_to_int64(const struct ldb_val *in, int64_t *v)
798 char *end;
799 char buf[64];
801 /* make sure we don't read past the end of the data */
802 if (in->length > sizeof(buf)-1) {
803 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
805 strncpy(buf, (char *)in->data, in->length);
806 buf[in->length] = 0;
808 *v = (int64_t) strtoll(buf, &end, 0);
809 if (*end != 0) {
810 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
812 return LDB_SUCCESS;
815 /* Canonicalisation of two 32-bit integers */
816 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
817 const struct ldb_val *in, struct ldb_val *out)
819 int32_t i;
820 int ret;
822 ret = val_to_int32(in, &i);
823 if (ret != LDB_SUCCESS) {
824 return ret;
826 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
827 if (out->data == NULL) {
828 ldb_oom(ldb);
829 return LDB_ERR_OPERATIONS_ERROR;
831 out->length = strlen((char *)out->data);
832 return 0;
835 /* Comparison of two 32-bit integers */
836 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
837 const struct ldb_val *v1, const struct ldb_val *v2)
839 int32_t i1=0, i2=0;
840 val_to_int32(v1, &i1);
841 val_to_int32(v2, &i2);
842 if (i1 == i2) return 0;
843 return i1 > i2? 1 : -1;
846 /* Canonicalisation of two 64-bit integers */
847 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
848 const struct ldb_val *in, struct ldb_val *out)
850 int64_t i;
851 int ret;
853 ret = val_to_int64(in, &i);
854 if (ret != LDB_SUCCESS) {
855 return ret;
857 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
858 if (out->data == NULL) {
859 ldb_oom(ldb);
860 return LDB_ERR_OPERATIONS_ERROR;
862 out->length = strlen((char *)out->data);
863 return 0;
866 /* Comparison of two 64-bit integers */
867 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
868 const struct ldb_val *v1, const struct ldb_val *v2)
870 int64_t i1=0, i2=0;
871 val_to_int64(v1, &i1);
872 val_to_int64(v2, &i2);
873 if (i1 == i2) return 0;
874 return i1 > i2? 1 : -1;
878 convert a NDR formatted blob to a ldif formatted repsFromTo
880 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
881 const struct ldb_val *in, struct ldb_val *out)
883 return ldif_write_NDR(ldb, mem_ctx, in, out,
884 sizeof(struct repsFromToBlob),
885 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
886 (ndr_print_fn_t)ndr_print_repsFromToBlob,
887 true);
891 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
893 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
894 const struct ldb_val *in, struct ldb_val *out)
896 return ldif_write_NDR(ldb, mem_ctx, in, out,
897 sizeof(struct replPropertyMetaDataBlob),
898 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
899 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
900 true);
904 convert a NDR formatted blob to a ldif formatted replUpToDateVector
906 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
907 const struct ldb_val *in, struct ldb_val *out)
909 return ldif_write_NDR(ldb, mem_ctx, in, out,
910 sizeof(struct replUpToDateVectorBlob),
911 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
912 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
913 true);
916 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
917 const struct ldb_val *in, struct ldb_val *out,
918 size_t struct_size,
919 ndr_pull_flags_fn_t pull_fn,
920 ndr_print_fn_t print_fn,
921 bool mask_errors)
923 uint8_t *p = NULL;
924 enum ndr_err_code err;
925 struct dsdb_dn *dsdb_dn = NULL;
926 char *dn_str = NULL;
927 char *str = NULL;
929 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
930 return ldb_handler_copy(ldb, mem_ctx, in, out);
933 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
934 if (dsdb_dn == NULL) {
935 return ldb_handler_copy(ldb, mem_ctx, in, out);
938 p = talloc_size(dsdb_dn, struct_size);
939 if (p == NULL) {
940 TALLOC_FREE(dsdb_dn);
941 return ldb_handler_copy(ldb, mem_ctx, in, out);
944 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
945 if (err != NDR_ERR_SUCCESS) {
946 /* fail in not in mask_error mode */
947 if (!mask_errors) {
948 return -1;
950 TALLOC_FREE(dsdb_dn);
951 return ldb_handler_copy(ldb, mem_ctx, in, out);
954 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
955 if (dn_str == NULL) {
956 TALLOC_FREE(dsdb_dn);
957 return ldb_handler_copy(ldb, mem_ctx, in, out);
960 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
961 TALLOC_FREE(dsdb_dn);
962 if (str == NULL) {
963 return ldb_handler_copy(ldb, mem_ctx, in, out);
966 *out = data_blob_string_const(str);
967 return 0;
970 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
971 const struct ldb_val *in, struct ldb_val *out)
973 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
974 sizeof(struct replPropertyMetaData1),
975 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
976 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
977 true);
981 convert a NDR formatted blob to a ldif formatted dnsRecord
983 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
984 const struct ldb_val *in, struct ldb_val *out)
986 return ldif_write_NDR(ldb, mem_ctx, in, out,
987 sizeof(struct dnsp_DnssrvRpcRecord),
988 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
989 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
990 true);
994 convert a NDR formatted blob to a ldif formatted dnsProperty
996 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
997 const struct ldb_val *in, struct ldb_val *out)
999 return ldif_write_NDR(ldb, mem_ctx, in, out,
1000 sizeof(struct dnsp_DnsProperty),
1001 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1002 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1003 true);
1007 convert a NDR formatted blob of a supplementalCredentials into text
1009 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1010 const struct ldb_val *in, struct ldb_val *out)
1012 return ldif_write_NDR(ldb, mem_ctx, in, out,
1013 sizeof(struct supplementalCredentialsBlob),
1014 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1015 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1016 true);
1020 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1022 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1023 const struct ldb_val *in, struct ldb_val *out)
1025 return ldif_write_NDR(ldb, mem_ctx, in, out,
1026 sizeof(struct trustAuthInOutBlob),
1027 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1028 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1029 true);
1033 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1035 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1036 const struct ldb_val *in, struct ldb_val *out)
1038 return ldif_write_NDR(ldb, mem_ctx, in, out,
1039 sizeof(struct ForestTrustInfo),
1040 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1041 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1042 true);
1045 convert a NDR formatted blob of a partialAttributeSet into text
1047 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1048 const struct ldb_val *in, struct ldb_val *out)
1050 return ldif_write_NDR(ldb, mem_ctx, in, out,
1051 sizeof(struct partialAttributeSetBlob),
1052 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1053 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1054 true);
1058 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1059 const struct ldb_val *in, struct ldb_val *out)
1061 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1062 if (!out->data) {
1063 return -1;
1065 return 0;
1069 compare two dns
1071 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1072 const struct ldb_val *v1, const struct ldb_val *v2)
1074 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1075 int ret;
1077 if (dsdb_dn_is_deleted_val(v1)) {
1078 /* If the DN is deleted, then we can't search for it */
1079 return -1;
1082 if (dsdb_dn_is_deleted_val(v2)) {
1083 /* If the DN is deleted, then we can't search for it */
1084 return -1;
1087 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1088 if ( ! ldb_dn_validate(dn1)) return -1;
1090 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1091 if ( ! ldb_dn_validate(dn2)) {
1092 talloc_free(dn1);
1093 return -1;
1096 ret = ldb_dn_compare(dn1, dn2);
1098 talloc_free(dn1);
1099 talloc_free(dn2);
1100 return ret;
1103 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1104 const struct ldb_val *in, struct ldb_val *out)
1106 struct ldb_dn *dn;
1107 int ret = -1;
1109 out->length = 0;
1110 out->data = NULL;
1112 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1113 if ( ! ldb_dn_validate(dn)) {
1114 return LDB_ERR_INVALID_DN_SYNTAX;
1117 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1118 * does not casually match a not deleted DN */
1119 if (dsdb_dn_is_deleted_val(in)) {
1120 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1121 "<RMD_FLAGS=%u>%s",
1122 dsdb_dn_val_rmd_flags(in),
1123 ldb_dn_get_casefold(dn));
1124 } else {
1125 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1128 if (out->data == NULL) {
1129 goto done;
1131 out->length = strlen((char *)out->data);
1133 ret = 0;
1135 done:
1136 talloc_free(dn);
1138 return ret;
1143 write a 64 bit 2-part range
1145 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1146 const struct ldb_val *in, struct ldb_val *out)
1148 int64_t v;
1149 int ret;
1150 ret = val_to_int64(in, &v);
1151 if (ret != LDB_SUCCESS) {
1152 return ret;
1154 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1155 (unsigned long)(v&0xFFFFFFFF),
1156 (unsigned long)(v>>32));
1157 if (out->data == NULL) {
1158 ldb_oom(ldb);
1159 return LDB_ERR_OPERATIONS_ERROR;
1161 out->length = strlen((char *)out->data);
1162 return LDB_SUCCESS;
1166 read a 64 bit 2-part range
1168 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1169 const struct ldb_val *in, struct ldb_val *out)
1171 unsigned long high, low;
1172 char buf[64];
1174 if (memchr(in->data, '-', in->length) == NULL) {
1175 return ldb_handler_copy(ldb, mem_ctx, in, out);
1178 if (in->length > sizeof(buf)-1) {
1179 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1181 strncpy(buf, (const char *)in->data, in->length);
1182 buf[in->length] = 0;
1184 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1185 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1188 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1189 (unsigned long long)(((uint64_t)high)<<32) | (low));
1191 if (out->data == NULL) {
1192 ldb_oom(ldb);
1193 return LDB_ERR_OPERATIONS_ERROR;
1195 out->length = strlen((char *)out->data);
1196 return LDB_SUCCESS;
1200 when this operator_fn is set for a syntax, the backend calls is in
1201 preference to the comparison function. We are told the exact
1202 comparison operation that is needed, and we can return errors
1204 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1205 const struct ldb_schema_attribute *a,
1206 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1208 switch (operation) {
1209 case LDB_OP_AND:
1210 case LDB_OP_OR:
1211 case LDB_OP_NOT:
1212 case LDB_OP_SUBSTRING:
1213 case LDB_OP_APPROX:
1214 case LDB_OP_EXTENDED:
1215 /* handled in the backends */
1216 return LDB_ERR_INAPPROPRIATE_MATCHING;
1218 case LDB_OP_GREATER:
1219 case LDB_OP_LESS:
1220 case LDB_OP_EQUALITY:
1222 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1223 int ret;
1224 if (tmp_ctx == NULL) {
1225 return ldb_oom(ldb);
1227 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1228 talloc_free(tmp_ctx);
1229 if (operation == LDB_OP_GREATER) {
1230 *matched = (ret >= 0);
1231 } else if (operation == LDB_OP_LESS) {
1232 *matched = (ret <= 0);
1233 } else {
1234 *matched = (ret == 0);
1236 return LDB_SUCCESS;
1239 case LDB_OP_PRESENT:
1240 *matched = true;
1241 return LDB_SUCCESS;
1244 /* we shouldn't get here */
1245 return LDB_ERR_INAPPROPRIATE_MATCHING;
1249 compare two binary objects. This is correct for sorting as the sort order is:
1256 rather than ldb_comparison_binary() which is:
1264 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1265 const struct ldb_val *v1, const struct ldb_val *v2)
1267 return data_blob_cmp(v1, v2);
1271 when this operator_fn is set for a syntax, the backend calls is in
1272 preference to the comparison function. We are told the exact
1273 comparison operation that is needed, and we can return errors.
1275 This mode optimises for ldb_comparison_binary() if we need equality,
1276 as this should be faster as it can do a length-check first.
1278 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1279 const struct ldb_schema_attribute *a,
1280 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1282 if (operation == LDB_OP_EQUALITY) {
1283 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1284 return LDB_SUCCESS;
1286 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1290 see if two DNs match, comparing first by GUID, then by SID, and
1291 finally by string components
1293 static int samba_dn_extended_match(struct ldb_context *ldb,
1294 const struct ldb_val *v1,
1295 const struct ldb_val *v2,
1296 bool *matched)
1298 TALLOC_CTX *tmp_ctx;
1299 struct ldb_dn *dn1, *dn2;
1300 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1301 uint32_t rmd_flags1, rmd_flags2;
1303 tmp_ctx = talloc_new(ldb);
1305 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1306 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1307 if (!dn1 || !dn2) {
1308 /* couldn't parse as DN's */
1309 talloc_free(tmp_ctx);
1310 (*matched) = false;
1311 return LDB_SUCCESS;
1314 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1315 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1317 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1318 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1319 /* only match if they have the same deletion status */
1320 talloc_free(tmp_ctx);
1321 (*matched) = false;
1322 return LDB_SUCCESS;
1326 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1327 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1328 if (guid1 && guid2) {
1329 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1330 talloc_free(tmp_ctx);
1331 return LDB_SUCCESS;
1334 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1335 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1336 if (sid1 && sid2) {
1337 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1338 talloc_free(tmp_ctx);
1339 return LDB_SUCCESS;
1342 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1344 talloc_free(tmp_ctx);
1345 return LDB_SUCCESS;
1349 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1351 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1352 const struct ldb_schema_attribute *a,
1353 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1355 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1356 /* If the DN is deleted, then we can't search for it */
1358 /* should this be for equality too? */
1359 *matched = false;
1360 return LDB_SUCCESS;
1363 if (operation == LDB_OP_EQUALITY &&
1364 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1365 return LDB_SUCCESS;
1368 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1372 static const struct ldb_schema_syntax samba_syntaxes[] = {
1374 .name = LDB_SYNTAX_SAMBA_SID,
1375 .ldif_read_fn = ldif_read_objectSid,
1376 .ldif_write_fn = ldif_write_objectSid,
1377 .canonicalise_fn = ldif_canonicalise_objectSid,
1378 .comparison_fn = ldif_comparison_objectSid,
1379 .operator_fn = samba_syntax_operator_fn
1381 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1382 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1383 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1384 .canonicalise_fn = ldb_handler_copy,
1385 .comparison_fn = samba_ldb_comparison_binary,
1386 .operator_fn = samba_syntax_binary_operator_fn
1388 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1389 .ldif_read_fn = ldb_handler_copy,
1390 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1391 .canonicalise_fn = ldb_handler_fold,
1392 .comparison_fn = ldb_comparison_fold,
1393 .operator_fn = samba_syntax_operator_fn
1395 .name = LDB_SYNTAX_SAMBA_GUID,
1396 .ldif_read_fn = ldif_read_objectGUID,
1397 .ldif_write_fn = ldif_write_objectGUID,
1398 .canonicalise_fn = ldif_canonicalise_objectGUID,
1399 .comparison_fn = ldif_comparison_objectGUID,
1400 .operator_fn = samba_syntax_operator_fn
1402 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1403 .ldif_read_fn = ldb_handler_copy,
1404 .ldif_write_fn = ldb_handler_copy,
1405 .canonicalise_fn = ldif_canonicalise_objectCategory,
1406 .comparison_fn = ldif_comparison_objectCategory,
1407 .operator_fn = samba_syntax_operator_fn
1409 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1410 .ldif_read_fn = ldb_handler_copy,
1411 .ldif_write_fn = ldif_write_schemaInfo,
1412 .canonicalise_fn = ldb_handler_copy,
1413 .comparison_fn = samba_ldb_comparison_binary,
1414 .operator_fn = samba_syntax_binary_operator_fn
1416 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1417 .ldif_read_fn = ldif_read_prefixMap,
1418 .ldif_write_fn = ldif_write_prefixMap,
1419 .canonicalise_fn = ldif_canonicalise_prefixMap,
1420 .comparison_fn = ldif_comparison_prefixMap,
1421 .operator_fn = samba_syntax_operator_fn
1423 .name = LDB_SYNTAX_SAMBA_INT32,
1424 .ldif_read_fn = ldb_handler_copy,
1425 .ldif_write_fn = ldb_handler_copy,
1426 .canonicalise_fn = ldif_canonicalise_int32,
1427 .comparison_fn = ldif_comparison_int32,
1428 .operator_fn = samba_syntax_operator_fn
1430 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1431 .ldif_read_fn = ldb_handler_copy,
1432 .ldif_write_fn = ldif_write_repsFromTo,
1433 .canonicalise_fn = ldb_handler_copy,
1434 .comparison_fn = samba_ldb_comparison_binary,
1435 .operator_fn = samba_syntax_binary_operator_fn
1437 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1438 .ldif_read_fn = ldb_handler_copy,
1439 .ldif_write_fn = ldif_write_replPropertyMetaData,
1440 .canonicalise_fn = ldb_handler_copy,
1441 .comparison_fn = samba_ldb_comparison_binary,
1442 .operator_fn = samba_syntax_binary_operator_fn
1444 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1445 .ldif_read_fn = ldb_handler_copy,
1446 .ldif_write_fn = ldif_write_replUpToDateVector,
1447 .canonicalise_fn = ldb_handler_copy,
1448 .comparison_fn = samba_ldb_comparison_binary,
1449 .operator_fn = samba_syntax_binary_operator_fn
1451 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1452 .ldif_read_fn = ldb_handler_copy,
1453 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1454 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1455 .comparison_fn = dsdb_dn_binary_comparison,
1456 .operator_fn = samba_syntax_operator_fn
1458 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1459 .ldif_read_fn = ldb_handler_copy,
1460 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1461 .canonicalise_fn = ldb_handler_copy,
1462 .comparison_fn = samba_ldb_comparison_binary,
1463 .operator_fn = samba_syntax_binary_operator_fn
1465 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1466 .ldif_read_fn = ldb_handler_copy,
1467 .ldif_write_fn = ldif_write_ForestTrustInfo,
1468 .canonicalise_fn = ldb_handler_copy,
1469 .comparison_fn = samba_ldb_comparison_binary,
1470 .operator_fn = samba_syntax_binary_operator_fn
1472 .name = DSDB_SYNTAX_BINARY_DN,
1473 .ldif_read_fn = ldb_handler_copy,
1474 .ldif_write_fn = ldb_handler_copy,
1475 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1476 .comparison_fn = dsdb_dn_binary_comparison,
1477 .operator_fn = samba_syntax_operator_fn
1479 .name = DSDB_SYNTAX_STRING_DN,
1480 .ldif_read_fn = ldb_handler_copy,
1481 .ldif_write_fn = ldb_handler_copy,
1482 .canonicalise_fn = dsdb_dn_string_canonicalise,
1483 .comparison_fn = dsdb_dn_string_comparison,
1484 .operator_fn = samba_syntax_operator_fn
1486 .name = LDB_SYNTAX_DN,
1487 .ldif_read_fn = ldb_handler_copy,
1488 .ldif_write_fn = ldb_handler_copy,
1489 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1490 .comparison_fn = samba_ldb_dn_link_comparison,
1491 .operator_fn = samba_syntax_operator_dn
1493 .name = LDB_SYNTAX_SAMBA_RANGE64,
1494 .ldif_read_fn = ldif_read_range64,
1495 .ldif_write_fn = ldif_write_range64,
1496 .canonicalise_fn = ldif_canonicalise_int64,
1497 .comparison_fn = ldif_comparison_int64,
1498 .operator_fn = samba_syntax_operator_fn
1500 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1501 .ldif_read_fn = ldb_handler_copy,
1502 .ldif_write_fn = ldif_write_dnsRecord,
1503 .canonicalise_fn = ldb_handler_copy,
1504 .comparison_fn = samba_ldb_comparison_binary,
1505 .operator_fn = samba_syntax_binary_operator_fn
1507 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1508 .ldif_read_fn = ldb_handler_copy,
1509 .ldif_write_fn = ldif_write_dnsProperty,
1510 .canonicalise_fn = ldb_handler_copy,
1511 .comparison_fn = samba_ldb_comparison_binary,
1512 .operator_fn = samba_syntax_binary_operator_fn
1514 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1515 .ldif_read_fn = ldb_handler_copy,
1516 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1517 .canonicalise_fn = ldb_handler_copy,
1518 .comparison_fn = samba_ldb_comparison_binary,
1519 .operator_fn = samba_syntax_binary_operator_fn
1521 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1522 .ldif_read_fn = ldb_handler_copy,
1523 .ldif_write_fn = ldif_write_partialAttributeSet,
1524 .canonicalise_fn = ldb_handler_copy,
1525 .comparison_fn = samba_ldb_comparison_binary,
1526 .operator_fn = samba_syntax_binary_operator_fn
1528 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1529 .ldif_read_fn = ldb_handler_copy,
1530 .ldif_write_fn = ldb_handler_copy,
1531 .canonicalise_fn = ldb_handler_copy,
1532 .comparison_fn = samba_ldb_comparison_binary,
1533 .operator_fn = samba_syntax_binary_operator_fn
1537 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1539 .name = "SID",
1540 .read_fn = extended_dn_read_SID,
1541 .write_clear_fn = ldif_write_objectSid,
1542 .write_hex_fn = extended_dn_write_hex
1544 .name = "GUID",
1545 .read_fn = extended_dn_read_GUID,
1546 .write_clear_fn = ldif_write_objectGUID,
1547 .write_hex_fn = extended_dn_write_hex
1549 .name = "WKGUID",
1550 .read_fn = ldb_handler_copy,
1551 .write_clear_fn = ldb_handler_copy,
1552 .write_hex_fn = ldb_handler_copy
1554 .name = "RMD_INVOCID",
1555 .read_fn = extended_dn_read_GUID,
1556 .write_clear_fn = ldif_write_objectGUID,
1557 .write_hex_fn = extended_dn_write_hex
1559 .name = "RMD_FLAGS",
1560 .read_fn = ldb_handler_copy,
1561 .write_clear_fn = ldb_handler_copy,
1562 .write_hex_fn = ldb_handler_copy
1564 .name = "RMD_ADDTIME",
1565 .read_fn = ldb_handler_copy,
1566 .write_clear_fn = ldb_handler_copy,
1567 .write_hex_fn = ldb_handler_copy
1569 .name = "RMD_CHANGETIME",
1570 .read_fn = ldb_handler_copy,
1571 .write_clear_fn = ldb_handler_copy,
1572 .write_hex_fn = ldb_handler_copy
1574 .name = "RMD_LOCAL_USN",
1575 .read_fn = ldb_handler_copy,
1576 .write_clear_fn = ldb_handler_copy,
1577 .write_hex_fn = ldb_handler_copy
1579 .name = "RMD_ORIGINATING_USN",
1580 .read_fn = ldb_handler_copy,
1581 .write_clear_fn = ldb_handler_copy,
1582 .write_hex_fn = ldb_handler_copy
1584 .name = "RMD_VERSION",
1585 .read_fn = ldb_handler_copy,
1586 .write_clear_fn = ldb_handler_copy,
1587 .write_hex_fn = ldb_handler_copy
1591 /* TODO: Should be dynamic at some point */
1592 static const struct {
1593 const char *name;
1594 const char *syntax;
1595 } samba_attributes[] = {
1596 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1597 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1598 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1599 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1600 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1601 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1602 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1603 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1604 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1605 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1606 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1607 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1608 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1609 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1610 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1611 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1612 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1615 * these are extracted by searching
1616 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1618 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1619 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1620 * hat can be used to identify the set of policies when applied to a resource.
1621 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1622 * server, we ignore it here.
1624 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1625 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1626 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1627 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1628 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1629 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1630 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1631 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1632 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1635 * these are extracted by searching
1636 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1638 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1639 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1640 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1641 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1642 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1643 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1644 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1645 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1646 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1647 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1648 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1649 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1650 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1651 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1652 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1653 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1654 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1655 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1656 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1657 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1658 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1659 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1660 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1661 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1662 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1663 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1664 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1665 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1668 * these are known to be GUIDs
1670 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1671 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1673 /* These NDR encoded things we want to be able to read with --show-binary */
1674 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1675 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1676 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1677 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1680 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1682 unsigned int j;
1683 const struct ldb_schema_syntax *s = NULL;
1685 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1686 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1687 s = &samba_syntaxes[j];
1688 break;
1691 return s;
1694 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1696 unsigned int j;
1697 const struct ldb_schema_syntax *s = NULL;
1699 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1700 if (strcmp(samba_attributes[j].name, name) == 0) {
1701 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1702 break;
1706 return s;
1709 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret", NULL};
1712 register the samba ldif handlers
1714 int ldb_register_samba_handlers(struct ldb_context *ldb)
1716 unsigned int i;
1717 int ret;
1719 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1720 return LDB_SUCCESS;
1723 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1724 if (ret != LDB_SUCCESS) {
1725 return ret;
1728 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1729 const struct ldb_schema_syntax *s = NULL;
1731 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1733 if (!s) {
1734 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1737 if (!s) {
1738 return LDB_ERR_OPERATIONS_ERROR;
1741 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1742 if (ret != LDB_SUCCESS) {
1743 return ret;
1747 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1748 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1749 if (ret != LDB_SUCCESS) {
1750 return ret;
1755 ret = ldb_register_samba_matching_rules(ldb);
1756 if (ret != LDB_SUCCESS) {
1757 talloc_free(ldb);
1758 return LDB_SUCCESS;
1761 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1762 if (ret != LDB_SUCCESS) {
1763 return ret;
1766 return LDB_SUCCESS;