VERSION: Disable GIT_SNAPSHOT for the 4.17.0rc4 release.
[Samba.git] / lib / ldb-samba / ldif_handlers.c
blob78a433748bbe9f243c52ef9b9f06dc42bd111fe3
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"
39 #include "lib/util/smb_strtox.h"
42 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
44 If mask_errors is true, then function succeeds but out data
45 is set to "<Unable to decode binary data>" message
47 \return 0 on success; -1 on error
49 static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
50 const struct ldb_val *in, struct ldb_val *out,
51 size_t struct_size,
52 ndr_pull_flags_fn_t pull_fn,
53 ndr_print_fn_t print_fn,
54 bool mask_errors)
56 uint8_t *p;
57 enum ndr_err_code err;
58 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
59 return ldb_handler_copy(ldb, mem_ctx, in, out);
61 p = talloc_size(mem_ctx, struct_size);
62 err = ndr_pull_struct_blob(in, mem_ctx,
63 p, pull_fn);
64 if (err != NDR_ERR_SUCCESS) {
65 /* fail in not in mask_error mode */
66 if (!mask_errors) {
67 return -1;
69 talloc_free(p);
70 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
71 out->length = strlen((const char *)out->data);
72 return 0;
74 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
75 talloc_free(p);
76 if (out->data == NULL) {
77 return ldb_handler_copy(ldb, mem_ctx, in, out);
79 out->length = strlen((char *)out->data);
80 return 0;
84 convert a ldif formatted objectSid to a NDR formatted blob
86 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
87 const struct ldb_val *in, struct ldb_val *out)
89 bool ret;
90 enum ndr_err_code ndr_err;
91 struct dom_sid sid;
92 if (in->length > DOM_SID_STR_BUFLEN) {
93 return -1;
94 } else {
95 char p[in->length+1];
96 memcpy(p, in->data, in->length);
97 p[in->length] = '\0';
99 ret = dom_sid_parse(p, &sid);
100 if (ret == false) {
101 return -1;
104 *out = data_blob_talloc(mem_ctx, NULL,
105 ndr_size_dom_sid(&sid, 0));
106 if (out->data == NULL) {
107 return -1;
110 ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
111 (ndr_push_flags_fn_t)ndr_push_dom_sid);
112 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
113 return -1;
116 return 0;
120 convert a NDR formatted blob to a ldif formatted objectSid
122 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
123 const struct ldb_val *in, struct ldb_val *out)
125 struct dom_sid sid;
126 enum ndr_err_code ndr_err;
128 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
129 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
130 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
131 return -1;
133 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
134 if (out->data == NULL) {
135 return -1;
137 return 0;
140 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
142 if (v->length < 3) {
143 return false;
146 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
148 return true;
152 compare two objectSids
154 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
155 const struct ldb_val *v1, const struct ldb_val *v2)
157 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
158 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
159 } else if (ldif_comparision_objectSid_isString(v1)
160 && !ldif_comparision_objectSid_isString(v2)) {
161 struct ldb_val v;
162 int ret;
163 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
164 /* Perhaps not a string after all */
165 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
167 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
168 talloc_free(v.data);
169 return ret;
170 } else if (!ldif_comparision_objectSid_isString(v1)
171 && ldif_comparision_objectSid_isString(v2)) {
172 struct ldb_val v;
173 int ret;
174 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
175 /* Perhaps not a string after all */
176 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
178 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
179 talloc_free(v.data);
180 return ret;
182 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
186 canonicalise a objectSid
188 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
189 const struct ldb_val *in, struct ldb_val *out)
191 if (ldif_comparision_objectSid_isString(in)) {
192 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
193 /* Perhaps not a string after all */
194 return ldb_handler_copy(ldb, mem_ctx, in, out);
196 return 0;
198 return ldb_handler_copy(ldb, mem_ctx, in, out);
201 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
202 const struct ldb_val *in, struct ldb_val *out)
204 struct dom_sid sid;
205 enum ndr_err_code ndr_err;
206 if (ldif_comparision_objectSid_isString(in)) {
207 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
208 return 0;
212 /* Perhaps not a string after all */
213 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
215 if (!out->data) {
216 return -1;
219 (*out).length = strhex_to_str((char *)out->data, out->length,
220 (const char *)in->data, in->length);
222 /* Check it looks like a SID */
223 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
224 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
225 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
226 return -1;
228 return 0;
232 convert a ldif formatted objectGUID to a NDR formatted blob
234 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
235 const struct ldb_val *in, struct ldb_val *out)
237 struct GUID guid;
238 NTSTATUS status;
240 status = GUID_from_data_blob(in, &guid);
241 if (!NT_STATUS_IS_OK(status)) {
242 return -1;
245 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
246 if (!NT_STATUS_IS_OK(status)) {
247 return -1;
249 return 0;
253 convert a NDR formatted blob to a ldif formatted objectGUID
255 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
256 const struct ldb_val *in, struct ldb_val *out)
258 struct GUID guid;
259 NTSTATUS status;
261 status = GUID_from_ndr_blob(in, &guid);
262 if (!NT_STATUS_IS_OK(status)) {
263 return -1;
265 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
266 if (out->data == NULL) {
267 return -1;
269 out->length = strlen((const char *)out->data);
270 return 0;
273 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
275 if (v->length != 36 && v->length != 38) return false;
277 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
278 return true;
281 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
282 const struct ldb_val *in, struct ldb_val *out)
285 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
286 return 0;
289 /* Try as 'hex' form */
290 if (in->length != 32) {
291 return -1;
294 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
296 if (!out->data) {
297 return -1;
300 (*out).length = strhex_to_str((char *)out->data, out->length,
301 (const char *)in->data, in->length);
303 /* Check it looks like a GUID */
304 if ((*out).length != 16) {
305 data_blob_free(out);
306 return -1;
309 return 0;
313 compare two objectGUIDs
315 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
316 const struct ldb_val *v1, const struct ldb_val *v2)
318 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
319 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
320 } else if (ldif_comparision_objectGUID_isString(v1)
321 && !ldif_comparision_objectGUID_isString(v2)) {
322 struct ldb_val v;
323 int ret;
324 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
325 /* Perhaps it wasn't a valid string after all */
326 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
328 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
329 talloc_free(v.data);
330 return ret;
331 } else if (!ldif_comparision_objectGUID_isString(v1)
332 && ldif_comparision_objectGUID_isString(v2)) {
333 struct ldb_val v;
334 int ret;
335 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
336 /* Perhaps it wasn't a valid string after all */
337 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
339 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
340 talloc_free(v.data);
341 return ret;
343 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
347 canonicalise a objectGUID
349 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
350 const struct ldb_val *in, struct ldb_val *out)
352 if (ldif_comparision_objectGUID_isString(in)) {
353 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
354 /* Perhaps it wasn't a valid string after all */
355 return ldb_handler_copy(ldb, mem_ctx, in, out);
357 return 0;
359 return ldb_handler_copy(ldb, mem_ctx, in, out);
364 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
366 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
367 const struct ldb_val *in, struct ldb_val *out)
369 struct security_descriptor *sd;
370 enum ndr_err_code ndr_err;
372 sd = talloc(mem_ctx, struct security_descriptor);
373 if (sd == NULL) {
374 return -1;
377 ndr_err = ndr_pull_struct_blob(in, sd, sd,
378 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
379 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
380 /* If this does not parse, then it is probably SDDL, and we should try it that way */
382 const struct dom_sid *sid = samdb_domain_sid(ldb);
383 talloc_free(sd);
384 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
385 if (sd == NULL) {
386 return -1;
390 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
391 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
392 talloc_free(sd);
393 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
394 return -1;
397 return 0;
401 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
403 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
404 const struct ldb_val *in, struct ldb_val *out)
406 struct security_descriptor *sd;
407 enum ndr_err_code ndr_err;
409 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
410 return ldif_write_NDR(ldb, mem_ctx, in, out,
411 sizeof(struct security_descriptor),
412 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
413 (ndr_print_fn_t)ndr_print_security_descriptor,
414 true);
418 sd = talloc(mem_ctx, struct security_descriptor);
419 if (sd == NULL) {
420 return -1;
422 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
423 ndr_err = ndr_pull_struct_blob(in, sd, sd,
424 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
425 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
426 talloc_free(sd);
427 return -1;
429 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
430 talloc_free(sd);
431 if (out->data == NULL) {
432 return -1;
434 out->length = strlen((const char *)out->data);
435 return 0;
439 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
441 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
442 const struct ldb_val *in, struct ldb_val *out)
444 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
445 struct security_descriptor *sd;
446 const struct dom_sid *sid = samdb_domain_sid(ldb);
448 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
449 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
450 (ndr_print_fn_t)ndr_print_security_descriptor,
451 "SDDL", sd);
452 out->length = strlen((const char *)out->data);
453 talloc_free(sd);
454 return 0;
457 return ldb_handler_copy(ldb, mem_ctx, in, out);
461 canonicalise an objectCategory. We use the long form as the canonical form:
462 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
464 Also any short name of an objectClass that points to a different
465 class (such as user) has the canonical form of the class it's
466 defaultObjectCategory points to (eg
467 cn=Person,cn=Schema,cn=Configuration,<basedn>)
470 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
471 const struct ldb_val *in, struct ldb_val *out)
473 struct ldb_dn *dn1 = NULL;
474 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
475 const struct dsdb_class *sclass;
476 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
477 if (!tmp_ctx) {
478 return LDB_ERR_OPERATIONS_ERROR;
481 if (!schema) {
482 talloc_free(tmp_ctx);
483 *out = data_blob_talloc(mem_ctx, in->data, in->length);
484 if (in->data && !out->data) {
485 return LDB_ERR_OPERATIONS_ERROR;
487 return LDB_SUCCESS;
489 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
490 if ( ! ldb_dn_validate(dn1)) {
491 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
492 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
493 if (sclass) {
494 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
495 sclass->defaultObjectCategory);
496 if (dn == NULL) {
497 talloc_free(tmp_ctx);
498 return LDB_ERR_OPERATIONS_ERROR;
501 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
502 talloc_free(tmp_ctx);
504 if (!out->data) {
505 return LDB_ERR_OPERATIONS_ERROR;
507 return LDB_SUCCESS;
508 } else {
509 *out = data_blob_talloc(mem_ctx, in->data, in->length);
510 talloc_free(tmp_ctx);
512 if (in->data && !out->data) {
513 return LDB_ERR_OPERATIONS_ERROR;
515 return LDB_SUCCESS;
518 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
519 talloc_free(tmp_ctx);
521 if (!out->data) {
522 return LDB_ERR_OPERATIONS_ERROR;
524 return LDB_SUCCESS;
527 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
528 const struct ldb_val *v1,
529 const struct ldb_val *v2)
531 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
532 v1, v2);
536 convert a NDR formatted blob to a ldif formatted schemaInfo
538 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
539 const struct ldb_val *in, struct ldb_val *out)
541 return ldif_write_NDR(ldb, mem_ctx, in, out,
542 sizeof(struct repsFromToBlob),
543 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
544 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
545 true);
549 convert a ldif formatted prefixMap to a NDR formatted blob
551 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
552 const struct ldb_val *in, struct ldb_val *out)
554 struct prefixMapBlob *blob;
555 enum ndr_err_code ndr_err;
556 char *string, *line, *p, *oid;
557 DATA_BLOB oid_blob;
559 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
561 if (tmp_ctx == NULL) {
562 return -1;
565 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
566 if (blob == NULL) {
567 talloc_free(tmp_ctx);
568 return -1;
571 /* use the switch value to detect if this is in the binary
572 * format
574 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
575 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
576 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
577 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
578 ndr_err = ndr_push_struct_blob(out, mem_ctx,
579 blob,
580 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
581 talloc_free(tmp_ctx);
582 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
583 return -1;
585 return 0;
589 /* If this does not parse, then it is probably the text version, and we should try it that way */
590 blob->version = PREFIX_MAP_VERSION_DSDB;
592 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
593 if (string == NULL) {
594 talloc_free(blob);
595 return -1;
598 line = string;
599 while (line && line[0]) {
600 int error = 0;
602 p=strchr(line, ';');
603 if (p) {
604 p[0] = '\0';
605 } else {
606 p=strchr(line, '\n');
607 if (p) {
608 p[0] = '\0';
611 /* allow a trailing separator */
612 if (line == p) {
613 break;
616 blob->ctr.dsdb.mappings = talloc_realloc(blob,
617 blob->ctr.dsdb.mappings,
618 struct drsuapi_DsReplicaOIDMapping,
619 blob->ctr.dsdb.num_mappings+1);
620 if (!blob->ctr.dsdb.mappings) {
621 talloc_free(tmp_ctx);
622 return -1;
625 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
626 smb_strtoul(line, &oid, 10, &error, SMB_STR_STANDARD);
628 if (oid[0] != ':' || error != 0) {
629 talloc_free(tmp_ctx);
630 return -1;
633 /* we know there must be at least ":" */
634 oid++;
636 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
637 talloc_free(tmp_ctx);
638 return -1;
640 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
641 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
643 blob->ctr.dsdb.num_mappings++;
645 /* Now look past the terminator we added above */
646 if (p) {
647 line = p + 1;
648 } else {
649 line = NULL;
653 ndr_err = ndr_push_struct_blob(out, mem_ctx,
654 blob,
655 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
656 talloc_free(tmp_ctx);
657 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
658 return -1;
660 return 0;
664 convert a NDR formatted blob to a ldif formatted prefixMap
666 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
667 const struct ldb_val *in, struct ldb_val *out)
669 struct prefixMapBlob *blob;
670 enum ndr_err_code ndr_err;
671 char *string;
672 uint32_t i;
674 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
675 int err;
676 /* try to decode the blob as S4 prefixMap */
677 err = ldif_write_NDR(ldb, mem_ctx, in, out,
678 sizeof(struct prefixMapBlob),
679 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
680 (ndr_print_fn_t)ndr_print_prefixMapBlob,
681 false);
682 if (0 == err) {
683 return err;
685 /* try parsing it as Windows PrefixMap value */
686 return ldif_write_NDR(ldb, mem_ctx, in, out,
687 sizeof(struct drsuapi_MSPrefixMap_Ctr),
688 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
689 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
690 true);
693 blob = talloc(mem_ctx, struct prefixMapBlob);
694 if (blob == NULL) {
695 return -1;
697 ndr_err = ndr_pull_struct_blob_all(in, blob,
698 blob,
699 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
700 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
701 goto failed;
703 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
704 goto failed;
706 string = talloc_strdup(mem_ctx, "");
707 if (string == NULL) {
708 goto failed;
711 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
712 DATA_BLOB oid_blob;
713 char *partial_oid = NULL;
715 if (i > 0) {
716 string = talloc_asprintf_append(string, ";");
719 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
720 blob->ctr.dsdb.mappings[i].oid.length);
721 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
722 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
723 blob->ctr.dsdb.mappings[i].id_prefix));
724 goto failed;
726 string = talloc_asprintf_append(string, "%u:%s",
727 blob->ctr.dsdb.mappings[i].id_prefix,
728 partial_oid);
729 talloc_free(discard_const(partial_oid));
730 if (string == NULL) {
731 goto failed;
735 talloc_free(blob);
736 *out = data_blob_string_const(string);
737 return 0;
739 failed:
740 talloc_free(blob);
741 return -1;
744 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
746 if (v->length < 4) {
747 return true;
750 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
751 return false;
754 return true;
758 canonicalise a prefixMap
760 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
761 const struct ldb_val *in, struct ldb_val *out)
763 if (ldif_comparision_prefixMap_isString(in)) {
764 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
766 return ldb_handler_copy(ldb, mem_ctx, in, out);
769 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
770 const struct ldb_val *v1,
771 const struct ldb_val *v2)
773 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
774 v1, v2);
777 /* length limited conversion of a ldb_val to a int32_t */
778 static int val_to_int32(const struct ldb_val *in, int32_t *v)
780 char *end;
781 char buf[64];
783 /* make sure we don't read past the end of the data */
784 if (in->length > sizeof(buf)-1) {
785 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
787 strncpy(buf, (char *)in->data, in->length);
788 buf[in->length] = 0;
790 /* We've to use "strtoll" here to have the intended overflows.
791 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
792 *v = (int32_t) strtoll(buf, &end, 0);
793 if (*end != 0) {
794 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
796 return LDB_SUCCESS;
799 /* length limited conversion of a ldb_val to a int64_t */
800 static int val_to_int64(const struct ldb_val *in, int64_t *v)
802 char *end;
803 char buf[64];
805 /* make sure we don't read past the end of the data */
806 if (in->length > sizeof(buf)-1) {
807 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
809 strncpy(buf, (char *)in->data, in->length);
810 buf[in->length] = 0;
812 *v = (int64_t) strtoll(buf, &end, 0);
813 if (*end != 0) {
814 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
816 return LDB_SUCCESS;
819 /* Canonicalisation of two 32-bit integers */
820 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
821 const struct ldb_val *in, struct ldb_val *out)
823 int32_t i;
824 int ret;
826 ret = val_to_int32(in, &i);
827 if (ret != LDB_SUCCESS) {
828 return ret;
830 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
831 if (out->data == NULL) {
832 ldb_oom(ldb);
833 return LDB_ERR_OPERATIONS_ERROR;
835 out->length = strlen((char *)out->data);
836 return 0;
840 * Lexicographically sorted representation for a 32-bit integer
842 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
843 * n o p
845 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
846 * corresponding documentation for 64-bit integers.
848 * The same rules apply but use INT32_MIN and INT32_MAX.
850 * String representation padding is done to 10 characters.
852 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
855 static int ldif_index_format_int32(struct ldb_context *ldb,
856 void *mem_ctx,
857 const struct ldb_val *in,
858 struct ldb_val *out)
860 int32_t i;
861 int ret;
862 char prefix;
863 size_t len;
865 ret = val_to_int32(in, &i);
866 if (ret != LDB_SUCCESS) {
867 return ret;
870 if (i < 0) {
872 * i is negative, so this is subtraction rather than
873 * wrap-around.
875 prefix = 'n';
876 i = INT32_MAX + i + 1;
877 } else if (i > 0) {
878 prefix = 'p';
879 } else {
880 prefix = 'o';
883 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
884 if (out->data == NULL) {
885 ldb_oom(ldb);
886 return LDB_ERR_OPERATIONS_ERROR;
889 len = talloc_array_length(out->data) - 1;
890 if (len != 11) {
891 ldb_debug(ldb, LDB_DEBUG_ERROR,
892 __location__ ": expected index format str %s to"
893 " have length 11 but got %zu",
894 (char*)out->data, len);
895 return LDB_ERR_OPERATIONS_ERROR;
898 out->length = 11;
899 return 0;
902 /* Comparison of two 32-bit integers */
903 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
904 const struct ldb_val *v1, const struct ldb_val *v2)
906 int32_t i1=0, i2=0;
907 val_to_int32(v1, &i1);
908 val_to_int32(v2, &i2);
909 if (i1 == i2) return 0;
910 return i1 > i2? 1 : -1;
913 /* Canonicalisation of two 64-bit integers */
914 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
915 const struct ldb_val *in, struct ldb_val *out)
917 int64_t i;
918 int ret;
920 ret = val_to_int64(in, &i);
921 if (ret != LDB_SUCCESS) {
922 return ret;
924 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
925 if (out->data == NULL) {
926 ldb_oom(ldb);
927 return LDB_ERR_OPERATIONS_ERROR;
929 out->length = strlen((char *)out->data);
930 return 0;
933 /* Comparison of two 64-bit integers */
934 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
935 const struct ldb_val *v1, const struct ldb_val *v2)
937 int64_t i1=0, i2=0;
938 val_to_int64(v1, &i1);
939 val_to_int64(v2, &i2);
940 if (i1 == i2) return 0;
941 return i1 > i2? 1 : -1;
945 convert a NDR formatted blob to a ldif formatted repsFromTo
947 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
948 const struct ldb_val *in, struct ldb_val *out)
950 return ldif_write_NDR(ldb, mem_ctx, in, out,
951 sizeof(struct repsFromToBlob),
952 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
953 (ndr_print_fn_t)ndr_print_repsFromToBlob,
954 true);
958 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
960 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
961 const struct ldb_val *in, struct ldb_val *out)
963 return ldif_write_NDR(ldb, mem_ctx, in, out,
964 sizeof(struct replPropertyMetaDataBlob),
965 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
966 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
967 true);
971 convert a NDR formatted blob to a ldif formatted replUpToDateVector
973 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
974 const struct ldb_val *in, struct ldb_val *out)
976 return ldif_write_NDR(ldb, mem_ctx, in, out,
977 sizeof(struct replUpToDateVectorBlob),
978 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
979 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
980 true);
983 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
984 const struct ldb_val *in, struct ldb_val *out,
985 size_t struct_size,
986 ndr_pull_flags_fn_t pull_fn,
987 ndr_print_fn_t print_fn,
988 bool mask_errors)
990 uint8_t *p = NULL;
991 enum ndr_err_code err;
992 struct dsdb_dn *dsdb_dn = NULL;
993 char *dn_str = NULL;
994 char *str = NULL;
996 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
997 return ldb_handler_copy(ldb, mem_ctx, in, out);
1000 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
1001 if (dsdb_dn == NULL) {
1002 return ldb_handler_copy(ldb, mem_ctx, in, out);
1005 p = talloc_size(dsdb_dn, struct_size);
1006 if (p == NULL) {
1007 TALLOC_FREE(dsdb_dn);
1008 return ldb_handler_copy(ldb, mem_ctx, in, out);
1011 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
1012 if (err != NDR_ERR_SUCCESS) {
1013 /* fail in not in mask_error mode */
1014 if (!mask_errors) {
1015 return -1;
1017 TALLOC_FREE(dsdb_dn);
1018 return ldb_handler_copy(ldb, mem_ctx, in, out);
1021 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
1022 if (dn_str == NULL) {
1023 TALLOC_FREE(dsdb_dn);
1024 return ldb_handler_copy(ldb, mem_ctx, in, out);
1027 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
1028 TALLOC_FREE(dsdb_dn);
1029 if (str == NULL) {
1030 return ldb_handler_copy(ldb, mem_ctx, in, out);
1033 *out = data_blob_string_const(str);
1034 return 0;
1037 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
1038 const struct ldb_val *in, struct ldb_val *out)
1040 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
1041 sizeof(struct replPropertyMetaData1),
1042 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
1043 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
1044 true);
1048 convert a NDR formatted blob to a ldif formatted dnsRecord
1050 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
1051 const struct ldb_val *in, struct ldb_val *out)
1053 return ldif_write_NDR(ldb, mem_ctx, in, out,
1054 sizeof(struct dnsp_DnssrvRpcRecord),
1055 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
1056 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
1057 true);
1061 convert a NDR formatted blob to a ldif formatted dnsProperty
1063 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1064 const struct ldb_val *in, struct ldb_val *out)
1066 return ldif_write_NDR(ldb, mem_ctx, in, out,
1067 sizeof(struct dnsp_DnsProperty),
1068 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1069 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1070 true);
1074 convert a NDR formatted blob of a supplementalCredentials into text
1076 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1077 const struct ldb_val *in, struct ldb_val *out)
1079 return ldif_write_NDR(ldb, mem_ctx, in, out,
1080 sizeof(struct supplementalCredentialsBlob),
1081 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1082 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1083 true);
1087 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1089 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1090 const struct ldb_val *in, struct ldb_val *out)
1092 return ldif_write_NDR(ldb, mem_ctx, in, out,
1093 sizeof(struct trustAuthInOutBlob),
1094 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1095 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1096 true);
1100 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1102 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1103 const struct ldb_val *in, struct ldb_val *out)
1105 return ldif_write_NDR(ldb, mem_ctx, in, out,
1106 sizeof(struct ForestTrustInfo),
1107 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1108 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1109 true);
1112 convert a NDR formatted blob of a partialAttributeSet into text
1114 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1115 const struct ldb_val *in, struct ldb_val *out)
1117 return ldif_write_NDR(ldb, mem_ctx, in, out,
1118 sizeof(struct partialAttributeSetBlob),
1119 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1120 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1121 true);
1125 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1126 const struct ldb_val *in, struct ldb_val *out)
1128 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1129 if (!out->data) {
1130 return -1;
1132 return 0;
1136 compare two dns
1138 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1139 const struct ldb_val *v1, const struct ldb_val *v2)
1141 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1142 int ret;
1144 if (dsdb_dn_is_deleted_val(v1)) {
1145 /* If the DN is deleted, then we can't search for it */
1146 return -1;
1149 if (dsdb_dn_is_deleted_val(v2)) {
1150 /* If the DN is deleted, then we can't search for it */
1151 return -1;
1154 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1155 if ( ! ldb_dn_validate(dn1)) return -1;
1157 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1158 if ( ! ldb_dn_validate(dn2)) {
1159 talloc_free(dn1);
1160 return -1;
1163 ret = ldb_dn_compare(dn1, dn2);
1165 talloc_free(dn1);
1166 talloc_free(dn2);
1167 return ret;
1170 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1171 const struct ldb_val *in, struct ldb_val *out)
1173 struct ldb_dn *dn;
1174 int ret = -1;
1176 out->length = 0;
1177 out->data = NULL;
1179 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1180 if ( ! ldb_dn_validate(dn)) {
1181 return LDB_ERR_INVALID_DN_SYNTAX;
1184 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1185 * does not casually match a not deleted DN */
1186 if (dsdb_dn_is_deleted_val(in)) {
1187 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1188 "<RMD_FLAGS=%u>%s",
1189 dsdb_dn_val_rmd_flags(in),
1190 ldb_dn_get_casefold(dn));
1191 } else {
1192 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1195 if (out->data == NULL) {
1196 goto done;
1198 out->length = strlen((char *)out->data);
1200 ret = 0;
1202 done:
1203 talloc_free(dn);
1205 return ret;
1210 write a 64 bit 2-part range
1212 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1213 const struct ldb_val *in, struct ldb_val *out)
1215 int64_t v;
1216 int ret;
1217 ret = val_to_int64(in, &v);
1218 if (ret != LDB_SUCCESS) {
1219 return ret;
1221 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1222 (unsigned long)(v&0xFFFFFFFF),
1223 (unsigned long)(v>>32));
1224 if (out->data == NULL) {
1225 ldb_oom(ldb);
1226 return LDB_ERR_OPERATIONS_ERROR;
1228 out->length = strlen((char *)out->data);
1229 return LDB_SUCCESS;
1233 read a 64 bit 2-part range
1235 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1236 const struct ldb_val *in, struct ldb_val *out)
1238 unsigned long high, low;
1239 char buf[64];
1241 if (memchr(in->data, '-', in->length) == NULL) {
1242 return ldb_handler_copy(ldb, mem_ctx, in, out);
1245 if (in->length > sizeof(buf)-1) {
1246 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1248 strncpy(buf, (const char *)in->data, in->length);
1249 buf[in->length] = 0;
1251 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1252 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1255 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1256 (unsigned long long)(((uint64_t)high)<<32) | (low));
1258 if (out->data == NULL) {
1259 ldb_oom(ldb);
1260 return LDB_ERR_OPERATIONS_ERROR;
1262 out->length = strlen((char *)out->data);
1263 return LDB_SUCCESS;
1267 when this operator_fn is set for a syntax, the backend calls is in
1268 preference to the comparison function. We are told the exact
1269 comparison operation that is needed, and we can return errors
1271 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1272 const struct ldb_schema_attribute *a,
1273 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1275 switch (operation) {
1276 case LDB_OP_AND:
1277 case LDB_OP_OR:
1278 case LDB_OP_NOT:
1279 case LDB_OP_SUBSTRING:
1280 case LDB_OP_APPROX:
1281 case LDB_OP_EXTENDED:
1282 /* handled in the backends */
1283 return LDB_ERR_INAPPROPRIATE_MATCHING;
1285 case LDB_OP_GREATER:
1286 case LDB_OP_LESS:
1287 case LDB_OP_EQUALITY:
1289 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1290 int ret;
1291 if (tmp_ctx == NULL) {
1292 return ldb_oom(ldb);
1294 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1295 talloc_free(tmp_ctx);
1296 if (operation == LDB_OP_GREATER) {
1297 *matched = (ret >= 0);
1298 } else if (operation == LDB_OP_LESS) {
1299 *matched = (ret <= 0);
1300 } else {
1301 *matched = (ret == 0);
1303 return LDB_SUCCESS;
1306 case LDB_OP_PRESENT:
1307 *matched = true;
1308 return LDB_SUCCESS;
1311 /* we shouldn't get here */
1312 return LDB_ERR_INAPPROPRIATE_MATCHING;
1316 compare two binary objects. This is correct for sorting as the sort order is:
1323 rather than ldb_comparison_binary() which is:
1331 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1332 const struct ldb_val *v1, const struct ldb_val *v2)
1334 return data_blob_cmp(v1, v2);
1338 when this operator_fn is set for a syntax, the backend calls is in
1339 preference to the comparison function. We are told the exact
1340 comparison operation that is needed, and we can return errors.
1342 This mode optimises for ldb_comparison_binary() if we need equality,
1343 as this should be faster as it can do a length-check first.
1345 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1346 const struct ldb_schema_attribute *a,
1347 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1349 if (operation == LDB_OP_EQUALITY) {
1350 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1351 return LDB_SUCCESS;
1353 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1357 see if two DNs match, comparing first by GUID, then by SID, and
1358 finally by string components
1360 static int samba_dn_extended_match(struct ldb_context *ldb,
1361 const struct ldb_val *v1,
1362 const struct ldb_val *v2,
1363 bool *matched)
1365 TALLOC_CTX *tmp_ctx;
1366 struct ldb_dn *dn1, *dn2;
1367 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1368 uint32_t rmd_flags1, rmd_flags2;
1370 tmp_ctx = talloc_new(ldb);
1372 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1373 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1374 if (!dn1 || !dn2) {
1375 /* couldn't parse as DN's */
1376 talloc_free(tmp_ctx);
1377 (*matched) = false;
1378 return LDB_SUCCESS;
1381 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1382 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1384 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1385 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1386 /* only match if they have the same deletion status */
1387 talloc_free(tmp_ctx);
1388 (*matched) = false;
1389 return LDB_SUCCESS;
1393 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1394 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1395 if (guid1 && guid2) {
1396 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1397 talloc_free(tmp_ctx);
1398 return LDB_SUCCESS;
1401 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1402 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1403 if (sid1 && sid2) {
1404 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1405 talloc_free(tmp_ctx);
1406 return LDB_SUCCESS;
1409 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1411 talloc_free(tmp_ctx);
1412 return LDB_SUCCESS;
1416 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1418 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1419 const struct ldb_schema_attribute *a,
1420 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1422 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1423 /* If the DN is deleted, then we can't search for it */
1425 /* should this be for equality too? */
1426 *matched = false;
1427 return LDB_SUCCESS;
1430 if (operation == LDB_OP_EQUALITY &&
1431 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1432 return LDB_SUCCESS;
1435 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1439 static const struct ldb_schema_syntax samba_syntaxes[] = {
1441 .name = LDB_SYNTAX_SAMBA_SID,
1442 .ldif_read_fn = ldif_read_objectSid,
1443 .ldif_write_fn = ldif_write_objectSid,
1444 .canonicalise_fn = ldif_canonicalise_objectSid,
1445 .comparison_fn = ldif_comparison_objectSid,
1446 .operator_fn = samba_syntax_operator_fn
1448 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1449 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1450 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1451 .canonicalise_fn = ldb_handler_copy,
1452 .comparison_fn = samba_ldb_comparison_binary,
1453 .operator_fn = samba_syntax_binary_operator_fn
1455 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1456 .ldif_read_fn = ldb_handler_copy,
1457 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1458 .canonicalise_fn = ldb_handler_fold,
1459 .comparison_fn = ldb_comparison_fold,
1460 .operator_fn = samba_syntax_operator_fn
1462 .name = LDB_SYNTAX_SAMBA_GUID,
1463 .ldif_read_fn = ldif_read_objectGUID,
1464 .ldif_write_fn = ldif_write_objectGUID,
1465 .canonicalise_fn = ldif_canonicalise_objectGUID,
1466 .comparison_fn = ldif_comparison_objectGUID,
1467 .operator_fn = samba_syntax_operator_fn
1469 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1470 .ldif_read_fn = ldb_handler_copy,
1471 .ldif_write_fn = ldb_handler_copy,
1472 .canonicalise_fn = ldif_canonicalise_objectCategory,
1473 .comparison_fn = ldif_comparison_objectCategory,
1474 .operator_fn = samba_syntax_operator_fn
1476 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1477 .ldif_read_fn = ldb_handler_copy,
1478 .ldif_write_fn = ldif_write_schemaInfo,
1479 .canonicalise_fn = ldb_handler_copy,
1480 .comparison_fn = samba_ldb_comparison_binary,
1481 .operator_fn = samba_syntax_binary_operator_fn
1483 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1484 .ldif_read_fn = ldif_read_prefixMap,
1485 .ldif_write_fn = ldif_write_prefixMap,
1486 .canonicalise_fn = ldif_canonicalise_prefixMap,
1487 .comparison_fn = ldif_comparison_prefixMap,
1488 .operator_fn = samba_syntax_operator_fn
1490 .name = LDB_SYNTAX_SAMBA_INT32,
1491 .ldif_read_fn = ldb_handler_copy,
1492 .ldif_write_fn = ldb_handler_copy,
1493 .canonicalise_fn = ldif_canonicalise_int32,
1494 .index_format_fn = ldif_index_format_int32,
1495 .comparison_fn = ldif_comparison_int32,
1496 .operator_fn = samba_syntax_operator_fn
1498 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1499 .ldif_read_fn = ldb_handler_copy,
1500 .ldif_write_fn = ldif_write_repsFromTo,
1501 .canonicalise_fn = ldb_handler_copy,
1502 .comparison_fn = samba_ldb_comparison_binary,
1503 .operator_fn = samba_syntax_binary_operator_fn
1505 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1506 .ldif_read_fn = ldb_handler_copy,
1507 .ldif_write_fn = ldif_write_replPropertyMetaData,
1508 .canonicalise_fn = ldb_handler_copy,
1509 .comparison_fn = samba_ldb_comparison_binary,
1510 .operator_fn = samba_syntax_binary_operator_fn
1512 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1513 .ldif_read_fn = ldb_handler_copy,
1514 .ldif_write_fn = ldif_write_replUpToDateVector,
1515 .canonicalise_fn = ldb_handler_copy,
1516 .comparison_fn = samba_ldb_comparison_binary,
1517 .operator_fn = samba_syntax_binary_operator_fn
1519 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1520 .ldif_read_fn = ldb_handler_copy,
1521 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1522 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1523 .comparison_fn = dsdb_dn_binary_comparison,
1524 .operator_fn = samba_syntax_operator_fn
1526 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1527 .ldif_read_fn = ldb_handler_copy,
1528 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1529 .canonicalise_fn = ldb_handler_copy,
1530 .comparison_fn = samba_ldb_comparison_binary,
1531 .operator_fn = samba_syntax_binary_operator_fn
1533 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1534 .ldif_read_fn = ldb_handler_copy,
1535 .ldif_write_fn = ldif_write_ForestTrustInfo,
1536 .canonicalise_fn = ldb_handler_copy,
1537 .comparison_fn = samba_ldb_comparison_binary,
1538 .operator_fn = samba_syntax_binary_operator_fn
1540 .name = DSDB_SYNTAX_BINARY_DN,
1541 .ldif_read_fn = ldb_handler_copy,
1542 .ldif_write_fn = ldb_handler_copy,
1543 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1544 .comparison_fn = dsdb_dn_binary_comparison,
1545 .operator_fn = samba_syntax_operator_fn
1547 .name = DSDB_SYNTAX_STRING_DN,
1548 .ldif_read_fn = ldb_handler_copy,
1549 .ldif_write_fn = ldb_handler_copy,
1550 .canonicalise_fn = dsdb_dn_string_canonicalise,
1551 .comparison_fn = dsdb_dn_string_comparison,
1552 .operator_fn = samba_syntax_operator_fn
1554 .name = LDB_SYNTAX_DN,
1555 .ldif_read_fn = ldb_handler_copy,
1556 .ldif_write_fn = ldb_handler_copy,
1557 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1558 .comparison_fn = samba_ldb_dn_link_comparison,
1559 .operator_fn = samba_syntax_operator_dn
1561 .name = LDB_SYNTAX_SAMBA_RANGE64,
1562 .ldif_read_fn = ldif_read_range64,
1563 .ldif_write_fn = ldif_write_range64,
1564 .canonicalise_fn = ldif_canonicalise_int64,
1565 .comparison_fn = ldif_comparison_int64,
1566 .operator_fn = samba_syntax_operator_fn
1568 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1569 .ldif_read_fn = ldb_handler_copy,
1570 .ldif_write_fn = ldif_write_dnsRecord,
1571 .canonicalise_fn = ldb_handler_copy,
1572 .comparison_fn = samba_ldb_comparison_binary,
1573 .operator_fn = samba_syntax_binary_operator_fn
1575 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1576 .ldif_read_fn = ldb_handler_copy,
1577 .ldif_write_fn = ldif_write_dnsProperty,
1578 .canonicalise_fn = ldb_handler_copy,
1579 .comparison_fn = samba_ldb_comparison_binary,
1580 .operator_fn = samba_syntax_binary_operator_fn
1582 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1583 .ldif_read_fn = ldb_handler_copy,
1584 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1585 .canonicalise_fn = ldb_handler_copy,
1586 .comparison_fn = samba_ldb_comparison_binary,
1587 .operator_fn = samba_syntax_binary_operator_fn
1589 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1590 .ldif_read_fn = ldb_handler_copy,
1591 .ldif_write_fn = ldif_write_partialAttributeSet,
1592 .canonicalise_fn = ldb_handler_copy,
1593 .comparison_fn = samba_ldb_comparison_binary,
1594 .operator_fn = samba_syntax_binary_operator_fn
1596 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1597 .ldif_read_fn = ldb_handler_copy,
1598 .ldif_write_fn = ldb_handler_copy,
1599 .canonicalise_fn = ldb_handler_copy,
1600 .comparison_fn = samba_ldb_comparison_binary,
1601 .operator_fn = samba_syntax_binary_operator_fn
1605 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1607 .name = "SID",
1608 .read_fn = extended_dn_read_SID,
1609 .write_clear_fn = ldif_write_objectSid,
1610 .write_hex_fn = extended_dn_write_hex
1612 .name = "GUID",
1613 .read_fn = extended_dn_read_GUID,
1614 .write_clear_fn = ldif_write_objectGUID,
1615 .write_hex_fn = extended_dn_write_hex
1617 .name = "WKGUID",
1618 .read_fn = ldb_handler_copy,
1619 .write_clear_fn = ldb_handler_copy,
1620 .write_hex_fn = ldb_handler_copy
1622 .name = "RMD_INVOCID",
1623 .read_fn = extended_dn_read_GUID,
1624 .write_clear_fn = ldif_write_objectGUID,
1625 .write_hex_fn = extended_dn_write_hex
1627 .name = "RMD_FLAGS",
1628 .read_fn = ldb_handler_copy,
1629 .write_clear_fn = ldb_handler_copy,
1630 .write_hex_fn = ldb_handler_copy
1632 .name = "RMD_ADDTIME",
1633 .read_fn = ldb_handler_copy,
1634 .write_clear_fn = ldb_handler_copy,
1635 .write_hex_fn = ldb_handler_copy
1637 .name = "RMD_CHANGETIME",
1638 .read_fn = ldb_handler_copy,
1639 .write_clear_fn = ldb_handler_copy,
1640 .write_hex_fn = ldb_handler_copy
1642 .name = "RMD_LOCAL_USN",
1643 .read_fn = ldb_handler_copy,
1644 .write_clear_fn = ldb_handler_copy,
1645 .write_hex_fn = ldb_handler_copy
1647 .name = "RMD_ORIGINATING_USN",
1648 .read_fn = ldb_handler_copy,
1649 .write_clear_fn = ldb_handler_copy,
1650 .write_hex_fn = ldb_handler_copy
1652 .name = "RMD_VERSION",
1653 .read_fn = ldb_handler_copy,
1654 .write_clear_fn = ldb_handler_copy,
1655 .write_hex_fn = ldb_handler_copy
1659 /* TODO: Should be dynamic at some point */
1660 static const struct {
1661 const char *name;
1662 const char *syntax;
1663 } samba_attributes[] = {
1664 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1665 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1666 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1667 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1668 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1669 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1670 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1671 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1672 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1673 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1674 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1675 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1676 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1677 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1678 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1679 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1680 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1683 * these are extracted by searching
1684 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1686 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1687 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1688 * hat can be used to identify the set of policies when applied to a resource.
1689 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1690 * server, we ignore it here.
1692 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1693 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1694 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1695 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1696 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1697 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1698 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1699 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1700 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1703 * these are extracted by searching
1704 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1706 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1707 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1708 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1709 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1710 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1711 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1712 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1713 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1714 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1715 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1716 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1717 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1718 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1719 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1720 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1721 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1722 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1723 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1724 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1725 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1726 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1727 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1728 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1729 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1730 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1731 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1732 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1733 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1736 * these are known to be GUIDs
1738 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1739 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1741 /* These NDR encoded things we want to be able to read with --show-binary */
1742 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1743 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1744 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1745 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1748 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1750 unsigned int j;
1751 const struct ldb_schema_syntax *s = NULL;
1753 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1754 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1755 s = &samba_syntaxes[j];
1756 break;
1759 return s;
1762 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1764 unsigned int j;
1765 const struct ldb_schema_syntax *s = NULL;
1767 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1768 if (strcmp(samba_attributes[j].name, name) == 0) {
1769 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1770 break;
1774 return s;
1777 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1778 "priorSecret", NULL};
1781 register the samba ldif handlers
1783 int ldb_register_samba_handlers(struct ldb_context *ldb)
1785 unsigned int i;
1786 int ret;
1788 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1789 return LDB_SUCCESS;
1792 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1793 if (ret != LDB_SUCCESS) {
1794 return ret;
1797 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1798 const struct ldb_schema_syntax *s = NULL;
1800 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1802 if (!s) {
1803 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1806 if (!s) {
1807 return LDB_ERR_OPERATIONS_ERROR;
1810 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1811 if (ret != LDB_SUCCESS) {
1812 return ret;
1816 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1817 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1818 if (ret != LDB_SUCCESS) {
1819 return ret;
1824 ret = ldb_register_samba_matching_rules(ldb);
1825 if (ret != LDB_SUCCESS) {
1826 talloc_free(ldb);
1827 return LDB_SUCCESS;
1830 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1831 if (ret != LDB_SUCCESS) {
1832 return ret;
1835 return LDB_SUCCESS;