s3:utils: let connections_forall_read() report if the session was authenticated
[samba4-gss.git] / lib / ldb-samba / ldif_handlers.c
blob355312226111d278979f7ed7966beae6bc556987
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;
95 if (in->length < 5) { /* "S-1-x" */
96 return -1;
98 if (in->data[0] != 'S' && in->data[0] != 's') {
99 return -1;
100 } else {
101 char p[DOM_SID_STR_BUFLEN + 1];
102 memcpy(p, in->data, in->length);
103 p[in->length] = '\0';
105 ret = dom_sid_parse(p, &sid);
106 if (ret == false) {
107 return -1;
110 *out = data_blob_talloc(mem_ctx, NULL,
111 ndr_size_dom_sid(&sid, 0));
112 if (out->data == NULL) {
113 return -1;
116 ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
117 (ndr_push_flags_fn_t)ndr_push_dom_sid);
118 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
119 TALLOC_FREE(out->data);
120 return -1;
123 return 0;
127 convert a NDR formatted blob to a ldif formatted objectSid
129 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
130 const struct ldb_val *in, struct ldb_val *out)
132 struct dom_sid sid;
133 enum ndr_err_code ndr_err;
135 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
136 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
137 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
138 return -1;
140 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
141 if (out->data == NULL) {
142 return -1;
144 return 0;
148 compare two objectSids
150 If the SIDs seem to be strings, they are converted to binary form.
152 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
153 const struct ldb_val *v1, const struct ldb_val *v2)
155 struct ldb_val parsed_1 = {.data = NULL};
156 struct ldb_val parsed_2 = {.data = NULL};
157 int ret;
159 * If the ldb_vals look like SID strings (i.e. start with "S-"
160 * or "s-"), we treat them as strings.
162 * It is not really possible for a blob to be both a SID string and a
163 * SID struct -- the first two bytes of a struct dom_sid (including in
164 * NDR form) are the version (1), and the number of sub-auths (<= 15),
165 * neither of which are close to 'S' or '-'.
167 ret = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1);
168 if (ret == 0) {
169 v1 = &parsed_1;
171 ret = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2);
172 if (ret == 0) {
173 v2 = &parsed_2;
176 ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
178 TALLOC_FREE(parsed_1.data);
179 TALLOC_FREE(parsed_2.data);
180 return ret;
184 canonicalise a objectSid
186 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
187 const struct ldb_val *in, struct ldb_val *out)
189 /* First try as a string SID */
190 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
191 return 0;
193 /* not a string after all */
194 return ldb_handler_copy(ldb, mem_ctx, in, out);
197 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
198 const struct ldb_val *in, struct ldb_val *out)
200 struct dom_sid sid;
201 enum ndr_err_code ndr_err;
203 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
204 return 0;
207 /* Perhaps not a string after all */
208 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
210 if (!out->data) {
211 return -1;
214 (*out).length = strhex_to_str((char *)out->data, out->length,
215 (const char *)in->data, in->length);
217 /* Check it looks like a SID */
218 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
219 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
220 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
221 TALLOC_FREE(out->data);
222 return -1;
224 return 0;
228 convert a ldif formatted objectGUID to a NDR formatted blob
230 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
231 const struct ldb_val *in, struct ldb_val *out)
233 struct GUID guid;
234 NTSTATUS status;
236 status = GUID_from_data_blob(in, &guid);
237 if (!NT_STATUS_IS_OK(status)) {
238 return -1;
241 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
242 if (!NT_STATUS_IS_OK(status)) {
243 return -1;
245 return 0;
249 convert a NDR formatted blob to a ldif formatted objectGUID
251 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
252 const struct ldb_val *in, struct ldb_val *out)
254 struct GUID guid;
255 NTSTATUS status;
257 status = GUID_from_ndr_blob(in, &guid);
258 if (!NT_STATUS_IS_OK(status)) {
259 return -1;
261 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
262 if (out->data == NULL) {
263 return -1;
265 out->length = strlen((const char *)out->data);
266 return 0;
269 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
271 if (v->length != 36 && v->length != 38) return false;
273 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
274 return true;
277 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
278 const struct ldb_val *in, struct ldb_val *out)
281 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
282 return 0;
285 /* Try as 'hex' form */
286 if (in->length != 32) {
287 return -1;
290 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
292 if (!out->data) {
293 return -1;
296 (*out).length = strhex_to_str((char *)out->data, out->length,
297 (const char *)in->data, in->length);
299 /* Check it looks like a GUID */
300 if ((*out).length != 16) {
301 data_blob_free(out);
302 return -1;
305 return 0;
309 compare two objectGUIDs
311 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
312 const struct ldb_val *v1, const struct ldb_val *v2)
314 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
315 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
316 } else if (ldif_comparision_objectGUID_isString(v1)
317 && !ldif_comparision_objectGUID_isString(v2)) {
318 struct ldb_val v;
319 int ret;
320 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
321 /* Perhaps it wasn't a valid string after all */
322 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
324 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
325 talloc_free(v.data);
326 return ret;
327 } else if (!ldif_comparision_objectGUID_isString(v1)
328 && ldif_comparision_objectGUID_isString(v2)) {
329 struct ldb_val v;
330 int ret;
331 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
332 /* Perhaps it wasn't a valid string after all */
333 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
335 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
336 talloc_free(v.data);
337 return ret;
339 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
343 canonicalise a objectGUID
345 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
346 const struct ldb_val *in, struct ldb_val *out)
348 if (ldif_comparision_objectGUID_isString(in)) {
349 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
350 /* Perhaps it wasn't a valid string after all */
351 return ldb_handler_copy(ldb, mem_ctx, in, out);
353 return 0;
355 return ldb_handler_copy(ldb, mem_ctx, in, out);
360 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
362 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
363 const struct ldb_val *in, struct ldb_val *out)
365 struct security_descriptor *sd;
366 enum ndr_err_code ndr_err;
368 if (in->length >= 2 && isupper(in->data[0]) && in->data[1] == ':') {
370 * If it starts with an upper case character followed by ':',
371 * we know it's not NDR, but most likely SDDL...
373 const struct dom_sid *sid = samdb_domain_sid(ldb);
375 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
376 if (sd == NULL) {
377 return -1;
380 goto decoded;
383 sd = talloc(mem_ctx, struct security_descriptor);
384 if (sd == NULL) {
385 return -1;
388 ndr_err = ndr_pull_struct_blob(in, sd, sd,
389 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
390 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
391 talloc_free(sd);
392 return -1;
395 decoded:
396 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
397 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
398 talloc_free(sd);
399 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
400 return -1;
403 return 0;
407 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
409 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
410 const struct ldb_val *in, struct ldb_val *out)
412 struct security_descriptor *sd;
413 enum ndr_err_code ndr_err;
415 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
416 return ldif_write_NDR(ldb, mem_ctx, in, out,
417 sizeof(struct security_descriptor),
418 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
419 (ndr_print_fn_t)ndr_print_security_descriptor,
420 true);
424 sd = talloc(mem_ctx, struct security_descriptor);
425 if (sd == NULL) {
426 return -1;
428 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
429 ndr_err = ndr_pull_struct_blob(in, sd, sd,
430 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
431 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
432 talloc_free(sd);
433 return -1;
435 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
436 talloc_free(sd);
437 if (out->data == NULL) {
438 return -1;
440 out->length = strlen((const char *)out->data);
441 return 0;
445 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
447 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
448 const struct ldb_val *in, struct ldb_val *out)
450 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
451 struct security_descriptor *sd;
452 const struct dom_sid *sid = samdb_domain_sid(ldb);
454 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
455 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
456 (ndr_print_fn_t)ndr_print_security_descriptor,
457 "SDDL", sd);
458 out->length = strlen((const char *)out->data);
459 talloc_free(sd);
460 return 0;
463 return ldb_handler_copy(ldb, mem_ctx, in, out);
467 canonicalise an objectCategory. We use the long form as the canonical form:
468 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
470 Also any short name of an objectClass that points to a different
471 class (such as user) has the canonical form of the class it's
472 defaultObjectCategory points to (eg
473 cn=Person,cn=Schema,cn=Configuration,<basedn>)
476 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
477 const struct ldb_val *in, struct ldb_val *out)
479 struct ldb_dn *dn1 = NULL;
480 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
481 const struct dsdb_class *sclass;
482 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
483 if (!tmp_ctx) {
484 return LDB_ERR_OPERATIONS_ERROR;
487 if (!schema) {
488 talloc_free(tmp_ctx);
489 *out = data_blob_talloc(mem_ctx, in->data, in->length);
490 if (in->data && !out->data) {
491 return LDB_ERR_OPERATIONS_ERROR;
493 return LDB_SUCCESS;
495 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
496 if ( ! ldb_dn_validate(dn1)) {
497 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
498 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
499 if (sclass) {
500 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
501 sclass->defaultObjectCategory);
502 if (dn == NULL) {
503 talloc_free(tmp_ctx);
504 return LDB_ERR_OPERATIONS_ERROR;
507 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
508 talloc_free(tmp_ctx);
510 if (!out->data) {
511 return LDB_ERR_OPERATIONS_ERROR;
513 return LDB_SUCCESS;
514 } else {
515 *out = data_blob_talloc(mem_ctx, in->data, in->length);
516 talloc_free(tmp_ctx);
518 if (in->data && !out->data) {
519 return LDB_ERR_OPERATIONS_ERROR;
521 return LDB_SUCCESS;
524 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
525 talloc_free(tmp_ctx);
527 if (!out->data) {
528 return LDB_ERR_OPERATIONS_ERROR;
530 return LDB_SUCCESS;
533 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
534 const struct ldb_val *v1,
535 const struct ldb_val *v2)
537 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
538 v1, v2);
542 convert a NDR formatted blob to a ldif formatted schemaInfo
544 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
545 const struct ldb_val *in, struct ldb_val *out)
547 return ldif_write_NDR(ldb, mem_ctx, in, out,
548 sizeof(struct schemaInfoBlob),
549 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
550 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
551 true);
555 convert a ldif formatted prefixMap to a NDR formatted blob
557 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
558 const struct ldb_val *in, struct ldb_val *out)
560 struct prefixMapBlob *blob;
561 enum ndr_err_code ndr_err;
562 char *string, *line, *p, *oid;
563 DATA_BLOB oid_blob;
565 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
567 if (tmp_ctx == NULL) {
568 return -1;
571 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
572 if (blob == NULL) {
573 talloc_free(tmp_ctx);
574 return -1;
577 /* use the switch value to detect if this is in the binary
578 * format
580 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
581 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
582 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
583 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
584 ndr_err = ndr_push_struct_blob(out, mem_ctx,
585 blob,
586 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
587 talloc_free(tmp_ctx);
588 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
589 return -1;
591 return 0;
595 /* If this does not parse, then it is probably the text version, and we should try it that way */
596 blob->version = PREFIX_MAP_VERSION_DSDB;
598 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
599 if (string == NULL) {
600 talloc_free(blob);
601 return -1;
604 line = string;
605 while (line && line[0]) {
606 int error = 0;
608 p=strchr(line, ';');
609 if (p) {
610 p[0] = '\0';
611 } else {
612 p=strchr(line, '\n');
613 if (p) {
614 p[0] = '\0';
617 /* allow a trailing separator */
618 if (line == p) {
619 break;
622 blob->ctr.dsdb.mappings = talloc_realloc(blob,
623 blob->ctr.dsdb.mappings,
624 struct drsuapi_DsReplicaOIDMapping,
625 blob->ctr.dsdb.num_mappings+1);
626 if (!blob->ctr.dsdb.mappings) {
627 talloc_free(tmp_ctx);
628 return -1;
631 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
632 smb_strtoul(line, &oid, 10, &error, SMB_STR_STANDARD);
634 if (oid[0] != ':' || error != 0) {
635 talloc_free(tmp_ctx);
636 return -1;
639 /* we know there must be at least ":" */
640 oid++;
642 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
643 talloc_free(tmp_ctx);
644 return -1;
646 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
647 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
649 blob->ctr.dsdb.num_mappings++;
651 /* Now look past the terminator we added above */
652 if (p) {
653 line = p + 1;
654 } else {
655 line = NULL;
659 ndr_err = ndr_push_struct_blob(out, mem_ctx,
660 blob,
661 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
662 talloc_free(tmp_ctx);
663 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
664 return -1;
666 return 0;
670 convert a NDR formatted blob to a ldif formatted prefixMap
672 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
673 const struct ldb_val *in, struct ldb_val *out)
675 struct prefixMapBlob *blob;
676 enum ndr_err_code ndr_err;
677 char *string;
678 uint32_t i;
680 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
681 int err;
682 /* try to decode the blob as S4 prefixMap */
683 err = ldif_write_NDR(ldb, mem_ctx, in, out,
684 sizeof(struct prefixMapBlob),
685 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
686 (ndr_print_fn_t)ndr_print_prefixMapBlob,
687 false);
688 if (0 == err) {
689 return err;
691 /* try parsing it as Windows PrefixMap value */
692 return ldif_write_NDR(ldb, mem_ctx, in, out,
693 sizeof(struct drsuapi_MSPrefixMap_Ctr),
694 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
695 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
696 true);
699 blob = talloc(mem_ctx, struct prefixMapBlob);
700 if (blob == NULL) {
701 return -1;
703 ndr_err = ndr_pull_struct_blob_all(in, blob,
704 blob,
705 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
706 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
707 goto failed;
709 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
710 goto failed;
712 string = talloc_strdup(mem_ctx, "");
713 if (string == NULL) {
714 goto failed;
717 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
718 DATA_BLOB oid_blob;
719 char *partial_oid = NULL;
721 if (i > 0) {
722 talloc_asprintf_addbuf(&string, ";");
725 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
726 blob->ctr.dsdb.mappings[i].oid.length);
727 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
728 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X\n",
729 blob->ctr.dsdb.mappings[i].id_prefix));
730 goto failed;
732 talloc_asprintf_addbuf(&string, "%u:%s",
733 blob->ctr.dsdb.mappings[i].id_prefix,
734 partial_oid);
735 talloc_free(discard_const(partial_oid));
738 talloc_free(blob);
739 *out = data_blob_string_const(string);
740 return 0;
742 failed:
743 talloc_free(blob);
744 return -1;
747 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
749 if (v->length < 4) {
750 return true;
753 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
754 return false;
757 return true;
761 canonicalise a prefixMap
763 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
764 const struct ldb_val *in, struct ldb_val *out)
766 if (ldif_comparision_prefixMap_isString(in)) {
767 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
769 return ldb_handler_copy(ldb, mem_ctx, in, out);
772 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
773 const struct ldb_val *v1,
774 const struct ldb_val *v2)
776 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
777 v1, v2);
780 /* length limited conversion of a ldb_val to a int32_t */
781 static int val_to_int32(const struct ldb_val *in, int32_t *v)
783 char *end;
784 char buf[64];
786 /* make sure we don't read past the end of the data */
787 if (in->length > sizeof(buf)-1) {
788 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
790 strncpy(buf, (char *)in->data, in->length);
791 buf[in->length] = 0;
793 /* We've to use "strtoll" here to have the intended overflows.
794 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
795 *v = (int32_t) strtoll(buf, &end, 0);
796 if (*end != 0) {
797 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
799 return LDB_SUCCESS;
802 /* length limited conversion of a ldb_val to a int64_t */
803 static int val_to_int64(const struct ldb_val *in, int64_t *v)
805 char *end;
806 char buf[64];
808 /* make sure we don't read past the end of the data */
809 if (in->length > sizeof(buf)-1) {
810 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
812 strncpy(buf, (char *)in->data, in->length);
813 buf[in->length] = 0;
815 *v = (int64_t) strtoll(buf, &end, 0);
816 if (*end != 0) {
817 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
819 return LDB_SUCCESS;
822 /* Canonicalisation of two 32-bit integers */
823 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
824 const struct ldb_val *in, struct ldb_val *out)
826 int32_t i;
827 int ret;
829 ret = val_to_int32(in, &i);
830 if (ret != LDB_SUCCESS) {
831 return ret;
833 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
834 if (out->data == NULL) {
835 ldb_oom(ldb);
836 return LDB_ERR_OPERATIONS_ERROR;
838 out->length = strlen((char *)out->data);
839 return 0;
843 * Lexicographically sorted representation for a 32-bit integer
845 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
846 * n o p
848 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
849 * corresponding documentation for 64-bit integers.
851 * The same rules apply but use INT32_MIN and INT32_MAX.
853 * String representation padding is done to 10 characters.
855 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
858 static int ldif_index_format_int32(struct ldb_context *ldb,
859 void *mem_ctx,
860 const struct ldb_val *in,
861 struct ldb_val *out)
863 int32_t i;
864 int ret;
865 char prefix;
866 size_t len;
868 ret = val_to_int32(in, &i);
869 if (ret != LDB_SUCCESS) {
870 return ret;
873 if (i < 0) {
875 * i is negative, so this is subtraction rather than
876 * wrap-around.
878 prefix = 'n';
879 i = INT32_MAX + i + 1;
880 } else if (i > 0) {
881 prefix = 'p';
882 } else {
883 prefix = 'o';
886 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
887 if (out->data == NULL) {
888 ldb_oom(ldb);
889 return LDB_ERR_OPERATIONS_ERROR;
892 len = talloc_array_length(out->data) - 1;
893 if (len != 11) {
894 ldb_debug(ldb, LDB_DEBUG_ERROR,
895 __location__ ": expected index format str %s to"
896 " have length 11 but got %zu",
897 (char*)out->data, len);
898 return LDB_ERR_OPERATIONS_ERROR;
901 out->length = 11;
902 return 0;
905 /* Comparison of two 32-bit integers */
906 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
907 const struct ldb_val *v1, const struct ldb_val *v2)
909 int32_t i1=0, i2=0;
910 val_to_int32(v1, &i1);
911 val_to_int32(v2, &i2);
912 if (i1 == i2) return 0;
913 return i1 > i2? 1 : -1;
916 /* Canonicalisation of two 64-bit integers */
917 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
918 const struct ldb_val *in, struct ldb_val *out)
920 int64_t i;
921 int ret;
923 ret = val_to_int64(in, &i);
924 if (ret != LDB_SUCCESS) {
925 return ret;
927 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
928 if (out->data == NULL) {
929 ldb_oom(ldb);
930 return LDB_ERR_OPERATIONS_ERROR;
932 out->length = strlen((char *)out->data);
933 return 0;
936 /* Comparison of two 64-bit integers */
937 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
938 const struct ldb_val *v1, const struct ldb_val *v2)
940 int64_t i1=0, i2=0;
941 val_to_int64(v1, &i1);
942 val_to_int64(v2, &i2);
943 if (i1 == i2) return 0;
944 return i1 > i2? 1 : -1;
948 convert a NDR formatted blob to a ldif formatted repsFromTo
950 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
951 const struct ldb_val *in, struct ldb_val *out)
953 return ldif_write_NDR(ldb, mem_ctx, in, out,
954 sizeof(struct repsFromToBlob),
955 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
956 (ndr_print_fn_t)ndr_print_repsFromToBlob,
957 true);
961 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
963 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
964 const struct ldb_val *in, struct ldb_val *out)
966 return ldif_write_NDR(ldb, mem_ctx, in, out,
967 sizeof(struct replPropertyMetaDataBlob),
968 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
969 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
970 true);
974 convert a NDR formatted blob to a ldif formatted replUpToDateVector
976 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
977 const struct ldb_val *in, struct ldb_val *out)
979 return ldif_write_NDR(ldb, mem_ctx, in, out,
980 sizeof(struct replUpToDateVectorBlob),
981 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
982 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
983 true);
986 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
987 const struct ldb_val *in, struct ldb_val *out,
988 size_t struct_size,
989 ndr_pull_flags_fn_t pull_fn,
990 ndr_print_fn_t print_fn,
991 bool mask_errors)
993 uint8_t *p = NULL;
994 enum ndr_err_code err;
995 struct dsdb_dn *dsdb_dn = NULL;
996 char *dn_str = NULL;
997 char *str = NULL;
999 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
1000 return ldb_handler_copy(ldb, mem_ctx, in, out);
1003 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
1004 if (dsdb_dn == NULL) {
1005 return ldb_handler_copy(ldb, mem_ctx, in, out);
1008 p = talloc_size(dsdb_dn, struct_size);
1009 if (p == NULL) {
1010 TALLOC_FREE(dsdb_dn);
1011 return ldb_handler_copy(ldb, mem_ctx, in, out);
1014 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
1015 if (err != NDR_ERR_SUCCESS) {
1016 /* fail in not in mask_error mode */
1017 if (!mask_errors) {
1018 return -1;
1020 TALLOC_FREE(dsdb_dn);
1021 return ldb_handler_copy(ldb, mem_ctx, in, out);
1024 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
1025 if (dn_str == NULL) {
1026 TALLOC_FREE(dsdb_dn);
1027 return ldb_handler_copy(ldb, mem_ctx, in, out);
1030 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
1031 TALLOC_FREE(dsdb_dn);
1032 if (str == NULL) {
1033 return ldb_handler_copy(ldb, mem_ctx, in, out);
1036 *out = data_blob_string_const(str);
1037 return 0;
1040 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
1041 const struct ldb_val *in, struct ldb_val *out)
1043 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
1044 sizeof(struct replPropertyMetaData1),
1045 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
1046 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
1047 true);
1051 convert a NDR formatted blob to a ldif formatted dnsRecord
1053 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
1054 const struct ldb_val *in, struct ldb_val *out)
1056 return ldif_write_NDR(ldb, mem_ctx, in, out,
1057 sizeof(struct dnsp_DnssrvRpcRecord),
1058 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
1059 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
1060 true);
1064 convert a NDR formatted blob to a ldif formatted dnsProperty
1066 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1067 const struct ldb_val *in, struct ldb_val *out)
1069 return ldif_write_NDR(ldb, mem_ctx, in, out,
1070 sizeof(struct dnsp_DnsProperty),
1071 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1072 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1073 true);
1077 convert a NDR formatted blob of a supplementalCredentials into text
1079 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1080 const struct ldb_val *in, struct ldb_val *out)
1082 return ldif_write_NDR(ldb, mem_ctx, in, out,
1083 sizeof(struct supplementalCredentialsBlob),
1084 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1085 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1086 true);
1090 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1092 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1093 const struct ldb_val *in, struct ldb_val *out)
1095 return ldif_write_NDR(ldb, mem_ctx, in, out,
1096 sizeof(struct trustAuthInOutBlob),
1097 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1098 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1099 true);
1103 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1105 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1106 const struct ldb_val *in, struct ldb_val *out)
1108 return ldif_write_NDR(ldb, mem_ctx, in, out,
1109 sizeof(struct ForestTrustInfo),
1110 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1111 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1112 true);
1115 convert a NDR formatted blob of a partialAttributeSet into text
1117 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1118 const struct ldb_val *in, struct ldb_val *out)
1120 return ldif_write_NDR(ldb, mem_ctx, in, out,
1121 sizeof(struct partialAttributeSetBlob),
1122 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1123 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1124 true);
1128 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1129 const struct ldb_val *in, struct ldb_val *out)
1131 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1132 if (!out->data) {
1133 return -1;
1135 return 0;
1139 compare two dns
1141 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1142 const struct ldb_val *v1, const struct ldb_val *v2)
1144 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1145 int ret;
1148 * In a sort context, Deleted DNs get shifted to the end.
1149 * They never match in an equality
1151 if (dsdb_dn_is_deleted_val(v1)) {
1152 if (! dsdb_dn_is_deleted_val(v2)) {
1153 return 1;
1156 * They are both deleted!
1158 * The soundest thing to do at this point is carry on
1159 * and compare the DNs normally. This matches the
1160 * behaviour of samba_dn_extended_match() below.
1162 } else if (dsdb_dn_is_deleted_val(v2)) {
1163 return -1;
1166 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1167 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1169 if ( ! ldb_dn_validate(dn1)) {
1170 TALLOC_FREE(dn1);
1171 if ( ! ldb_dn_validate(dn2)) {
1172 TALLOC_FREE(dn2);
1173 return 0;
1175 TALLOC_FREE(dn2);
1176 return 1;
1179 if ( ! ldb_dn_validate(dn2)) {
1180 TALLOC_FREE(dn1);
1181 TALLOC_FREE(dn2);
1182 return -1;
1185 ret = ldb_dn_compare(dn1, dn2);
1187 talloc_free(dn1);
1188 talloc_free(dn2);
1189 return ret;
1192 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1193 const struct ldb_val *in, struct ldb_val *out)
1195 struct ldb_dn *dn;
1196 int ret = -1;
1198 out->length = 0;
1199 out->data = NULL;
1201 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1202 if ( ! ldb_dn_validate(dn)) {
1203 return LDB_ERR_INVALID_DN_SYNTAX;
1206 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1207 * does not casually match a not deleted DN */
1208 if (dsdb_dn_is_deleted_val(in)) {
1209 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1210 "<RMD_FLAGS=%u>%s",
1211 dsdb_dn_val_rmd_flags(in),
1212 ldb_dn_get_casefold(dn));
1213 } else {
1214 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1217 if (out->data == NULL) {
1218 goto done;
1220 out->length = strlen((char *)out->data);
1222 ret = 0;
1224 done:
1225 talloc_free(dn);
1227 return ret;
1232 write a 64 bit 2-part range
1234 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1235 const struct ldb_val *in, struct ldb_val *out)
1237 int64_t v;
1238 int ret;
1239 ret = val_to_int64(in, &v);
1240 if (ret != LDB_SUCCESS) {
1241 return ret;
1243 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1244 (unsigned long)(v&0xFFFFFFFF),
1245 (unsigned long)(v>>32));
1246 if (out->data == NULL) {
1247 ldb_oom(ldb);
1248 return LDB_ERR_OPERATIONS_ERROR;
1250 out->length = strlen((char *)out->data);
1251 return LDB_SUCCESS;
1255 read a 64 bit 2-part range
1257 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1258 const struct ldb_val *in, struct ldb_val *out)
1260 unsigned long high, low;
1261 char buf[64];
1263 if (memchr(in->data, '-', in->length) == NULL) {
1264 return ldb_handler_copy(ldb, mem_ctx, in, out);
1267 if (in->length > sizeof(buf)-1) {
1268 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1270 strncpy(buf, (const char *)in->data, in->length);
1271 buf[in->length] = 0;
1273 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1274 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1277 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1278 (unsigned long long)(((uint64_t)high)<<32) | (low));
1280 if (out->data == NULL) {
1281 ldb_oom(ldb);
1282 return LDB_ERR_OPERATIONS_ERROR;
1284 out->length = strlen((char *)out->data);
1285 return LDB_SUCCESS;
1289 when this operator_fn is set for a syntax, the backend calls is in
1290 preference to the comparison function. We are told the exact
1291 comparison operation that is needed, and we can return errors
1293 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1294 const struct ldb_schema_attribute *a,
1295 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1297 switch (operation) {
1298 case LDB_OP_AND:
1299 case LDB_OP_OR:
1300 case LDB_OP_NOT:
1301 case LDB_OP_SUBSTRING:
1302 case LDB_OP_APPROX:
1303 case LDB_OP_EXTENDED:
1304 /* handled in the backends */
1305 return LDB_ERR_INAPPROPRIATE_MATCHING;
1307 case LDB_OP_GREATER:
1308 case LDB_OP_LESS:
1309 case LDB_OP_EQUALITY:
1311 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1312 int ret;
1313 if (tmp_ctx == NULL) {
1314 return ldb_oom(ldb);
1316 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1317 talloc_free(tmp_ctx);
1318 if (operation == LDB_OP_GREATER) {
1319 *matched = (ret >= 0);
1320 } else if (operation == LDB_OP_LESS) {
1321 *matched = (ret <= 0);
1322 } else {
1323 *matched = (ret == 0);
1325 return LDB_SUCCESS;
1328 case LDB_OP_PRESENT:
1329 *matched = true;
1330 return LDB_SUCCESS;
1333 /* we shouldn't get here */
1334 return LDB_ERR_INAPPROPRIATE_MATCHING;
1338 compare two binary objects. This is correct for sorting as the sort order is:
1345 rather than ldb_comparison_binary() which is:
1353 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1354 const struct ldb_val *v1, const struct ldb_val *v2)
1356 return data_blob_cmp(v1, v2);
1360 when this operator_fn is set for a syntax, the backend calls is in
1361 preference to the comparison function. We are told the exact
1362 comparison operation that is needed, and we can return errors.
1364 This mode optimises for ldb_comparison_binary() if we need equality,
1365 as this should be faster as it can do a length-check first.
1367 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1368 const struct ldb_schema_attribute *a,
1369 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1371 if (operation == LDB_OP_EQUALITY) {
1372 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1373 return LDB_SUCCESS;
1375 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1379 see if two DNs match, comparing first by GUID, then by SID, and
1380 finally by string components
1382 static int samba_dn_extended_match(struct ldb_context *ldb,
1383 const struct ldb_val *v1,
1384 const struct ldb_val *v2,
1385 bool *matched)
1387 TALLOC_CTX *tmp_ctx;
1388 struct ldb_dn *dn1, *dn2;
1389 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1390 uint32_t rmd_flags1, rmd_flags2;
1392 tmp_ctx = talloc_new(ldb);
1394 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1395 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1396 if (!dn1 || !dn2) {
1397 /* couldn't parse as DN's */
1398 talloc_free(tmp_ctx);
1399 (*matched) = false;
1400 return LDB_SUCCESS;
1403 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1404 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1406 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1407 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1408 /* only match if they have the same deletion status */
1409 talloc_free(tmp_ctx);
1410 (*matched) = false;
1411 return LDB_SUCCESS;
1415 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1416 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1417 if (guid1 && guid2) {
1418 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1419 talloc_free(tmp_ctx);
1420 return LDB_SUCCESS;
1423 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1424 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1425 if (sid1 && sid2) {
1426 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1427 talloc_free(tmp_ctx);
1428 return LDB_SUCCESS;
1431 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1433 talloc_free(tmp_ctx);
1434 return LDB_SUCCESS;
1438 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1440 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1441 const struct ldb_schema_attribute *a,
1442 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1444 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1445 /* If the DN is deleted, then we can't search for it */
1447 /* should this be for equality too? */
1448 *matched = false;
1449 return LDB_SUCCESS;
1452 if (operation == LDB_OP_EQUALITY &&
1453 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1454 return LDB_SUCCESS;
1457 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1461 static const struct ldb_schema_syntax samba_syntaxes[] = {
1463 .name = LDB_SYNTAX_SAMBA_SID,
1464 .ldif_read_fn = ldif_read_objectSid,
1465 .ldif_write_fn = ldif_write_objectSid,
1466 .canonicalise_fn = ldif_canonicalise_objectSid,
1467 .comparison_fn = ldif_comparison_objectSid,
1468 .operator_fn = samba_syntax_operator_fn
1470 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1471 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1472 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1473 .canonicalise_fn = ldb_handler_copy,
1474 .comparison_fn = samba_ldb_comparison_binary,
1475 .operator_fn = samba_syntax_binary_operator_fn
1477 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1478 .ldif_read_fn = ldb_handler_copy,
1479 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1480 .canonicalise_fn = ldb_handler_fold,
1481 .comparison_fn = ldb_comparison_fold,
1482 .operator_fn = samba_syntax_operator_fn
1484 .name = LDB_SYNTAX_SAMBA_GUID,
1485 .ldif_read_fn = ldif_read_objectGUID,
1486 .ldif_write_fn = ldif_write_objectGUID,
1487 .canonicalise_fn = ldif_canonicalise_objectGUID,
1488 .comparison_fn = ldif_comparison_objectGUID,
1489 .operator_fn = samba_syntax_operator_fn
1491 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1492 .ldif_read_fn = ldb_handler_copy,
1493 .ldif_write_fn = ldb_handler_copy,
1494 .canonicalise_fn = ldif_canonicalise_objectCategory,
1495 .comparison_fn = ldif_comparison_objectCategory,
1496 .operator_fn = samba_syntax_operator_fn
1498 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1499 .ldif_read_fn = ldb_handler_copy,
1500 .ldif_write_fn = ldif_write_schemaInfo,
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_PREFIX_MAP,
1506 .ldif_read_fn = ldif_read_prefixMap,
1507 .ldif_write_fn = ldif_write_prefixMap,
1508 .canonicalise_fn = ldif_canonicalise_prefixMap,
1509 .comparison_fn = ldif_comparison_prefixMap,
1510 .operator_fn = samba_syntax_operator_fn
1512 .name = LDB_SYNTAX_SAMBA_INT32,
1513 .ldif_read_fn = ldb_handler_copy,
1514 .ldif_write_fn = ldb_handler_copy,
1515 .canonicalise_fn = ldif_canonicalise_int32,
1516 .index_format_fn = ldif_index_format_int32,
1517 .comparison_fn = ldif_comparison_int32,
1518 .operator_fn = samba_syntax_operator_fn
1520 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1521 .ldif_read_fn = ldb_handler_copy,
1522 .ldif_write_fn = ldif_write_repsFromTo,
1523 .canonicalise_fn = ldb_handler_copy,
1524 .comparison_fn = samba_ldb_comparison_binary,
1525 .operator_fn = samba_syntax_binary_operator_fn
1527 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1528 .ldif_read_fn = ldb_handler_copy,
1529 .ldif_write_fn = ldif_write_replPropertyMetaData,
1530 .canonicalise_fn = ldb_handler_copy,
1531 .comparison_fn = samba_ldb_comparison_binary,
1532 .operator_fn = samba_syntax_binary_operator_fn
1534 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1535 .ldif_read_fn = ldb_handler_copy,
1536 .ldif_write_fn = ldif_write_replUpToDateVector,
1537 .canonicalise_fn = ldb_handler_copy,
1538 .comparison_fn = samba_ldb_comparison_binary,
1539 .operator_fn = samba_syntax_binary_operator_fn
1541 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1542 .ldif_read_fn = ldb_handler_copy,
1543 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1544 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1545 .comparison_fn = dsdb_dn_binary_comparison,
1546 .operator_fn = samba_syntax_operator_fn
1548 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1549 .ldif_read_fn = ldb_handler_copy,
1550 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1551 .canonicalise_fn = ldb_handler_copy,
1552 .comparison_fn = samba_ldb_comparison_binary,
1553 .operator_fn = samba_syntax_binary_operator_fn
1555 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1556 .ldif_read_fn = ldb_handler_copy,
1557 .ldif_write_fn = ldif_write_ForestTrustInfo,
1558 .canonicalise_fn = ldb_handler_copy,
1559 .comparison_fn = samba_ldb_comparison_binary,
1560 .operator_fn = samba_syntax_binary_operator_fn
1562 .name = DSDB_SYNTAX_BINARY_DN,
1563 .ldif_read_fn = ldb_handler_copy,
1564 .ldif_write_fn = ldb_handler_copy,
1565 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1566 .comparison_fn = dsdb_dn_binary_comparison,
1567 .operator_fn = samba_syntax_operator_fn
1569 .name = DSDB_SYNTAX_STRING_DN,
1570 .ldif_read_fn = ldb_handler_copy,
1571 .ldif_write_fn = ldb_handler_copy,
1572 .canonicalise_fn = dsdb_dn_string_canonicalise,
1573 .comparison_fn = dsdb_dn_string_comparison,
1574 .operator_fn = samba_syntax_operator_fn
1576 .name = LDB_SYNTAX_DN,
1577 .ldif_read_fn = ldb_handler_copy,
1578 .ldif_write_fn = ldb_handler_copy,
1579 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1580 .comparison_fn = samba_ldb_dn_link_comparison,
1581 .operator_fn = samba_syntax_operator_dn
1583 .name = LDB_SYNTAX_SAMBA_RANGE64,
1584 .ldif_read_fn = ldif_read_range64,
1585 .ldif_write_fn = ldif_write_range64,
1586 .canonicalise_fn = ldif_canonicalise_int64,
1587 .comparison_fn = ldif_comparison_int64,
1588 .operator_fn = samba_syntax_operator_fn
1590 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1591 .ldif_read_fn = ldb_handler_copy,
1592 .ldif_write_fn = ldif_write_dnsRecord,
1593 .canonicalise_fn = ldb_handler_copy,
1594 .comparison_fn = samba_ldb_comparison_binary,
1595 .operator_fn = samba_syntax_binary_operator_fn
1597 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1598 .ldif_read_fn = ldb_handler_copy,
1599 .ldif_write_fn = ldif_write_dnsProperty,
1600 .canonicalise_fn = ldb_handler_copy,
1601 .comparison_fn = samba_ldb_comparison_binary,
1602 .operator_fn = samba_syntax_binary_operator_fn
1604 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1605 .ldif_read_fn = ldb_handler_copy,
1606 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1607 .canonicalise_fn = ldb_handler_copy,
1608 .comparison_fn = samba_ldb_comparison_binary,
1609 .operator_fn = samba_syntax_binary_operator_fn
1611 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1612 .ldif_read_fn = ldb_handler_copy,
1613 .ldif_write_fn = ldif_write_partialAttributeSet,
1614 .canonicalise_fn = ldb_handler_copy,
1615 .comparison_fn = samba_ldb_comparison_binary,
1616 .operator_fn = samba_syntax_binary_operator_fn
1618 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1619 .ldif_read_fn = ldb_handler_copy,
1620 .ldif_write_fn = ldb_handler_copy,
1621 .canonicalise_fn = ldb_handler_copy,
1622 .comparison_fn = samba_ldb_comparison_binary,
1623 .operator_fn = samba_syntax_binary_operator_fn
1627 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1629 .name = "SID",
1630 .read_fn = extended_dn_read_SID,
1631 .write_clear_fn = ldif_write_objectSid,
1632 .write_hex_fn = extended_dn_write_hex
1634 .name = "GUID",
1635 .read_fn = extended_dn_read_GUID,
1636 .write_clear_fn = ldif_write_objectGUID,
1637 .write_hex_fn = extended_dn_write_hex
1639 .name = "WKGUID",
1640 .read_fn = ldb_handler_copy,
1641 .write_clear_fn = ldb_handler_copy,
1642 .write_hex_fn = ldb_handler_copy
1644 .name = "RMD_INVOCID",
1645 .read_fn = extended_dn_read_GUID,
1646 .write_clear_fn = ldif_write_objectGUID,
1647 .write_hex_fn = extended_dn_write_hex
1649 .name = "RMD_FLAGS",
1650 .read_fn = ldb_handler_copy,
1651 .write_clear_fn = ldb_handler_copy,
1652 .write_hex_fn = ldb_handler_copy
1654 .name = "RMD_ADDTIME",
1655 .read_fn = ldb_handler_copy,
1656 .write_clear_fn = ldb_handler_copy,
1657 .write_hex_fn = ldb_handler_copy
1659 .name = "RMD_CHANGETIME",
1660 .read_fn = ldb_handler_copy,
1661 .write_clear_fn = ldb_handler_copy,
1662 .write_hex_fn = ldb_handler_copy
1664 .name = "RMD_LOCAL_USN",
1665 .read_fn = ldb_handler_copy,
1666 .write_clear_fn = ldb_handler_copy,
1667 .write_hex_fn = ldb_handler_copy
1669 .name = "RMD_ORIGINATING_USN",
1670 .read_fn = ldb_handler_copy,
1671 .write_clear_fn = ldb_handler_copy,
1672 .write_hex_fn = ldb_handler_copy
1674 .name = "RMD_VERSION",
1675 .read_fn = ldb_handler_copy,
1676 .write_clear_fn = ldb_handler_copy,
1677 .write_hex_fn = ldb_handler_copy
1681 /* TODO: Should be dynamic at some point */
1682 static const struct {
1683 const char *name;
1684 const char *syntax;
1685 } samba_attributes[] = {
1686 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1687 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1688 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1689 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1690 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1691 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1692 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1693 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1694 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1695 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1696 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1697 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1698 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1699 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1700 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1701 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1702 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1705 * these are extracted by searching
1706 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1708 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1709 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1710 * hat can be used to identify the set of policies when applied to a resource.
1711 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1712 * server, we ignore it here.
1714 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1715 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1716 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1717 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1718 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1719 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1720 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1721 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1722 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1725 * these are extracted by searching
1726 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1728 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1729 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1730 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1731 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1732 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1733 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1734 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1735 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1736 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1737 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1738 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1739 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1740 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1741 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1742 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1743 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1744 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1745 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1746 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1747 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1748 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1749 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1750 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1751 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1752 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1753 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1754 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1755 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1758 * these are known to be GUIDs
1760 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1761 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1763 /* These NDR encoded things we want to be able to read with --show-binary */
1764 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1765 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1766 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1767 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1770 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1772 unsigned int j;
1773 const struct ldb_schema_syntax *s = NULL;
1775 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1776 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1777 s = &samba_syntaxes[j];
1778 break;
1781 return s;
1784 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1786 unsigned int j;
1787 const struct ldb_schema_syntax *s = NULL;
1789 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1790 if (strcmp(samba_attributes[j].name, name) == 0) {
1791 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1792 break;
1796 return s;
1799 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1800 "priorSecret", NULL};
1803 register the samba ldif handlers
1805 int ldb_register_samba_handlers(struct ldb_context *ldb)
1807 unsigned int i;
1808 int ret;
1810 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1811 return LDB_SUCCESS;
1814 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1815 if (ret != LDB_SUCCESS) {
1816 return ret;
1819 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1820 const struct ldb_schema_syntax *s = NULL;
1822 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1824 if (!s) {
1825 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1828 if (!s) {
1829 return LDB_ERR_OPERATIONS_ERROR;
1832 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1833 if (ret != LDB_SUCCESS) {
1834 return ret;
1838 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1839 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1840 if (ret != LDB_SUCCESS) {
1841 return ret;
1846 ret = ldb_register_samba_matching_rules(ldb);
1847 if (ret != LDB_SUCCESS) {
1848 talloc_free(ldb);
1849 return LDB_SUCCESS;
1852 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1853 if (ret != LDB_SUCCESS) {
1854 return ret;
1857 return LDB_SUCCESS;