s3-netlogon: Fix setting the machinge account password.
[Samba.git] / source4 / lib / ldb-samba / ldif_handlers.c
blobaf3c4b46e17f5fe4c8b5ac4e2937608dc5617328
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 "librpc/gen_ndr/ndr_security.h"
31 #include "librpc/gen_ndr/ndr_misc.h"
32 #include "librpc/gen_ndr/ndr_drsblobs.h"
33 #include "librpc/gen_ndr/ndr_dnsp.h"
34 #include "librpc/ndr/libndr.h"
35 #include "libcli/security/security.h"
36 #include "param/param.h"
37 #include "../lib/util/asn1.h"
40 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
42 If mask_errors is true, then function succeeds but out data
43 is set to "<Unable to decode binary data>" message
45 \return 0 on success; -1 on error
47 static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
48 const struct ldb_val *in, struct ldb_val *out,
49 size_t struct_size,
50 ndr_pull_flags_fn_t pull_fn,
51 ndr_print_fn_t print_fn,
52 bool mask_errors)
54 uint8_t *p;
55 enum ndr_err_code err;
56 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
57 return ldb_handler_copy(ldb, mem_ctx, in, out);
59 p = talloc_size(mem_ctx, struct_size);
60 err = ndr_pull_struct_blob(in, mem_ctx,
61 p, pull_fn);
62 if (err != NDR_ERR_SUCCESS) {
63 /* fail in not in mask_error mode */
64 if (!mask_errors) {
65 return -1;
67 talloc_free(p);
68 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
69 out->length = strlen((const char *)out->data);
70 return 0;
72 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
73 talloc_free(p);
74 if (out->data == NULL) {
75 return ldb_handler_copy(ldb, mem_ctx, in, out);
77 out->length = strlen((char *)out->data);
78 return 0;
82 convert a ldif formatted objectSid to a NDR formatted blob
84 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
85 const struct ldb_val *in, struct ldb_val *out)
87 enum ndr_err_code ndr_err;
88 struct dom_sid *sid;
89 sid = dom_sid_parse_length(mem_ctx, in);
90 if (sid == NULL) {
91 return -1;
93 ndr_err = ndr_push_struct_blob(out, mem_ctx, sid,
94 (ndr_push_flags_fn_t)ndr_push_dom_sid);
95 talloc_free(sid);
96 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
97 return -1;
99 return 0;
103 convert a NDR formatted blob to a ldif formatted objectSid
105 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
106 const struct ldb_val *in, struct ldb_val *out)
108 struct dom_sid *sid;
109 enum ndr_err_code ndr_err;
111 sid = talloc(mem_ctx, struct dom_sid);
112 if (sid == NULL) {
113 return -1;
115 ndr_err = ndr_pull_struct_blob_all(in, sid, sid,
116 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
117 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
118 talloc_free(sid);
119 return -1;
121 *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
122 talloc_free(sid);
123 if (out->data == NULL) {
124 return -1;
126 return 0;
129 bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
131 if (v->length < 3) {
132 return false;
135 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
137 return true;
141 compare two objectSids
143 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
144 const struct ldb_val *v1, const struct ldb_val *v2)
146 if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
147 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
148 } else if (ldif_comparision_objectSid_isString(v1)
149 && !ldif_comparision_objectSid_isString(v2)) {
150 struct ldb_val v;
151 int ret;
152 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
153 /* Perhaps not a string after all */
154 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
156 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
157 talloc_free(v.data);
158 return ret;
159 } else if (!ldif_comparision_objectSid_isString(v1)
160 && ldif_comparision_objectSid_isString(v2)) {
161 struct ldb_val v;
162 int ret;
163 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
164 /* Perhaps not a string after all */
165 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
167 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
168 talloc_free(v.data);
169 return ret;
171 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
175 canonicalise a objectSid
177 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
178 const struct ldb_val *in, struct ldb_val *out)
180 if (ldif_comparision_objectSid_isString(in)) {
181 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
182 /* Perhaps not a string after all */
183 return ldb_handler_copy(ldb, mem_ctx, in, out);
185 return 0;
187 return ldb_handler_copy(ldb, mem_ctx, in, out);
190 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
191 const struct ldb_val *in, struct ldb_val *out)
193 struct dom_sid sid;
194 enum ndr_err_code ndr_err;
195 if (ldif_comparision_objectSid_isString(in)) {
196 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
197 return 0;
201 /* Perhaps not a string after all */
202 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
204 if (!out->data) {
205 return -1;
208 (*out).length = strhex_to_str((char *)out->data, out->length,
209 (const char *)in->data, in->length);
211 /* Check it looks like a SID */
212 ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, &sid,
213 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
214 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
215 return -1;
217 return 0;
221 convert a ldif formatted objectGUID to a NDR formatted blob
223 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
224 const struct ldb_val *in, struct ldb_val *out)
226 struct GUID guid;
227 NTSTATUS status;
229 status = GUID_from_data_blob(in, &guid);
230 if (!NT_STATUS_IS_OK(status)) {
231 return -1;
234 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
235 if (!NT_STATUS_IS_OK(status)) {
236 return -1;
238 return 0;
242 convert a NDR formatted blob to a ldif formatted objectGUID
244 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
245 const struct ldb_val *in, struct ldb_val *out)
247 struct GUID guid;
248 NTSTATUS status;
250 status = GUID_from_ndr_blob(in, &guid);
251 if (!NT_STATUS_IS_OK(status)) {
252 return -1;
254 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
255 if (out->data == NULL) {
256 return -1;
258 out->length = strlen((const char *)out->data);
259 return 0;
262 static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
264 if (v->length != 36 && v->length != 38) return false;
266 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
267 return true;
270 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
271 const struct ldb_val *in, struct ldb_val *out)
273 struct GUID guid;
274 NTSTATUS status;
276 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
277 return 0;
280 /* Try as 'hex' form */
281 if (in->length != 32) {
282 return -1;
285 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
287 if (!out->data) {
288 return -1;
291 (*out).length = strhex_to_str((char *)out->data, out->length,
292 (const char *)in->data, in->length);
294 /* Check it looks like a GUID */
295 status = GUID_from_ndr_blob(out, &guid);
296 if (!NT_STATUS_IS_OK(status)) {
297 data_blob_free(out);
298 return -1;
300 return 0;
304 compare two objectGUIDs
306 static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
307 const struct ldb_val *v1, const struct ldb_val *v2)
309 if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
310 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
311 } else if (ldif_comparision_objectGUID_isString(v1)
312 && !ldif_comparision_objectGUID_isString(v2)) {
313 struct ldb_val v;
314 int ret;
315 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
316 /* Perhaps it wasn't a valid string after all */
317 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
319 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
320 talloc_free(v.data);
321 return ret;
322 } else if (!ldif_comparision_objectGUID_isString(v1)
323 && ldif_comparision_objectGUID_isString(v2)) {
324 struct ldb_val v;
325 int ret;
326 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
327 /* Perhaps it wasn't a valid string after all */
328 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
330 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
331 talloc_free(v.data);
332 return ret;
334 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
338 canonicalise a objectGUID
340 static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
341 const struct ldb_val *in, struct ldb_val *out)
343 if (ldif_comparision_objectGUID_isString(in)) {
344 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
345 /* Perhaps it wasn't a valid string after all */
346 return ldb_handler_copy(ldb, mem_ctx, in, out);
348 return 0;
350 return ldb_handler_copy(ldb, mem_ctx, in, out);
355 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
357 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
358 const struct ldb_val *in, struct ldb_val *out)
360 struct security_descriptor *sd;
361 enum ndr_err_code ndr_err;
363 sd = talloc(mem_ctx, struct security_descriptor);
364 if (sd == NULL) {
365 return -1;
368 ndr_err = ndr_pull_struct_blob(in, sd, sd,
369 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
370 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
371 /* If this does not parse, then it is probably SDDL, and we should try it that way */
373 const struct dom_sid *sid = samdb_domain_sid(ldb);
374 talloc_free(sd);
375 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
376 if (sd == NULL) {
377 return -1;
381 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
382 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
383 talloc_free(sd);
384 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
385 return -1;
388 return 0;
392 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
394 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
395 const struct ldb_val *in, struct ldb_val *out)
397 struct security_descriptor *sd;
398 enum ndr_err_code ndr_err;
400 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
401 return ldif_write_NDR(ldb, mem_ctx, in, out,
402 sizeof(struct security_descriptor),
403 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
404 (ndr_print_fn_t)ndr_print_security_descriptor,
405 true);
409 sd = talloc(mem_ctx, struct security_descriptor);
410 if (sd == NULL) {
411 return -1;
413 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
414 ndr_err = ndr_pull_struct_blob(in, sd, sd,
415 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
416 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
417 talloc_free(sd);
418 return -1;
420 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
421 talloc_free(sd);
422 if (out->data == NULL) {
423 return -1;
425 out->length = strlen((const char *)out->data);
426 return 0;
430 canonicalise an objectCategory. We use the short form as the canonical form:
431 cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
434 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
435 const struct ldb_val *in, struct ldb_val *out)
437 struct ldb_dn *dn1 = NULL;
438 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
439 const struct dsdb_class *sclass;
440 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
441 if (!tmp_ctx) {
442 return LDB_ERR_OPERATIONS_ERROR;
445 if (!schema) {
446 talloc_free(tmp_ctx);
447 *out = data_blob_talloc(mem_ctx, in->data, in->length);
448 if (in->data && !out->data) {
449 return LDB_ERR_OPERATIONS_ERROR;
451 return LDB_SUCCESS;
453 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
454 if ( ! ldb_dn_validate(dn1)) {
455 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
456 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
457 if (sclass) {
458 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
459 sclass->defaultObjectCategory);
460 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
461 talloc_free(tmp_ctx);
463 if (!out->data) {
464 return LDB_ERR_OPERATIONS_ERROR;
466 return LDB_SUCCESS;
467 } else {
468 *out = data_blob_talloc(mem_ctx, in->data, in->length);
469 talloc_free(tmp_ctx);
471 if (in->data && !out->data) {
472 return LDB_ERR_OPERATIONS_ERROR;
474 return LDB_SUCCESS;
477 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
478 talloc_free(tmp_ctx);
480 if (!out->data) {
481 return LDB_ERR_OPERATIONS_ERROR;
483 return LDB_SUCCESS;
486 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
487 const struct ldb_val *v1,
488 const struct ldb_val *v2)
490 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
491 v1, v2);
495 convert a NDR formatted blob to a ldif formatted schemaInfo
497 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
498 const struct ldb_val *in, struct ldb_val *out)
500 return ldif_write_NDR(ldb, mem_ctx, in, out,
501 sizeof(struct repsFromToBlob),
502 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
503 (ndr_print_fn_t)ndr_print_schemaInfoBlob,
504 true);
508 convert a ldif formatted prefixMap to a NDR formatted blob
510 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
511 const struct ldb_val *in, struct ldb_val *out)
513 struct prefixMapBlob *blob;
514 enum ndr_err_code ndr_err;
515 char *string, *line, *p, *oid;
516 DATA_BLOB oid_blob;
518 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
520 if (tmp_ctx == NULL) {
521 return -1;
524 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
525 if (blob == NULL) {
526 talloc_free(tmp_ctx);
527 return -1;
530 /* use the switch value to detect if this is in the binary
531 * format
533 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
534 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
535 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
536 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
537 ndr_err = ndr_push_struct_blob(out, mem_ctx,
538 blob,
539 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
540 talloc_free(tmp_ctx);
541 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
542 return -1;
544 return 0;
548 /* If this does not parse, then it is probably the text version, and we should try it that way */
549 blob->version = PREFIX_MAP_VERSION_DSDB;
551 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
552 if (string == NULL) {
553 talloc_free(blob);
554 return -1;
557 line = string;
558 while (line && line[0]) {
559 p=strchr(line, ';');
560 if (p) {
561 p[0] = '\0';
562 } else {
563 p=strchr(line, '\n');
564 if (p) {
565 p[0] = '\0';
568 /* allow a trailing separator */
569 if (line == p) {
570 break;
573 blob->ctr.dsdb.mappings = talloc_realloc(blob,
574 blob->ctr.dsdb.mappings,
575 struct drsuapi_DsReplicaOIDMapping,
576 blob->ctr.dsdb.num_mappings+1);
577 if (!blob->ctr.dsdb.mappings) {
578 talloc_free(tmp_ctx);
579 return -1;
582 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
584 if (oid[0] != ':') {
585 talloc_free(tmp_ctx);
586 return -1;
589 /* we know there must be at least ":" */
590 oid++;
592 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
593 talloc_free(tmp_ctx);
594 return -1;
596 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
597 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
599 blob->ctr.dsdb.num_mappings++;
601 /* Now look past the terminator we added above */
602 if (p) {
603 line = p + 1;
604 } else {
605 line = NULL;
609 ndr_err = ndr_push_struct_blob(out, mem_ctx,
610 blob,
611 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
612 talloc_free(tmp_ctx);
613 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
614 return -1;
616 return 0;
620 convert a NDR formatted blob to a ldif formatted prefixMap
622 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
623 const struct ldb_val *in, struct ldb_val *out)
625 struct prefixMapBlob *blob;
626 enum ndr_err_code ndr_err;
627 char *string;
628 uint32_t i;
630 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
631 int err;
632 /* try to decode the blob as S4 prefixMap */
633 err = ldif_write_NDR(ldb, mem_ctx, in, out,
634 sizeof(struct prefixMapBlob),
635 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
636 (ndr_print_fn_t)ndr_print_prefixMapBlob,
637 false);
638 if (0 == err) {
639 return err;
641 /* try parsing it as Windows PrefixMap value */
642 return ldif_write_NDR(ldb, mem_ctx, in, out,
643 sizeof(struct drsuapi_MSPrefixMap_Ctr),
644 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
645 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
646 true);
649 blob = talloc(mem_ctx, struct prefixMapBlob);
650 if (blob == NULL) {
651 return -1;
653 ndr_err = ndr_pull_struct_blob_all(in, blob,
654 blob,
655 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
656 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
657 goto failed;
659 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
660 goto failed;
662 string = talloc_strdup(mem_ctx, "");
663 if (string == NULL) {
664 goto failed;
667 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
668 DATA_BLOB oid_blob;
669 char *partial_oid = NULL;
671 if (i > 0) {
672 string = talloc_asprintf_append(string, ";");
675 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
676 blob->ctr.dsdb.mappings[i].oid.length);
677 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
678 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
679 blob->ctr.dsdb.mappings[i].id_prefix));
680 goto failed;
682 string = talloc_asprintf_append(string, "%u:%s",
683 blob->ctr.dsdb.mappings[i].id_prefix,
684 partial_oid);
685 talloc_free(discard_const(partial_oid));
686 if (string == NULL) {
687 goto failed;
691 talloc_free(blob);
692 *out = data_blob_string_const(string);
693 return 0;
695 failed:
696 talloc_free(blob);
697 return -1;
700 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
702 if (v->length < 4) {
703 return true;
706 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
707 return false;
710 return true;
714 canonicalise a prefixMap
716 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
717 const struct ldb_val *in, struct ldb_val *out)
719 if (ldif_comparision_prefixMap_isString(in)) {
720 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
722 return ldb_handler_copy(ldb, mem_ctx, in, out);
725 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
726 const struct ldb_val *v1,
727 const struct ldb_val *v2)
729 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
730 v1, v2);
733 /* length limited conversion of a ldb_val to a int32_t */
734 static int val_to_int32(const struct ldb_val *in, int32_t *v)
736 char *end;
737 char buf[64];
739 /* make sure we don't read past the end of the data */
740 if (in->length > sizeof(buf)-1) {
741 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
743 strncpy(buf, (char *)in->data, in->length);
744 buf[in->length] = 0;
746 /* We've to use "strtoll" here to have the intended overflows.
747 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
748 *v = (int32_t) strtoll(buf, &end, 0);
749 if (*end != 0) {
750 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
752 return LDB_SUCCESS;
755 /* length limited conversion of a ldb_val to a int64_t */
756 static int val_to_int64(const struct ldb_val *in, int64_t *v)
758 char *end;
759 char buf[64];
761 /* make sure we don't read past the end of the data */
762 if (in->length > sizeof(buf)-1) {
763 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
765 strncpy(buf, (char *)in->data, in->length);
766 buf[in->length] = 0;
768 *v = (int64_t) strtoll(buf, &end, 0);
769 if (*end != 0) {
770 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
772 return LDB_SUCCESS;
775 /* Canonicalisation of two 32-bit integers */
776 static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
777 const struct ldb_val *in, struct ldb_val *out)
779 int32_t i;
780 int ret;
782 ret = val_to_int32(in, &i);
783 if (ret != LDB_SUCCESS) {
784 return ret;
786 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
787 if (out->data == NULL) {
788 ldb_oom(ldb);
789 return LDB_ERR_OPERATIONS_ERROR;
791 out->length = strlen((char *)out->data);
792 return 0;
795 /* Comparison of two 32-bit integers */
796 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
797 const struct ldb_val *v1, const struct ldb_val *v2)
799 int32_t i1=0, i2=0;
800 val_to_int32(v1, &i1);
801 val_to_int32(v2, &i2);
802 if (i1 == i2) return 0;
803 return i1 > i2? 1 : -1;
806 /* Canonicalisation of two 64-bit integers */
807 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
808 const struct ldb_val *in, struct ldb_val *out)
810 int64_t i;
811 int ret;
813 ret = val_to_int64(in, &i);
814 if (ret != LDB_SUCCESS) {
815 return ret;
817 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
818 if (out->data == NULL) {
819 ldb_oom(ldb);
820 return LDB_ERR_OPERATIONS_ERROR;
822 out->length = strlen((char *)out->data);
823 return 0;
826 /* Comparison of two 64-bit integers */
827 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
828 const struct ldb_val *v1, const struct ldb_val *v2)
830 int64_t i1=0, i2=0;
831 val_to_int64(v1, &i1);
832 val_to_int64(v2, &i2);
833 if (i1 == i2) return 0;
834 return i1 > i2? 1 : -1;
838 convert a NDR formatted blob to a ldif formatted repsFromTo
840 static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
841 const struct ldb_val *in, struct ldb_val *out)
843 return ldif_write_NDR(ldb, mem_ctx, in, out,
844 sizeof(struct repsFromToBlob),
845 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
846 (ndr_print_fn_t)ndr_print_repsFromToBlob,
847 true);
851 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
853 static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
854 const struct ldb_val *in, struct ldb_val *out)
856 return ldif_write_NDR(ldb, mem_ctx, in, out,
857 sizeof(struct replPropertyMetaDataBlob),
858 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
859 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
860 true);
864 convert a NDR formatted blob to a ldif formatted replUpToDateVector
866 static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
867 const struct ldb_val *in, struct ldb_val *out)
869 return ldif_write_NDR(ldb, mem_ctx, in, out,
870 sizeof(struct replUpToDateVectorBlob),
871 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
872 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
873 true);
878 convert a NDR formatted blob to a ldif formatted dnsRecord
880 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
881 const struct ldb_val *in, struct ldb_val *out)
883 return ldif_write_NDR(ldb, mem_ctx, in, out,
884 sizeof(struct dnsp_DnssrvRpcRecord),
885 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
886 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
887 true);
891 convert a NDR formatted blob of a supplementalCredentials into text
893 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
894 const struct ldb_val *in, struct ldb_val *out)
896 return ldif_write_NDR(ldb, mem_ctx, in, out,
897 sizeof(struct supplementalCredentialsBlob),
898 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
899 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
900 true);
904 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
905 const struct ldb_val *in, struct ldb_val *out)
907 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
908 if (!out->data) {
909 return -1;
911 return 0;
915 compare two dns
917 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
918 const struct ldb_val *v1, const struct ldb_val *v2)
920 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
921 int ret;
923 if (dsdb_dn_is_deleted_val(v1)) {
924 /* If the DN is deleted, then we can't search for it */
925 return -1;
928 if (dsdb_dn_is_deleted_val(v2)) {
929 /* If the DN is deleted, then we can't search for it */
930 return -1;
933 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
934 if ( ! ldb_dn_validate(dn1)) return -1;
936 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
937 if ( ! ldb_dn_validate(dn2)) {
938 talloc_free(dn1);
939 return -1;
942 ret = ldb_dn_compare(dn1, dn2);
944 talloc_free(dn1);
945 talloc_free(dn2);
946 return ret;
949 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
950 const struct ldb_val *in, struct ldb_val *out)
952 struct ldb_dn *dn;
953 int ret = -1;
955 out->length = 0;
956 out->data = NULL;
958 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
959 if ( ! ldb_dn_validate(dn)) {
960 return LDB_ERR_INVALID_DN_SYNTAX;
963 /* By including the RMD_FLAGS of a deleted DN, we ensure it
964 * does not casually match a not deleted DN */
965 if (dsdb_dn_is_deleted_val(in)) {
966 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
967 "<RMD_FLAGS=%u>%s",
968 dsdb_dn_val_rmd_flags(in),
969 ldb_dn_get_casefold(dn));
970 } else {
971 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
974 if (out->data == NULL) {
975 goto done;
977 out->length = strlen((char *)out->data);
979 ret = 0;
981 done:
982 talloc_free(dn);
984 return ret;
989 write a 64 bit 2-part range
991 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
992 const struct ldb_val *in, struct ldb_val *out)
994 int64_t v;
995 int ret;
996 ret = val_to_int64(in, &v);
997 if (ret != LDB_SUCCESS) {
998 return ret;
1000 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1001 (unsigned long)(v&0xFFFFFFFF),
1002 (unsigned long)(v>>32));
1003 if (out->data == NULL) {
1004 ldb_oom(ldb);
1005 return LDB_ERR_OPERATIONS_ERROR;
1007 out->length = strlen((char *)out->data);
1008 return LDB_SUCCESS;
1012 read a 64 bit 2-part range
1014 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1015 const struct ldb_val *in, struct ldb_val *out)
1017 unsigned long high, low;
1018 char buf[64];
1020 if (memchr(in->data, '-', in->length) == NULL) {
1021 return ldb_handler_copy(ldb, mem_ctx, in, out);
1024 if (in->length > sizeof(buf)-1) {
1025 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1027 strncpy(buf, (const char *)in->data, in->length);
1028 buf[in->length] = 0;
1030 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1031 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1034 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1035 (unsigned long long)(((uint64_t)high)<<32) | (low));
1037 if (out->data == NULL) {
1038 ldb_oom(ldb);
1039 return LDB_ERR_OPERATIONS_ERROR;
1041 out->length = strlen((char *)out->data);
1042 return LDB_SUCCESS;
1046 when this operator_fn is set for a syntax, the backend calls is in
1047 preference to the comparison function. We are told the exact
1048 comparison operation that is needed, and we can return errors
1050 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1051 const struct ldb_schema_attribute *a,
1052 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1054 switch (operation) {
1055 case LDB_OP_AND:
1056 case LDB_OP_OR:
1057 case LDB_OP_NOT:
1058 case LDB_OP_SUBSTRING:
1059 case LDB_OP_APPROX:
1060 case LDB_OP_EXTENDED:
1061 /* handled in the backends */
1062 return LDB_ERR_INAPPROPRIATE_MATCHING;
1064 case LDB_OP_GREATER:
1065 case LDB_OP_LESS:
1066 case LDB_OP_EQUALITY:
1068 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1069 int ret;
1070 if (tmp_ctx == NULL) {
1071 return ldb_oom(ldb);
1073 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1074 talloc_free(tmp_ctx);
1075 if (operation == LDB_OP_GREATER) {
1076 *matched = (ret > 0);
1077 } else if (operation == LDB_OP_LESS) {
1078 *matched = (ret < 0);
1079 } else {
1080 *matched = (ret == 0);
1082 return LDB_SUCCESS;
1085 case LDB_OP_PRESENT:
1086 *matched = true;
1087 return LDB_SUCCESS;
1090 /* we shouldn't get here */
1091 return LDB_ERR_INAPPROPRIATE_MATCHING;
1095 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1097 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1098 const struct ldb_schema_attribute *a,
1099 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1101 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1102 /* If the DN is deleted, then we can't search for it */
1103 *matched = false;
1104 return LDB_SUCCESS;
1106 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1110 static const struct ldb_schema_syntax samba_syntaxes[] = {
1112 .name = LDB_SYNTAX_SAMBA_SID,
1113 .ldif_read_fn = ldif_read_objectSid,
1114 .ldif_write_fn = ldif_write_objectSid,
1115 .canonicalise_fn = ldif_canonicalise_objectSid,
1116 .comparison_fn = ldif_comparison_objectSid,
1117 .operator_fn = samba_syntax_operator_fn
1119 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1120 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1121 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1122 .canonicalise_fn = ldb_handler_copy,
1123 .comparison_fn = ldb_comparison_binary,
1124 .operator_fn = samba_syntax_operator_fn
1126 .name = LDB_SYNTAX_SAMBA_GUID,
1127 .ldif_read_fn = ldif_read_objectGUID,
1128 .ldif_write_fn = ldif_write_objectGUID,
1129 .canonicalise_fn = ldif_canonicalise_objectGUID,
1130 .comparison_fn = ldif_comparison_objectGUID,
1131 .operator_fn = samba_syntax_operator_fn
1133 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1134 .ldif_read_fn = ldb_handler_copy,
1135 .ldif_write_fn = ldb_handler_copy,
1136 .canonicalise_fn = ldif_canonicalise_objectCategory,
1137 .comparison_fn = ldif_comparison_objectCategory,
1138 .operator_fn = samba_syntax_operator_fn
1140 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1141 .ldif_read_fn = ldb_handler_copy,
1142 .ldif_write_fn = ldif_write_schemaInfo,
1143 .canonicalise_fn = ldb_handler_copy,
1144 .comparison_fn = ldb_comparison_binary,
1145 .operator_fn = samba_syntax_operator_fn
1147 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1148 .ldif_read_fn = ldif_read_prefixMap,
1149 .ldif_write_fn = ldif_write_prefixMap,
1150 .canonicalise_fn = ldif_canonicalise_prefixMap,
1151 .comparison_fn = ldif_comparison_prefixMap,
1152 .operator_fn = samba_syntax_operator_fn
1154 .name = LDB_SYNTAX_SAMBA_INT32,
1155 .ldif_read_fn = ldb_handler_copy,
1156 .ldif_write_fn = ldb_handler_copy,
1157 .canonicalise_fn = ldif_canonicalise_int32,
1158 .comparison_fn = ldif_comparison_int32,
1159 .operator_fn = samba_syntax_operator_fn
1161 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1162 .ldif_read_fn = ldb_handler_copy,
1163 .ldif_write_fn = ldif_write_repsFromTo,
1164 .canonicalise_fn = ldb_handler_copy,
1165 .comparison_fn = ldb_comparison_binary,
1166 .operator_fn = samba_syntax_operator_fn
1168 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1169 .ldif_read_fn = ldb_handler_copy,
1170 .ldif_write_fn = ldif_write_replPropertyMetaData,
1171 .canonicalise_fn = ldb_handler_copy,
1172 .comparison_fn = ldb_comparison_binary,
1173 .operator_fn = samba_syntax_operator_fn
1175 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1176 .ldif_read_fn = ldb_handler_copy,
1177 .ldif_write_fn = ldif_write_replUpToDateVector,
1178 .canonicalise_fn = ldb_handler_copy,
1179 .comparison_fn = ldb_comparison_binary,
1180 .operator_fn = samba_syntax_operator_fn
1182 .name = DSDB_SYNTAX_BINARY_DN,
1183 .ldif_read_fn = ldb_handler_copy,
1184 .ldif_write_fn = ldb_handler_copy,
1185 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1186 .comparison_fn = dsdb_dn_binary_comparison,
1187 .operator_fn = samba_syntax_operator_fn
1189 .name = DSDB_SYNTAX_STRING_DN,
1190 .ldif_read_fn = ldb_handler_copy,
1191 .ldif_write_fn = ldb_handler_copy,
1192 .canonicalise_fn = dsdb_dn_string_canonicalise,
1193 .comparison_fn = dsdb_dn_string_comparison,
1194 .operator_fn = samba_syntax_operator_fn
1196 .name = LDB_SYNTAX_DN,
1197 .ldif_read_fn = ldb_handler_copy,
1198 .ldif_write_fn = ldb_handler_copy,
1199 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1200 .comparison_fn = samba_ldb_dn_link_comparison,
1201 .operator_fn = samba_syntax_operator_dn
1203 .name = LDB_SYNTAX_SAMBA_RANGE64,
1204 .ldif_read_fn = ldif_read_range64,
1205 .ldif_write_fn = ldif_write_range64,
1206 .canonicalise_fn = ldif_canonicalise_int64,
1207 .comparison_fn = ldif_comparison_int64,
1208 .operator_fn = samba_syntax_operator_fn
1210 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1211 .ldif_read_fn = ldb_handler_copy,
1212 .ldif_write_fn = ldif_write_dnsRecord,
1213 .canonicalise_fn = ldb_handler_copy,
1214 .comparison_fn = ldb_comparison_binary,
1215 .operator_fn = samba_syntax_operator_fn
1217 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1218 .ldif_read_fn = ldb_handler_copy,
1219 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1220 .canonicalise_fn = ldb_handler_copy,
1221 .comparison_fn = ldb_comparison_binary,
1222 .operator_fn = samba_syntax_operator_fn
1226 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1228 .name = "SID",
1229 .read_fn = extended_dn_read_SID,
1230 .write_clear_fn = ldif_write_objectSid,
1231 .write_hex_fn = extended_dn_write_hex
1233 .name = "GUID",
1234 .read_fn = extended_dn_read_GUID,
1235 .write_clear_fn = ldif_write_objectGUID,
1236 .write_hex_fn = extended_dn_write_hex
1238 .name = "WKGUID",
1239 .read_fn = ldb_handler_copy,
1240 .write_clear_fn = ldb_handler_copy,
1241 .write_hex_fn = ldb_handler_copy
1243 .name = "RMD_INVOCID",
1244 .read_fn = extended_dn_read_GUID,
1245 .write_clear_fn = ldif_write_objectGUID,
1246 .write_hex_fn = extended_dn_write_hex
1248 .name = "RMD_FLAGS",
1249 .read_fn = ldb_handler_copy,
1250 .write_clear_fn = ldb_handler_copy,
1251 .write_hex_fn = ldb_handler_copy
1253 .name = "RMD_ADDTIME",
1254 .read_fn = ldb_handler_copy,
1255 .write_clear_fn = ldb_handler_copy,
1256 .write_hex_fn = ldb_handler_copy
1258 .name = "RMD_CHANGETIME",
1259 .read_fn = ldb_handler_copy,
1260 .write_clear_fn = ldb_handler_copy,
1261 .write_hex_fn = ldb_handler_copy
1263 .name = "RMD_LOCAL_USN",
1264 .read_fn = ldb_handler_copy,
1265 .write_clear_fn = ldb_handler_copy,
1266 .write_hex_fn = ldb_handler_copy
1268 .name = "RMD_ORIGINATING_USN",
1269 .read_fn = ldb_handler_copy,
1270 .write_clear_fn = ldb_handler_copy,
1271 .write_hex_fn = ldb_handler_copy
1273 .name = "RMD_VERSION",
1274 .read_fn = ldb_handler_copy,
1275 .write_clear_fn = ldb_handler_copy,
1276 .write_hex_fn = ldb_handler_copy
1280 /* TODO: Should be dynamic at some point */
1281 static const struct {
1282 const char *name;
1283 const char *syntax;
1284 } samba_attributes[] = {
1285 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1286 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1287 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1288 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1289 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1290 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1291 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1292 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1293 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1294 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1295 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1296 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1297 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1298 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1299 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1302 * these are extracted by searching
1303 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1305 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1306 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1307 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1308 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1309 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1310 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1311 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1312 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1313 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1314 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1315 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1316 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1317 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1318 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1319 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1320 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1321 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1322 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1323 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1324 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1325 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1326 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1327 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1328 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1331 * these are known to be GUIDs
1333 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1334 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1335 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1337 /* These NDR encoded things we want to be able to read with --show-binary */
1338 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1339 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS}
1342 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1344 unsigned int j;
1345 const struct ldb_schema_syntax *s = NULL;
1347 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1348 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1349 s = &samba_syntaxes[j];
1350 break;
1353 return s;
1356 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1358 unsigned int j;
1359 const struct ldb_schema_syntax *s = NULL;
1361 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1362 if (strcmp(samba_attributes[j].name, name) == 0) {
1363 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1364 break;
1368 return s;
1372 register the samba ldif handlers
1374 int ldb_register_samba_handlers(struct ldb_context *ldb)
1376 unsigned int i;
1377 int ret;
1379 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1380 return LDB_SUCCESS;
1383 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1384 const struct ldb_schema_syntax *s = NULL;
1386 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1388 if (!s) {
1389 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1392 if (!s) {
1393 return LDB_ERR_OPERATIONS_ERROR;
1396 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1397 if (ret != LDB_SUCCESS) {
1398 return ret;
1402 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1403 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1404 if (ret != LDB_SUCCESS) {
1405 return ret;
1410 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1411 if (ret != LDB_SUCCESS) {
1412 return ret;
1415 return LDB_SUCCESS;