VERSION: Disable git snapshots for the 4.2.11 release.
[Samba.git] / lib / ldb-samba / ldif_handlers.c
blobd9d799ccb8ca09844c3ba04d949757b7d843f3b6
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 enum ndr_err_code ndr_err;
89 struct dom_sid *sid;
90 sid = dom_sid_parse_length(mem_ctx, in);
91 if (sid == NULL) {
92 return -1;
94 ndr_err = ndr_push_struct_blob(out, mem_ctx, sid,
95 (ndr_push_flags_fn_t)ndr_push_dom_sid);
96 talloc_free(sid);
97 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
98 return -1;
100 return 0;
104 convert a NDR formatted blob to a ldif formatted objectSid
106 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
107 const struct ldb_val *in, struct ldb_val *out)
109 struct dom_sid *sid;
110 enum ndr_err_code ndr_err;
112 sid = talloc(mem_ctx, struct dom_sid);
113 if (sid == NULL) {
114 return -1;
116 ndr_err = ndr_pull_struct_blob_all(in, sid, sid,
117 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
118 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
119 talloc_free(sid);
120 return -1;
122 *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
123 talloc_free(sid);
124 if (out->data == NULL) {
125 return -1;
127 return 0;
130 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
132 if (v->length < 3) {
133 return false;
136 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
138 return true;
142 compare two objectSids
144 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
145 const struct ldb_val *v1, const struct ldb_val *v2)
147 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
148 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
149 } else if (ldif_comparision_objectSid_isString(v1)
150 && !ldif_comparision_objectSid_isString(v2)) {
151 struct ldb_val v;
152 int ret;
153 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
154 /* Perhaps not a string after all */
155 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
157 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
158 talloc_free(v.data);
159 return ret;
160 } else if (!ldif_comparision_objectSid_isString(v1)
161 && ldif_comparision_objectSid_isString(v2)) {
162 struct ldb_val v;
163 int ret;
164 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
165 /* Perhaps not a string after all */
166 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
168 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
169 talloc_free(v.data);
170 return ret;
172 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
176 canonicalise a objectSid
178 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
179 const struct ldb_val *in, struct ldb_val *out)
181 if (ldif_comparision_objectSid_isString(in)) {
182 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
183 /* Perhaps not a string after all */
184 return ldb_handler_copy(ldb, mem_ctx, in, out);
186 return 0;
188 return ldb_handler_copy(ldb, mem_ctx, in, out);
191 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
192 const struct ldb_val *in, struct ldb_val *out)
194 struct dom_sid sid;
195 enum ndr_err_code ndr_err;
196 if (ldif_comparision_objectSid_isString(in)) {
197 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
198 return 0;
202 /* Perhaps not a string after all */
203 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
205 if (!out->data) {
206 return -1;
209 (*out).length = strhex_to_str((char *)out->data, out->length,
210 (const char *)in->data, in->length);
212 /* Check it looks like a SID */
213 ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, &sid,
214 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
215 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
216 return -1;
218 return 0;
222 convert a ldif formatted objectGUID to a NDR formatted blob
224 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
225 const struct ldb_val *in, struct ldb_val *out)
227 struct GUID guid;
228 NTSTATUS status;
230 status = GUID_from_data_blob(in, &guid);
231 if (!NT_STATUS_IS_OK(status)) {
232 return -1;
235 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
236 if (!NT_STATUS_IS_OK(status)) {
237 return -1;
239 return 0;
243 convert a NDR formatted blob to a ldif formatted objectGUID
245 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
246 const struct ldb_val *in, struct ldb_val *out)
248 struct GUID guid;
249 NTSTATUS status;
251 status = GUID_from_ndr_blob(in, &guid);
252 if (!NT_STATUS_IS_OK(status)) {
253 return -1;
255 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
256 if (out->data == NULL) {
257 return -1;
259 out->length = strlen((const char *)out->data);
260 return 0;
263 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
265 if (v->length != 36 && v->length != 38) return false;
267 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
268 return true;
271 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
272 const struct ldb_val *in, struct ldb_val *out)
274 struct GUID guid;
275 NTSTATUS status;
277 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
278 return 0;
281 /* Try as 'hex' form */
282 if (in->length != 32) {
283 return -1;
286 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
288 if (!out->data) {
289 return -1;
292 (*out).length = strhex_to_str((char *)out->data, out->length,
293 (const char *)in->data, in->length);
295 /* Check it looks like a GUID */
296 status = GUID_from_ndr_blob(out, &guid);
297 if (!NT_STATUS_IS_OK(status)) {
298 data_blob_free(out);
299 return -1;
301 return 0;
305 compare two objectGUIDs
307 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
308 const struct ldb_val *v1, const struct ldb_val *v2)
310 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
311 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
312 } else if (ldif_comparision_objectGUID_isString(v1)
313 && !ldif_comparision_objectGUID_isString(v2)) {
314 struct ldb_val v;
315 int ret;
316 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
317 /* Perhaps it wasn't a valid string after all */
318 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
320 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
321 talloc_free(v.data);
322 return ret;
323 } else if (!ldif_comparision_objectGUID_isString(v1)
324 && ldif_comparision_objectGUID_isString(v2)) {
325 struct ldb_val v;
326 int ret;
327 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
328 /* Perhaps it wasn't a valid string after all */
329 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
331 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
332 talloc_free(v.data);
333 return ret;
335 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
339 canonicalise a objectGUID
341 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
342 const struct ldb_val *in, struct ldb_val *out)
344 if (ldif_comparision_objectGUID_isString(in)) {
345 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
346 /* Perhaps it wasn't a valid string after all */
347 return ldb_handler_copy(ldb, mem_ctx, in, out);
349 return 0;
351 return ldb_handler_copy(ldb, mem_ctx, in, out);
356 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
358 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
359 const struct ldb_val *in, struct ldb_val *out)
361 struct security_descriptor *sd;
362 enum ndr_err_code ndr_err;
364 sd = talloc(mem_ctx, struct security_descriptor);
365 if (sd == NULL) {
366 return -1;
369 ndr_err = ndr_pull_struct_blob(in, sd, sd,
370 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
371 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
372 /* If this does not parse, then it is probably SDDL, and we should try it that way */
374 const struct dom_sid *sid = samdb_domain_sid(ldb);
375 talloc_free(sd);
376 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
377 if (sd == NULL) {
378 return -1;
382 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
383 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
384 talloc_free(sd);
385 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
386 return -1;
389 return 0;
393 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
395 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
396 const struct ldb_val *in, struct ldb_val *out)
398 struct security_descriptor *sd;
399 enum ndr_err_code ndr_err;
401 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
402 return ldif_write_NDR(ldb, mem_ctx, in, out,
403 sizeof(struct security_descriptor),
404 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
405 (ndr_print_fn_t)ndr_print_security_descriptor,
406 true);
410 sd = talloc(mem_ctx, struct security_descriptor);
411 if (sd == NULL) {
412 return -1;
414 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
415 ndr_err = ndr_pull_struct_blob(in, sd, sd,
416 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
417 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
418 talloc_free(sd);
419 return -1;
421 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
422 talloc_free(sd);
423 if (out->data == NULL) {
424 return -1;
426 out->length = strlen((const char *)out->data);
427 return 0;
431 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
433 static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
434 const struct ldb_val *in, struct ldb_val *out)
436 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
437 struct security_descriptor *sd;
438 const struct dom_sid *sid = samdb_domain_sid(ldb);
440 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
441 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
442 (ndr_print_fn_t)ndr_print_security_descriptor,
443 "SDDL", sd);
444 out->length = strlen((const char *)out->data);
445 talloc_free(sd);
446 return 0;
449 return ldb_handler_copy(ldb, mem_ctx, in, out);
453 canonicalise an objectCategory. We use the long form as the canonical form:
454 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
456 Also any short name of an objectClass that points to a different
457 class (such as user) has the canonical form of the class it's
458 defaultObjectCategory points to (eg
459 cn=Person,cn=Schema,cn=Configuration,<basedn>)
462 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
463 const struct ldb_val *in, struct ldb_val *out)
465 struct ldb_dn *dn1 = NULL;
466 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
467 const struct dsdb_class *sclass;
468 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
469 if (!tmp_ctx) {
470 return LDB_ERR_OPERATIONS_ERROR;
473 if (!schema) {
474 talloc_free(tmp_ctx);
475 *out = data_blob_talloc(mem_ctx, in->data, in->length);
476 if (in->data && !out->data) {
477 return LDB_ERR_OPERATIONS_ERROR;
479 return LDB_SUCCESS;
481 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
482 if ( ! ldb_dn_validate(dn1)) {
483 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
484 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
485 if (sclass) {
486 struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
487 sclass->defaultObjectCategory);
488 if (dn == NULL) {
489 talloc_free(tmp_ctx);
490 return LDB_ERR_OPERATIONS_ERROR;
493 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
494 talloc_free(tmp_ctx);
496 if (!out->data) {
497 return LDB_ERR_OPERATIONS_ERROR;
499 return LDB_SUCCESS;
500 } else {
501 *out = data_blob_talloc(mem_ctx, in->data, in->length);
502 talloc_free(tmp_ctx);
504 if (in->data && !out->data) {
505 return LDB_ERR_OPERATIONS_ERROR;
507 return LDB_SUCCESS;
510 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
511 talloc_free(tmp_ctx);
513 if (!out->data) {
514 return LDB_ERR_OPERATIONS_ERROR;
516 return LDB_SUCCESS;
519 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
520 const struct ldb_val *v1,
521 const struct ldb_val *v2)
523 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
524 v1, v2);
528 convert a NDR formatted blob to a ldif formatted schemaInfo
530 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
531 const struct ldb_val *in, struct ldb_val *out)
533 return ldif_write_NDR(ldb, mem_ctx, in, out,
534 sizeof(struct repsFromToBlob),
535 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
536 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
537 true);
541 convert a ldif formatted prefixMap to a NDR formatted blob
543 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
544 const struct ldb_val *in, struct ldb_val *out)
546 struct prefixMapBlob *blob;
547 enum ndr_err_code ndr_err;
548 char *string, *line, *p, *oid;
549 DATA_BLOB oid_blob;
551 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
553 if (tmp_ctx == NULL) {
554 return -1;
557 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
558 if (blob == NULL) {
559 talloc_free(tmp_ctx);
560 return -1;
563 /* use the switch value to detect if this is in the binary
564 * format
566 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
567 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
568 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
569 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
570 ndr_err = ndr_push_struct_blob(out, mem_ctx,
571 blob,
572 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
573 talloc_free(tmp_ctx);
574 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
575 return -1;
577 return 0;
581 /* If this does not parse, then it is probably the text version, and we should try it that way */
582 blob->version = PREFIX_MAP_VERSION_DSDB;
584 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
585 if (string == NULL) {
586 talloc_free(blob);
587 return -1;
590 line = string;
591 while (line && line[0]) {
592 p=strchr(line, ';');
593 if (p) {
594 p[0] = '\0';
595 } else {
596 p=strchr(line, '\n');
597 if (p) {
598 p[0] = '\0';
601 /* allow a trailing separator */
602 if (line == p) {
603 break;
606 blob->ctr.dsdb.mappings = talloc_realloc(blob,
607 blob->ctr.dsdb.mappings,
608 struct drsuapi_DsReplicaOIDMapping,
609 blob->ctr.dsdb.num_mappings+1);
610 if (!blob->ctr.dsdb.mappings) {
611 talloc_free(tmp_ctx);
612 return -1;
615 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
617 if (oid[0] != ':') {
618 talloc_free(tmp_ctx);
619 return -1;
622 /* we know there must be at least ":" */
623 oid++;
625 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
626 talloc_free(tmp_ctx);
627 return -1;
629 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
630 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
632 blob->ctr.dsdb.num_mappings++;
634 /* Now look past the terminator we added above */
635 if (p) {
636 line = p + 1;
637 } else {
638 line = NULL;
642 ndr_err = ndr_push_struct_blob(out, mem_ctx,
643 blob,
644 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
645 talloc_free(tmp_ctx);
646 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
647 return -1;
649 return 0;
653 convert a NDR formatted blob to a ldif formatted prefixMap
655 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
656 const struct ldb_val *in, struct ldb_val *out)
658 struct prefixMapBlob *blob;
659 enum ndr_err_code ndr_err;
660 char *string;
661 uint32_t i;
663 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
664 int err;
665 /* try to decode the blob as S4 prefixMap */
666 err = ldif_write_NDR(ldb, mem_ctx, in, out,
667 sizeof(struct prefixMapBlob),
668 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
669 (ndr_print_fn_t)ndr_print_prefixMapBlob,
670 false);
671 if (0 == err) {
672 return err;
674 /* try parsing it as Windows PrefixMap value */
675 return ldif_write_NDR(ldb, mem_ctx, in, out,
676 sizeof(struct drsuapi_MSPrefixMap_Ctr),
677 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
678 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
679 true);
682 blob = talloc(mem_ctx, struct prefixMapBlob);
683 if (blob == NULL) {
684 return -1;
686 ndr_err = ndr_pull_struct_blob_all(in, blob,
687 blob,
688 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
689 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
690 goto failed;
692 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
693 goto failed;
695 string = talloc_strdup(mem_ctx, "");
696 if (string == NULL) {
697 goto failed;
700 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
701 DATA_BLOB oid_blob;
702 char *partial_oid = NULL;
704 if (i > 0) {
705 string = talloc_asprintf_append(string, ";");
708 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
709 blob->ctr.dsdb.mappings[i].oid.length);
710 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
711 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
712 blob->ctr.dsdb.mappings[i].id_prefix));
713 goto failed;
715 string = talloc_asprintf_append(string, "%u:%s",
716 blob->ctr.dsdb.mappings[i].id_prefix,
717 partial_oid);
718 talloc_free(discard_const(partial_oid));
719 if (string == NULL) {
720 goto failed;
724 talloc_free(blob);
725 *out = data_blob_string_const(string);
726 return 0;
728 failed:
729 talloc_free(blob);
730 return -1;
733 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
735 if (v->length < 4) {
736 return true;
739 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
740 return false;
743 return true;
747 canonicalise a prefixMap
749 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
750 const struct ldb_val *in, struct ldb_val *out)
752 if (ldif_comparision_prefixMap_isString(in)) {
753 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
755 return ldb_handler_copy(ldb, mem_ctx, in, out);
758 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
759 const struct ldb_val *v1,
760 const struct ldb_val *v2)
762 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
763 v1, v2);
766 /* length limited conversion of a ldb_val to a int32_t */
767 static int val_to_int32(const struct ldb_val *in, int32_t *v)
769 char *end;
770 char buf[64];
772 /* make sure we don't read past the end of the data */
773 if (in->length > sizeof(buf)-1) {
774 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
776 strncpy(buf, (char *)in->data, in->length);
777 buf[in->length] = 0;
779 /* We've to use "strtoll" here to have the intended overflows.
780 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
781 *v = (int32_t) strtoll(buf, &end, 0);
782 if (*end != 0) {
783 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
785 return LDB_SUCCESS;
788 /* length limited conversion of a ldb_val to a int64_t */
789 static int val_to_int64(const struct ldb_val *in, int64_t *v)
791 char *end;
792 char buf[64];
794 /* make sure we don't read past the end of the data */
795 if (in->length > sizeof(buf)-1) {
796 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
798 strncpy(buf, (char *)in->data, in->length);
799 buf[in->length] = 0;
801 *v = (int64_t) strtoll(buf, &end, 0);
802 if (*end != 0) {
803 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
805 return LDB_SUCCESS;
808 /* Canonicalisation of two 32-bit integers */
809 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
810 const struct ldb_val *in, struct ldb_val *out)
812 int32_t i;
813 int ret;
815 ret = val_to_int32(in, &i);
816 if (ret != LDB_SUCCESS) {
817 return ret;
819 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
820 if (out->data == NULL) {
821 ldb_oom(ldb);
822 return LDB_ERR_OPERATIONS_ERROR;
824 out->length = strlen((char *)out->data);
825 return 0;
828 /* Comparison of two 32-bit integers */
829 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
830 const struct ldb_val *v1, const struct ldb_val *v2)
832 int32_t i1=0, i2=0;
833 val_to_int32(v1, &i1);
834 val_to_int32(v2, &i2);
835 if (i1 == i2) return 0;
836 return i1 > i2? 1 : -1;
839 /* Canonicalisation of two 64-bit integers */
840 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
841 const struct ldb_val *in, struct ldb_val *out)
843 int64_t i;
844 int ret;
846 ret = val_to_int64(in, &i);
847 if (ret != LDB_SUCCESS) {
848 return ret;
850 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
851 if (out->data == NULL) {
852 ldb_oom(ldb);
853 return LDB_ERR_OPERATIONS_ERROR;
855 out->length = strlen((char *)out->data);
856 return 0;
859 /* Comparison of two 64-bit integers */
860 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
861 const struct ldb_val *v1, const struct ldb_val *v2)
863 int64_t i1=0, i2=0;
864 val_to_int64(v1, &i1);
865 val_to_int64(v2, &i2);
866 if (i1 == i2) return 0;
867 return i1 > i2? 1 : -1;
871 convert a NDR formatted blob to a ldif formatted repsFromTo
873 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
874 const struct ldb_val *in, struct ldb_val *out)
876 return ldif_write_NDR(ldb, mem_ctx, in, out,
877 sizeof(struct repsFromToBlob),
878 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
879 (ndr_print_fn_t)ndr_print_repsFromToBlob,
880 true);
884 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
886 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
887 const struct ldb_val *in, struct ldb_val *out)
889 return ldif_write_NDR(ldb, mem_ctx, in, out,
890 sizeof(struct replPropertyMetaDataBlob),
891 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
892 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
893 true);
897 convert a NDR formatted blob to a ldif formatted replUpToDateVector
899 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
900 const struct ldb_val *in, struct ldb_val *out)
902 return ldif_write_NDR(ldb, mem_ctx, in, out,
903 sizeof(struct replUpToDateVectorBlob),
904 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
905 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
906 true);
911 convert a NDR formatted blob to a ldif formatted dnsRecord
913 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
914 const struct ldb_val *in, struct ldb_val *out)
916 return ldif_write_NDR(ldb, mem_ctx, in, out,
917 sizeof(struct dnsp_DnssrvRpcRecord),
918 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
919 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
920 true);
924 convert a NDR formatted blob to a ldif formatted dnsProperty
926 static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
927 const struct ldb_val *in, struct ldb_val *out)
929 return ldif_write_NDR(ldb, mem_ctx, in, out,
930 sizeof(struct dnsp_DnsProperty),
931 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
932 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
933 true);
937 convert a NDR formatted blob of a supplementalCredentials into text
939 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
940 const struct ldb_val *in, struct ldb_val *out)
942 return ldif_write_NDR(ldb, mem_ctx, in, out,
943 sizeof(struct supplementalCredentialsBlob),
944 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
945 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
946 true);
950 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
952 static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
953 const struct ldb_val *in, struct ldb_val *out)
955 return ldif_write_NDR(ldb, mem_ctx, in, out,
956 sizeof(struct trustAuthInOutBlob),
957 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
958 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
959 true);
963 convert a NDR formatted blob of a partialAttributeSet into text
965 static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
966 const struct ldb_val *in, struct ldb_val *out)
968 return ldif_write_NDR(ldb, mem_ctx, in, out,
969 sizeof(struct partialAttributeSetBlob),
970 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
971 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
972 true);
976 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
977 const struct ldb_val *in, struct ldb_val *out)
979 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
980 if (!out->data) {
981 return -1;
983 return 0;
987 compare two dns
989 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
990 const struct ldb_val *v1, const struct ldb_val *v2)
992 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
993 int ret;
995 if (dsdb_dn_is_deleted_val(v1)) {
996 /* If the DN is deleted, then we can't search for it */
997 return -1;
1000 if (dsdb_dn_is_deleted_val(v2)) {
1001 /* If the DN is deleted, then we can't search for it */
1002 return -1;
1005 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1006 if ( ! ldb_dn_validate(dn1)) return -1;
1008 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1009 if ( ! ldb_dn_validate(dn2)) {
1010 talloc_free(dn1);
1011 return -1;
1014 ret = ldb_dn_compare(dn1, dn2);
1016 talloc_free(dn1);
1017 talloc_free(dn2);
1018 return ret;
1021 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1022 const struct ldb_val *in, struct ldb_val *out)
1024 struct ldb_dn *dn;
1025 int ret = -1;
1027 out->length = 0;
1028 out->data = NULL;
1030 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1031 if ( ! ldb_dn_validate(dn)) {
1032 return LDB_ERR_INVALID_DN_SYNTAX;
1035 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1036 * does not casually match a not deleted DN */
1037 if (dsdb_dn_is_deleted_val(in)) {
1038 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1039 "<RMD_FLAGS=%u>%s",
1040 dsdb_dn_val_rmd_flags(in),
1041 ldb_dn_get_casefold(dn));
1042 } else {
1043 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1046 if (out->data == NULL) {
1047 goto done;
1049 out->length = strlen((char *)out->data);
1051 ret = 0;
1053 done:
1054 talloc_free(dn);
1056 return ret;
1061 write a 64 bit 2-part range
1063 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1064 const struct ldb_val *in, struct ldb_val *out)
1066 int64_t v;
1067 int ret;
1068 ret = val_to_int64(in, &v);
1069 if (ret != LDB_SUCCESS) {
1070 return ret;
1072 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1073 (unsigned long)(v&0xFFFFFFFF),
1074 (unsigned long)(v>>32));
1075 if (out->data == NULL) {
1076 ldb_oom(ldb);
1077 return LDB_ERR_OPERATIONS_ERROR;
1079 out->length = strlen((char *)out->data);
1080 return LDB_SUCCESS;
1084 read a 64 bit 2-part range
1086 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1087 const struct ldb_val *in, struct ldb_val *out)
1089 unsigned long high, low;
1090 char buf[64];
1092 if (memchr(in->data, '-', in->length) == NULL) {
1093 return ldb_handler_copy(ldb, mem_ctx, in, out);
1096 if (in->length > sizeof(buf)-1) {
1097 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1099 strncpy(buf, (const char *)in->data, in->length);
1100 buf[in->length] = 0;
1102 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1103 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1106 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1107 (unsigned long long)(((uint64_t)high)<<32) | (low));
1109 if (out->data == NULL) {
1110 ldb_oom(ldb);
1111 return LDB_ERR_OPERATIONS_ERROR;
1113 out->length = strlen((char *)out->data);
1114 return LDB_SUCCESS;
1118 when this operator_fn is set for a syntax, the backend calls is in
1119 preference to the comparison function. We are told the exact
1120 comparison operation that is needed, and we can return errors
1122 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1123 const struct ldb_schema_attribute *a,
1124 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1126 switch (operation) {
1127 case LDB_OP_AND:
1128 case LDB_OP_OR:
1129 case LDB_OP_NOT:
1130 case LDB_OP_SUBSTRING:
1131 case LDB_OP_APPROX:
1132 case LDB_OP_EXTENDED:
1133 /* handled in the backends */
1134 return LDB_ERR_INAPPROPRIATE_MATCHING;
1136 case LDB_OP_GREATER:
1137 case LDB_OP_LESS:
1138 case LDB_OP_EQUALITY:
1140 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1141 int ret;
1142 if (tmp_ctx == NULL) {
1143 return ldb_oom(ldb);
1145 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1146 talloc_free(tmp_ctx);
1147 if (operation == LDB_OP_GREATER) {
1148 *matched = (ret >= 0);
1149 } else if (operation == LDB_OP_LESS) {
1150 *matched = (ret <= 0);
1151 } else {
1152 *matched = (ret == 0);
1154 return LDB_SUCCESS;
1157 case LDB_OP_PRESENT:
1158 *matched = true;
1159 return LDB_SUCCESS;
1162 /* we shouldn't get here */
1163 return LDB_ERR_INAPPROPRIATE_MATCHING;
1167 see if two DNs match, comparing first by GUID, then by SID, and
1168 finally by string components
1170 static int samba_dn_extended_match(struct ldb_context *ldb,
1171 const struct ldb_val *v1,
1172 const struct ldb_val *v2,
1173 bool *matched)
1175 TALLOC_CTX *tmp_ctx;
1176 struct ldb_dn *dn1, *dn2;
1177 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1178 uint32_t rmd_flags1, rmd_flags2;
1180 tmp_ctx = talloc_new(ldb);
1182 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1183 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1184 if (!dn1 || !dn2) {
1185 /* couldn't parse as DN's */
1186 talloc_free(tmp_ctx);
1187 (*matched) = false;
1188 return LDB_SUCCESS;
1191 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1192 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1194 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1195 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1196 /* only match if they have the same deletion status */
1197 talloc_free(tmp_ctx);
1198 (*matched) = false;
1199 return LDB_SUCCESS;
1203 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1204 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1205 if (guid1 && guid2) {
1206 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1207 talloc_free(tmp_ctx);
1208 return LDB_SUCCESS;
1211 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1212 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1213 if (sid1 && sid2) {
1214 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1215 talloc_free(tmp_ctx);
1216 return LDB_SUCCESS;
1219 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1221 talloc_free(tmp_ctx);
1222 return LDB_SUCCESS;
1226 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1228 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1229 const struct ldb_schema_attribute *a,
1230 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1232 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1233 /* If the DN is deleted, then we can't search for it */
1235 /* should this be for equality too? */
1236 *matched = false;
1237 return LDB_SUCCESS;
1240 if (operation == LDB_OP_EQUALITY &&
1241 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1242 return LDB_SUCCESS;
1245 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1249 static const struct ldb_schema_syntax samba_syntaxes[] = {
1251 .name = LDB_SYNTAX_SAMBA_SID,
1252 .ldif_read_fn = ldif_read_objectSid,
1253 .ldif_write_fn = ldif_write_objectSid,
1254 .canonicalise_fn = ldif_canonicalise_objectSid,
1255 .comparison_fn = ldif_comparison_objectSid,
1256 .operator_fn = samba_syntax_operator_fn
1258 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1259 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1260 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1261 .canonicalise_fn = ldb_handler_copy,
1262 .comparison_fn = ldb_comparison_binary,
1263 .operator_fn = samba_syntax_operator_fn
1265 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1266 .ldif_read_fn = ldb_handler_copy,
1267 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1268 .canonicalise_fn = ldb_handler_fold,
1269 .comparison_fn = ldb_comparison_fold,
1270 .operator_fn = samba_syntax_operator_fn
1272 .name = LDB_SYNTAX_SAMBA_GUID,
1273 .ldif_read_fn = ldif_read_objectGUID,
1274 .ldif_write_fn = ldif_write_objectGUID,
1275 .canonicalise_fn = ldif_canonicalise_objectGUID,
1276 .comparison_fn = ldif_comparison_objectGUID,
1277 .operator_fn = samba_syntax_operator_fn
1279 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1280 .ldif_read_fn = ldb_handler_copy,
1281 .ldif_write_fn = ldb_handler_copy,
1282 .canonicalise_fn = ldif_canonicalise_objectCategory,
1283 .comparison_fn = ldif_comparison_objectCategory,
1284 .operator_fn = samba_syntax_operator_fn
1286 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1287 .ldif_read_fn = ldb_handler_copy,
1288 .ldif_write_fn = ldif_write_schemaInfo,
1289 .canonicalise_fn = ldb_handler_copy,
1290 .comparison_fn = ldb_comparison_binary,
1291 .operator_fn = samba_syntax_operator_fn
1293 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1294 .ldif_read_fn = ldif_read_prefixMap,
1295 .ldif_write_fn = ldif_write_prefixMap,
1296 .canonicalise_fn = ldif_canonicalise_prefixMap,
1297 .comparison_fn = ldif_comparison_prefixMap,
1298 .operator_fn = samba_syntax_operator_fn
1300 .name = LDB_SYNTAX_SAMBA_INT32,
1301 .ldif_read_fn = ldb_handler_copy,
1302 .ldif_write_fn = ldb_handler_copy,
1303 .canonicalise_fn = ldif_canonicalise_int32,
1304 .comparison_fn = ldif_comparison_int32,
1305 .operator_fn = samba_syntax_operator_fn
1307 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1308 .ldif_read_fn = ldb_handler_copy,
1309 .ldif_write_fn = ldif_write_repsFromTo,
1310 .canonicalise_fn = ldb_handler_copy,
1311 .comparison_fn = ldb_comparison_binary,
1312 .operator_fn = samba_syntax_operator_fn
1314 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1315 .ldif_read_fn = ldb_handler_copy,
1316 .ldif_write_fn = ldif_write_replPropertyMetaData,
1317 .canonicalise_fn = ldb_handler_copy,
1318 .comparison_fn = ldb_comparison_binary,
1319 .operator_fn = samba_syntax_operator_fn
1321 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1322 .ldif_read_fn = ldb_handler_copy,
1323 .ldif_write_fn = ldif_write_replUpToDateVector,
1324 .canonicalise_fn = ldb_handler_copy,
1325 .comparison_fn = ldb_comparison_binary,
1326 .operator_fn = samba_syntax_operator_fn
1328 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1329 .ldif_read_fn = ldb_handler_copy,
1330 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1331 .canonicalise_fn = ldb_handler_copy,
1332 .comparison_fn = ldb_comparison_binary,
1333 .operator_fn = samba_syntax_operator_fn
1335 .name = DSDB_SYNTAX_BINARY_DN,
1336 .ldif_read_fn = ldb_handler_copy,
1337 .ldif_write_fn = ldb_handler_copy,
1338 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1339 .comparison_fn = dsdb_dn_binary_comparison,
1340 .operator_fn = samba_syntax_operator_fn
1342 .name = DSDB_SYNTAX_STRING_DN,
1343 .ldif_read_fn = ldb_handler_copy,
1344 .ldif_write_fn = ldb_handler_copy,
1345 .canonicalise_fn = dsdb_dn_string_canonicalise,
1346 .comparison_fn = dsdb_dn_string_comparison,
1347 .operator_fn = samba_syntax_operator_fn
1349 .name = LDB_SYNTAX_DN,
1350 .ldif_read_fn = ldb_handler_copy,
1351 .ldif_write_fn = ldb_handler_copy,
1352 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1353 .comparison_fn = samba_ldb_dn_link_comparison,
1354 .operator_fn = samba_syntax_operator_dn
1356 .name = LDB_SYNTAX_SAMBA_RANGE64,
1357 .ldif_read_fn = ldif_read_range64,
1358 .ldif_write_fn = ldif_write_range64,
1359 .canonicalise_fn = ldif_canonicalise_int64,
1360 .comparison_fn = ldif_comparison_int64,
1361 .operator_fn = samba_syntax_operator_fn
1363 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1364 .ldif_read_fn = ldb_handler_copy,
1365 .ldif_write_fn = ldif_write_dnsRecord,
1366 .canonicalise_fn = ldb_handler_copy,
1367 .comparison_fn = ldb_comparison_binary,
1368 .operator_fn = samba_syntax_operator_fn
1370 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1371 .ldif_read_fn = ldb_handler_copy,
1372 .ldif_write_fn = ldif_write_dnsProperty,
1373 .canonicalise_fn = ldb_handler_copy,
1374 .comparison_fn = ldb_comparison_binary,
1375 .operator_fn = samba_syntax_operator_fn
1377 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1378 .ldif_read_fn = ldb_handler_copy,
1379 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1380 .canonicalise_fn = ldb_handler_copy,
1381 .comparison_fn = ldb_comparison_binary,
1382 .operator_fn = samba_syntax_operator_fn
1384 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1385 .ldif_read_fn = ldb_handler_copy,
1386 .ldif_write_fn = ldif_write_partialAttributeSet,
1387 .canonicalise_fn = ldb_handler_copy,
1388 .comparison_fn = ldb_comparison_binary,
1389 .operator_fn = samba_syntax_operator_fn
1393 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1395 .name = "SID",
1396 .read_fn = extended_dn_read_SID,
1397 .write_clear_fn = ldif_write_objectSid,
1398 .write_hex_fn = extended_dn_write_hex
1400 .name = "GUID",
1401 .read_fn = extended_dn_read_GUID,
1402 .write_clear_fn = ldif_write_objectGUID,
1403 .write_hex_fn = extended_dn_write_hex
1405 .name = "WKGUID",
1406 .read_fn = ldb_handler_copy,
1407 .write_clear_fn = ldb_handler_copy,
1408 .write_hex_fn = ldb_handler_copy
1410 .name = "RMD_INVOCID",
1411 .read_fn = extended_dn_read_GUID,
1412 .write_clear_fn = ldif_write_objectGUID,
1413 .write_hex_fn = extended_dn_write_hex
1415 .name = "RMD_FLAGS",
1416 .read_fn = ldb_handler_copy,
1417 .write_clear_fn = ldb_handler_copy,
1418 .write_hex_fn = ldb_handler_copy
1420 .name = "RMD_ADDTIME",
1421 .read_fn = ldb_handler_copy,
1422 .write_clear_fn = ldb_handler_copy,
1423 .write_hex_fn = ldb_handler_copy
1425 .name = "RMD_CHANGETIME",
1426 .read_fn = ldb_handler_copy,
1427 .write_clear_fn = ldb_handler_copy,
1428 .write_hex_fn = ldb_handler_copy
1430 .name = "RMD_LOCAL_USN",
1431 .read_fn = ldb_handler_copy,
1432 .write_clear_fn = ldb_handler_copy,
1433 .write_hex_fn = ldb_handler_copy
1435 .name = "RMD_ORIGINATING_USN",
1436 .read_fn = ldb_handler_copy,
1437 .write_clear_fn = ldb_handler_copy,
1438 .write_hex_fn = ldb_handler_copy
1440 .name = "RMD_VERSION",
1441 .read_fn = ldb_handler_copy,
1442 .write_clear_fn = ldb_handler_copy,
1443 .write_hex_fn = ldb_handler_copy
1447 /* TODO: Should be dynamic at some point */
1448 static const struct {
1449 const char *name;
1450 const char *syntax;
1451 } samba_attributes[] = {
1452 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1453 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1454 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1455 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1456 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1457 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1458 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1459 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1460 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1461 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1462 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1463 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1464 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1465 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1466 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1469 * these are extracted by searching
1470 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1472 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1473 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1474 * hat can be used to identify the set of policies when applied to a resource.
1475 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1476 * server, we ignore it here.
1478 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1479 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1480 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1481 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1482 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1483 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1484 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1485 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1486 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1489 * these are extracted by searching
1490 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1492 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1493 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1494 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1495 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1496 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1497 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1498 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1499 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1500 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1501 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1502 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1503 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1504 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1505 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1506 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1507 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1508 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1509 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1510 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1511 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1512 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1513 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1514 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1515 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1516 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1517 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1518 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1519 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1522 * these are known to be GUIDs
1524 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1525 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1527 /* These NDR encoded things we want to be able to read with --show-binary */
1528 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1529 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1530 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1531 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1534 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1536 unsigned int j;
1537 const struct ldb_schema_syntax *s = NULL;
1539 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1540 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1541 s = &samba_syntaxes[j];
1542 break;
1545 return s;
1548 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1550 unsigned int j;
1551 const struct ldb_schema_syntax *s = NULL;
1553 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1554 if (strcmp(samba_attributes[j].name, name) == 0) {
1555 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1556 break;
1560 return s;
1563 static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, NULL};
1566 register the samba ldif handlers
1568 int ldb_register_samba_handlers(struct ldb_context *ldb)
1570 unsigned int i;
1571 int ret;
1573 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1574 return LDB_SUCCESS;
1577 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1578 if (ret != LDB_SUCCESS) {
1579 return ret;
1582 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1583 const struct ldb_schema_syntax *s = NULL;
1585 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1587 if (!s) {
1588 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1591 if (!s) {
1592 return LDB_ERR_OPERATIONS_ERROR;
1595 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1596 if (ret != LDB_SUCCESS) {
1597 return ret;
1601 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1602 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1603 if (ret != LDB_SUCCESS) {
1604 return ret;
1609 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1610 if (ret != LDB_SUCCESS) {
1611 return ret;
1614 return LDB_SUCCESS;