ldb-samba: ldif-handlers: make ldif_comparison_objectSid() accurate
[Samba.git] / lib / ldb-samba / ldif_handlers.c
blob8873ee6e4e64df5fbfef3f877d38396adaf8b968
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 If the SIDs seem to be strings, they are converted to binary form.
156 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
157 const struct ldb_val *v1, const struct ldb_val *v2)
159 bool v1_is_string = ldif_comparision_objectSid_isString(v1);
160 bool v2_is_string = ldif_comparision_objectSid_isString(v2);
161 struct ldb_val parsed_1 = {};
162 struct ldb_val parsed_2 = {};
163 int ret;
165 * If the ldb_vals look like SID strings (i.e. start with "S-"
166 * or "s-"), we try to parse them as such. If that fails, we
167 * assume they are binary SIDs, even though that's not really
168 * possible -- the first two bytes of a struct dom_sid are the
169 * version (1), and the number of sub-auths (<= 15), neither
170 * of which are close to 'S' or '-'.
172 if (v1_is_string) {
173 int r = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1);
174 if (r == 0) {
175 v1 = &parsed_1;
178 if (v2_is_string) {
179 int r = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2);
180 if (r == 0) {
181 v2 = &parsed_2;
185 ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
187 if (v1_is_string) {
188 TALLOC_FREE(parsed_1.data);
190 if (v2_is_string) {
191 TALLOC_FREE(parsed_2.data);
193 return ret;
197 canonicalise a objectSid
199 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
200 const struct ldb_val *in, struct ldb_val *out)
202 if (ldif_comparision_objectSid_isString(in)) {
203 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
204 /* Perhaps not a string after all */
205 return ldb_handler_copy(ldb, mem_ctx, in, out);
207 return 0;
209 return ldb_handler_copy(ldb, mem_ctx, in, out);
212 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
213 const struct ldb_val *in, struct ldb_val *out)
215 struct dom_sid sid;
216 enum ndr_err_code ndr_err;
217 if (ldif_comparision_objectSid_isString(in)) {
218 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
219 return 0;
223 /* Perhaps not a string after all */
224 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
226 if (!out->data) {
227 return -1;
230 (*out).length = strhex_to_str((char *)out->data, out->length,
231 (const char *)in->data, in->length);
233 /* Check it looks like a SID */
234 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
235 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
236 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
237 return -1;
239 return 0;
243 convert a ldif formatted objectGUID to a NDR formatted blob
245 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
246 const struct ldb_val *in, struct ldb_val *out)
248 struct GUID guid;
249 NTSTATUS status;
251 status = GUID_from_data_blob(in, &guid);
252 if (!NT_STATUS_IS_OK(status)) {
253 return -1;
256 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
257 if (!NT_STATUS_IS_OK(status)) {
258 return -1;
260 return 0;
264 convert a NDR formatted blob to a ldif formatted objectGUID
266 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
267 const struct ldb_val *in, struct ldb_val *out)
269 struct GUID guid;
270 NTSTATUS status;
272 status = GUID_from_ndr_blob(in, &guid);
273 if (!NT_STATUS_IS_OK(status)) {
274 return -1;
276 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
277 if (out->data == NULL) {
278 return -1;
280 out->length = strlen((const char *)out->data);
281 return 0;
284 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
286 if (v->length != 36 && v->length != 38) return false;
288 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
289 return true;
292 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
293 const struct ldb_val *in, struct ldb_val *out)
296 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
297 return 0;
300 /* Try as 'hex' form */
301 if (in->length != 32) {
302 return -1;
305 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
307 if (!out->data) {
308 return -1;
311 (*out).length = strhex_to_str((char *)out->data, out->length,
312 (const char *)in->data, in->length);
314 /* Check it looks like a GUID */
315 if ((*out).length != 16) {
316 data_blob_free(out);
317 return -1;
320 return 0;
324 compare two objectGUIDs
326 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
327 const struct ldb_val *v1, const struct ldb_val *v2)
329 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
330 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
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, v1, &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, &v, v2);
340 talloc_free(v.data);
341 return ret;
342 } else if (!ldif_comparision_objectGUID_isString(v1)
343 && ldif_comparision_objectGUID_isString(v2)) {
344 struct ldb_val v;
345 int ret;
346 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
347 /* Perhaps it wasn't a valid string after all */
348 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
350 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
351 talloc_free(v.data);
352 return ret;
354 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
358 canonicalise a objectGUID
360 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
361 const struct ldb_val *in, struct ldb_val *out)
363 if (ldif_comparision_objectGUID_isString(in)) {
364 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
365 /* Perhaps it wasn't a valid string after all */
366 return ldb_handler_copy(ldb, mem_ctx, in, out);
368 return 0;
370 return ldb_handler_copy(ldb, mem_ctx, in, out);
375 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
377 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
378 const struct ldb_val *in, struct ldb_val *out)
380 struct security_descriptor *sd;
381 enum ndr_err_code ndr_err;
383 if (in->length >= 2 && isupper(in->data[0]) && in->data[1] == ':') {
385 * If it starts with an upper case character followed by ':',
386 * we know it's not NDR, but most likely SDDL...
388 const struct dom_sid *sid = samdb_domain_sid(ldb);
390 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
391 if (sd == NULL) {
392 return -1;
395 goto decoded;
398 sd = talloc(mem_ctx, struct security_descriptor);
399 if (sd == NULL) {
400 return -1;
403 ndr_err = ndr_pull_struct_blob(in, sd, sd,
404 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
405 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
406 talloc_free(sd);
407 return -1;
410 decoded:
411 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
412 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
413 talloc_free(sd);
414 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
415 return -1;
418 return 0;
422 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
424 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
425 const struct ldb_val *in, struct ldb_val *out)
427 struct security_descriptor *sd;
428 enum ndr_err_code ndr_err;
430 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
431 return ldif_write_NDR(ldb, mem_ctx, in, out,
432 sizeof(struct security_descriptor),
433 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
434 (ndr_print_fn_t)ndr_print_security_descriptor,
435 true);
439 sd = talloc(mem_ctx, struct security_descriptor);
440 if (sd == NULL) {
441 return -1;
443 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
444 ndr_err = ndr_pull_struct_blob(in, sd, sd,
445 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
446 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
447 talloc_free(sd);
448 return -1;
450 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
451 talloc_free(sd);
452 if (out->data == NULL) {
453 return -1;
455 out->length = strlen((const char *)out->data);
456 return 0;
460 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
462 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
463 const struct ldb_val *in, struct ldb_val *out)
465 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
466 struct security_descriptor *sd;
467 const struct dom_sid *sid = samdb_domain_sid(ldb);
469 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
470 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
471 (ndr_print_fn_t)ndr_print_security_descriptor,
472 "SDDL", sd);
473 out->length = strlen((const char *)out->data);
474 talloc_free(sd);
475 return 0;
478 return ldb_handler_copy(ldb, mem_ctx, in, out);
482 canonicalise an objectCategory. We use the long form as the canonical form:
483 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
485 Also any short name of an objectClass that points to a different
486 class (such as user) has the canonical form of the class it's
487 defaultObjectCategory points to (eg
488 cn=Person,cn=Schema,cn=Configuration,<basedn>)
491 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
492 const struct ldb_val *in, struct ldb_val *out)
494 struct ldb_dn *dn1 = NULL;
495 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
496 const struct dsdb_class *sclass;
497 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
498 if (!tmp_ctx) {
499 return LDB_ERR_OPERATIONS_ERROR;
502 if (!schema) {
503 talloc_free(tmp_ctx);
504 *out = data_blob_talloc(mem_ctx, in->data, in->length);
505 if (in->data && !out->data) {
506 return LDB_ERR_OPERATIONS_ERROR;
508 return LDB_SUCCESS;
510 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
511 if ( ! ldb_dn_validate(dn1)) {
512 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
513 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
514 if (sclass) {
515 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
516 sclass->defaultObjectCategory);
517 if (dn == NULL) {
518 talloc_free(tmp_ctx);
519 return LDB_ERR_OPERATIONS_ERROR;
522 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
523 talloc_free(tmp_ctx);
525 if (!out->data) {
526 return LDB_ERR_OPERATIONS_ERROR;
528 return LDB_SUCCESS;
529 } else {
530 *out = data_blob_talloc(mem_ctx, in->data, in->length);
531 talloc_free(tmp_ctx);
533 if (in->data && !out->data) {
534 return LDB_ERR_OPERATIONS_ERROR;
536 return LDB_SUCCESS;
539 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
540 talloc_free(tmp_ctx);
542 if (!out->data) {
543 return LDB_ERR_OPERATIONS_ERROR;
545 return LDB_SUCCESS;
548 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
549 const struct ldb_val *v1,
550 const struct ldb_val *v2)
552 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
553 v1, v2);
557 convert a NDR formatted blob to a ldif formatted schemaInfo
559 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
560 const struct ldb_val *in, struct ldb_val *out)
562 return ldif_write_NDR(ldb, mem_ctx, in, out,
563 sizeof(struct repsFromToBlob),
564 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
565 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
566 true);
570 convert a ldif formatted prefixMap to a NDR formatted blob
572 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
573 const struct ldb_val *in, struct ldb_val *out)
575 struct prefixMapBlob *blob;
576 enum ndr_err_code ndr_err;
577 char *string, *line, *p, *oid;
578 DATA_BLOB oid_blob;
580 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
582 if (tmp_ctx == NULL) {
583 return -1;
586 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
587 if (blob == NULL) {
588 talloc_free(tmp_ctx);
589 return -1;
592 /* use the switch value to detect if this is in the binary
593 * format
595 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
596 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
597 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
598 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
599 ndr_err = ndr_push_struct_blob(out, mem_ctx,
600 blob,
601 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
602 talloc_free(tmp_ctx);
603 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
604 return -1;
606 return 0;
610 /* If this does not parse, then it is probably the text version, and we should try it that way */
611 blob->version = PREFIX_MAP_VERSION_DSDB;
613 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
614 if (string == NULL) {
615 talloc_free(blob);
616 return -1;
619 line = string;
620 while (line && line[0]) {
621 int error = 0;
623 p=strchr(line, ';');
624 if (p) {
625 p[0] = '\0';
626 } else {
627 p=strchr(line, '\n');
628 if (p) {
629 p[0] = '\0';
632 /* allow a trailing separator */
633 if (line == p) {
634 break;
637 blob->ctr.dsdb.mappings = talloc_realloc(blob,
638 blob->ctr.dsdb.mappings,
639 struct drsuapi_DsReplicaOIDMapping,
640 blob->ctr.dsdb.num_mappings+1);
641 if (!blob->ctr.dsdb.mappings) {
642 talloc_free(tmp_ctx);
643 return -1;
646 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
647 smb_strtoul(line, &oid, 10, &error, SMB_STR_STANDARD);
649 if (oid[0] != ':' || error != 0) {
650 talloc_free(tmp_ctx);
651 return -1;
654 /* we know there must be at least ":" */
655 oid++;
657 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
658 talloc_free(tmp_ctx);
659 return -1;
661 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
662 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
664 blob->ctr.dsdb.num_mappings++;
666 /* Now look past the terminator we added above */
667 if (p) {
668 line = p + 1;
669 } else {
670 line = NULL;
674 ndr_err = ndr_push_struct_blob(out, mem_ctx,
675 blob,
676 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
677 talloc_free(tmp_ctx);
678 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
679 return -1;
681 return 0;
685 convert a NDR formatted blob to a ldif formatted prefixMap
687 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
688 const struct ldb_val *in, struct ldb_val *out)
690 struct prefixMapBlob *blob;
691 enum ndr_err_code ndr_err;
692 char *string;
693 uint32_t i;
695 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
696 int err;
697 /* try to decode the blob as S4 prefixMap */
698 err = ldif_write_NDR(ldb, mem_ctx, in, out,
699 sizeof(struct prefixMapBlob),
700 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
701 (ndr_print_fn_t)ndr_print_prefixMapBlob,
702 false);
703 if (0 == err) {
704 return err;
706 /* try parsing it as Windows PrefixMap value */
707 return ldif_write_NDR(ldb, mem_ctx, in, out,
708 sizeof(struct drsuapi_MSPrefixMap_Ctr),
709 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
710 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
711 true);
714 blob = talloc(mem_ctx, struct prefixMapBlob);
715 if (blob == NULL) {
716 return -1;
718 ndr_err = ndr_pull_struct_blob_all(in, blob,
719 blob,
720 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
721 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
722 goto failed;
724 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
725 goto failed;
727 string = talloc_strdup(mem_ctx, "");
728 if (string == NULL) {
729 goto failed;
732 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
733 DATA_BLOB oid_blob;
734 char *partial_oid = NULL;
736 if (i > 0) {
737 talloc_asprintf_addbuf(&string, ";");
740 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
741 blob->ctr.dsdb.mappings[i].oid.length);
742 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
743 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X\n",
744 blob->ctr.dsdb.mappings[i].id_prefix));
745 goto failed;
747 talloc_asprintf_addbuf(&string, "%u:%s",
748 blob->ctr.dsdb.mappings[i].id_prefix,
749 partial_oid);
750 talloc_free(discard_const(partial_oid));
753 talloc_free(blob);
754 *out = data_blob_string_const(string);
755 return 0;
757 failed:
758 talloc_free(blob);
759 return -1;
762 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
764 if (v->length < 4) {
765 return true;
768 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
769 return false;
772 return true;
776 canonicalise a prefixMap
778 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
779 const struct ldb_val *in, struct ldb_val *out)
781 if (ldif_comparision_prefixMap_isString(in)) {
782 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
784 return ldb_handler_copy(ldb, mem_ctx, in, out);
787 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
788 const struct ldb_val *v1,
789 const struct ldb_val *v2)
791 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
792 v1, v2);
795 /* length limited conversion of a ldb_val to a int32_t */
796 static int val_to_int32(const struct ldb_val *in, int32_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 /* We've to use "strtoll" here to have the intended overflows.
809 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
810 *v = (int32_t) strtoll(buf, &end, 0);
811 if (*end != 0) {
812 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
814 return LDB_SUCCESS;
817 /* length limited conversion of a ldb_val to a int64_t */
818 static int val_to_int64(const struct ldb_val *in, int64_t *v)
820 char *end;
821 char buf[64];
823 /* make sure we don't read past the end of the data */
824 if (in->length > sizeof(buf)-1) {
825 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
827 strncpy(buf, (char *)in->data, in->length);
828 buf[in->length] = 0;
830 *v = (int64_t) strtoll(buf, &end, 0);
831 if (*end != 0) {
832 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
834 return LDB_SUCCESS;
837 /* Canonicalisation of two 32-bit integers */
838 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
839 const struct ldb_val *in, struct ldb_val *out)
841 int32_t i;
842 int ret;
844 ret = val_to_int32(in, &i);
845 if (ret != LDB_SUCCESS) {
846 return ret;
848 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
849 if (out->data == NULL) {
850 ldb_oom(ldb);
851 return LDB_ERR_OPERATIONS_ERROR;
853 out->length = strlen((char *)out->data);
854 return 0;
858 * Lexicographically sorted representation for a 32-bit integer
860 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
861 * n o p
863 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
864 * corresponding documentation for 64-bit integers.
866 * The same rules apply but use INT32_MIN and INT32_MAX.
868 * String representation padding is done to 10 characters.
870 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
873 static int ldif_index_format_int32(struct ldb_context *ldb,
874 void *mem_ctx,
875 const struct ldb_val *in,
876 struct ldb_val *out)
878 int32_t i;
879 int ret;
880 char prefix;
881 size_t len;
883 ret = val_to_int32(in, &i);
884 if (ret != LDB_SUCCESS) {
885 return ret;
888 if (i < 0) {
890 * i is negative, so this is subtraction rather than
891 * wrap-around.
893 prefix = 'n';
894 i = INT32_MAX + i + 1;
895 } else if (i > 0) {
896 prefix = 'p';
897 } else {
898 prefix = 'o';
901 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
902 if (out->data == NULL) {
903 ldb_oom(ldb);
904 return LDB_ERR_OPERATIONS_ERROR;
907 len = talloc_array_length(out->data) - 1;
908 if (len != 11) {
909 ldb_debug(ldb, LDB_DEBUG_ERROR,
910 __location__ ": expected index format str %s to"
911 " have length 11 but got %zu",
912 (char*)out->data, len);
913 return LDB_ERR_OPERATIONS_ERROR;
916 out->length = 11;
917 return 0;
920 /* Comparison of two 32-bit integers */
921 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
922 const struct ldb_val *v1, const struct ldb_val *v2)
924 int32_t i1=0, i2=0;
925 val_to_int32(v1, &i1);
926 val_to_int32(v2, &i2);
927 if (i1 == i2) return 0;
928 return i1 > i2? 1 : -1;
931 /* Canonicalisation of two 64-bit integers */
932 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
933 const struct ldb_val *in, struct ldb_val *out)
935 int64_t i;
936 int ret;
938 ret = val_to_int64(in, &i);
939 if (ret != LDB_SUCCESS) {
940 return ret;
942 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
943 if (out->data == NULL) {
944 ldb_oom(ldb);
945 return LDB_ERR_OPERATIONS_ERROR;
947 out->length = strlen((char *)out->data);
948 return 0;
951 /* Comparison of two 64-bit integers */
952 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
953 const struct ldb_val *v1, const struct ldb_val *v2)
955 int64_t i1=0, i2=0;
956 val_to_int64(v1, &i1);
957 val_to_int64(v2, &i2);
958 if (i1 == i2) return 0;
959 return i1 > i2? 1 : -1;
963 convert a NDR formatted blob to a ldif formatted repsFromTo
965 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
966 const struct ldb_val *in, struct ldb_val *out)
968 return ldif_write_NDR(ldb, mem_ctx, in, out,
969 sizeof(struct repsFromToBlob),
970 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
971 (ndr_print_fn_t)ndr_print_repsFromToBlob,
972 true);
976 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
978 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
979 const struct ldb_val *in, struct ldb_val *out)
981 return ldif_write_NDR(ldb, mem_ctx, in, out,
982 sizeof(struct replPropertyMetaDataBlob),
983 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
984 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
985 true);
989 convert a NDR formatted blob to a ldif formatted replUpToDateVector
991 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
992 const struct ldb_val *in, struct ldb_val *out)
994 return ldif_write_NDR(ldb, mem_ctx, in, out,
995 sizeof(struct replUpToDateVectorBlob),
996 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
997 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
998 true);
1001 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
1002 const struct ldb_val *in, struct ldb_val *out,
1003 size_t struct_size,
1004 ndr_pull_flags_fn_t pull_fn,
1005 ndr_print_fn_t print_fn,
1006 bool mask_errors)
1008 uint8_t *p = NULL;
1009 enum ndr_err_code err;
1010 struct dsdb_dn *dsdb_dn = NULL;
1011 char *dn_str = NULL;
1012 char *str = NULL;
1014 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
1015 return ldb_handler_copy(ldb, mem_ctx, in, out);
1018 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
1019 if (dsdb_dn == NULL) {
1020 return ldb_handler_copy(ldb, mem_ctx, in, out);
1023 p = talloc_size(dsdb_dn, struct_size);
1024 if (p == NULL) {
1025 TALLOC_FREE(dsdb_dn);
1026 return ldb_handler_copy(ldb, mem_ctx, in, out);
1029 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
1030 if (err != NDR_ERR_SUCCESS) {
1031 /* fail in not in mask_error mode */
1032 if (!mask_errors) {
1033 return -1;
1035 TALLOC_FREE(dsdb_dn);
1036 return ldb_handler_copy(ldb, mem_ctx, in, out);
1039 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
1040 if (dn_str == NULL) {
1041 TALLOC_FREE(dsdb_dn);
1042 return ldb_handler_copy(ldb, mem_ctx, in, out);
1045 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
1046 TALLOC_FREE(dsdb_dn);
1047 if (str == NULL) {
1048 return ldb_handler_copy(ldb, mem_ctx, in, out);
1051 *out = data_blob_string_const(str);
1052 return 0;
1055 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
1056 const struct ldb_val *in, struct ldb_val *out)
1058 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
1059 sizeof(struct replPropertyMetaData1),
1060 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
1061 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
1062 true);
1066 convert a NDR formatted blob to a ldif formatted dnsRecord
1068 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
1069 const struct ldb_val *in, struct ldb_val *out)
1071 return ldif_write_NDR(ldb, mem_ctx, in, out,
1072 sizeof(struct dnsp_DnssrvRpcRecord),
1073 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
1074 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
1075 true);
1079 convert a NDR formatted blob to a ldif formatted dnsProperty
1081 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1082 const struct ldb_val *in, struct ldb_val *out)
1084 return ldif_write_NDR(ldb, mem_ctx, in, out,
1085 sizeof(struct dnsp_DnsProperty),
1086 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1087 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1088 true);
1092 convert a NDR formatted blob of a supplementalCredentials into text
1094 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1095 const struct ldb_val *in, struct ldb_val *out)
1097 return ldif_write_NDR(ldb, mem_ctx, in, out,
1098 sizeof(struct supplementalCredentialsBlob),
1099 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1100 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1101 true);
1105 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1107 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1108 const struct ldb_val *in, struct ldb_val *out)
1110 return ldif_write_NDR(ldb, mem_ctx, in, out,
1111 sizeof(struct trustAuthInOutBlob),
1112 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1113 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1114 true);
1118 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1120 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1121 const struct ldb_val *in, struct ldb_val *out)
1123 return ldif_write_NDR(ldb, mem_ctx, in, out,
1124 sizeof(struct ForestTrustInfo),
1125 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1126 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1127 true);
1130 convert a NDR formatted blob of a partialAttributeSet into text
1132 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1133 const struct ldb_val *in, struct ldb_val *out)
1135 return ldif_write_NDR(ldb, mem_ctx, in, out,
1136 sizeof(struct partialAttributeSetBlob),
1137 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1138 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1139 true);
1143 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1144 const struct ldb_val *in, struct ldb_val *out)
1146 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1147 if (!out->data) {
1148 return -1;
1150 return 0;
1154 compare two dns
1156 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1157 const struct ldb_val *v1, const struct ldb_val *v2)
1159 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1160 int ret;
1162 if (dsdb_dn_is_deleted_val(v1)) {
1163 /* If the DN is deleted, then we can't search for it */
1164 return -1;
1167 if (dsdb_dn_is_deleted_val(v2)) {
1168 /* If the DN is deleted, then we can't search for it */
1169 return -1;
1172 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1173 if ( ! ldb_dn_validate(dn1)) return -1;
1175 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1176 if ( ! ldb_dn_validate(dn2)) {
1177 talloc_free(dn1);
1178 return -1;
1181 ret = ldb_dn_compare(dn1, dn2);
1183 talloc_free(dn1);
1184 talloc_free(dn2);
1185 return ret;
1188 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1189 const struct ldb_val *in, struct ldb_val *out)
1191 struct ldb_dn *dn;
1192 int ret = -1;
1194 out->length = 0;
1195 out->data = NULL;
1197 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1198 if ( ! ldb_dn_validate(dn)) {
1199 return LDB_ERR_INVALID_DN_SYNTAX;
1202 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1203 * does not casually match a not deleted DN */
1204 if (dsdb_dn_is_deleted_val(in)) {
1205 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1206 "<RMD_FLAGS=%u>%s",
1207 dsdb_dn_val_rmd_flags(in),
1208 ldb_dn_get_casefold(dn));
1209 } else {
1210 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1213 if (out->data == NULL) {
1214 goto done;
1216 out->length = strlen((char *)out->data);
1218 ret = 0;
1220 done:
1221 talloc_free(dn);
1223 return ret;
1228 write a 64 bit 2-part range
1230 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1231 const struct ldb_val *in, struct ldb_val *out)
1233 int64_t v;
1234 int ret;
1235 ret = val_to_int64(in, &v);
1236 if (ret != LDB_SUCCESS) {
1237 return ret;
1239 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1240 (unsigned long)(v&0xFFFFFFFF),
1241 (unsigned long)(v>>32));
1242 if (out->data == NULL) {
1243 ldb_oom(ldb);
1244 return LDB_ERR_OPERATIONS_ERROR;
1246 out->length = strlen((char *)out->data);
1247 return LDB_SUCCESS;
1251 read a 64 bit 2-part range
1253 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1254 const struct ldb_val *in, struct ldb_val *out)
1256 unsigned long high, low;
1257 char buf[64];
1259 if (memchr(in->data, '-', in->length) == NULL) {
1260 return ldb_handler_copy(ldb, mem_ctx, in, out);
1263 if (in->length > sizeof(buf)-1) {
1264 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1266 strncpy(buf, (const char *)in->data, in->length);
1267 buf[in->length] = 0;
1269 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1270 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1273 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1274 (unsigned long long)(((uint64_t)high)<<32) | (low));
1276 if (out->data == NULL) {
1277 ldb_oom(ldb);
1278 return LDB_ERR_OPERATIONS_ERROR;
1280 out->length = strlen((char *)out->data);
1281 return LDB_SUCCESS;
1285 when this operator_fn is set for a syntax, the backend calls is in
1286 preference to the comparison function. We are told the exact
1287 comparison operation that is needed, and we can return errors
1289 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1290 const struct ldb_schema_attribute *a,
1291 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1293 switch (operation) {
1294 case LDB_OP_AND:
1295 case LDB_OP_OR:
1296 case LDB_OP_NOT:
1297 case LDB_OP_SUBSTRING:
1298 case LDB_OP_APPROX:
1299 case LDB_OP_EXTENDED:
1300 /* handled in the backends */
1301 return LDB_ERR_INAPPROPRIATE_MATCHING;
1303 case LDB_OP_GREATER:
1304 case LDB_OP_LESS:
1305 case LDB_OP_EQUALITY:
1307 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1308 int ret;
1309 if (tmp_ctx == NULL) {
1310 return ldb_oom(ldb);
1312 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1313 talloc_free(tmp_ctx);
1314 if (operation == LDB_OP_GREATER) {
1315 *matched = (ret >= 0);
1316 } else if (operation == LDB_OP_LESS) {
1317 *matched = (ret <= 0);
1318 } else {
1319 *matched = (ret == 0);
1321 return LDB_SUCCESS;
1324 case LDB_OP_PRESENT:
1325 *matched = true;
1326 return LDB_SUCCESS;
1329 /* we shouldn't get here */
1330 return LDB_ERR_INAPPROPRIATE_MATCHING;
1334 compare two binary objects. This is correct for sorting as the sort order is:
1341 rather than ldb_comparison_binary() which is:
1349 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1350 const struct ldb_val *v1, const struct ldb_val *v2)
1352 return data_blob_cmp(v1, v2);
1356 when this operator_fn is set for a syntax, the backend calls is in
1357 preference to the comparison function. We are told the exact
1358 comparison operation that is needed, and we can return errors.
1360 This mode optimises for ldb_comparison_binary() if we need equality,
1361 as this should be faster as it can do a length-check first.
1363 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1364 const struct ldb_schema_attribute *a,
1365 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1367 if (operation == LDB_OP_EQUALITY) {
1368 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1369 return LDB_SUCCESS;
1371 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1375 see if two DNs match, comparing first by GUID, then by SID, and
1376 finally by string components
1378 static int samba_dn_extended_match(struct ldb_context *ldb,
1379 const struct ldb_val *v1,
1380 const struct ldb_val *v2,
1381 bool *matched)
1383 TALLOC_CTX *tmp_ctx;
1384 struct ldb_dn *dn1, *dn2;
1385 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1386 uint32_t rmd_flags1, rmd_flags2;
1388 tmp_ctx = talloc_new(ldb);
1390 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1391 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1392 if (!dn1 || !dn2) {
1393 /* couldn't parse as DN's */
1394 talloc_free(tmp_ctx);
1395 (*matched) = false;
1396 return LDB_SUCCESS;
1399 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1400 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1402 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1403 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1404 /* only match if they have the same deletion status */
1405 talloc_free(tmp_ctx);
1406 (*matched) = false;
1407 return LDB_SUCCESS;
1411 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1412 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1413 if (guid1 && guid2) {
1414 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1415 talloc_free(tmp_ctx);
1416 return LDB_SUCCESS;
1419 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1420 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1421 if (sid1 && sid2) {
1422 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1423 talloc_free(tmp_ctx);
1424 return LDB_SUCCESS;
1427 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1429 talloc_free(tmp_ctx);
1430 return LDB_SUCCESS;
1434 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1436 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1437 const struct ldb_schema_attribute *a,
1438 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1440 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1441 /* If the DN is deleted, then we can't search for it */
1443 /* should this be for equality too? */
1444 *matched = false;
1445 return LDB_SUCCESS;
1448 if (operation == LDB_OP_EQUALITY &&
1449 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1450 return LDB_SUCCESS;
1453 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1457 static const struct ldb_schema_syntax samba_syntaxes[] = {
1459 .name = LDB_SYNTAX_SAMBA_SID,
1460 .ldif_read_fn = ldif_read_objectSid,
1461 .ldif_write_fn = ldif_write_objectSid,
1462 .canonicalise_fn = ldif_canonicalise_objectSid,
1463 .comparison_fn = ldif_comparison_objectSid,
1464 .operator_fn = samba_syntax_operator_fn
1466 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1467 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1468 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1469 .canonicalise_fn = ldb_handler_copy,
1470 .comparison_fn = samba_ldb_comparison_binary,
1471 .operator_fn = samba_syntax_binary_operator_fn
1473 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1474 .ldif_read_fn = ldb_handler_copy,
1475 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1476 .canonicalise_fn = ldb_handler_fold,
1477 .comparison_fn = ldb_comparison_fold,
1478 .operator_fn = samba_syntax_operator_fn
1480 .name = LDB_SYNTAX_SAMBA_GUID,
1481 .ldif_read_fn = ldif_read_objectGUID,
1482 .ldif_write_fn = ldif_write_objectGUID,
1483 .canonicalise_fn = ldif_canonicalise_objectGUID,
1484 .comparison_fn = ldif_comparison_objectGUID,
1485 .operator_fn = samba_syntax_operator_fn
1487 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1488 .ldif_read_fn = ldb_handler_copy,
1489 .ldif_write_fn = ldb_handler_copy,
1490 .canonicalise_fn = ldif_canonicalise_objectCategory,
1491 .comparison_fn = ldif_comparison_objectCategory,
1492 .operator_fn = samba_syntax_operator_fn
1494 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1495 .ldif_read_fn = ldb_handler_copy,
1496 .ldif_write_fn = ldif_write_schemaInfo,
1497 .canonicalise_fn = ldb_handler_copy,
1498 .comparison_fn = samba_ldb_comparison_binary,
1499 .operator_fn = samba_syntax_binary_operator_fn
1501 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1502 .ldif_read_fn = ldif_read_prefixMap,
1503 .ldif_write_fn = ldif_write_prefixMap,
1504 .canonicalise_fn = ldif_canonicalise_prefixMap,
1505 .comparison_fn = ldif_comparison_prefixMap,
1506 .operator_fn = samba_syntax_operator_fn
1508 .name = LDB_SYNTAX_SAMBA_INT32,
1509 .ldif_read_fn = ldb_handler_copy,
1510 .ldif_write_fn = ldb_handler_copy,
1511 .canonicalise_fn = ldif_canonicalise_int32,
1512 .index_format_fn = ldif_index_format_int32,
1513 .comparison_fn = ldif_comparison_int32,
1514 .operator_fn = samba_syntax_operator_fn
1516 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1517 .ldif_read_fn = ldb_handler_copy,
1518 .ldif_write_fn = ldif_write_repsFromTo,
1519 .canonicalise_fn = ldb_handler_copy,
1520 .comparison_fn = samba_ldb_comparison_binary,
1521 .operator_fn = samba_syntax_binary_operator_fn
1523 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1524 .ldif_read_fn = ldb_handler_copy,
1525 .ldif_write_fn = ldif_write_replPropertyMetaData,
1526 .canonicalise_fn = ldb_handler_copy,
1527 .comparison_fn = samba_ldb_comparison_binary,
1528 .operator_fn = samba_syntax_binary_operator_fn
1530 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1531 .ldif_read_fn = ldb_handler_copy,
1532 .ldif_write_fn = ldif_write_replUpToDateVector,
1533 .canonicalise_fn = ldb_handler_copy,
1534 .comparison_fn = samba_ldb_comparison_binary,
1535 .operator_fn = samba_syntax_binary_operator_fn
1537 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1538 .ldif_read_fn = ldb_handler_copy,
1539 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1540 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1541 .comparison_fn = dsdb_dn_binary_comparison,
1542 .operator_fn = samba_syntax_operator_fn
1544 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1545 .ldif_read_fn = ldb_handler_copy,
1546 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1547 .canonicalise_fn = ldb_handler_copy,
1548 .comparison_fn = samba_ldb_comparison_binary,
1549 .operator_fn = samba_syntax_binary_operator_fn
1551 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1552 .ldif_read_fn = ldb_handler_copy,
1553 .ldif_write_fn = ldif_write_ForestTrustInfo,
1554 .canonicalise_fn = ldb_handler_copy,
1555 .comparison_fn = samba_ldb_comparison_binary,
1556 .operator_fn = samba_syntax_binary_operator_fn
1558 .name = DSDB_SYNTAX_BINARY_DN,
1559 .ldif_read_fn = ldb_handler_copy,
1560 .ldif_write_fn = ldb_handler_copy,
1561 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1562 .comparison_fn = dsdb_dn_binary_comparison,
1563 .operator_fn = samba_syntax_operator_fn
1565 .name = DSDB_SYNTAX_STRING_DN,
1566 .ldif_read_fn = ldb_handler_copy,
1567 .ldif_write_fn = ldb_handler_copy,
1568 .canonicalise_fn = dsdb_dn_string_canonicalise,
1569 .comparison_fn = dsdb_dn_string_comparison,
1570 .operator_fn = samba_syntax_operator_fn
1572 .name = LDB_SYNTAX_DN,
1573 .ldif_read_fn = ldb_handler_copy,
1574 .ldif_write_fn = ldb_handler_copy,
1575 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1576 .comparison_fn = samba_ldb_dn_link_comparison,
1577 .operator_fn = samba_syntax_operator_dn
1579 .name = LDB_SYNTAX_SAMBA_RANGE64,
1580 .ldif_read_fn = ldif_read_range64,
1581 .ldif_write_fn = ldif_write_range64,
1582 .canonicalise_fn = ldif_canonicalise_int64,
1583 .comparison_fn = ldif_comparison_int64,
1584 .operator_fn = samba_syntax_operator_fn
1586 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1587 .ldif_read_fn = ldb_handler_copy,
1588 .ldif_write_fn = ldif_write_dnsRecord,
1589 .canonicalise_fn = ldb_handler_copy,
1590 .comparison_fn = samba_ldb_comparison_binary,
1591 .operator_fn = samba_syntax_binary_operator_fn
1593 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1594 .ldif_read_fn = ldb_handler_copy,
1595 .ldif_write_fn = ldif_write_dnsProperty,
1596 .canonicalise_fn = ldb_handler_copy,
1597 .comparison_fn = samba_ldb_comparison_binary,
1598 .operator_fn = samba_syntax_binary_operator_fn
1600 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1601 .ldif_read_fn = ldb_handler_copy,
1602 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1603 .canonicalise_fn = ldb_handler_copy,
1604 .comparison_fn = samba_ldb_comparison_binary,
1605 .operator_fn = samba_syntax_binary_operator_fn
1607 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1608 .ldif_read_fn = ldb_handler_copy,
1609 .ldif_write_fn = ldif_write_partialAttributeSet,
1610 .canonicalise_fn = ldb_handler_copy,
1611 .comparison_fn = samba_ldb_comparison_binary,
1612 .operator_fn = samba_syntax_binary_operator_fn
1614 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1615 .ldif_read_fn = ldb_handler_copy,
1616 .ldif_write_fn = ldb_handler_copy,
1617 .canonicalise_fn = ldb_handler_copy,
1618 .comparison_fn = samba_ldb_comparison_binary,
1619 .operator_fn = samba_syntax_binary_operator_fn
1623 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1625 .name = "SID",
1626 .read_fn = extended_dn_read_SID,
1627 .write_clear_fn = ldif_write_objectSid,
1628 .write_hex_fn = extended_dn_write_hex
1630 .name = "GUID",
1631 .read_fn = extended_dn_read_GUID,
1632 .write_clear_fn = ldif_write_objectGUID,
1633 .write_hex_fn = extended_dn_write_hex
1635 .name = "WKGUID",
1636 .read_fn = ldb_handler_copy,
1637 .write_clear_fn = ldb_handler_copy,
1638 .write_hex_fn = ldb_handler_copy
1640 .name = "RMD_INVOCID",
1641 .read_fn = extended_dn_read_GUID,
1642 .write_clear_fn = ldif_write_objectGUID,
1643 .write_hex_fn = extended_dn_write_hex
1645 .name = "RMD_FLAGS",
1646 .read_fn = ldb_handler_copy,
1647 .write_clear_fn = ldb_handler_copy,
1648 .write_hex_fn = ldb_handler_copy
1650 .name = "RMD_ADDTIME",
1651 .read_fn = ldb_handler_copy,
1652 .write_clear_fn = ldb_handler_copy,
1653 .write_hex_fn = ldb_handler_copy
1655 .name = "RMD_CHANGETIME",
1656 .read_fn = ldb_handler_copy,
1657 .write_clear_fn = ldb_handler_copy,
1658 .write_hex_fn = ldb_handler_copy
1660 .name = "RMD_LOCAL_USN",
1661 .read_fn = ldb_handler_copy,
1662 .write_clear_fn = ldb_handler_copy,
1663 .write_hex_fn = ldb_handler_copy
1665 .name = "RMD_ORIGINATING_USN",
1666 .read_fn = ldb_handler_copy,
1667 .write_clear_fn = ldb_handler_copy,
1668 .write_hex_fn = ldb_handler_copy
1670 .name = "RMD_VERSION",
1671 .read_fn = ldb_handler_copy,
1672 .write_clear_fn = ldb_handler_copy,
1673 .write_hex_fn = ldb_handler_copy
1677 /* TODO: Should be dynamic at some point */
1678 static const struct {
1679 const char *name;
1680 const char *syntax;
1681 } samba_attributes[] = {
1682 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1683 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1684 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1685 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1686 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1687 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1688 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1689 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1690 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1691 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1692 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1693 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1694 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1695 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1696 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1697 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1698 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1701 * these are extracted by searching
1702 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1704 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1705 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1706 * hat can be used to identify the set of policies when applied to a resource.
1707 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1708 * server, we ignore it here.
1710 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1711 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1712 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1713 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1714 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1715 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1716 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1717 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1718 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1721 * these are extracted by searching
1722 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1724 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1725 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1726 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1727 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1728 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1729 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1730 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1731 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1732 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1733 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1734 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1735 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1736 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1737 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1738 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1739 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1740 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1741 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1742 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1743 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1744 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1745 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1746 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1747 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1748 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1749 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1750 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1751 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1754 * these are known to be GUIDs
1756 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1757 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1759 /* These NDR encoded things we want to be able to read with --show-binary */
1760 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1761 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1762 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1763 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1766 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1768 unsigned int j;
1769 const struct ldb_schema_syntax *s = NULL;
1771 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1772 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1773 s = &samba_syntaxes[j];
1774 break;
1777 return s;
1780 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1782 unsigned int j;
1783 const struct ldb_schema_syntax *s = NULL;
1785 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1786 if (strcmp(samba_attributes[j].name, name) == 0) {
1787 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1788 break;
1792 return s;
1795 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1796 "priorSecret", NULL};
1799 register the samba ldif handlers
1801 int ldb_register_samba_handlers(struct ldb_context *ldb)
1803 unsigned int i;
1804 int ret;
1806 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1807 return LDB_SUCCESS;
1810 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1811 if (ret != LDB_SUCCESS) {
1812 return ret;
1815 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1816 const struct ldb_schema_syntax *s = NULL;
1818 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1820 if (!s) {
1821 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1824 if (!s) {
1825 return LDB_ERR_OPERATIONS_ERROR;
1828 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1829 if (ret != LDB_SUCCESS) {
1830 return ret;
1834 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1835 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1836 if (ret != LDB_SUCCESS) {
1837 return ret;
1842 ret = ldb_register_samba_matching_rules(ldb);
1843 if (ret != LDB_SUCCESS) {
1844 talloc_free(ldb);
1845 return LDB_SUCCESS;
1848 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1849 if (ret != LDB_SUCCESS) {
1850 return ret;
1853 return LDB_SUCCESS;