source: vendor/current/lib/ldb-samba/ldif_handlers.c

Last change on this file was 989, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.7

File size: 48.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 "dsdb/common/util.h"
31#include "librpc/gen_ndr/ndr_security.h"
32#include "librpc/gen_ndr/ndr_misc.h"
33#include "librpc/gen_ndr/ndr_drsblobs.h"
34#include "librpc/gen_ndr/ndr_dnsp.h"
35#include "librpc/ndr/libndr.h"
36#include "libcli/security/security.h"
37#include "param/param.h"
38#include "../lib/util/asn1.h"
39
40/*
41 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
42
43 If mask_errors is true, then function succeeds but out data
44 is set to "<Unable to decode binary data>" message
45
46 \return 0 on success; -1 on error
47*/
48static 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)
54{
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);
59 }
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;
67 }
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;
72 }
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);
77 }
78 out->length = strlen((char *)out->data);
79 return 0;
80}
81
82/*
83 convert a ldif formatted objectSid to a NDR formatted blob
84*/
85static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
86 const struct ldb_val *in, struct ldb_val *out)
87{
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;
93 }
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;
99 }
100 return 0;
101}
102
103/*
104 convert a NDR formatted blob to a ldif formatted objectSid
105*/
106int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
107 const struct ldb_val *in, struct ldb_val *out)
108{
109 struct dom_sid *sid;
110 enum ndr_err_code ndr_err;
111
112 sid = talloc(mem_ctx, struct dom_sid);
113 if (sid == NULL) {
114 return -1;
115 }
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;
121 }
122 *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
123 talloc_free(sid);
124 if (out->data == NULL) {
125 return -1;
126 }
127 return 0;
128}
129
130bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
131{
132 if (v->length < 3) {
133 return false;
134 }
135
136 if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
137
138 return true;
139}
140
141/*
142 compare two objectSids
143*/
144static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
145 const struct ldb_val *v1, const struct ldb_val *v2)
146{
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);
156 }
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);
167 }
168 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
169 talloc_free(v.data);
170 return ret;
171 }
172 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
173}
174
175/*
176 canonicalise a objectSid
177*/
178static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
179 const struct ldb_val *in, struct ldb_val *out)
180{
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);
185 }
186 return 0;
187 }
188 return ldb_handler_copy(ldb, mem_ctx, in, out);
189}
190
191static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
192 const struct ldb_val *in, struct ldb_val *out)
193{
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;
199 }
200 }
201
202 /* Perhaps not a string after all */
203 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
204
205 if (!out->data) {
206 return -1;
207 }
208
209 (*out).length = strhex_to_str((char *)out->data, out->length,
210 (const char *)in->data, in->length);
211
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;
217 }
218 return 0;
219}
220
221/*
222 convert a ldif formatted objectGUID to a NDR formatted blob
223*/
224static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
225 const struct ldb_val *in, struct ldb_val *out)
226{
227 struct GUID guid;
228 NTSTATUS status;
229
230 status = GUID_from_data_blob(in, &guid);
231 if (!NT_STATUS_IS_OK(status)) {
232 return -1;
233 }
234
235 status = GUID_to_ndr_blob(&guid, mem_ctx, out);
236 if (!NT_STATUS_IS_OK(status)) {
237 return -1;
238 }
239 return 0;
240}
241
242/*
243 convert a NDR formatted blob to a ldif formatted objectGUID
244*/
245static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
246 const struct ldb_val *in, struct ldb_val *out)
247{
248 struct GUID guid;
249 NTSTATUS status;
250
251 status = GUID_from_ndr_blob(in, &guid);
252 if (!NT_STATUS_IS_OK(status)) {
253 return -1;
254 }
255 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
256 if (out->data == NULL) {
257 return -1;
258 }
259 out->length = strlen((const char *)out->data);
260 return 0;
261}
262
263static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
264{
265 if (v->length != 36 && v->length != 38) return false;
266
267 /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
268 return true;
269}
270
271static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
272 const struct ldb_val *in, struct ldb_val *out)
273{
274 struct GUID guid;
275 NTSTATUS status;
276
277 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
278 return 0;
279 }
280
281 /* Try as 'hex' form */
282 if (in->length != 32) {
283 return -1;
284 }
285
286 *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
287
288 if (!out->data) {
289 return -1;
290 }
291
292 (*out).length = strhex_to_str((char *)out->data, out->length,
293 (const char *)in->data, in->length);
294
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;
300 }
301 return 0;
302}
303
304/*
305 compare two objectGUIDs
306*/
307static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
308 const struct ldb_val *v1, const struct ldb_val *v2)
309{
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);
319 }
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);
330 }
331 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
332 talloc_free(v.data);
333 return ret;
334 }
335 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
336}
337
338/*
339 canonicalise a objectGUID
340*/
341static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
342 const struct ldb_val *in, struct ldb_val *out)
343{
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);
348 }
349 return 0;
350 }
351 return ldb_handler_copy(ldb, mem_ctx, in, out);
352}
353
354
355/*
356 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
357*/
358static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
359 const struct ldb_val *in, struct ldb_val *out)
360{
361 struct security_descriptor *sd;
362 enum ndr_err_code ndr_err;
363
364 sd = talloc(mem_ctx, struct security_descriptor);
365 if (sd == NULL) {
366 return -1;
367 }
368
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 */
373
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;
379 }
380 }
381
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;
387 }
388
389 return 0;
390}
391
392/*
393 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
394*/
395static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
396 const struct ldb_val *in, struct ldb_val *out)
397{
398 struct security_descriptor *sd;
399 enum ndr_err_code ndr_err;
400
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);
407
408 }
409
410 sd = talloc(mem_ctx, struct security_descriptor);
411 if (sd == NULL) {
412 return -1;
413 }
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;
420 }
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;
425 }
426 out->length = strlen((const char *)out->data);
427 return 0;
428}
429
430/*
431 convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
432*/
433static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
434 const struct ldb_val *in, struct ldb_val *out)
435{
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);
439
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;
447 }
448
449 return ldb_handler_copy(ldb, mem_ctx, in, out);
450}
451
452/*
453 canonicalise an objectCategory. We use the long form as the canonical form:
454 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
455
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>)
460*/
461
462static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
463 const struct ldb_val *in, struct ldb_val *out)
464{
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;
471 }
472
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;
478 }
479 return LDB_SUCCESS;
480 }
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;
491 }
492
493 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
494 talloc_free(tmp_ctx);
495
496 if (!out->data) {
497 return LDB_ERR_OPERATIONS_ERROR;
498 }
499 return LDB_SUCCESS;
500 } else {
501 *out = data_blob_talloc(mem_ctx, in->data, in->length);
502 talloc_free(tmp_ctx);
503
504 if (in->data && !out->data) {
505 return LDB_ERR_OPERATIONS_ERROR;
506 }
507 return LDB_SUCCESS;
508 }
509 }
510 *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
511 talloc_free(tmp_ctx);
512
513 if (!out->data) {
514 return LDB_ERR_OPERATIONS_ERROR;
515 }
516 return LDB_SUCCESS;
517}
518
519static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
520 const struct ldb_val *v1,
521 const struct ldb_val *v2)
522{
523 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
524 v1, v2);
525}
526
527/*
528 convert a NDR formatted blob to a ldif formatted schemaInfo
529*/
530static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
531 const struct ldb_val *in, struct ldb_val *out)
532{
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);
538}
539
540/*
541 convert a ldif formatted prefixMap to a NDR formatted blob
542*/
543static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
544 const struct ldb_val *in, struct ldb_val *out)
545{
546 struct prefixMapBlob *blob;
547 enum ndr_err_code ndr_err;
548 char *string, *line, *p, *oid;
549 DATA_BLOB oid_blob;
550
551 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
552
553 if (tmp_ctx == NULL) {
554 return -1;
555 }
556
557 blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
558 if (blob == NULL) {
559 talloc_free(tmp_ctx);
560 return -1;
561 }
562
563 /* use the switch value to detect if this is in the binary
564 * format
565 */
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;
576 }
577 return 0;
578 }
579 }
580
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;
583
584 string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
585 if (string == NULL) {
586 talloc_free(blob);
587 return -1;
588 }
589
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';
599 }
600 }
601 /* allow a trailing separator */
602 if (line == p) {
603 break;
604 }
605
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;
613 }
614
615 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
616
617 if (oid[0] != ':') {
618 talloc_free(tmp_ctx);
619 return -1;
620 }
621
622 /* we know there must be at least ":" */
623 oid++;
624
625 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
626 talloc_free(tmp_ctx);
627 return -1;
628 }
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;
631
632 blob->ctr.dsdb.num_mappings++;
633
634 /* Now look past the terminator we added above */
635 if (p) {
636 line = p + 1;
637 } else {
638 line = NULL;
639 }
640 }
641
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;
648 }
649 return 0;
650}
651
652/*
653 convert a NDR formatted blob to a ldif formatted prefixMap
654*/
655static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
656 const struct ldb_val *in, struct ldb_val *out)
657{
658 struct prefixMapBlob *blob;
659 enum ndr_err_code ndr_err;
660 char *string;
661 uint32_t i;
662
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;
673 }
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);
680 }
681
682 blob = talloc(mem_ctx, struct prefixMapBlob);
683 if (blob == NULL) {
684 return -1;
685 }
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;
691 }
692 if (blob->version != PREFIX_MAP_VERSION_DSDB) {
693 goto failed;
694 }
695 string = talloc_strdup(mem_ctx, "");
696 if (string == NULL) {
697 goto failed;
698 }
699
700 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
701 DATA_BLOB oid_blob;
702 char *partial_oid = NULL;
703
704 if (i > 0) {
705 string = talloc_asprintf_append(string, ";");
706 }
707
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;
714 }
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;
721 }
722 }
723
724 talloc_free(blob);
725 *out = data_blob_string_const(string);
726 return 0;
727
728failed:
729 talloc_free(blob);
730 return -1;
731}
732
733static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
734{
735 if (v->length < 4) {
736 return true;
737 }
738
739 if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
740 return false;
741 }
742
743 return true;
744}
745
746/*
747 canonicalise a prefixMap
748*/
749static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
750 const struct ldb_val *in, struct ldb_val *out)
751{
752 if (ldif_comparision_prefixMap_isString(in)) {
753 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
754 }
755 return ldb_handler_copy(ldb, mem_ctx, in, out);
756}
757
758static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
759 const struct ldb_val *v1,
760 const struct ldb_val *v2)
761{
762 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
763 v1, v2);
764}
765
766/* length limited conversion of a ldb_val to a int32_t */
767static int val_to_int32(const struct ldb_val *in, int32_t *v)
768{
769 char *end;
770 char buf[64];
771
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;
775 }
776 strncpy(buf, (char *)in->data, in->length);
777 buf[in->length] = 0;
778
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;
784 }
785 return LDB_SUCCESS;
786}
787
788/* length limited conversion of a ldb_val to a int64_t */
789static int val_to_int64(const struct ldb_val *in, int64_t *v)
790{
791 char *end;
792 char buf[64];
793
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;
797 }
798 strncpy(buf, (char *)in->data, in->length);
799 buf[in->length] = 0;
800
801 *v = (int64_t) strtoll(buf, &end, 0);
802 if (*end != 0) {
803 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
804 }
805 return LDB_SUCCESS;
806}
807
808/* Canonicalisation of two 32-bit integers */
809static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
810 const struct ldb_val *in, struct ldb_val *out)
811{
812 int32_t i;
813 int ret;
814
815 ret = val_to_int32(in, &i);
816 if (ret != LDB_SUCCESS) {
817 return ret;
818 }
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;
823 }
824 out->length = strlen((char *)out->data);
825 return 0;
826}
827
828/* Comparison of two 32-bit integers */
829static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
830 const struct ldb_val *v1, const struct ldb_val *v2)
831{
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;
837}
838
839/* Canonicalisation of two 64-bit integers */
840static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
841 const struct ldb_val *in, struct ldb_val *out)
842{
843 int64_t i;
844 int ret;
845
846 ret = val_to_int64(in, &i);
847 if (ret != LDB_SUCCESS) {
848 return ret;
849 }
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;
854 }
855 out->length = strlen((char *)out->data);
856 return 0;
857}
858
859/* Comparison of two 64-bit integers */
860static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
861 const struct ldb_val *v1, const struct ldb_val *v2)
862{
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;
868}
869
870/*
871 convert a NDR formatted blob to a ldif formatted repsFromTo
872*/
873static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
874 const struct ldb_val *in, struct ldb_val *out)
875{
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);
881}
882
883/*
884 convert a NDR formatted blob to a ldif formatted replPropertyMetaData
885*/
886static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
887 const struct ldb_val *in, struct ldb_val *out)
888{
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);
894}
895
896/*
897 convert a NDR formatted blob to a ldif formatted replUpToDateVector
898*/
899static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
900 const struct ldb_val *in, struct ldb_val *out)
901{
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);
907}
908
909static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
910 const struct ldb_val *in, struct ldb_val *out,
911 size_t struct_size,
912 ndr_pull_flags_fn_t pull_fn,
913 ndr_print_fn_t print_fn,
914 bool mask_errors)
915{
916 uint8_t *p = NULL;
917 enum ndr_err_code err;
918 struct dsdb_dn *dsdb_dn = NULL;
919 char *dn_str = NULL;
920 char *str = NULL;
921
922 if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
923 return ldb_handler_copy(ldb, mem_ctx, in, out);
924 }
925
926 dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
927 if (dsdb_dn == NULL) {
928 return ldb_handler_copy(ldb, mem_ctx, in, out);
929 }
930
931 p = talloc_size(dsdb_dn, struct_size);
932 if (p == NULL) {
933 TALLOC_FREE(dsdb_dn);
934 return ldb_handler_copy(ldb, mem_ctx, in, out);
935 }
936
937 err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
938 if (err != NDR_ERR_SUCCESS) {
939 /* fail in not in mask_error mode */
940 if (!mask_errors) {
941 return -1;
942 }
943 TALLOC_FREE(dsdb_dn);
944 return ldb_handler_copy(ldb, mem_ctx, in, out);
945 }
946
947 dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
948 if (dn_str == NULL) {
949 TALLOC_FREE(dsdb_dn);
950 return ldb_handler_copy(ldb, mem_ctx, in, out);
951 }
952
953 str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
954 TALLOC_FREE(dsdb_dn);
955 if (str == NULL) {
956 return ldb_handler_copy(ldb, mem_ctx, in, out);
957 }
958
959 *out = data_blob_string_const(str);
960 return 0;
961}
962
963static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
964 const struct ldb_val *in, struct ldb_val *out)
965{
966 return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
967 sizeof(struct replPropertyMetaData1),
968 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
969 (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
970 true);
971}
972
973/*
974 convert a NDR formatted blob to a ldif formatted dnsRecord
975*/
976static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
977 const struct ldb_val *in, struct ldb_val *out)
978{
979 return ldif_write_NDR(ldb, mem_ctx, in, out,
980 sizeof(struct dnsp_DnssrvRpcRecord),
981 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
982 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
983 true);
984}
985
986/*
987 convert a NDR formatted blob to a ldif formatted dnsProperty
988*/
989static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
990 const struct ldb_val *in, struct ldb_val *out)
991{
992 return ldif_write_NDR(ldb, mem_ctx, in, out,
993 sizeof(struct dnsp_DnsProperty),
994 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
995 (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
996 true);
997}
998
999/*
1000 convert a NDR formatted blob of a supplementalCredentials into text
1001*/
1002static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1003 const struct ldb_val *in, struct ldb_val *out)
1004{
1005 return ldif_write_NDR(ldb, mem_ctx, in, out,
1006 sizeof(struct supplementalCredentialsBlob),
1007 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1008 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1009 true);
1010}
1011
1012/*
1013 convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1014*/
1015static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1016 const struct ldb_val *in, struct ldb_val *out)
1017{
1018 return ldif_write_NDR(ldb, mem_ctx, in, out,
1019 sizeof(struct trustAuthInOutBlob),
1020 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1021 (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1022 true);
1023}
1024
1025/*
1026 convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1027*/
1028static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1029 const struct ldb_val *in, struct ldb_val *out)
1030{
1031 return ldif_write_NDR(ldb, mem_ctx, in, out,
1032 sizeof(struct ForestTrustInfo),
1033 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1034 (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1035 true);
1036}
1037/*
1038 convert a NDR formatted blob of a partialAttributeSet into text
1039*/
1040static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1041 const struct ldb_val *in, struct ldb_val *out)
1042{
1043 return ldif_write_NDR(ldb, mem_ctx, in, out,
1044 sizeof(struct partialAttributeSetBlob),
1045 (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1046 (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1047 true);
1048}
1049
1050
1051static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1052 const struct ldb_val *in, struct ldb_val *out)
1053{
1054 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1055 if (!out->data) {
1056 return -1;
1057 }
1058 return 0;
1059}
1060
1061/*
1062 compare two dns
1063*/
1064static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1065 const struct ldb_val *v1, const struct ldb_val *v2)
1066{
1067 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1068 int ret;
1069
1070 if (dsdb_dn_is_deleted_val(v1)) {
1071 /* If the DN is deleted, then we can't search for it */
1072 return -1;
1073 }
1074
1075 if (dsdb_dn_is_deleted_val(v2)) {
1076 /* If the DN is deleted, then we can't search for it */
1077 return -1;
1078 }
1079
1080 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1081 if ( ! ldb_dn_validate(dn1)) return -1;
1082
1083 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1084 if ( ! ldb_dn_validate(dn2)) {
1085 talloc_free(dn1);
1086 return -1;
1087 }
1088
1089 ret = ldb_dn_compare(dn1, dn2);
1090
1091 talloc_free(dn1);
1092 talloc_free(dn2);
1093 return ret;
1094}
1095
1096static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1097 const struct ldb_val *in, struct ldb_val *out)
1098{
1099 struct ldb_dn *dn;
1100 int ret = -1;
1101
1102 out->length = 0;
1103 out->data = NULL;
1104
1105 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1106 if ( ! ldb_dn_validate(dn)) {
1107 return LDB_ERR_INVALID_DN_SYNTAX;
1108 }
1109
1110 /* By including the RMD_FLAGS of a deleted DN, we ensure it
1111 * does not casually match a not deleted DN */
1112 if (dsdb_dn_is_deleted_val(in)) {
1113 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1114 "<RMD_FLAGS=%u>%s",
1115 dsdb_dn_val_rmd_flags(in),
1116 ldb_dn_get_casefold(dn));
1117 } else {
1118 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1119 }
1120
1121 if (out->data == NULL) {
1122 goto done;
1123 }
1124 out->length = strlen((char *)out->data);
1125
1126 ret = 0;
1127
1128done:
1129 talloc_free(dn);
1130
1131 return ret;
1132}
1133
1134
1135/*
1136 write a 64 bit 2-part range
1137*/
1138static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1139 const struct ldb_val *in, struct ldb_val *out)
1140{
1141 int64_t v;
1142 int ret;
1143 ret = val_to_int64(in, &v);
1144 if (ret != LDB_SUCCESS) {
1145 return ret;
1146 }
1147 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1148 (unsigned long)(v&0xFFFFFFFF),
1149 (unsigned long)(v>>32));
1150 if (out->data == NULL) {
1151 ldb_oom(ldb);
1152 return LDB_ERR_OPERATIONS_ERROR;
1153 }
1154 out->length = strlen((char *)out->data);
1155 return LDB_SUCCESS;
1156}
1157
1158/*
1159 read a 64 bit 2-part range
1160*/
1161static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1162 const struct ldb_val *in, struct ldb_val *out)
1163{
1164 unsigned long high, low;
1165 char buf[64];
1166
1167 if (memchr(in->data, '-', in->length) == NULL) {
1168 return ldb_handler_copy(ldb, mem_ctx, in, out);
1169 }
1170
1171 if (in->length > sizeof(buf)-1) {
1172 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1173 }
1174 strncpy(buf, (const char *)in->data, in->length);
1175 buf[in->length] = 0;
1176
1177 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1178 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1179 }
1180
1181 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1182 (unsigned long long)(((uint64_t)high)<<32) | (low));
1183
1184 if (out->data == NULL) {
1185 ldb_oom(ldb);
1186 return LDB_ERR_OPERATIONS_ERROR;
1187 }
1188 out->length = strlen((char *)out->data);
1189 return LDB_SUCCESS;
1190}
1191
1192/*
1193 when this operator_fn is set for a syntax, the backend calls is in
1194 preference to the comparison function. We are told the exact
1195 comparison operation that is needed, and we can return errors
1196 */
1197static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1198 const struct ldb_schema_attribute *a,
1199 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1200{
1201 switch (operation) {
1202 case LDB_OP_AND:
1203 case LDB_OP_OR:
1204 case LDB_OP_NOT:
1205 case LDB_OP_SUBSTRING:
1206 case LDB_OP_APPROX:
1207 case LDB_OP_EXTENDED:
1208 /* handled in the backends */
1209 return LDB_ERR_INAPPROPRIATE_MATCHING;
1210
1211 case LDB_OP_GREATER:
1212 case LDB_OP_LESS:
1213 case LDB_OP_EQUALITY:
1214 {
1215 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1216 int ret;
1217 if (tmp_ctx == NULL) {
1218 return ldb_oom(ldb);
1219 }
1220 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1221 talloc_free(tmp_ctx);
1222 if (operation == LDB_OP_GREATER) {
1223 *matched = (ret >= 0);
1224 } else if (operation == LDB_OP_LESS) {
1225 *matched = (ret <= 0);
1226 } else {
1227 *matched = (ret == 0);
1228 }
1229 return LDB_SUCCESS;
1230 }
1231
1232 case LDB_OP_PRESENT:
1233 *matched = true;
1234 return LDB_SUCCESS;
1235 }
1236
1237 /* we shouldn't get here */
1238 return LDB_ERR_INAPPROPRIATE_MATCHING;
1239}
1240
1241/*
1242 see if two DNs match, comparing first by GUID, then by SID, and
1243 finally by string components
1244 */
1245static int samba_dn_extended_match(struct ldb_context *ldb,
1246 const struct ldb_val *v1,
1247 const struct ldb_val *v2,
1248 bool *matched)
1249{
1250 TALLOC_CTX *tmp_ctx;
1251 struct ldb_dn *dn1, *dn2;
1252 const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1253 uint32_t rmd_flags1, rmd_flags2;
1254
1255 tmp_ctx = talloc_new(ldb);
1256
1257 dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1258 dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1259 if (!dn1 || !dn2) {
1260 /* couldn't parse as DN's */
1261 talloc_free(tmp_ctx);
1262 (*matched) = false;
1263 return LDB_SUCCESS;
1264 }
1265
1266 rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1267 rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1268
1269 if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1270 (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1271 /* only match if they have the same deletion status */
1272 talloc_free(tmp_ctx);
1273 (*matched) = false;
1274 return LDB_SUCCESS;
1275 }
1276
1277
1278 guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1279 guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1280 if (guid1 && guid2) {
1281 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1282 talloc_free(tmp_ctx);
1283 return LDB_SUCCESS;
1284 }
1285
1286 sid1 = ldb_dn_get_extended_component(dn1, "SID");
1287 sid2 = ldb_dn_get_extended_component(dn2, "SID");
1288 if (sid1 && sid2) {
1289 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1290 talloc_free(tmp_ctx);
1291 return LDB_SUCCESS;
1292 }
1293
1294 (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1295
1296 talloc_free(tmp_ctx);
1297 return LDB_SUCCESS;
1298}
1299
1300/*
1301 special operation for DNs, to take account of the RMD_FLAGS deleted bit
1302 */
1303static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1304 const struct ldb_schema_attribute *a,
1305 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1306{
1307 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1308 /* If the DN is deleted, then we can't search for it */
1309
1310 /* should this be for equality too? */
1311 *matched = false;
1312 return LDB_SUCCESS;
1313 }
1314
1315 if (operation == LDB_OP_EQUALITY &&
1316 samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1317 return LDB_SUCCESS;
1318 }
1319
1320 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1321}
1322
1323
1324static const struct ldb_schema_syntax samba_syntaxes[] = {
1325 {
1326 .name = LDB_SYNTAX_SAMBA_SID,
1327 .ldif_read_fn = ldif_read_objectSid,
1328 .ldif_write_fn = ldif_write_objectSid,
1329 .canonicalise_fn = ldif_canonicalise_objectSid,
1330 .comparison_fn = ldif_comparison_objectSid,
1331 .operator_fn = samba_syntax_operator_fn
1332 },{
1333 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1334 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1335 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1336 .canonicalise_fn = ldb_handler_copy,
1337 .comparison_fn = ldb_comparison_binary,
1338 .operator_fn = samba_syntax_operator_fn
1339 },{
1340 .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1341 .ldif_read_fn = ldb_handler_copy,
1342 .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1343 .canonicalise_fn = ldb_handler_fold,
1344 .comparison_fn = ldb_comparison_fold,
1345 .operator_fn = samba_syntax_operator_fn
1346 },{
1347 .name = LDB_SYNTAX_SAMBA_GUID,
1348 .ldif_read_fn = ldif_read_objectGUID,
1349 .ldif_write_fn = ldif_write_objectGUID,
1350 .canonicalise_fn = ldif_canonicalise_objectGUID,
1351 .comparison_fn = ldif_comparison_objectGUID,
1352 .operator_fn = samba_syntax_operator_fn
1353 },{
1354 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1355 .ldif_read_fn = ldb_handler_copy,
1356 .ldif_write_fn = ldb_handler_copy,
1357 .canonicalise_fn = ldif_canonicalise_objectCategory,
1358 .comparison_fn = ldif_comparison_objectCategory,
1359 .operator_fn = samba_syntax_operator_fn
1360 },{
1361 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1362 .ldif_read_fn = ldb_handler_copy,
1363 .ldif_write_fn = ldif_write_schemaInfo,
1364 .canonicalise_fn = ldb_handler_copy,
1365 .comparison_fn = ldb_comparison_binary,
1366 .operator_fn = samba_syntax_operator_fn
1367 },{
1368 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1369 .ldif_read_fn = ldif_read_prefixMap,
1370 .ldif_write_fn = ldif_write_prefixMap,
1371 .canonicalise_fn = ldif_canonicalise_prefixMap,
1372 .comparison_fn = ldif_comparison_prefixMap,
1373 .operator_fn = samba_syntax_operator_fn
1374 },{
1375 .name = LDB_SYNTAX_SAMBA_INT32,
1376 .ldif_read_fn = ldb_handler_copy,
1377 .ldif_write_fn = ldb_handler_copy,
1378 .canonicalise_fn = ldif_canonicalise_int32,
1379 .comparison_fn = ldif_comparison_int32,
1380 .operator_fn = samba_syntax_operator_fn
1381 },{
1382 .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1383 .ldif_read_fn = ldb_handler_copy,
1384 .ldif_write_fn = ldif_write_repsFromTo,
1385 .canonicalise_fn = ldb_handler_copy,
1386 .comparison_fn = ldb_comparison_binary,
1387 .operator_fn = samba_syntax_operator_fn
1388 },{
1389 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1390 .ldif_read_fn = ldb_handler_copy,
1391 .ldif_write_fn = ldif_write_replPropertyMetaData,
1392 .canonicalise_fn = ldb_handler_copy,
1393 .comparison_fn = ldb_comparison_binary,
1394 .operator_fn = samba_syntax_operator_fn
1395 },{
1396 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1397 .ldif_read_fn = ldb_handler_copy,
1398 .ldif_write_fn = ldif_write_replUpToDateVector,
1399 .canonicalise_fn = ldb_handler_copy,
1400 .comparison_fn = ldb_comparison_binary,
1401 .operator_fn = samba_syntax_operator_fn
1402 },{
1403 .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1404 .ldif_read_fn = ldb_handler_copy,
1405 .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1406 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1407 .comparison_fn = dsdb_dn_binary_comparison,
1408 .operator_fn = samba_syntax_operator_fn
1409 },{
1410 .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1411 .ldif_read_fn = ldb_handler_copy,
1412 .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1413 .canonicalise_fn = ldb_handler_copy,
1414 .comparison_fn = ldb_comparison_binary,
1415 .operator_fn = samba_syntax_operator_fn
1416 },{
1417 .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1418 .ldif_read_fn = ldb_handler_copy,
1419 .ldif_write_fn = ldif_write_ForestTrustInfo,
1420 .canonicalise_fn = ldb_handler_copy,
1421 .comparison_fn = ldb_comparison_binary,
1422 .operator_fn = samba_syntax_operator_fn
1423 },{
1424 .name = DSDB_SYNTAX_BINARY_DN,
1425 .ldif_read_fn = ldb_handler_copy,
1426 .ldif_write_fn = ldb_handler_copy,
1427 .canonicalise_fn = dsdb_dn_binary_canonicalise,
1428 .comparison_fn = dsdb_dn_binary_comparison,
1429 .operator_fn = samba_syntax_operator_fn
1430 },{
1431 .name = DSDB_SYNTAX_STRING_DN,
1432 .ldif_read_fn = ldb_handler_copy,
1433 .ldif_write_fn = ldb_handler_copy,
1434 .canonicalise_fn = dsdb_dn_string_canonicalise,
1435 .comparison_fn = dsdb_dn_string_comparison,
1436 .operator_fn = samba_syntax_operator_fn
1437 },{
1438 .name = LDB_SYNTAX_DN,
1439 .ldif_read_fn = ldb_handler_copy,
1440 .ldif_write_fn = ldb_handler_copy,
1441 .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1442 .comparison_fn = samba_ldb_dn_link_comparison,
1443 .operator_fn = samba_syntax_operator_dn
1444 },{
1445 .name = LDB_SYNTAX_SAMBA_RANGE64,
1446 .ldif_read_fn = ldif_read_range64,
1447 .ldif_write_fn = ldif_write_range64,
1448 .canonicalise_fn = ldif_canonicalise_int64,
1449 .comparison_fn = ldif_comparison_int64,
1450 .operator_fn = samba_syntax_operator_fn
1451 },{
1452 .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1453 .ldif_read_fn = ldb_handler_copy,
1454 .ldif_write_fn = ldif_write_dnsRecord,
1455 .canonicalise_fn = ldb_handler_copy,
1456 .comparison_fn = ldb_comparison_binary,
1457 .operator_fn = samba_syntax_operator_fn
1458 },{
1459 .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1460 .ldif_read_fn = ldb_handler_copy,
1461 .ldif_write_fn = ldif_write_dnsProperty,
1462 .canonicalise_fn = ldb_handler_copy,
1463 .comparison_fn = ldb_comparison_binary,
1464 .operator_fn = samba_syntax_operator_fn
1465 },{
1466 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1467 .ldif_read_fn = ldb_handler_copy,
1468 .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1469 .canonicalise_fn = ldb_handler_copy,
1470 .comparison_fn = ldb_comparison_binary,
1471 .operator_fn = samba_syntax_operator_fn
1472 },{
1473 .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1474 .ldif_read_fn = ldb_handler_copy,
1475 .ldif_write_fn = ldif_write_partialAttributeSet,
1476 .canonicalise_fn = ldb_handler_copy,
1477 .comparison_fn = ldb_comparison_binary,
1478 .operator_fn = samba_syntax_operator_fn
1479 }
1480};
1481
1482static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1483 {
1484 .name = "SID",
1485 .read_fn = extended_dn_read_SID,
1486 .write_clear_fn = ldif_write_objectSid,
1487 .write_hex_fn = extended_dn_write_hex
1488 },{
1489 .name = "GUID",
1490 .read_fn = extended_dn_read_GUID,
1491 .write_clear_fn = ldif_write_objectGUID,
1492 .write_hex_fn = extended_dn_write_hex
1493 },{
1494 .name = "WKGUID",
1495 .read_fn = ldb_handler_copy,
1496 .write_clear_fn = ldb_handler_copy,
1497 .write_hex_fn = ldb_handler_copy
1498 },{
1499 .name = "RMD_INVOCID",
1500 .read_fn = extended_dn_read_GUID,
1501 .write_clear_fn = ldif_write_objectGUID,
1502 .write_hex_fn = extended_dn_write_hex
1503 },{
1504 .name = "RMD_FLAGS",
1505 .read_fn = ldb_handler_copy,
1506 .write_clear_fn = ldb_handler_copy,
1507 .write_hex_fn = ldb_handler_copy
1508 },{
1509 .name = "RMD_ADDTIME",
1510 .read_fn = ldb_handler_copy,
1511 .write_clear_fn = ldb_handler_copy,
1512 .write_hex_fn = ldb_handler_copy
1513 },{
1514 .name = "RMD_CHANGETIME",
1515 .read_fn = ldb_handler_copy,
1516 .write_clear_fn = ldb_handler_copy,
1517 .write_hex_fn = ldb_handler_copy
1518 },{
1519 .name = "RMD_LOCAL_USN",
1520 .read_fn = ldb_handler_copy,
1521 .write_clear_fn = ldb_handler_copy,
1522 .write_hex_fn = ldb_handler_copy
1523 },{
1524 .name = "RMD_ORIGINATING_USN",
1525 .read_fn = ldb_handler_copy,
1526 .write_clear_fn = ldb_handler_copy,
1527 .write_hex_fn = ldb_handler_copy
1528 },{
1529 .name = "RMD_VERSION",
1530 .read_fn = ldb_handler_copy,
1531 .write_clear_fn = ldb_handler_copy,
1532 .write_hex_fn = ldb_handler_copy
1533 }
1534};
1535
1536/* TODO: Should be dynamic at some point */
1537static const struct {
1538 const char *name;
1539 const char *syntax;
1540} samba_attributes[] = {
1541 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1542 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1543 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1544 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1545 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1546 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1547 { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1548 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1549 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1550 { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1551 { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1552 { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1553 { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1554 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1555 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1556 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1557 { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1558
1559 /*
1560 * these are extracted by searching
1561 * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1562 *
1563 * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1564 * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1565 * hat can be used to identify the set of policies when applied to a resource.
1566 * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1567 * server, we ignore it here.
1568 */
1569 { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1570 { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1571 { "objectSid", LDB_SYNTAX_SAMBA_SID },
1572 { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1573 { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1574 { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1575 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1576 { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1577 { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1578
1579 /*
1580 * these are extracted by searching
1581 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1582 */
1583 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1584 { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1585 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1586 { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1587 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1588 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1589 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1590 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1591 { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1592 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1593 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1594 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1595 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1596 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1597 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1598 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1599 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1600 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1601 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1602 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1603 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1604 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1605 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1606 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1607 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1608 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1609 { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1610 { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1611
1612 /*
1613 * these are known to be GUIDs
1614 */
1615 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1616 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1617
1618 /* These NDR encoded things we want to be able to read with --show-binary */
1619 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1620 { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1621 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1622 { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1623};
1624
1625const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1626{
1627 unsigned int j;
1628 const struct ldb_schema_syntax *s = NULL;
1629
1630 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1631 if (strcmp(name, samba_syntaxes[j].name) == 0) {
1632 s = &samba_syntaxes[j];
1633 break;
1634 }
1635 }
1636 return s;
1637}
1638
1639const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1640{
1641 unsigned int j;
1642 const struct ldb_schema_syntax *s = NULL;
1643
1644 for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1645 if (strcmp(samba_attributes[j].name, name) == 0) {
1646 s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1647 break;
1648 }
1649 }
1650
1651 return s;
1652}
1653
1654static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret", NULL};
1655
1656/*
1657 register the samba ldif handlers
1658*/
1659int ldb_register_samba_handlers(struct ldb_context *ldb)
1660{
1661 unsigned int i;
1662 int ret;
1663
1664 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1665 return LDB_SUCCESS;
1666 }
1667
1668 ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1669 if (ret != LDB_SUCCESS) {
1670 return ret;
1671 }
1672
1673 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1674 const struct ldb_schema_syntax *s = NULL;
1675
1676 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1677
1678 if (!s) {
1679 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1680 }
1681
1682 if (!s) {
1683 return LDB_ERR_OPERATIONS_ERROR;
1684 }
1685
1686 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1687 if (ret != LDB_SUCCESS) {
1688 return ret;
1689 }
1690 }
1691
1692 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1693 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1694 if (ret != LDB_SUCCESS) {
1695 return ret;
1696 }
1697
1698 }
1699
1700 ret = ldb_register_samba_matching_rules(ldb);
1701 if (ret != LDB_SUCCESS) {
1702 talloc_free(ldb);
1703 return LDB_SUCCESS;
1704 }
1705
1706 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1707 if (ret != LDB_SUCCESS) {
1708 return ret;
1709 }
1710
1711 return LDB_SUCCESS;
1712}
Note: See TracBrowser for help on using the repository browser.