tevent: let epoll_check_reopen() clear all events before reopening them
[Samba.git] / lib / ldb-samba / ldif_handlers.c
blobf77a268c1a8c64e1d8f04285c432bc3ed04126f4
1 /*
2 ldb database library - ldif handlers for Samba
4 Copyright (C) Andrew Tridgell 2005
5 Copyright (C) Andrew Bartlett 2006-2009
6 Copyright (C) Matthias Dieter Wallnöfer 2009
7 ** NOTE! The following LGPL license applies to the ldb
8 ** library. This does NOT imply that all of Samba is released
9 ** under the LGPL
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include <ldb.h>
27 #include <ldb_module.h>
28 #include "ldb_handlers.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "dsdb/common/util.h"
31 #include "librpc/gen_ndr/ndr_security.h"
32 #include "librpc/gen_ndr/ndr_misc.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "librpc/gen_ndr/ndr_dnsp.h"
35 #include "librpc/ndr/libndr.h"
36 #include "libcli/security/security.h"
37 #include "param/param.h"
38 #include "../lib/util/asn1.h"
39 #include "lib/util/smb_strtox.h"
42 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
44 If mask_errors is true, then function succeeds but out data
45 is set to "<Unable to decode binary data>" message
47 \return 0 on success; -1 on error
49 static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
50 const struct ldb_val *in, struct ldb_val *out,
51 size_t struct_size,
52 ndr_pull_flags_fn_t pull_fn,
53 ndr_print_fn_t print_fn,
54 bool mask_errors)
56 uint8_t *p;
57 enum ndr_err_code err;
58 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
59 return ldb_handler_copy(ldb, mem_ctx, in, out);
61 p = talloc_size(mem_ctx, struct_size);
62 err = ndr_pull_struct_blob(in, mem_ctx,
63 p, pull_fn);
64 if (err != NDR_ERR_SUCCESS) {
65 /* fail in not in mask_error mode */
66 if (!mask_errors) {
67 return -1;
69 talloc_free(p);
70 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
71 out->length = strlen((const char *)out->data);
72 return 0;
74 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
75 talloc_free(p);
76 if (out->data == NULL) {
77 return ldb_handler_copy(ldb, mem_ctx, in, out);
79 out->length = strlen((char *)out->data);
80 return 0;
84 convert a ldif formatted objectSid to a NDR formatted blob
86 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
87 const struct ldb_val *in, struct ldb_val *out)
89 bool ret;
90 enum ndr_err_code ndr_err;
91 struct dom_sid sid;
92 if (in->length > DOM_SID_STR_BUFLEN) {
93 return -1;
94 } else {
95 char p[in->length+1];
96 memcpy(p, in->data, in->length);
97 p[in->length] = '\0';
99 ret = dom_sid_parse(p, &sid);
100 if (ret == false) {
101 return -1;
104 *out = data_blob_talloc(mem_ctx, NULL,
105 ndr_size_dom_sid(&sid, 0));
106 if (out->data == NULL) {
107 return -1;
110 ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
111 (ndr_push_flags_fn_t)ndr_push_dom_sid);
112 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
113 return -1;
116 return 0;
120 convert a NDR formatted blob to a ldif formatted objectSid
122 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
123 const struct ldb_val *in, struct ldb_val *out)
125 struct dom_sid sid;
126 enum ndr_err_code ndr_err;
128 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
129 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
130 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
131 return -1;
133 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
134 if (out->data == NULL) {
135 return -1;
137 return 0;
140 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
142 if (v->length < 3) {
143 return false;
146 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
148 return true;
152 compare two objectSids
154 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
155 const struct ldb_val *v1, const struct ldb_val *v2)
157 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
158 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
159 } else if (ldif_comparision_objectSid_isString(v1)
160 && !ldif_comparision_objectSid_isString(v2)) {
161 struct ldb_val v;
162 int ret;
163 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
164 /* Perhaps not a string after all */
165 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
167 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
168 talloc_free(v.data);
169 return ret;
170 } else if (!ldif_comparision_objectSid_isString(v1)
171 && ldif_comparision_objectSid_isString(v2)) {
172 struct ldb_val v;
173 int ret;
174 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
175 /* Perhaps not a string after all */
176 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
178 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
179 talloc_free(v.data);
180 return ret;
182 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
186 canonicalise a objectSid
188 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
189 const struct ldb_val *in, struct ldb_val *out)
191 if (ldif_comparision_objectSid_isString(in)) {
192 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
193 /* Perhaps not a string after all */
194 return ldb_handler_copy(ldb, mem_ctx, in, out);
196 return 0;
198 return ldb_handler_copy(ldb, mem_ctx, in, out);
201 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
202 const struct ldb_val *in, struct ldb_val *out)
204 struct dom_sid sid;
205 enum ndr_err_code ndr_err;
206 if (ldif_comparision_objectSid_isString(in)) {
207 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
208 return 0;
212 /* Perhaps not a string after all */
213 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
215 if (!out->data) {
216 return -1;
219 (*out).length = strhex_to_str((char *)out->data, out->length,
220 (const char *)in->data, in->length);
222 /* Check it looks like a SID */
223 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
224 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
225 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
226 return -1;
228 return 0;
232 convert a ldif formatted objectGUID to a NDR formatted blob
234 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
235 const struct ldb_val *in, struct ldb_val *out)
237 struct GUID guid;
238 NTSTATUS status;
240 status = GUID_from_data_blob(in, &guid);
241 if (!NT_STATUS_IS_OK(status)) {
242 return -1;
245 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
246 if (!NT_STATUS_IS_OK(status)) {
247 return -1;
249 return 0;
253 convert a NDR formatted blob to a ldif formatted objectGUID
255 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
256 const struct ldb_val *in, struct ldb_val *out)
258 struct GUID guid;
259 NTSTATUS status;
261 status = GUID_from_ndr_blob(in, &guid);
262 if (!NT_STATUS_IS_OK(status)) {
263 return -1;
265 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
266 if (out->data == NULL) {
267 return -1;
269 out->length = strlen((const char *)out->data);
270 return 0;
273 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
275 if (v->length != 36 && v->length != 38) return false;
277 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
278 return true;
281 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
282 const struct ldb_val *in, struct ldb_val *out)
285 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
286 return 0;
289 /* Try as 'hex' form */
290 if (in->length != 32) {
291 return -1;
294 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
296 if (!out->data) {
297 return -1;
300 (*out).length = strhex_to_str((char *)out->data, out->length,
301 (const char *)in->data, in->length);
303 /* Check it looks like a GUID */
304 if ((*out).length != 16) {
305 data_blob_free(out);
306 return -1;
309 return 0;
313 compare two objectGUIDs
315 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
316 const struct ldb_val *v1, const struct ldb_val *v2)
318 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
319 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
320 } else if (ldif_comparision_objectGUID_isString(v1)
321 && !ldif_comparision_objectGUID_isString(v2)) {
322 struct ldb_val v;
323 int ret;
324 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
325 /* Perhaps it wasn't a valid string after all */
326 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
328 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
329 talloc_free(v.data);
330 return ret;
331 } else if (!ldif_comparision_objectGUID_isString(v1)
332 && ldif_comparision_objectGUID_isString(v2)) {
333 struct ldb_val v;
334 int ret;
335 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
336 /* Perhaps it wasn't a valid string after all */
337 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
339 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
340 talloc_free(v.data);
341 return ret;
343 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
347 canonicalise a objectGUID
349 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
350 const struct ldb_val *in, struct ldb_val *out)
352 if (ldif_comparision_objectGUID_isString(in)) {
353 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
354 /* Perhaps it wasn't a valid string after all */
355 return ldb_handler_copy(ldb, mem_ctx, in, out);
357 return 0;
359 return ldb_handler_copy(ldb, mem_ctx, in, out);
364 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
366 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
367 const struct ldb_val *in, struct ldb_val *out)
369 struct security_descriptor *sd;
370 enum ndr_err_code ndr_err;
372 if (in->length >= 2 && isupper(in->data[0]) && in->data[1] == ':') {
374 * If it starts with an upper case character followed by ':',
375 * we know it's not NDR, but most likely SDDL...
377 const struct dom_sid *sid = samdb_domain_sid(ldb);
379 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
380 if (sd == NULL) {
381 return -1;
384 goto decoded;
387 sd = talloc(mem_ctx, struct security_descriptor);
388 if (sd == NULL) {
389 return -1;
392 ndr_err = ndr_pull_struct_blob(in, sd, sd,
393 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
394 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
395 talloc_free(sd);
396 return -1;
399 decoded:
400 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
401 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
402 talloc_free(sd);
403 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
404 return -1;
407 return 0;
411 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
413 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
414 const struct ldb_val *in, struct ldb_val *out)
416 struct security_descriptor *sd;
417 enum ndr_err_code ndr_err;
419 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
420 return ldif_write_NDR(ldb, mem_ctx, in, out,
421 sizeof(struct security_descriptor),
422 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
423 (ndr_print_fn_t)ndr_print_security_descriptor,
424 true);
428 sd = talloc(mem_ctx, struct security_descriptor);
429 if (sd == NULL) {
430 return -1;
432 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
433 ndr_err = ndr_pull_struct_blob(in, sd, sd,
434 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
435 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
436 talloc_free(sd);
437 return -1;
439 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
440 talloc_free(sd);
441 if (out->data == NULL) {
442 return -1;
444 out->length = strlen((const char *)out->data);
445 return 0;
449 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
451 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
452 const struct ldb_val *in, struct ldb_val *out)
454 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
455 struct security_descriptor *sd;
456 const struct dom_sid *sid = samdb_domain_sid(ldb);
458 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
459 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
460 (ndr_print_fn_t)ndr_print_security_descriptor,
461 "SDDL", sd);
462 out->length = strlen((const char *)out->data);
463 talloc_free(sd);
464 return 0;
467 return ldb_handler_copy(ldb, mem_ctx, in, out);
471 canonicalise an objectCategory. We use the long form as the canonical form:
472 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
474 Also any short name of an objectClass that points to a different
475 class (such as user) has the canonical form of the class it's
476 defaultObjectCategory points to (eg
477 cn=Person,cn=Schema,cn=Configuration,<basedn>)
480 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
481 const struct ldb_val *in, struct ldb_val *out)
483 struct ldb_dn *dn1 = NULL;
484 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
485 const struct dsdb_class *sclass;
486 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
487 if (!tmp_ctx) {
488 return LDB_ERR_OPERATIONS_ERROR;
491 if (!schema) {
492 talloc_free(tmp_ctx);
493 *out = data_blob_talloc(mem_ctx, in->data, in->length);
494 if (in->data && !out->data) {
495 return LDB_ERR_OPERATIONS_ERROR;
497 return LDB_SUCCESS;
499 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
500 if ( ! ldb_dn_validate(dn1)) {
501 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
502 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
503 if (sclass) {
504 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
505 sclass->defaultObjectCategory);
506 if (dn == NULL) {
507 talloc_free(tmp_ctx);
508 return LDB_ERR_OPERATIONS_ERROR;
511 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
512 talloc_free(tmp_ctx);
514 if (!out->data) {
515 return LDB_ERR_OPERATIONS_ERROR;
517 return LDB_SUCCESS;
518 } else {
519 *out = data_blob_talloc(mem_ctx, in->data, in->length);
520 talloc_free(tmp_ctx);
522 if (in->data && !out->data) {
523 return LDB_ERR_OPERATIONS_ERROR;
525 return LDB_SUCCESS;
528 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
529 talloc_free(tmp_ctx);
531 if (!out->data) {
532 return LDB_ERR_OPERATIONS_ERROR;
534 return LDB_SUCCESS;
537 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
538 const struct ldb_val *v1,
539 const struct ldb_val *v2)
541 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
542 v1, v2);
546 convert a NDR formatted blob to a ldif formatted schemaInfo
548 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
549 const struct ldb_val *in, struct ldb_val *out)
551 return ldif_write_NDR(ldb, mem_ctx, in, out,
552 sizeof(struct repsFromToBlob),
553 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
554 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
555 true);
559 convert a ldif formatted prefixMap to a NDR formatted blob
561 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
562 const struct ldb_val *in, struct ldb_val *out)
564 struct prefixMapBlob *blob;
565 enum ndr_err_code ndr_err;
566 char *string, *line, *p, *oid;
567 DATA_BLOB oid_blob;
569 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
571 if (tmp_ctx == NULL) {
572 return -1;
575 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
576 if (blob == NULL) {
577 talloc_free(tmp_ctx);
578 return -1;
581 /* use the switch value to detect if this is in the binary
582 * format
584 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
585 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
586 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
587 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
588 ndr_err = ndr_push_struct_blob(out, mem_ctx,
589 blob,
590 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
591 talloc_free(tmp_ctx);
592 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
593 return -1;
595 return 0;
599 /* If this does not parse, then it is probably the text version, and we should try it that way */
600 blob->version = PREFIX_MAP_VERSION_DSDB;
602 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
603 if (string == NULL) {
604 talloc_free(blob);
605 return -1;
608 line = string;
609 while (line && line[0]) {
610 int error = 0;
612 p=strchr(line, ';');
613 if (p) {
614 p[0] = '\0';
615 } else {
616 p=strchr(line, '\n');
617 if (p) {
618 p[0] = '\0';
621 /* allow a trailing separator */
622 if (line == p) {
623 break;
626 blob->ctr.dsdb.mappings = talloc_realloc(blob,
627 blob->ctr.dsdb.mappings,
628 struct drsuapi_DsReplicaOIDMapping,
629 blob->ctr.dsdb.num_mappings+1);
630 if (!blob->ctr.dsdb.mappings) {
631 talloc_free(tmp_ctx);
632 return -1;
635 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
636 smb_strtoul(line, &oid, 10, &error, SMB_STR_STANDARD);
638 if (oid[0] != ':' || error != 0) {
639 talloc_free(tmp_ctx);
640 return -1;
643 /* we know there must be at least ":" */
644 oid++;
646 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
647 talloc_free(tmp_ctx);
648 return -1;
650 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
651 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
653 blob->ctr.dsdb.num_mappings++;
655 /* Now look past the terminator we added above */
656 if (p) {
657 line = p + 1;
658 } else {
659 line = NULL;
663 ndr_err = ndr_push_struct_blob(out, mem_ctx,
664 blob,
665 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
666 talloc_free(tmp_ctx);
667 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
668 return -1;
670 return 0;
674 convert a NDR formatted blob to a ldif formatted prefixMap
676 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
677 const struct ldb_val *in, struct ldb_val *out)
679 struct prefixMapBlob *blob;
680 enum ndr_err_code ndr_err;
681 char *string;
682 uint32_t i;
684 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
685 int err;
686 /* try to decode the blob as S4 prefixMap */
687 err = ldif_write_NDR(ldb, mem_ctx, in, out,
688 sizeof(struct prefixMapBlob),
689 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
690 (ndr_print_fn_t)ndr_print_prefixMapBlob,
691 false);
692 if (0 == err) {
693 return err;
695 /* try parsing it as Windows PrefixMap value */
696 return ldif_write_NDR(ldb, mem_ctx, in, out,
697 sizeof(struct drsuapi_MSPrefixMap_Ctr),
698 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
699 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
700 true);
703 blob = talloc(mem_ctx, struct prefixMapBlob);
704 if (blob == NULL) {
705 return -1;
707 ndr_err = ndr_pull_struct_blob_all(in, blob,
708 blob,
709 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
710 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
711 goto failed;
713 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
714 goto failed;
716 string = talloc_strdup(mem_ctx, "");
717 if (string == NULL) {
718 goto failed;
721 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
722 DATA_BLOB oid_blob;
723 char *partial_oid = NULL;
725 if (i > 0) {
726 talloc_asprintf_addbuf(&string, ";");
729 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
730 blob->ctr.dsdb.mappings[i].oid.length);
731 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
732 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
733 blob->ctr.dsdb.mappings[i].id_prefix));
734 goto failed;
736 talloc_asprintf_addbuf(&string, "%u:%s",
737 blob->ctr.dsdb.mappings[i].id_prefix,
738 partial_oid);
739 talloc_free(discard_const(partial_oid));
742 talloc_free(blob);
743 *out = data_blob_string_const(string);
744 return 0;
746 failed:
747 talloc_free(blob);
748 return -1;
751 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
753 if (v->length < 4) {
754 return true;
757 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
758 return false;
761 return true;
765 canonicalise a prefixMap
767 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
768 const struct ldb_val *in, struct ldb_val *out)
770 if (ldif_comparision_prefixMap_isString(in)) {
771 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
773 return ldb_handler_copy(ldb, mem_ctx, in, out);
776 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
777 const struct ldb_val *v1,
778 const struct ldb_val *v2)
780 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
781 v1, v2);
784 /* length limited conversion of a ldb_val to a int32_t */
785 static int val_to_int32(const struct ldb_val *in, int32_t *v)
787 char *end;
788 char buf[64];
790 /* make sure we don't read past the end of the data */
791 if (in->length > sizeof(buf)-1) {
792 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
794 strncpy(buf, (char *)in->data, in->length);
795 buf[in->length] = 0;
797 /* We've to use "strtoll" here to have the intended overflows.
798 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
799 *v = (int32_t) strtoll(buf, &end, 0);
800 if (*end != 0) {
801 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
803 return LDB_SUCCESS;
806 /* length limited conversion of a ldb_val to a int64_t */
807 static int val_to_int64(const struct ldb_val *in, int64_t *v)
809 char *end;
810 char buf[64];
812 /* make sure we don't read past the end of the data */
813 if (in->length > sizeof(buf)-1) {
814 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
816 strncpy(buf, (char *)in->data, in->length);
817 buf[in->length] = 0;
819 *v = (int64_t) strtoll(buf, &end, 0);
820 if (*end != 0) {
821 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
823 return LDB_SUCCESS;
826 /* Canonicalisation of two 32-bit integers */
827 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
828 const struct ldb_val *in, struct ldb_val *out)
830 int32_t i;
831 int ret;
833 ret = val_to_int32(in, &i);
834 if (ret != LDB_SUCCESS) {
835 return ret;
837 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
838 if (out->data == NULL) {
839 ldb_oom(ldb);
840 return LDB_ERR_OPERATIONS_ERROR;
842 out->length = strlen((char *)out->data);
843 return 0;
847 * Lexicographically sorted representation for a 32-bit integer
849 * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
850 * n o p
852 * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
853 * corresponding documentation for 64-bit integers.
855 * The same rules apply but use INT32_MIN and INT32_MAX.
857 * String representation padding is done to 10 characters.
859 * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
862 static int ldif_index_format_int32(struct ldb_context *ldb,
863 void *mem_ctx,
864 const struct ldb_val *in,
865 struct ldb_val *out)
867 int32_t i;
868 int ret;
869 char prefix;
870 size_t len;
872 ret = val_to_int32(in, &i);
873 if (ret != LDB_SUCCESS) {
874 return ret;
877 if (i < 0) {
879 * i is negative, so this is subtraction rather than
880 * wrap-around.
882 prefix = 'n';
883 i = INT32_MAX + i + 1;
884 } else if (i > 0) {
885 prefix = 'p';
886 } else {
887 prefix = 'o';
890 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
891 if (out->data == NULL) {
892 ldb_oom(ldb);
893 return LDB_ERR_OPERATIONS_ERROR;
896 len = talloc_array_length(out->data) - 1;
897 if (len != 11) {
898 ldb_debug(ldb, LDB_DEBUG_ERROR,
899 __location__ ": expected index format str %s to"
900 " have length 11 but got %zu",
901 (char*)out->data, len);
902 return LDB_ERR_OPERATIONS_ERROR;
905 out->length = 11;
906 return 0;
909 /* Comparison of two 32-bit integers */
910 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
911 const struct ldb_val *v1, const struct ldb_val *v2)
913 int32_t i1=0, i2=0;
914 val_to_int32(v1, &i1);
915 val_to_int32(v2, &i2);
916 if (i1 == i2) return 0;
917 return i1 > i2? 1 : -1;
920 /* Canonicalisation of two 64-bit integers */
921 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
922 const struct ldb_val *in, struct ldb_val *out)
924 int64_t i;
925 int ret;
927 ret = val_to_int64(in, &i);
928 if (ret != LDB_SUCCESS) {
929 return ret;
931 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
932 if (out->data == NULL) {
933 ldb_oom(ldb);
934 return LDB_ERR_OPERATIONS_ERROR;
936 out->length = strlen((char *)out->data);
937 return 0;
940 /* Comparison of two 64-bit integers */
941 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
942 const struct ldb_val *v1, const struct ldb_val *v2)
944 int64_t i1=0, i2=0;
945 val_to_int64(v1, &i1);
946 val_to_int64(v2, &i2);
947 if (i1 == i2) return 0;
948 return i1 > i2? 1 : -1;
952 convert a NDR formatted blob to a ldif formatted repsFromTo
954 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
955 const struct ldb_val *in, struct ldb_val *out)
957 return ldif_write_NDR(ldb, mem_ctx, in, out,
958 sizeof(struct repsFromToBlob),
959 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
960 (ndr_print_fn_t)ndr_print_repsFromToBlob,
961 true);
965 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
967 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
968 const struct ldb_val *in, struct ldb_val *out)
970 return ldif_write_NDR(ldb, mem_ctx, in, out,
971 sizeof(struct replPropertyMetaDataBlob),
972 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
973 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
974 true);
978 convert a NDR formatted blob to a ldif formatted replUpToDateVector
980 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
981 const struct ldb_val *in, struct ldb_val *out)
983 return ldif_write_NDR(ldb, mem_ctx, in, out,
984 sizeof(struct replUpToDateVectorBlob),
985 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
986 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
987 true);
990 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
991 const struct ldb_val *in, struct ldb_val *out,
992 size_t struct_size,
993 ndr_pull_flags_fn_t pull_fn,
994 ndr_print_fn_t print_fn,
995 bool mask_errors)
997 uint8_t *p = NULL;
998 enum ndr_err_code err;
999 struct dsdb_dn *dsdb_dn = NULL;
1000 char *dn_str = NULL;
1001 char *str = NULL;
1003 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
1004 return ldb_handler_copy(ldb, mem_ctx, in, out);
1007 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
1008 if (dsdb_dn == NULL) {
1009 return ldb_handler_copy(ldb, mem_ctx, in, out);
1012 p = talloc_size(dsdb_dn, struct_size);
1013 if (p == NULL) {
1014 TALLOC_FREE(dsdb_dn);
1015 return ldb_handler_copy(ldb, mem_ctx, in, out);
1018 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
1019 if (err != NDR_ERR_SUCCESS) {
1020 /* fail in not in mask_error mode */
1021 if (!mask_errors) {
1022 return -1;
1024 TALLOC_FREE(dsdb_dn);
1025 return ldb_handler_copy(ldb, mem_ctx, in, out);
1028 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
1029 if (dn_str == NULL) {
1030 TALLOC_FREE(dsdb_dn);
1031 return ldb_handler_copy(ldb, mem_ctx, in, out);
1034 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
1035 TALLOC_FREE(dsdb_dn);
1036 if (str == NULL) {
1037 return ldb_handler_copy(ldb, mem_ctx, in, out);
1040 *out = data_blob_string_const(str);
1041 return 0;
1044 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
1045 const struct ldb_val *in, struct ldb_val *out)
1047 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
1048 sizeof(struct replPropertyMetaData1),
1049 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
1050 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
1051 true);
1055 convert a NDR formatted blob to a ldif formatted dnsRecord
1057 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
1058 const struct ldb_val *in, struct ldb_val *out)
1060 return ldif_write_NDR(ldb, mem_ctx, in, out,
1061 sizeof(struct dnsp_DnssrvRpcRecord),
1062 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
1063 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
1064 true);
1068 convert a NDR formatted blob to a ldif formatted dnsProperty
1070 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1071 const struct ldb_val *in, struct ldb_val *out)
1073 return ldif_write_NDR(ldb, mem_ctx, in, out,
1074 sizeof(struct dnsp_DnsProperty),
1075 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1076 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1077 true);
1081 convert a NDR formatted blob of a supplementalCredentials into text
1083 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1084 const struct ldb_val *in, struct ldb_val *out)
1086 return ldif_write_NDR(ldb, mem_ctx, in, out,
1087 sizeof(struct supplementalCredentialsBlob),
1088 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1089 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1090 true);
1094 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1096 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1097 const struct ldb_val *in, struct ldb_val *out)
1099 return ldif_write_NDR(ldb, mem_ctx, in, out,
1100 sizeof(struct trustAuthInOutBlob),
1101 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1102 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1103 true);
1107 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1109 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1110 const struct ldb_val *in, struct ldb_val *out)
1112 return ldif_write_NDR(ldb, mem_ctx, in, out,
1113 sizeof(struct ForestTrustInfo),
1114 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1115 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1116 true);
1119 convert a NDR formatted blob of a partialAttributeSet into text
1121 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1122 const struct ldb_val *in, struct ldb_val *out)
1124 return ldif_write_NDR(ldb, mem_ctx, in, out,
1125 sizeof(struct partialAttributeSetBlob),
1126 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1127 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1128 true);
1132 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1133 const struct ldb_val *in, struct ldb_val *out)
1135 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1136 if (!out->data) {
1137 return -1;
1139 return 0;
1143 compare two dns
1145 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1146 const struct ldb_val *v1, const struct ldb_val *v2)
1148 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1149 int ret;
1151 if (dsdb_dn_is_deleted_val(v1)) {
1152 /* If the DN is deleted, then we can't search for it */
1153 return -1;
1156 if (dsdb_dn_is_deleted_val(v2)) {
1157 /* If the DN is deleted, then we can't search for it */
1158 return -1;
1161 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1162 if ( ! ldb_dn_validate(dn1)) return -1;
1164 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1165 if ( ! ldb_dn_validate(dn2)) {
1166 talloc_free(dn1);
1167 return -1;
1170 ret = ldb_dn_compare(dn1, dn2);
1172 talloc_free(dn1);
1173 talloc_free(dn2);
1174 return ret;
1177 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1178 const struct ldb_val *in, struct ldb_val *out)
1180 struct ldb_dn *dn;
1181 int ret = -1;
1183 out->length = 0;
1184 out->data = NULL;
1186 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1187 if ( ! ldb_dn_validate(dn)) {
1188 return LDB_ERR_INVALID_DN_SYNTAX;
1191 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1192 * does not casually match a not deleted DN */
1193 if (dsdb_dn_is_deleted_val(in)) {
1194 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1195 "<RMD_FLAGS=%u>%s",
1196 dsdb_dn_val_rmd_flags(in),
1197 ldb_dn_get_casefold(dn));
1198 } else {
1199 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1202 if (out->data == NULL) {
1203 goto done;
1205 out->length = strlen((char *)out->data);
1207 ret = 0;
1209 done:
1210 talloc_free(dn);
1212 return ret;
1217 write a 64 bit 2-part range
1219 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1220 const struct ldb_val *in, struct ldb_val *out)
1222 int64_t v;
1223 int ret;
1224 ret = val_to_int64(in, &v);
1225 if (ret != LDB_SUCCESS) {
1226 return ret;
1228 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1229 (unsigned long)(v&0xFFFFFFFF),
1230 (unsigned long)(v>>32));
1231 if (out->data == NULL) {
1232 ldb_oom(ldb);
1233 return LDB_ERR_OPERATIONS_ERROR;
1235 out->length = strlen((char *)out->data);
1236 return LDB_SUCCESS;
1240 read a 64 bit 2-part range
1242 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1243 const struct ldb_val *in, struct ldb_val *out)
1245 unsigned long high, low;
1246 char buf[64];
1248 if (memchr(in->data, '-', in->length) == NULL) {
1249 return ldb_handler_copy(ldb, mem_ctx, in, out);
1252 if (in->length > sizeof(buf)-1) {
1253 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1255 strncpy(buf, (const char *)in->data, in->length);
1256 buf[in->length] = 0;
1258 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1259 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1262 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1263 (unsigned long long)(((uint64_t)high)<<32) | (low));
1265 if (out->data == NULL) {
1266 ldb_oom(ldb);
1267 return LDB_ERR_OPERATIONS_ERROR;
1269 out->length = strlen((char *)out->data);
1270 return LDB_SUCCESS;
1274 when this operator_fn is set for a syntax, the backend calls is in
1275 preference to the comparison function. We are told the exact
1276 comparison operation that is needed, and we can return errors
1278 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1279 const struct ldb_schema_attribute *a,
1280 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1282 switch (operation) {
1283 case LDB_OP_AND:
1284 case LDB_OP_OR:
1285 case LDB_OP_NOT:
1286 case LDB_OP_SUBSTRING:
1287 case LDB_OP_APPROX:
1288 case LDB_OP_EXTENDED:
1289 /* handled in the backends */
1290 return LDB_ERR_INAPPROPRIATE_MATCHING;
1292 case LDB_OP_GREATER:
1293 case LDB_OP_LESS:
1294 case LDB_OP_EQUALITY:
1296 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1297 int ret;
1298 if (tmp_ctx == NULL) {
1299 return ldb_oom(ldb);
1301 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1302 talloc_free(tmp_ctx);
1303 if (operation == LDB_OP_GREATER) {
1304 *matched = (ret >= 0);
1305 } else if (operation == LDB_OP_LESS) {
1306 *matched = (ret <= 0);
1307 } else {
1308 *matched = (ret == 0);
1310 return LDB_SUCCESS;
1313 case LDB_OP_PRESENT:
1314 *matched = true;
1315 return LDB_SUCCESS;
1318 /* we shouldn't get here */
1319 return LDB_ERR_INAPPROPRIATE_MATCHING;
1323 compare two binary objects. This is correct for sorting as the sort order is:
1330 rather than ldb_comparison_binary() which is:
1338 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1339 const struct ldb_val *v1, const struct ldb_val *v2)
1341 return data_blob_cmp(v1, v2);
1345 when this operator_fn is set for a syntax, the backend calls is in
1346 preference to the comparison function. We are told the exact
1347 comparison operation that is needed, and we can return errors.
1349 This mode optimises for ldb_comparison_binary() if we need equality,
1350 as this should be faster as it can do a length-check first.
1352 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1353 const struct ldb_schema_attribute *a,
1354 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1356 if (operation == LDB_OP_EQUALITY) {
1357 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1358 return LDB_SUCCESS;
1360 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1364 see if two DNs match, comparing first by GUID, then by SID, and
1365 finally by string components
1367 static int samba_dn_extended_match(struct ldb_context *ldb,
1368 const struct ldb_val *v1,
1369 const struct ldb_val *v2,
1370 bool *matched)
1372 TALLOC_CTX *tmp_ctx;
1373 struct ldb_dn *dn1, *dn2;
1374 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1375 uint32_t rmd_flags1, rmd_flags2;
1377 tmp_ctx = talloc_new(ldb);
1379 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1380 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1381 if (!dn1 || !dn2) {
1382 /* couldn't parse as DN's */
1383 talloc_free(tmp_ctx);
1384 (*matched) = false;
1385 return LDB_SUCCESS;
1388 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1389 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1391 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1392 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1393 /* only match if they have the same deletion status */
1394 talloc_free(tmp_ctx);
1395 (*matched) = false;
1396 return LDB_SUCCESS;
1400 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1401 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1402 if (guid1 && guid2) {
1403 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1404 talloc_free(tmp_ctx);
1405 return LDB_SUCCESS;
1408 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1409 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1410 if (sid1 && sid2) {
1411 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1412 talloc_free(tmp_ctx);
1413 return LDB_SUCCESS;
1416 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1418 talloc_free(tmp_ctx);
1419 return LDB_SUCCESS;
1423 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1425 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1426 const struct ldb_schema_attribute *a,
1427 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1429 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1430 /* If the DN is deleted, then we can't search for it */
1432 /* should this be for equality too? */
1433 *matched = false;
1434 return LDB_SUCCESS;
1437 if (operation == LDB_OP_EQUALITY &&
1438 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1439 return LDB_SUCCESS;
1442 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1446 static const struct ldb_schema_syntax samba_syntaxes[] = {
1448 .name = LDB_SYNTAX_SAMBA_SID,
1449 .ldif_read_fn = ldif_read_objectSid,
1450 .ldif_write_fn = ldif_write_objectSid,
1451 .canonicalise_fn = ldif_canonicalise_objectSid,
1452 .comparison_fn = ldif_comparison_objectSid,
1453 .operator_fn = samba_syntax_operator_fn
1455 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1456 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1457 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1458 .canonicalise_fn = ldb_handler_copy,
1459 .comparison_fn = samba_ldb_comparison_binary,
1460 .operator_fn = samba_syntax_binary_operator_fn
1462 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1463 .ldif_read_fn = ldb_handler_copy,
1464 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1465 .canonicalise_fn = ldb_handler_fold,
1466 .comparison_fn = ldb_comparison_fold,
1467 .operator_fn = samba_syntax_operator_fn
1469 .name = LDB_SYNTAX_SAMBA_GUID,
1470 .ldif_read_fn = ldif_read_objectGUID,
1471 .ldif_write_fn = ldif_write_objectGUID,
1472 .canonicalise_fn = ldif_canonicalise_objectGUID,
1473 .comparison_fn = ldif_comparison_objectGUID,
1474 .operator_fn = samba_syntax_operator_fn
1476 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1477 .ldif_read_fn = ldb_handler_copy,
1478 .ldif_write_fn = ldb_handler_copy,
1479 .canonicalise_fn = ldif_canonicalise_objectCategory,
1480 .comparison_fn = ldif_comparison_objectCategory,
1481 .operator_fn = samba_syntax_operator_fn
1483 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1484 .ldif_read_fn = ldb_handler_copy,
1485 .ldif_write_fn = ldif_write_schemaInfo,
1486 .canonicalise_fn = ldb_handler_copy,
1487 .comparison_fn = samba_ldb_comparison_binary,
1488 .operator_fn = samba_syntax_binary_operator_fn
1490 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1491 .ldif_read_fn = ldif_read_prefixMap,
1492 .ldif_write_fn = ldif_write_prefixMap,
1493 .canonicalise_fn = ldif_canonicalise_prefixMap,
1494 .comparison_fn = ldif_comparison_prefixMap,
1495 .operator_fn = samba_syntax_operator_fn
1497 .name = LDB_SYNTAX_SAMBA_INT32,
1498 .ldif_read_fn = ldb_handler_copy,
1499 .ldif_write_fn = ldb_handler_copy,
1500 .canonicalise_fn = ldif_canonicalise_int32,
1501 .index_format_fn = ldif_index_format_int32,
1502 .comparison_fn = ldif_comparison_int32,
1503 .operator_fn = samba_syntax_operator_fn
1505 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1506 .ldif_read_fn = ldb_handler_copy,
1507 .ldif_write_fn = ldif_write_repsFromTo,
1508 .canonicalise_fn = ldb_handler_copy,
1509 .comparison_fn = samba_ldb_comparison_binary,
1510 .operator_fn = samba_syntax_binary_operator_fn
1512 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1513 .ldif_read_fn = ldb_handler_copy,
1514 .ldif_write_fn = ldif_write_replPropertyMetaData,
1515 .canonicalise_fn = ldb_handler_copy,
1516 .comparison_fn = samba_ldb_comparison_binary,
1517 .operator_fn = samba_syntax_binary_operator_fn
1519 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1520 .ldif_read_fn = ldb_handler_copy,
1521 .ldif_write_fn = ldif_write_replUpToDateVector,
1522 .canonicalise_fn = ldb_handler_copy,
1523 .comparison_fn = samba_ldb_comparison_binary,
1524 .operator_fn = samba_syntax_binary_operator_fn
1526 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1527 .ldif_read_fn = ldb_handler_copy,
1528 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1529 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1530 .comparison_fn = dsdb_dn_binary_comparison,
1531 .operator_fn = samba_syntax_operator_fn
1533 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1534 .ldif_read_fn = ldb_handler_copy,
1535 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1536 .canonicalise_fn = ldb_handler_copy,
1537 .comparison_fn = samba_ldb_comparison_binary,
1538 .operator_fn = samba_syntax_binary_operator_fn
1540 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1541 .ldif_read_fn = ldb_handler_copy,
1542 .ldif_write_fn = ldif_write_ForestTrustInfo,
1543 .canonicalise_fn = ldb_handler_copy,
1544 .comparison_fn = samba_ldb_comparison_binary,
1545 .operator_fn = samba_syntax_binary_operator_fn
1547 .name = DSDB_SYNTAX_BINARY_DN,
1548 .ldif_read_fn = ldb_handler_copy,
1549 .ldif_write_fn = ldb_handler_copy,
1550 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1551 .comparison_fn = dsdb_dn_binary_comparison,
1552 .operator_fn = samba_syntax_operator_fn
1554 .name = DSDB_SYNTAX_STRING_DN,
1555 .ldif_read_fn = ldb_handler_copy,
1556 .ldif_write_fn = ldb_handler_copy,
1557 .canonicalise_fn = dsdb_dn_string_canonicalise,
1558 .comparison_fn = dsdb_dn_string_comparison,
1559 .operator_fn = samba_syntax_operator_fn
1561 .name = LDB_SYNTAX_DN,
1562 .ldif_read_fn = ldb_handler_copy,
1563 .ldif_write_fn = ldb_handler_copy,
1564 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1565 .comparison_fn = samba_ldb_dn_link_comparison,
1566 .operator_fn = samba_syntax_operator_dn
1568 .name = LDB_SYNTAX_SAMBA_RANGE64,
1569 .ldif_read_fn = ldif_read_range64,
1570 .ldif_write_fn = ldif_write_range64,
1571 .canonicalise_fn = ldif_canonicalise_int64,
1572 .comparison_fn = ldif_comparison_int64,
1573 .operator_fn = samba_syntax_operator_fn
1575 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1576 .ldif_read_fn = ldb_handler_copy,
1577 .ldif_write_fn = ldif_write_dnsRecord,
1578 .canonicalise_fn = ldb_handler_copy,
1579 .comparison_fn = samba_ldb_comparison_binary,
1580 .operator_fn = samba_syntax_binary_operator_fn
1582 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1583 .ldif_read_fn = ldb_handler_copy,
1584 .ldif_write_fn = ldif_write_dnsProperty,
1585 .canonicalise_fn = ldb_handler_copy,
1586 .comparison_fn = samba_ldb_comparison_binary,
1587 .operator_fn = samba_syntax_binary_operator_fn
1589 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1590 .ldif_read_fn = ldb_handler_copy,
1591 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1592 .canonicalise_fn = ldb_handler_copy,
1593 .comparison_fn = samba_ldb_comparison_binary,
1594 .operator_fn = samba_syntax_binary_operator_fn
1596 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1597 .ldif_read_fn = ldb_handler_copy,
1598 .ldif_write_fn = ldif_write_partialAttributeSet,
1599 .canonicalise_fn = ldb_handler_copy,
1600 .comparison_fn = samba_ldb_comparison_binary,
1601 .operator_fn = samba_syntax_binary_operator_fn
1603 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1604 .ldif_read_fn = ldb_handler_copy,
1605 .ldif_write_fn = ldb_handler_copy,
1606 .canonicalise_fn = ldb_handler_copy,
1607 .comparison_fn = samba_ldb_comparison_binary,
1608 .operator_fn = samba_syntax_binary_operator_fn
1612 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1614 .name = "SID",
1615 .read_fn = extended_dn_read_SID,
1616 .write_clear_fn = ldif_write_objectSid,
1617 .write_hex_fn = extended_dn_write_hex
1619 .name = "GUID",
1620 .read_fn = extended_dn_read_GUID,
1621 .write_clear_fn = ldif_write_objectGUID,
1622 .write_hex_fn = extended_dn_write_hex
1624 .name = "WKGUID",
1625 .read_fn = ldb_handler_copy,
1626 .write_clear_fn = ldb_handler_copy,
1627 .write_hex_fn = ldb_handler_copy
1629 .name = "RMD_INVOCID",
1630 .read_fn = extended_dn_read_GUID,
1631 .write_clear_fn = ldif_write_objectGUID,
1632 .write_hex_fn = extended_dn_write_hex
1634 .name = "RMD_FLAGS",
1635 .read_fn = ldb_handler_copy,
1636 .write_clear_fn = ldb_handler_copy,
1637 .write_hex_fn = ldb_handler_copy
1639 .name = "RMD_ADDTIME",
1640 .read_fn = ldb_handler_copy,
1641 .write_clear_fn = ldb_handler_copy,
1642 .write_hex_fn = ldb_handler_copy
1644 .name = "RMD_CHANGETIME",
1645 .read_fn = ldb_handler_copy,
1646 .write_clear_fn = ldb_handler_copy,
1647 .write_hex_fn = ldb_handler_copy
1649 .name = "RMD_LOCAL_USN",
1650 .read_fn = ldb_handler_copy,
1651 .write_clear_fn = ldb_handler_copy,
1652 .write_hex_fn = ldb_handler_copy
1654 .name = "RMD_ORIGINATING_USN",
1655 .read_fn = ldb_handler_copy,
1656 .write_clear_fn = ldb_handler_copy,
1657 .write_hex_fn = ldb_handler_copy
1659 .name = "RMD_VERSION",
1660 .read_fn = ldb_handler_copy,
1661 .write_clear_fn = ldb_handler_copy,
1662 .write_hex_fn = ldb_handler_copy
1666 /* TODO: Should be dynamic at some point */
1667 static const struct {
1668 const char *name;
1669 const char *syntax;
1670 } samba_attributes[] = {
1671 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1672 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1673 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1674 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1675 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1676 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1677 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1678 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1679 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1680 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1681 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1682 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1683 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1684 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1685 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1686 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1687 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1690 * these are extracted by searching
1691 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1693 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1694 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1695 * hat can be used to identify the set of policies when applied to a resource.
1696 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1697 * server, we ignore it here.
1699 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1700 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1701 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1702 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1703 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1704 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1705 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1706 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1707 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1710 * these are extracted by searching
1711 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1713 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1714 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1715 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1716 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1717 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1718 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1719 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1720 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1721 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1722 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1723 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1724 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1725 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1726 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1727 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1728 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1729 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1730 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1731 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1732 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1733 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1734 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1735 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1736 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1737 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1738 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1739 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1740 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1743 * these are known to be GUIDs
1745 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1746 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1748 /* These NDR encoded things we want to be able to read with --show-binary */
1749 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1750 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1751 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1752 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1755 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1757 unsigned int j;
1758 const struct ldb_schema_syntax *s = NULL;
1760 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1761 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1762 s = &samba_syntaxes[j];
1763 break;
1766 return s;
1769 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1771 unsigned int j;
1772 const struct ldb_schema_syntax *s = NULL;
1774 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1775 if (strcmp(samba_attributes[j].name, name) == 0) {
1776 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1777 break;
1781 return s;
1784 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1785 "priorSecret", NULL};
1788 register the samba ldif handlers
1790 int ldb_register_samba_handlers(struct ldb_context *ldb)
1792 unsigned int i;
1793 int ret;
1795 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1796 return LDB_SUCCESS;
1799 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1800 if (ret != LDB_SUCCESS) {
1801 return ret;
1804 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1805 const struct ldb_schema_syntax *s = NULL;
1807 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1809 if (!s) {
1810 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1813 if (!s) {
1814 return LDB_ERR_OPERATIONS_ERROR;
1817 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1818 if (ret != LDB_SUCCESS) {
1819 return ret;
1823 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1824 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1825 if (ret != LDB_SUCCESS) {
1826 return ret;
1831 ret = ldb_register_samba_matching_rules(ldb);
1832 if (ret != LDB_SUCCESS) {
1833 talloc_free(ldb);
1834 return LDB_SUCCESS;
1837 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1838 if (ret != LDB_SUCCESS) {
1839 return ret;
1842 return LDB_SUCCESS;