source: trunk/server/source4/lib/ldb-samba/ldif_handlers.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 40.5 KB
Line 
1/*
2 ldb database library - ldif handlers for Samba
3
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
10
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.
15
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.
20
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/>.
23*/
24
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"
38
39/*
40 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
41
42 If mask_errors is true, then function succeeds but out data
43 is set to "<Unable to decode binary data>" message
44
45 \return 0 on success; -1 on error
46*/
47static 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)
53{
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);
58 }
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;
66 }
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;
71 }
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);
76 }
77 out->length = strlen((char *)out->data);
78 return 0;
79}
80
81/*
82 convert a ldif formatted objectSid to a NDR formatted blob
83*/
84static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
85 const struct ldb_val *in, struct ldb_val *out)
86{
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;
92 }
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;
98 }
99 return 0;
100}
101
102/*
103 convert a NDR formatted blob to a ldif formatted objectSid
104*/
105int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
106 const struct ldb_val *in, struct ldb_val *out)
107{
108 struct dom_sid *sid;
109 enum ndr_err_code ndr_err;
110
111 sid = talloc(mem_ctx, struct dom_sid);
112 if (sid == NULL) {
113 return -1;
114 }
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;
120 }
121 *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
122 talloc_free(sid);
123 if (out->data == NULL) {
124 return -1;
125 }
126 return 0;
127}
128
129bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
130{
131 if (v->length < 3) {
132 return false;
133 }
134
135 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
136
137 return true;
138}
139
140/*
141 compare two objectSids
142*/
143static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
144 const struct ldb_val *v1, const struct ldb_val *v2)
145{
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);
155 }
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);
166 }
167 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
168 talloc_free(v.data);
169 return ret;
170 }
171 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
172}
173
174/*
175 canonicalise a objectSid
176*/
177static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
178 const struct ldb_val *in, struct ldb_val *out)
179{
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);
184 }
185 return 0;
186 }
187 return ldb_handler_copy(ldb, mem_ctx, in, out);
188}
189
190static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
191 const struct ldb_val *in, struct ldb_val *out)
192{
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;
198 }
199 }
200
201 /* Perhaps not a string after all */
202 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
203
204 if (!out->data) {
205 return -1;
206 }
207
208 (*out).length = strhex_to_str((char *)out->data, out->length,
209 (const char *)in->data, in->length);
210
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;
216 }
217 return 0;
218}
219
220/*
221 convert a ldif formatted objectGUID to a NDR formatted blob
222*/
223static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
224 const struct ldb_val *in, struct ldb_val *out)
225{
226 struct GUID guid;
227 NTSTATUS status;
228
229 status = GUID_from_data_blob(in, &guid);
230 if (!NT_STATUS_IS_OK(status)) {
231 return -1;
232 }
233
234 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
235 if (!NT_STATUS_IS_OK(status)) {
236 return -1;
237 }
238 return 0;
239}
240
241/*
242 convert a NDR formatted blob to a ldif formatted objectGUID
243*/
244static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
245 const struct ldb_val *in, struct ldb_val *out)
246{
247 struct GUID guid;
248 NTSTATUS status;
249
250 status = GUID_from_ndr_blob(in, &guid);
251 if (!NT_STATUS_IS_OK(status)) {
252 return -1;
253 }
254 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
255 if (out->data == NULL) {
256 return -1;
257 }
258 out->length = strlen((const char *)out->data);
259 return 0;
260}
261
262static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
263{
264 if (v->length != 36 && v->length != 38) return false;
265
266 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
267 return true;
268}
269
270static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
271 const struct ldb_val *in, struct ldb_val *out)
272{
273 struct GUID guid;
274 NTSTATUS status;
275
276 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
277 return 0;
278 }
279
280 /* Try as 'hex' form */
281 if (in->length != 32) {
282 return -1;
283 }
284
285 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
286
287 if (!out->data) {
288 return -1;
289 }
290
291 (*out).length = strhex_to_str((char *)out->data, out->length,
292 (const char *)in->data, in->length);
293
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;
299 }
300 return 0;
301}
302
303/*
304 compare two objectGUIDs
305*/
306static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
307 const struct ldb_val *v1, const struct ldb_val *v2)
308{
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);
318 }
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);
329 }
330 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
331 talloc_free(v.data);
332 return ret;
333 }
334 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
335}
336
337/*
338 canonicalise a objectGUID
339*/
340static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
341 const struct ldb_val *in, struct ldb_val *out)
342{
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);
347 }
348 return 0;
349 }
350 return ldb_handler_copy(ldb, mem_ctx, in, out);
351}
352
353
354/*
355 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
356*/
357static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
358 const struct ldb_val *in, struct ldb_val *out)
359{
360 struct security_descriptor *sd;
361 enum ndr_err_code ndr_err;
362
363 sd = talloc(mem_ctx, struct security_descriptor);
364 if (sd == NULL) {
365 return -1;
366 }
367
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 */
372
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;
378 }
379 }
380
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;
386 }
387
388 return 0;
389}
390
391/*
392 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
393*/
394static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
395 const struct ldb_val *in, struct ldb_val *out)
396{
397 struct security_descriptor *sd;
398 enum ndr_err_code ndr_err;
399
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);
406
407 }
408
409 sd = talloc(mem_ctx, struct security_descriptor);
410 if (sd == NULL) {
411 return -1;
412 }
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;
419 }
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;
424 }
425 out->length = strlen((const char *)out->data);
426 return 0;
427}
428
429/*
430 canonicalise an objectCategory. We use the short form as the canonical form:
431 cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
432*/
433
434static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
435 const struct ldb_val *in, struct ldb_val *out)
436{
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;
443 }
444
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;
450 }
451 return LDB_SUCCESS;
452 }
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);
462
463 if (!out->data) {
464 return LDB_ERR_OPERATIONS_ERROR;
465 }
466 return LDB_SUCCESS;
467 } else {
468 *out = data_blob_talloc(mem_ctx, in->data, in->length);
469 talloc_free(tmp_ctx);
470
471 if (in->data && !out->data) {
472 return LDB_ERR_OPERATIONS_ERROR;
473 }
474 return LDB_SUCCESS;
475 }
476 }
477 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
478 talloc_free(tmp_ctx);
479
480 if (!out->data) {
481 return LDB_ERR_OPERATIONS_ERROR;
482 }
483 return LDB_SUCCESS;
484}
485
486static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
487 const struct ldb_val *v1,
488 const struct ldb_val *v2)
489{
490 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
491 v1, v2);
492}
493
494/*
495 convert a NDR formatted blob to a ldif formatted schemaInfo
496*/
497static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
498 const struct ldb_val *in, struct ldb_val *out)
499{
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);
505}
506
507/*
508 convert a ldif formatted prefixMap to a NDR formatted blob
509*/
510static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
511 const struct ldb_val *in, struct ldb_val *out)
512{
513 struct prefixMapBlob *blob;
514 enum ndr_err_code ndr_err;
515 char *string, *line, *p, *oid;
516 DATA_BLOB oid_blob;
517
518 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
519
520 if (tmp_ctx == NULL) {
521 return -1;
522 }
523
524 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
525 if (blob == NULL) {
526 talloc_free(tmp_ctx);
527 return -1;
528 }
529
530 /* use the switch value to detect if this is in the binary
531 * format
532 */
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;
543 }
544 return 0;
545 }
546 }
547
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;
550
551 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
552 if (string == NULL) {
553 talloc_free(blob);
554 return -1;
555 }
556
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';
566 }
567 }
568 /* allow a trailing separator */
569 if (line == p) {
570 break;
571 }
572
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;
580 }
581
582 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
583
584 if (oid[0] != ':') {
585 talloc_free(tmp_ctx);
586 return -1;
587 }
588
589 /* we know there must be at least ":" */
590 oid++;
591
592 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
593 talloc_free(tmp_ctx);
594 return -1;
595 }
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;
598
599 blob->ctr.dsdb.num_mappings++;
600
601 /* Now look past the terminator we added above */
602 if (p) {
603 line = p + 1;
604 } else {
605 line = NULL;
606 }
607 }
608
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;
615 }
616 return 0;
617}
618
619/*
620 convert a NDR formatted blob to a ldif formatted prefixMap
621*/
622static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
623 const struct ldb_val *in, struct ldb_val *out)
624{
625 struct prefixMapBlob *blob;
626 enum ndr_err_code ndr_err;
627 char *string;
628 uint32_t i;
629
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;
640 }
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);
647 }
648
649 blob = talloc(mem_ctx, struct prefixMapBlob);
650 if (blob == NULL) {
651 return -1;
652 }
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;
658 }
659 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
660 goto failed;
661 }
662 string = talloc_strdup(mem_ctx, "");
663 if (string == NULL) {
664 goto failed;
665 }
666
667 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
668 DATA_BLOB oid_blob;
669 char *partial_oid = NULL;
670
671 if (i > 0) {
672 string = talloc_asprintf_append(string, ";");
673 }
674
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;
681 }
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;
688 }
689 }
690
691 talloc_free(blob);
692 *out = data_blob_string_const(string);
693 return 0;
694
695failed:
696 talloc_free(blob);
697 return -1;
698}
699
700static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
701{
702 if (v->length < 4) {
703 return true;
704 }
705
706 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
707 return false;
708 }
709
710 return true;
711}
712
713/*
714 canonicalise a prefixMap
715*/
716static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
717 const struct ldb_val *in, struct ldb_val *out)
718{
719 if (ldif_comparision_prefixMap_isString(in)) {
720 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
721 }
722 return ldb_handler_copy(ldb, mem_ctx, in, out);
723}
724
725static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
726 const struct ldb_val *v1,
727 const struct ldb_val *v2)
728{
729 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
730 v1, v2);
731}
732
733/* length limited conversion of a ldb_val to a int32_t */
734static int val_to_int32(const struct ldb_val *in, int32_t *v)
735{
736 char *end;
737 char buf[64];
738
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;
742 }
743 strncpy(buf, (char *)in->data, in->length);
744 buf[in->length] = 0;
745
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;
751 }
752 return LDB_SUCCESS;
753}
754
755/* length limited conversion of a ldb_val to a int64_t */
756static int val_to_int64(const struct ldb_val *in, int64_t *v)
757{
758 char *end;
759 char buf[64];
760
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;
764 }
765 strncpy(buf, (char *)in->data, in->length);
766 buf[in->length] = 0;
767
768 *v = (int64_t) strtoll(buf, &end, 0);
769 if (*end != 0) {
770 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
771 }
772 return LDB_SUCCESS;
773}
774
775/* Canonicalisation of two 32-bit integers */
776static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
777 const struct ldb_val *in, struct ldb_val *out)
778{
779 int32_t i;
780 int ret;
781
782 ret = val_to_int32(in, &i);
783 if (ret != LDB_SUCCESS) {
784 return ret;
785 }
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;
790 }
791 out->length = strlen((char *)out->data);
792 return 0;
793}
794
795/* Comparison of two 32-bit integers */
796static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
797 const struct ldb_val *v1, const struct ldb_val *v2)
798{
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;
804}
805
806/* Canonicalisation of two 64-bit integers */
807static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
808 const struct ldb_val *in, struct ldb_val *out)
809{
810 int64_t i;
811 int ret;
812
813 ret = val_to_int64(in, &i);
814 if (ret != LDB_SUCCESS) {
815 return ret;
816 }
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;
821 }
822 out->length = strlen((char *)out->data);
823 return 0;
824}
825
826/* Comparison of two 64-bit integers */
827static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
828 const struct ldb_val *v1, const struct ldb_val *v2)
829{
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;
835}
836
837/*
838 convert a NDR formatted blob to a ldif formatted repsFromTo
839*/
840static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
841 const struct ldb_val *in, struct ldb_val *out)
842{
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);
848}
849
850/*
851 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
852*/
853static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
854 const struct ldb_val *in, struct ldb_val *out)
855{
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);
861}
862
863/*
864 convert a NDR formatted blob to a ldif formatted replUpToDateVector
865*/
866static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
867 const struct ldb_val *in, struct ldb_val *out)
868{
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);
874}
875
876
877/*
878 convert a NDR formatted blob to a ldif formatted dnsRecord
879*/
880static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
881 const struct ldb_val *in, struct ldb_val *out)
882{
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);
888}
889
890/*
891 convert a NDR formatted blob of a supplementalCredentials into text
892*/
893static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
894 const struct ldb_val *in, struct ldb_val *out)
895{
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);
901}
902
903
904static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
905 const struct ldb_val *in, struct ldb_val *out)
906{
907 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
908 if (!out->data) {
909 return -1;
910 }
911 return 0;
912}
913
914/*
915 compare two dns
916*/
917static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
918 const struct ldb_val *v1, const struct ldb_val *v2)
919{
920 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
921 int ret;
922
923 if (dsdb_dn_is_deleted_val(v1)) {
924 /* If the DN is deleted, then we can't search for it */
925 return -1;
926 }
927
928 if (dsdb_dn_is_deleted_val(v2)) {
929 /* If the DN is deleted, then we can't search for it */
930 return -1;
931 }
932
933 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
934 if ( ! ldb_dn_validate(dn1)) return -1;
935
936 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
937 if ( ! ldb_dn_validate(dn2)) {
938 talloc_free(dn1);
939 return -1;
940 }
941
942 ret = ldb_dn_compare(dn1, dn2);
943
944 talloc_free(dn1);
945 talloc_free(dn2);
946 return ret;
947}
948
949static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
950 const struct ldb_val *in, struct ldb_val *out)
951{
952 struct ldb_dn *dn;
953 int ret = -1;
954
955 out->length = 0;
956 out->data = NULL;
957
958 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
959 if ( ! ldb_dn_validate(dn)) {
960 return LDB_ERR_INVALID_DN_SYNTAX;
961 }
962
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);
972 }
973
974 if (out->data == NULL) {
975 goto done;
976 }
977 out->length = strlen((char *)out->data);
978
979 ret = 0;
980
981done:
982 talloc_free(dn);
983
984 return ret;
985}
986
987
988/*
989 write a 64 bit 2-part range
990*/
991static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
992 const struct ldb_val *in, struct ldb_val *out)
993{
994 int64_t v;
995 int ret;
996 ret = val_to_int64(in, &v);
997 if (ret != LDB_SUCCESS) {
998 return ret;
999 }
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;
1006 }
1007 out->length = strlen((char *)out->data);
1008 return LDB_SUCCESS;
1009}
1010
1011/*
1012 read a 64 bit 2-part range
1013*/
1014static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1015 const struct ldb_val *in, struct ldb_val *out)
1016{
1017 unsigned long high, low;
1018 char buf[64];
1019
1020 if (memchr(in->data, '-', in->length) == NULL) {
1021 return ldb_handler_copy(ldb, mem_ctx, in, out);
1022 }
1023
1024 if (in->length > sizeof(buf)-1) {
1025 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1026 }
1027 strncpy(buf, (const char *)in->data, in->length);
1028 buf[in->length] = 0;
1029
1030 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1031 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1032 }
1033
1034 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1035 (unsigned long long)(((uint64_t)high)<<32) | (low));
1036
1037 if (out->data == NULL) {
1038 ldb_oom(ldb);
1039 return LDB_ERR_OPERATIONS_ERROR;
1040 }
1041 out->length = strlen((char *)out->data);
1042 return LDB_SUCCESS;
1043}
1044
1045/*
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
1049 */
1050static 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)
1053{
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;
1063
1064 case LDB_OP_GREATER:
1065 case LDB_OP_LESS:
1066 case LDB_OP_EQUALITY:
1067 {
1068 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1069 int ret;
1070 if (tmp_ctx == NULL) {
1071 return ldb_oom(ldb);
1072 }
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);
1081 }
1082 return LDB_SUCCESS;
1083 }
1084
1085 case LDB_OP_PRESENT:
1086 *matched = true;
1087 return LDB_SUCCESS;
1088 }
1089
1090 /* we shouldn't get here */
1091 return LDB_ERR_INAPPROPRIATE_MATCHING;
1092}
1093
1094/*
1095 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1096 */
1097static 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)
1100{
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;
1105 }
1106 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1107}
1108
1109
1110static const struct ldb_schema_syntax samba_syntaxes[] = {
1111 {
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
1118 },{
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
1125 },{
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
1132 },{
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
1139 },{
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
1146 },{
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
1153 },{
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
1160 },{
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
1167 },{
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
1174 },{
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
1181 },{
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
1188 },{
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
1195 },{
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
1202 },{
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
1209 },{
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
1216 },{
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
1223 }
1224};
1225
1226static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1227 {
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
1232 },{
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
1237 },{
1238 .name = "WKGUID",
1239 .read_fn = ldb_handler_copy,
1240 .write_clear_fn = ldb_handler_copy,
1241 .write_hex_fn = ldb_handler_copy
1242 },{
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
1247 },{
1248 .name = "RMD_FLAGS",
1249 .read_fn = ldb_handler_copy,
1250 .write_clear_fn = ldb_handler_copy,
1251 .write_hex_fn = ldb_handler_copy
1252 },{
1253 .name = "RMD_ADDTIME",
1254 .read_fn = ldb_handler_copy,
1255 .write_clear_fn = ldb_handler_copy,
1256 .write_hex_fn = ldb_handler_copy
1257 },{
1258 .name = "RMD_CHANGETIME",
1259 .read_fn = ldb_handler_copy,
1260 .write_clear_fn = ldb_handler_copy,
1261 .write_hex_fn = ldb_handler_copy
1262 },{
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
1267 },{
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
1272 },{
1273 .name = "RMD_VERSION",
1274 .read_fn = ldb_handler_copy,
1275 .write_clear_fn = ldb_handler_copy,
1276 .write_hex_fn = ldb_handler_copy
1277 }
1278};
1279
1280/* TODO: Should be dynamic at some point */
1281static 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 },
1300
1301 /*
1302 * these are extracted by searching
1303 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1304 */
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 },
1329
1330 /*
1331 * these are known to be GUIDs
1332 */
1333 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1334 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1335 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1336
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}
1340};
1341
1342const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1343{
1344 unsigned int j;
1345 const struct ldb_schema_syntax *s = NULL;
1346
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;
1351 }
1352 }
1353 return s;
1354}
1355
1356const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1357{
1358 unsigned int j;
1359 const struct ldb_schema_syntax *s = NULL;
1360
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;
1365 }
1366 }
1367
1368 return s;
1369}
1370
1371/*
1372 register the samba ldif handlers
1373*/
1374int ldb_register_samba_handlers(struct ldb_context *ldb)
1375{
1376 unsigned int i;
1377 int ret;
1378
1379 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1380 return LDB_SUCCESS;
1381 }
1382
1383 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1384 const struct ldb_schema_syntax *s = NULL;
1385
1386 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1387
1388 if (!s) {
1389 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1390 }
1391
1392 if (!s) {
1393 return LDB_ERR_OPERATIONS_ERROR;
1394 }
1395
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;
1399 }
1400 }
1401
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;
1406 }
1407
1408 }
1409
1410 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1411 if (ret != LDB_SUCCESS) {
1412 return ret;
1413 }
1414
1415 return LDB_SUCCESS;
1416}
Note: See TracBrowser for help on using the repository browser.