rpc_server: Avoid casts in DBG statements
[Samba.git] / lib / ldb-samba / ldif_handlers.c
blobd38cdd0c9a32d7c2c91b0a0a9dad57b264f7dc29
1 /*
2 ldb database library - ldif handlers for Samba
4 Copyright (C) Andrew Tridgell 2005
5 Copyright (C) Andrew Bartlett 2006-2009
6 Copyright (C) Matthias Dieter Wallnöfer 2009
7 ** NOTE! The following LGPL license applies to the ldb
8 ** library. This does NOT imply that all of Samba is released
9 ** under the LGPL
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include <ldb.h>
27 #include <ldb_module.h>
28 #include "ldb_handlers.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "dsdb/common/util.h"
31 #include "librpc/gen_ndr/ndr_security.h"
32 #include "librpc/gen_ndr/ndr_misc.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "librpc/gen_ndr/ndr_dnsp.h"
35 #include "librpc/ndr/libndr.h"
36 #include "libcli/security/security.h"
37 #include "param/param.h"
38 #include "../lib/util/asn1.h"
41 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
43 If mask_errors is true, then function succeeds but out data
44 is set to "<Unable to decode binary data>" message
46 \return 0 on success; -1 on error
48 static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
49 const struct ldb_val *in, struct ldb_val *out,
50 size_t struct_size,
51 ndr_pull_flags_fn_t pull_fn,
52 ndr_print_fn_t print_fn,
53 bool mask_errors)
55 uint8_t *p;
56 enum ndr_err_code err;
57 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
58 return ldb_handler_copy(ldb, mem_ctx, in, out);
60 p = talloc_size(mem_ctx, struct_size);
61 err = ndr_pull_struct_blob(in, mem_ctx,
62 p, pull_fn);
63 if (err != NDR_ERR_SUCCESS) {
64 /* fail in not in mask_error mode */
65 if (!mask_errors) {
66 return -1;
68 talloc_free(p);
69 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
70 out->length = strlen((const char *)out->data);
71 return 0;
73 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
74 talloc_free(p);
75 if (out->data == NULL) {
76 return ldb_handler_copy(ldb, mem_ctx, in, out);
78 out->length = strlen((char *)out->data);
79 return 0;
83 convert a ldif formatted objectSid to a NDR formatted blob
85 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
86 const struct ldb_val *in, struct ldb_val *out)
88 bool ret;
89 enum ndr_err_code ndr_err;
90 struct dom_sid sid;
91 if (in->length > DOM_SID_STR_BUFLEN) {
92 return -1;
93 } else {
94 char p[in->length+1];
95 memcpy(p, in->data, in->length);
96 p[in->length] = '\0';
98 ret = dom_sid_parse(p, &sid);
99 if (ret == false) {
100 return -1;
103 *out = data_blob_talloc(mem_ctx, NULL,
104 ndr_size_dom_sid(&sid, 0));
105 if (out->data == NULL) {
106 return -1;
109 ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
110 (ndr_push_flags_fn_t)ndr_push_dom_sid);
111 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
112 return -1;
115 return 0;
119 convert a NDR formatted blob to a ldif formatted objectSid
121 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
122 const struct ldb_val *in, struct ldb_val *out)
124 struct dom_sid sid;
125 enum ndr_err_code ndr_err;
127 ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
128 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
129 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
130 return -1;
132 *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
133 if (out->data == NULL) {
134 return -1;
136 return 0;
139 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
141 if (v->length < 3) {
142 return false;
145 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
147 return true;
151 compare two objectSids
153 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
154 const struct ldb_val *v1, const struct ldb_val *v2)
156 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
157 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
158 } else if (ldif_comparision_objectSid_isString(v1)
159 && !ldif_comparision_objectSid_isString(v2)) {
160 struct ldb_val v;
161 int ret;
162 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
163 /* Perhaps not a string after all */
164 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
166 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
167 talloc_free(v.data);
168 return ret;
169 } else if (!ldif_comparision_objectSid_isString(v1)
170 && ldif_comparision_objectSid_isString(v2)) {
171 struct ldb_val v;
172 int ret;
173 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
174 /* Perhaps not a string after all */
175 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
177 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
178 talloc_free(v.data);
179 return ret;
181 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
185 canonicalise a objectSid
187 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
188 const struct ldb_val *in, struct ldb_val *out)
190 if (ldif_comparision_objectSid_isString(in)) {
191 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
192 /* Perhaps not a string after all */
193 return ldb_handler_copy(ldb, mem_ctx, in, out);
195 return 0;
197 return ldb_handler_copy(ldb, mem_ctx, in, out);
200 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
201 const struct ldb_val *in, struct ldb_val *out)
203 struct dom_sid sid;
204 enum ndr_err_code ndr_err;
205 if (ldif_comparision_objectSid_isString(in)) {
206 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
207 return 0;
211 /* Perhaps not a string after all */
212 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
214 if (!out->data) {
215 return -1;
218 (*out).length = strhex_to_str((char *)out->data, out->length,
219 (const char *)in->data, in->length);
221 /* Check it looks like a SID */
222 ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
223 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
224 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
225 return -1;
227 return 0;
231 convert a ldif formatted objectGUID to a NDR formatted blob
233 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
234 const struct ldb_val *in, struct ldb_val *out)
236 struct GUID guid;
237 NTSTATUS status;
239 status = GUID_from_data_blob(in, &guid);
240 if (!NT_STATUS_IS_OK(status)) {
241 return -1;
244 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
245 if (!NT_STATUS_IS_OK(status)) {
246 return -1;
248 return 0;
252 convert a NDR formatted blob to a ldif formatted objectGUID
254 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
255 const struct ldb_val *in, struct ldb_val *out)
257 struct GUID guid;
258 NTSTATUS status;
260 status = GUID_from_ndr_blob(in, &guid);
261 if (!NT_STATUS_IS_OK(status)) {
262 return -1;
264 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
265 if (out->data == NULL) {
266 return -1;
268 out->length = strlen((const char *)out->data);
269 return 0;
272 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
274 if (v->length != 36 && v->length != 38) return false;
276 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
277 return true;
280 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
281 const struct ldb_val *in, struct ldb_val *out)
284 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
285 return 0;
288 /* Try as 'hex' form */
289 if (in->length != 32) {
290 return -1;
293 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
295 if (!out->data) {
296 return -1;
299 (*out).length = strhex_to_str((char *)out->data, out->length,
300 (const char *)in->data, in->length);
302 /* Check it looks like a GUID */
303 if ((*out).length != 16) {
304 data_blob_free(out);
305 return -1;
308 return 0;
312 compare two objectGUIDs
314 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
315 const struct ldb_val *v1, const struct ldb_val *v2)
317 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
318 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
319 } else if (ldif_comparision_objectGUID_isString(v1)
320 && !ldif_comparision_objectGUID_isString(v2)) {
321 struct ldb_val v;
322 int ret;
323 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
324 /* Perhaps it wasn't a valid string after all */
325 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
327 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
328 talloc_free(v.data);
329 return ret;
330 } else if (!ldif_comparision_objectGUID_isString(v1)
331 && ldif_comparision_objectGUID_isString(v2)) {
332 struct ldb_val v;
333 int ret;
334 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
335 /* Perhaps it wasn't a valid string after all */
336 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
338 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
339 talloc_free(v.data);
340 return ret;
342 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
346 canonicalise a objectGUID
348 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
349 const struct ldb_val *in, struct ldb_val *out)
351 if (ldif_comparision_objectGUID_isString(in)) {
352 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
353 /* Perhaps it wasn't a valid string after all */
354 return ldb_handler_copy(ldb, mem_ctx, in, out);
356 return 0;
358 return ldb_handler_copy(ldb, mem_ctx, in, out);
363 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
365 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
366 const struct ldb_val *in, struct ldb_val *out)
368 struct security_descriptor *sd;
369 enum ndr_err_code ndr_err;
371 sd = talloc(mem_ctx, struct security_descriptor);
372 if (sd == NULL) {
373 return -1;
376 ndr_err = ndr_pull_struct_blob(in, sd, sd,
377 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
378 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
379 /* If this does not parse, then it is probably SDDL, and we should try it that way */
381 const struct dom_sid *sid = samdb_domain_sid(ldb);
382 talloc_free(sd);
383 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
384 if (sd == NULL) {
385 return -1;
389 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
390 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
391 talloc_free(sd);
392 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
393 return -1;
396 return 0;
400 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
402 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
403 const struct ldb_val *in, struct ldb_val *out)
405 struct security_descriptor *sd;
406 enum ndr_err_code ndr_err;
408 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
409 return ldif_write_NDR(ldb, mem_ctx, in, out,
410 sizeof(struct security_descriptor),
411 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
412 (ndr_print_fn_t)ndr_print_security_descriptor,
413 true);
417 sd = talloc(mem_ctx, struct security_descriptor);
418 if (sd == NULL) {
419 return -1;
421 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
422 ndr_err = ndr_pull_struct_blob(in, sd, sd,
423 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
424 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
425 talloc_free(sd);
426 return -1;
428 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
429 talloc_free(sd);
430 if (out->data == NULL) {
431 return -1;
433 out->length = strlen((const char *)out->data);
434 return 0;
438 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
440 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
441 const struct ldb_val *in, struct ldb_val *out)
443 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
444 struct security_descriptor *sd;
445 const struct dom_sid *sid = samdb_domain_sid(ldb);
447 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
448 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
449 (ndr_print_fn_t)ndr_print_security_descriptor,
450 "SDDL", sd);
451 out->length = strlen((const char *)out->data);
452 talloc_free(sd);
453 return 0;
456 return ldb_handler_copy(ldb, mem_ctx, in, out);
460 canonicalise an objectCategory. We use the long form as the canonical form:
461 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
463 Also any short name of an objectClass that points to a different
464 class (such as user) has the canonical form of the class it's
465 defaultObjectCategory points to (eg
466 cn=Person,cn=Schema,cn=Configuration,<basedn>)
469 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
470 const struct ldb_val *in, struct ldb_val *out)
472 struct ldb_dn *dn1 = NULL;
473 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
474 const struct dsdb_class *sclass;
475 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
476 if (!tmp_ctx) {
477 return LDB_ERR_OPERATIONS_ERROR;
480 if (!schema) {
481 talloc_free(tmp_ctx);
482 *out = data_blob_talloc(mem_ctx, in->data, in->length);
483 if (in->data && !out->data) {
484 return LDB_ERR_OPERATIONS_ERROR;
486 return LDB_SUCCESS;
488 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
489 if ( ! ldb_dn_validate(dn1)) {
490 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
491 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
492 if (sclass) {
493 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
494 sclass->defaultObjectCategory);
495 if (dn == NULL) {
496 talloc_free(tmp_ctx);
497 return LDB_ERR_OPERATIONS_ERROR;
500 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
501 talloc_free(tmp_ctx);
503 if (!out->data) {
504 return LDB_ERR_OPERATIONS_ERROR;
506 return LDB_SUCCESS;
507 } else {
508 *out = data_blob_talloc(mem_ctx, in->data, in->length);
509 talloc_free(tmp_ctx);
511 if (in->data && !out->data) {
512 return LDB_ERR_OPERATIONS_ERROR;
514 return LDB_SUCCESS;
517 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
518 talloc_free(tmp_ctx);
520 if (!out->data) {
521 return LDB_ERR_OPERATIONS_ERROR;
523 return LDB_SUCCESS;
526 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
527 const struct ldb_val *v1,
528 const struct ldb_val *v2)
530 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
531 v1, v2);
535 convert a NDR formatted blob to a ldif formatted schemaInfo
537 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
538 const struct ldb_val *in, struct ldb_val *out)
540 return ldif_write_NDR(ldb, mem_ctx, in, out,
541 sizeof(struct repsFromToBlob),
542 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
543 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
544 true);
548 convert a ldif formatted prefixMap to a NDR formatted blob
550 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
551 const struct ldb_val *in, struct ldb_val *out)
553 struct prefixMapBlob *blob;
554 enum ndr_err_code ndr_err;
555 char *string, *line, *p, *oid;
556 DATA_BLOB oid_blob;
558 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
560 if (tmp_ctx == NULL) {
561 return -1;
564 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
565 if (blob == NULL) {
566 talloc_free(tmp_ctx);
567 return -1;
570 /* use the switch value to detect if this is in the binary
571 * format
573 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
574 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
575 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
576 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
577 ndr_err = ndr_push_struct_blob(out, mem_ctx,
578 blob,
579 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
580 talloc_free(tmp_ctx);
581 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
582 return -1;
584 return 0;
588 /* If this does not parse, then it is probably the text version, and we should try it that way */
589 blob->version = PREFIX_MAP_VERSION_DSDB;
591 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
592 if (string == NULL) {
593 talloc_free(blob);
594 return -1;
597 line = string;
598 while (line && line[0]) {
599 int error = 0;
601 p=strchr(line, ';');
602 if (p) {
603 p[0] = '\0';
604 } else {
605 p=strchr(line, '\n');
606 if (p) {
607 p[0] = '\0';
610 /* allow a trailing separator */
611 if (line == p) {
612 break;
615 blob->ctr.dsdb.mappings = talloc_realloc(blob,
616 blob->ctr.dsdb.mappings,
617 struct drsuapi_DsReplicaOIDMapping,
618 blob->ctr.dsdb.num_mappings+1);
619 if (!blob->ctr.dsdb.mappings) {
620 talloc_free(tmp_ctx);
621 return -1;
624 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
625 strtoul_err(line, &oid, 10, &error);
627 if (oid[0] != ':' || error != 0) {
628 talloc_free(tmp_ctx);
629 return -1;
632 /* we know there must be at least ":" */
633 oid++;
635 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
636 talloc_free(tmp_ctx);
637 return -1;
639 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
640 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
642 blob->ctr.dsdb.num_mappings++;
644 /* Now look past the terminator we added above */
645 if (p) {
646 line = p + 1;
647 } else {
648 line = NULL;
652 ndr_err = ndr_push_struct_blob(out, mem_ctx,
653 blob,
654 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
655 talloc_free(tmp_ctx);
656 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
657 return -1;
659 return 0;
663 convert a NDR formatted blob to a ldif formatted prefixMap
665 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
666 const struct ldb_val *in, struct ldb_val *out)
668 struct prefixMapBlob *blob;
669 enum ndr_err_code ndr_err;
670 char *string;
671 uint32_t i;
673 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
674 int err;
675 /* try to decode the blob as S4 prefixMap */
676 err = ldif_write_NDR(ldb, mem_ctx, in, out,
677 sizeof(struct prefixMapBlob),
678 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
679 (ndr_print_fn_t)ndr_print_prefixMapBlob,
680 false);
681 if (0 == err) {
682 return err;
684 /* try parsing it as Windows PrefixMap value */
685 return ldif_write_NDR(ldb, mem_ctx, in, out,
686 sizeof(struct drsuapi_MSPrefixMap_Ctr),
687 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
688 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
689 true);
692 blob = talloc(mem_ctx, struct prefixMapBlob);
693 if (blob == NULL) {
694 return -1;
696 ndr_err = ndr_pull_struct_blob_all(in, blob,
697 blob,
698 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
699 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
700 goto failed;
702 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
703 goto failed;
705 string = talloc_strdup(mem_ctx, "");
706 if (string == NULL) {
707 goto failed;
710 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
711 DATA_BLOB oid_blob;
712 char *partial_oid = NULL;
714 if (i > 0) {
715 string = talloc_asprintf_append(string, ";");
718 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
719 blob->ctr.dsdb.mappings[i].oid.length);
720 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
721 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
722 blob->ctr.dsdb.mappings[i].id_prefix));
723 goto failed;
725 string = talloc_asprintf_append(string, "%u:%s",
726 blob->ctr.dsdb.mappings[i].id_prefix,
727 partial_oid);
728 talloc_free(discard_const(partial_oid));
729 if (string == NULL) {
730 goto failed;
734 talloc_free(blob);
735 *out = data_blob_string_const(string);
736 return 0;
738 failed:
739 talloc_free(blob);
740 return -1;
743 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
745 if (v->length < 4) {
746 return true;
749 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
750 return false;
753 return true;
757 canonicalise a prefixMap
759 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
760 const struct ldb_val *in, struct ldb_val *out)
762 if (ldif_comparision_prefixMap_isString(in)) {
763 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
765 return ldb_handler_copy(ldb, mem_ctx, in, out);
768 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
769 const struct ldb_val *v1,
770 const struct ldb_val *v2)
772 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
773 v1, v2);
776 /* length limited conversion of a ldb_val to a int32_t */
777 static int val_to_int32(const struct ldb_val *in, int32_t *v)
779 char *end;
780 char buf[64];
782 /* make sure we don't read past the end of the data */
783 if (in->length > sizeof(buf)-1) {
784 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
786 strncpy(buf, (char *)in->data, in->length);
787 buf[in->length] = 0;
789 /* We've to use "strtoll" here to have the intended overflows.
790 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
791 *v = (int32_t) strtoll(buf, &end, 0);
792 if (*end != 0) {
793 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
795 return LDB_SUCCESS;
798 /* length limited conversion of a ldb_val to a int64_t */
799 static int val_to_int64(const struct ldb_val *in, int64_t *v)
801 char *end;
802 char buf[64];
804 /* make sure we don't read past the end of the data */
805 if (in->length > sizeof(buf)-1) {
806 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
808 strncpy(buf, (char *)in->data, in->length);
809 buf[in->length] = 0;
811 *v = (int64_t) strtoll(buf, &end, 0);
812 if (*end != 0) {
813 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
815 return LDB_SUCCESS;
818 /* Canonicalisation of two 32-bit integers */
819 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
820 const struct ldb_val *in, struct ldb_val *out)
822 int32_t i;
823 int ret;
825 ret = val_to_int32(in, &i);
826 if (ret != LDB_SUCCESS) {
827 return ret;
829 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
830 if (out->data == NULL) {
831 ldb_oom(ldb);
832 return LDB_ERR_OPERATIONS_ERROR;
834 out->length = strlen((char *)out->data);
835 return 0;
838 /* Comparison of two 32-bit integers */
839 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
840 const struct ldb_val *v1, const struct ldb_val *v2)
842 int32_t i1=0, i2=0;
843 val_to_int32(v1, &i1);
844 val_to_int32(v2, &i2);
845 if (i1 == i2) return 0;
846 return i1 > i2? 1 : -1;
849 /* Canonicalisation of two 64-bit integers */
850 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
851 const struct ldb_val *in, struct ldb_val *out)
853 int64_t i;
854 int ret;
856 ret = val_to_int64(in, &i);
857 if (ret != LDB_SUCCESS) {
858 return ret;
860 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
861 if (out->data == NULL) {
862 ldb_oom(ldb);
863 return LDB_ERR_OPERATIONS_ERROR;
865 out->length = strlen((char *)out->data);
866 return 0;
869 /* Comparison of two 64-bit integers */
870 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
871 const struct ldb_val *v1, const struct ldb_val *v2)
873 int64_t i1=0, i2=0;
874 val_to_int64(v1, &i1);
875 val_to_int64(v2, &i2);
876 if (i1 == i2) return 0;
877 return i1 > i2? 1 : -1;
881 convert a NDR formatted blob to a ldif formatted repsFromTo
883 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
884 const struct ldb_val *in, struct ldb_val *out)
886 return ldif_write_NDR(ldb, mem_ctx, in, out,
887 sizeof(struct repsFromToBlob),
888 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
889 (ndr_print_fn_t)ndr_print_repsFromToBlob,
890 true);
894 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
896 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
897 const struct ldb_val *in, struct ldb_val *out)
899 return ldif_write_NDR(ldb, mem_ctx, in, out,
900 sizeof(struct replPropertyMetaDataBlob),
901 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
902 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
903 true);
907 convert a NDR formatted blob to a ldif formatted replUpToDateVector
909 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
910 const struct ldb_val *in, struct ldb_val *out)
912 return ldif_write_NDR(ldb, mem_ctx, in, out,
913 sizeof(struct replUpToDateVectorBlob),
914 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
915 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
916 true);
919 static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
920 const struct ldb_val *in, struct ldb_val *out,
921 size_t struct_size,
922 ndr_pull_flags_fn_t pull_fn,
923 ndr_print_fn_t print_fn,
924 bool mask_errors)
926 uint8_t *p = NULL;
927 enum ndr_err_code err;
928 struct dsdb_dn *dsdb_dn = NULL;
929 char *dn_str = NULL;
930 char *str = NULL;
932 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
933 return ldb_handler_copy(ldb, mem_ctx, in, out);
936 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
937 if (dsdb_dn == NULL) {
938 return ldb_handler_copy(ldb, mem_ctx, in, out);
941 p = talloc_size(dsdb_dn, struct_size);
942 if (p == NULL) {
943 TALLOC_FREE(dsdb_dn);
944 return ldb_handler_copy(ldb, mem_ctx, in, out);
947 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
948 if (err != NDR_ERR_SUCCESS) {
949 /* fail in not in mask_error mode */
950 if (!mask_errors) {
951 return -1;
953 TALLOC_FREE(dsdb_dn);
954 return ldb_handler_copy(ldb, mem_ctx, in, out);
957 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
958 if (dn_str == NULL) {
959 TALLOC_FREE(dsdb_dn);
960 return ldb_handler_copy(ldb, mem_ctx, in, out);
963 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
964 TALLOC_FREE(dsdb_dn);
965 if (str == NULL) {
966 return ldb_handler_copy(ldb, mem_ctx, in, out);
969 *out = data_blob_string_const(str);
970 return 0;
973 static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
974 const struct ldb_val *in, struct ldb_val *out)
976 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
977 sizeof(struct replPropertyMetaData1),
978 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
979 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
980 true);
984 convert a NDR formatted blob to a ldif formatted dnsRecord
986 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
987 const struct ldb_val *in, struct ldb_val *out)
989 return ldif_write_NDR(ldb, mem_ctx, in, out,
990 sizeof(struct dnsp_DnssrvRpcRecord),
991 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
992 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
993 true);
997 convert a NDR formatted blob to a ldif formatted dnsProperty
999 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1000 const struct ldb_val *in, struct ldb_val *out)
1002 return ldif_write_NDR(ldb, mem_ctx, in, out,
1003 sizeof(struct dnsp_DnsProperty),
1004 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1005 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1006 true);
1010 convert a NDR formatted blob of a supplementalCredentials into text
1012 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1013 const struct ldb_val *in, struct ldb_val *out)
1015 return ldif_write_NDR(ldb, mem_ctx, in, out,
1016 sizeof(struct supplementalCredentialsBlob),
1017 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1018 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1019 true);
1023 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1025 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1026 const struct ldb_val *in, struct ldb_val *out)
1028 return ldif_write_NDR(ldb, mem_ctx, in, out,
1029 sizeof(struct trustAuthInOutBlob),
1030 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1031 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1032 true);
1036 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1038 static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1039 const struct ldb_val *in, struct ldb_val *out)
1041 return ldif_write_NDR(ldb, mem_ctx, in, out,
1042 sizeof(struct ForestTrustInfo),
1043 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1044 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1045 true);
1048 convert a NDR formatted blob of a partialAttributeSet into text
1050 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1051 const struct ldb_val *in, struct ldb_val *out)
1053 return ldif_write_NDR(ldb, mem_ctx, in, out,
1054 sizeof(struct partialAttributeSetBlob),
1055 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1056 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1057 true);
1061 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1062 const struct ldb_val *in, struct ldb_val *out)
1064 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1065 if (!out->data) {
1066 return -1;
1068 return 0;
1072 compare two dns
1074 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1075 const struct ldb_val *v1, const struct ldb_val *v2)
1077 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1078 int ret;
1080 if (dsdb_dn_is_deleted_val(v1)) {
1081 /* If the DN is deleted, then we can't search for it */
1082 return -1;
1085 if (dsdb_dn_is_deleted_val(v2)) {
1086 /* If the DN is deleted, then we can't search for it */
1087 return -1;
1090 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1091 if ( ! ldb_dn_validate(dn1)) return -1;
1093 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1094 if ( ! ldb_dn_validate(dn2)) {
1095 talloc_free(dn1);
1096 return -1;
1099 ret = ldb_dn_compare(dn1, dn2);
1101 talloc_free(dn1);
1102 talloc_free(dn2);
1103 return ret;
1106 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1107 const struct ldb_val *in, struct ldb_val *out)
1109 struct ldb_dn *dn;
1110 int ret = -1;
1112 out->length = 0;
1113 out->data = NULL;
1115 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1116 if ( ! ldb_dn_validate(dn)) {
1117 return LDB_ERR_INVALID_DN_SYNTAX;
1120 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1121 * does not casually match a not deleted DN */
1122 if (dsdb_dn_is_deleted_val(in)) {
1123 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1124 "<RMD_FLAGS=%u>%s",
1125 dsdb_dn_val_rmd_flags(in),
1126 ldb_dn_get_casefold(dn));
1127 } else {
1128 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1131 if (out->data == NULL) {
1132 goto done;
1134 out->length = strlen((char *)out->data);
1136 ret = 0;
1138 done:
1139 talloc_free(dn);
1141 return ret;
1146 write a 64 bit 2-part range
1148 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1149 const struct ldb_val *in, struct ldb_val *out)
1151 int64_t v;
1152 int ret;
1153 ret = val_to_int64(in, &v);
1154 if (ret != LDB_SUCCESS) {
1155 return ret;
1157 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1158 (unsigned long)(v&0xFFFFFFFF),
1159 (unsigned long)(v>>32));
1160 if (out->data == NULL) {
1161 ldb_oom(ldb);
1162 return LDB_ERR_OPERATIONS_ERROR;
1164 out->length = strlen((char *)out->data);
1165 return LDB_SUCCESS;
1169 read a 64 bit 2-part range
1171 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1172 const struct ldb_val *in, struct ldb_val *out)
1174 unsigned long high, low;
1175 char buf[64];
1177 if (memchr(in->data, '-', in->length) == NULL) {
1178 return ldb_handler_copy(ldb, mem_ctx, in, out);
1181 if (in->length > sizeof(buf)-1) {
1182 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1184 strncpy(buf, (const char *)in->data, in->length);
1185 buf[in->length] = 0;
1187 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1188 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1191 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1192 (unsigned long long)(((uint64_t)high)<<32) | (low));
1194 if (out->data == NULL) {
1195 ldb_oom(ldb);
1196 return LDB_ERR_OPERATIONS_ERROR;
1198 out->length = strlen((char *)out->data);
1199 return LDB_SUCCESS;
1203 when this operator_fn is set for a syntax, the backend calls is in
1204 preference to the comparison function. We are told the exact
1205 comparison operation that is needed, and we can return errors
1207 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1208 const struct ldb_schema_attribute *a,
1209 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1211 switch (operation) {
1212 case LDB_OP_AND:
1213 case LDB_OP_OR:
1214 case LDB_OP_NOT:
1215 case LDB_OP_SUBSTRING:
1216 case LDB_OP_APPROX:
1217 case LDB_OP_EXTENDED:
1218 /* handled in the backends */
1219 return LDB_ERR_INAPPROPRIATE_MATCHING;
1221 case LDB_OP_GREATER:
1222 case LDB_OP_LESS:
1223 case LDB_OP_EQUALITY:
1225 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1226 int ret;
1227 if (tmp_ctx == NULL) {
1228 return ldb_oom(ldb);
1230 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1231 talloc_free(tmp_ctx);
1232 if (operation == LDB_OP_GREATER) {
1233 *matched = (ret >= 0);
1234 } else if (operation == LDB_OP_LESS) {
1235 *matched = (ret <= 0);
1236 } else {
1237 *matched = (ret == 0);
1239 return LDB_SUCCESS;
1242 case LDB_OP_PRESENT:
1243 *matched = true;
1244 return LDB_SUCCESS;
1247 /* we shouldn't get here */
1248 return LDB_ERR_INAPPROPRIATE_MATCHING;
1252 compare two binary objects. This is correct for sorting as the sort order is:
1259 rather than ldb_comparison_binary() which is:
1267 static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1268 const struct ldb_val *v1, const struct ldb_val *v2)
1270 return data_blob_cmp(v1, v2);
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 This mode optimises for ldb_comparison_binary() if we need equality,
1279 as this should be faster as it can do a length-check first.
1281 static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1282 const struct ldb_schema_attribute *a,
1283 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1285 if (operation == LDB_OP_EQUALITY) {
1286 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1287 return LDB_SUCCESS;
1289 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1293 see if two DNs match, comparing first by GUID, then by SID, and
1294 finally by string components
1296 static int samba_dn_extended_match(struct ldb_context *ldb,
1297 const struct ldb_val *v1,
1298 const struct ldb_val *v2,
1299 bool *matched)
1301 TALLOC_CTX *tmp_ctx;
1302 struct ldb_dn *dn1, *dn2;
1303 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1304 uint32_t rmd_flags1, rmd_flags2;
1306 tmp_ctx = talloc_new(ldb);
1308 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1309 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1310 if (!dn1 || !dn2) {
1311 /* couldn't parse as DN's */
1312 talloc_free(tmp_ctx);
1313 (*matched) = false;
1314 return LDB_SUCCESS;
1317 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1318 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1320 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1321 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1322 /* only match if they have the same deletion status */
1323 talloc_free(tmp_ctx);
1324 (*matched) = false;
1325 return LDB_SUCCESS;
1329 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1330 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1331 if (guid1 && guid2) {
1332 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1333 talloc_free(tmp_ctx);
1334 return LDB_SUCCESS;
1337 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1338 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1339 if (sid1 && sid2) {
1340 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1341 talloc_free(tmp_ctx);
1342 return LDB_SUCCESS;
1345 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1347 talloc_free(tmp_ctx);
1348 return LDB_SUCCESS;
1352 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1354 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1355 const struct ldb_schema_attribute *a,
1356 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1358 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1359 /* If the DN is deleted, then we can't search for it */
1361 /* should this be for equality too? */
1362 *matched = false;
1363 return LDB_SUCCESS;
1366 if (operation == LDB_OP_EQUALITY &&
1367 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1368 return LDB_SUCCESS;
1371 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1375 static const struct ldb_schema_syntax samba_syntaxes[] = {
1377 .name = LDB_SYNTAX_SAMBA_SID,
1378 .ldif_read_fn = ldif_read_objectSid,
1379 .ldif_write_fn = ldif_write_objectSid,
1380 .canonicalise_fn = ldif_canonicalise_objectSid,
1381 .comparison_fn = ldif_comparison_objectSid,
1382 .operator_fn = samba_syntax_operator_fn
1384 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1385 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1386 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1387 .canonicalise_fn = ldb_handler_copy,
1388 .comparison_fn = samba_ldb_comparison_binary,
1389 .operator_fn = samba_syntax_binary_operator_fn
1391 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1392 .ldif_read_fn = ldb_handler_copy,
1393 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1394 .canonicalise_fn = ldb_handler_fold,
1395 .comparison_fn = ldb_comparison_fold,
1396 .operator_fn = samba_syntax_operator_fn
1398 .name = LDB_SYNTAX_SAMBA_GUID,
1399 .ldif_read_fn = ldif_read_objectGUID,
1400 .ldif_write_fn = ldif_write_objectGUID,
1401 .canonicalise_fn = ldif_canonicalise_objectGUID,
1402 .comparison_fn = ldif_comparison_objectGUID,
1403 .operator_fn = samba_syntax_operator_fn
1405 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1406 .ldif_read_fn = ldb_handler_copy,
1407 .ldif_write_fn = ldb_handler_copy,
1408 .canonicalise_fn = ldif_canonicalise_objectCategory,
1409 .comparison_fn = ldif_comparison_objectCategory,
1410 .operator_fn = samba_syntax_operator_fn
1412 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1413 .ldif_read_fn = ldb_handler_copy,
1414 .ldif_write_fn = ldif_write_schemaInfo,
1415 .canonicalise_fn = ldb_handler_copy,
1416 .comparison_fn = samba_ldb_comparison_binary,
1417 .operator_fn = samba_syntax_binary_operator_fn
1419 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1420 .ldif_read_fn = ldif_read_prefixMap,
1421 .ldif_write_fn = ldif_write_prefixMap,
1422 .canonicalise_fn = ldif_canonicalise_prefixMap,
1423 .comparison_fn = ldif_comparison_prefixMap,
1424 .operator_fn = samba_syntax_operator_fn
1426 .name = LDB_SYNTAX_SAMBA_INT32,
1427 .ldif_read_fn = ldb_handler_copy,
1428 .ldif_write_fn = ldb_handler_copy,
1429 .canonicalise_fn = ldif_canonicalise_int32,
1430 .comparison_fn = ldif_comparison_int32,
1431 .operator_fn = samba_syntax_operator_fn
1433 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1434 .ldif_read_fn = ldb_handler_copy,
1435 .ldif_write_fn = ldif_write_repsFromTo,
1436 .canonicalise_fn = ldb_handler_copy,
1437 .comparison_fn = samba_ldb_comparison_binary,
1438 .operator_fn = samba_syntax_binary_operator_fn
1440 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1441 .ldif_read_fn = ldb_handler_copy,
1442 .ldif_write_fn = ldif_write_replPropertyMetaData,
1443 .canonicalise_fn = ldb_handler_copy,
1444 .comparison_fn = samba_ldb_comparison_binary,
1445 .operator_fn = samba_syntax_binary_operator_fn
1447 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1448 .ldif_read_fn = ldb_handler_copy,
1449 .ldif_write_fn = ldif_write_replUpToDateVector,
1450 .canonicalise_fn = ldb_handler_copy,
1451 .comparison_fn = samba_ldb_comparison_binary,
1452 .operator_fn = samba_syntax_binary_operator_fn
1454 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1455 .ldif_read_fn = ldb_handler_copy,
1456 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1457 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1458 .comparison_fn = dsdb_dn_binary_comparison,
1459 .operator_fn = samba_syntax_operator_fn
1461 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1462 .ldif_read_fn = ldb_handler_copy,
1463 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1464 .canonicalise_fn = ldb_handler_copy,
1465 .comparison_fn = samba_ldb_comparison_binary,
1466 .operator_fn = samba_syntax_binary_operator_fn
1468 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1469 .ldif_read_fn = ldb_handler_copy,
1470 .ldif_write_fn = ldif_write_ForestTrustInfo,
1471 .canonicalise_fn = ldb_handler_copy,
1472 .comparison_fn = samba_ldb_comparison_binary,
1473 .operator_fn = samba_syntax_binary_operator_fn
1475 .name = DSDB_SYNTAX_BINARY_DN,
1476 .ldif_read_fn = ldb_handler_copy,
1477 .ldif_write_fn = ldb_handler_copy,
1478 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1479 .comparison_fn = dsdb_dn_binary_comparison,
1480 .operator_fn = samba_syntax_operator_fn
1482 .name = DSDB_SYNTAX_STRING_DN,
1483 .ldif_read_fn = ldb_handler_copy,
1484 .ldif_write_fn = ldb_handler_copy,
1485 .canonicalise_fn = dsdb_dn_string_canonicalise,
1486 .comparison_fn = dsdb_dn_string_comparison,
1487 .operator_fn = samba_syntax_operator_fn
1489 .name = LDB_SYNTAX_DN,
1490 .ldif_read_fn = ldb_handler_copy,
1491 .ldif_write_fn = ldb_handler_copy,
1492 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1493 .comparison_fn = samba_ldb_dn_link_comparison,
1494 .operator_fn = samba_syntax_operator_dn
1496 .name = LDB_SYNTAX_SAMBA_RANGE64,
1497 .ldif_read_fn = ldif_read_range64,
1498 .ldif_write_fn = ldif_write_range64,
1499 .canonicalise_fn = ldif_canonicalise_int64,
1500 .comparison_fn = ldif_comparison_int64,
1501 .operator_fn = samba_syntax_operator_fn
1503 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1504 .ldif_read_fn = ldb_handler_copy,
1505 .ldif_write_fn = ldif_write_dnsRecord,
1506 .canonicalise_fn = ldb_handler_copy,
1507 .comparison_fn = samba_ldb_comparison_binary,
1508 .operator_fn = samba_syntax_binary_operator_fn
1510 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1511 .ldif_read_fn = ldb_handler_copy,
1512 .ldif_write_fn = ldif_write_dnsProperty,
1513 .canonicalise_fn = ldb_handler_copy,
1514 .comparison_fn = samba_ldb_comparison_binary,
1515 .operator_fn = samba_syntax_binary_operator_fn
1517 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1518 .ldif_read_fn = ldb_handler_copy,
1519 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1520 .canonicalise_fn = ldb_handler_copy,
1521 .comparison_fn = samba_ldb_comparison_binary,
1522 .operator_fn = samba_syntax_binary_operator_fn
1524 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1525 .ldif_read_fn = ldb_handler_copy,
1526 .ldif_write_fn = ldif_write_partialAttributeSet,
1527 .canonicalise_fn = ldb_handler_copy,
1528 .comparison_fn = samba_ldb_comparison_binary,
1529 .operator_fn = samba_syntax_binary_operator_fn
1531 .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1532 .ldif_read_fn = ldb_handler_copy,
1533 .ldif_write_fn = ldb_handler_copy,
1534 .canonicalise_fn = ldb_handler_copy,
1535 .comparison_fn = samba_ldb_comparison_binary,
1536 .operator_fn = samba_syntax_binary_operator_fn
1540 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1542 .name = "SID",
1543 .read_fn = extended_dn_read_SID,
1544 .write_clear_fn = ldif_write_objectSid,
1545 .write_hex_fn = extended_dn_write_hex
1547 .name = "GUID",
1548 .read_fn = extended_dn_read_GUID,
1549 .write_clear_fn = ldif_write_objectGUID,
1550 .write_hex_fn = extended_dn_write_hex
1552 .name = "WKGUID",
1553 .read_fn = ldb_handler_copy,
1554 .write_clear_fn = ldb_handler_copy,
1555 .write_hex_fn = ldb_handler_copy
1557 .name = "RMD_INVOCID",
1558 .read_fn = extended_dn_read_GUID,
1559 .write_clear_fn = ldif_write_objectGUID,
1560 .write_hex_fn = extended_dn_write_hex
1562 .name = "RMD_FLAGS",
1563 .read_fn = ldb_handler_copy,
1564 .write_clear_fn = ldb_handler_copy,
1565 .write_hex_fn = ldb_handler_copy
1567 .name = "RMD_ADDTIME",
1568 .read_fn = ldb_handler_copy,
1569 .write_clear_fn = ldb_handler_copy,
1570 .write_hex_fn = ldb_handler_copy
1572 .name = "RMD_CHANGETIME",
1573 .read_fn = ldb_handler_copy,
1574 .write_clear_fn = ldb_handler_copy,
1575 .write_hex_fn = ldb_handler_copy
1577 .name = "RMD_LOCAL_USN",
1578 .read_fn = ldb_handler_copy,
1579 .write_clear_fn = ldb_handler_copy,
1580 .write_hex_fn = ldb_handler_copy
1582 .name = "RMD_ORIGINATING_USN",
1583 .read_fn = ldb_handler_copy,
1584 .write_clear_fn = ldb_handler_copy,
1585 .write_hex_fn = ldb_handler_copy
1587 .name = "RMD_VERSION",
1588 .read_fn = ldb_handler_copy,
1589 .write_clear_fn = ldb_handler_copy,
1590 .write_hex_fn = ldb_handler_copy
1594 /* TODO: Should be dynamic at some point */
1595 static const struct {
1596 const char *name;
1597 const char *syntax;
1598 } samba_attributes[] = {
1599 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1600 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1601 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1602 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1603 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1604 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1605 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1606 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1607 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1608 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1609 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1610 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1611 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1612 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1613 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1614 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1615 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1618 * these are extracted by searching
1619 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1621 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1622 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1623 * hat can be used to identify the set of policies when applied to a resource.
1624 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1625 * server, we ignore it here.
1627 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1628 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1629 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1630 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1631 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1632 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1633 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1634 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1635 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1638 * these are extracted by searching
1639 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1641 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1642 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1643 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1644 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1645 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1646 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1647 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1648 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1649 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1650 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1651 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1652 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1653 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1654 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1655 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1656 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1657 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1658 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1659 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1660 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1661 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1662 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1663 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1664 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1665 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1666 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1667 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1668 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1671 * these are known to be GUIDs
1673 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1674 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1676 /* These NDR encoded things we want to be able to read with --show-binary */
1677 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1678 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1679 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1680 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1683 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1685 unsigned int j;
1686 const struct ldb_schema_syntax *s = NULL;
1688 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1689 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1690 s = &samba_syntaxes[j];
1691 break;
1694 return s;
1697 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1699 unsigned int j;
1700 const struct ldb_schema_syntax *s = NULL;
1702 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1703 if (strcmp(samba_attributes[j].name, name) == 0) {
1704 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1705 break;
1709 return s;
1712 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1713 "priorSecret", NULL};
1716 register the samba ldif handlers
1718 int ldb_register_samba_handlers(struct ldb_context *ldb)
1720 unsigned int i;
1721 int ret;
1723 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1724 return LDB_SUCCESS;
1727 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1728 if (ret != LDB_SUCCESS) {
1729 return ret;
1732 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1733 const struct ldb_schema_syntax *s = NULL;
1735 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1737 if (!s) {
1738 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1741 if (!s) {
1742 return LDB_ERR_OPERATIONS_ERROR;
1745 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1746 if (ret != LDB_SUCCESS) {
1747 return ret;
1751 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1752 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1753 if (ret != LDB_SUCCESS) {
1754 return ret;
1759 ret = ldb_register_samba_matching_rules(ldb);
1760 if (ret != LDB_SUCCESS) {
1761 talloc_free(ldb);
1762 return LDB_SUCCESS;
1765 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1766 if (ret != LDB_SUCCESS) {
1767 return ret;
1770 return LDB_SUCCESS;