Line data Source code
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 : #include "lib/util/smb_strtox.h"
40 :
41 : /*
42 : use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
43 :
44 : If mask_errors is true, then function succeeds but out data
45 : is set to "<Unable to decode binary data>" message
46 :
47 : \return 0 on success; -1 on error
48 : */
49 802 : static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
50 : const struct ldb_val *in, struct ldb_val *out,
51 : size_t struct_size,
52 : ndr_pull_flags_fn_t pull_fn,
53 : ndr_print_fn_t print_fn,
54 : bool mask_errors)
55 : {
56 : uint8_t *p;
57 : enum ndr_err_code err;
58 802 : if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
59 790 : return ldb_handler_copy(ldb, mem_ctx, in, out);
60 : }
61 12 : p = talloc_size(mem_ctx, struct_size);
62 12 : err = ndr_pull_struct_blob(in, mem_ctx,
63 : p, pull_fn);
64 12 : if (err != NDR_ERR_SUCCESS) {
65 : /* fail in not in mask_error mode */
66 0 : if (!mask_errors) {
67 0 : return -1;
68 : }
69 0 : talloc_free(p);
70 0 : out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
71 0 : out->length = strlen((const char *)out->data);
72 0 : return 0;
73 : }
74 12 : out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
75 12 : talloc_free(p);
76 12 : if (out->data == NULL) {
77 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
78 : }
79 12 : out->length = strlen((char *)out->data);
80 12 : return 0;
81 : }
82 :
83 : /*
84 : convert a ldif formatted objectSid to a NDR formatted blob
85 : */
86 4988078 : static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
87 : const struct ldb_val *in, struct ldb_val *out)
88 : {
89 : bool ret;
90 : enum ndr_err_code ndr_err;
91 : struct dom_sid sid;
92 4988078 : if (in->length > DOM_SID_STR_BUFLEN) {
93 0 : return -1;
94 4988078 : } else {
95 4988078 : char p[in->length+1];
96 4988078 : memcpy(p, in->data, in->length);
97 4988078 : p[in->length] = '\0';
98 :
99 4988078 : ret = dom_sid_parse(p, &sid);
100 4988078 : if (ret == false) {
101 0 : return -1;
102 : }
103 :
104 4988078 : *out = data_blob_talloc(mem_ctx, NULL,
105 : ndr_size_dom_sid(&sid, 0));
106 4988078 : if (out->data == NULL) {
107 0 : return -1;
108 : }
109 :
110 4988078 : ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
111 : (ndr_push_flags_fn_t)ndr_push_dom_sid);
112 4988078 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
113 0 : return -1;
114 : }
115 : }
116 4988078 : return 0;
117 : }
118 :
119 : /*
120 : convert a NDR formatted blob to a ldif formatted objectSid
121 : */
122 2378944 : int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
123 : const struct ldb_val *in, struct ldb_val *out)
124 : {
125 : struct dom_sid sid;
126 : enum ndr_err_code ndr_err;
127 :
128 2378944 : ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
129 : (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
130 2378944 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
131 0 : return -1;
132 : }
133 2378944 : *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
134 2378944 : if (out->data == NULL) {
135 0 : return -1;
136 : }
137 2378944 : return 0;
138 : }
139 :
140 15820805 : bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
141 : {
142 15820805 : if (v->length < 3) {
143 0 : return false;
144 : }
145 :
146 15820805 : if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
147 :
148 5064674 : return true;
149 : }
150 :
151 : /*
152 : compare two objectSids
153 : */
154 1539195 : static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
155 : const struct ldb_val *v1, const struct ldb_val *v2)
156 : {
157 1539195 : if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
158 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
159 1539195 : } else if (ldif_comparision_objectSid_isString(v1)
160 83591 : && !ldif_comparision_objectSid_isString(v2)) {
161 : struct ldb_val v;
162 : int ret;
163 83591 : if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
164 : /* Perhaps not a string after all */
165 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
166 : }
167 83591 : ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
168 83591 : talloc_free(v.data);
169 83591 : return ret;
170 1455604 : } else if (!ldif_comparision_objectSid_isString(v1)
171 1455604 : && ldif_comparision_objectSid_isString(v2)) {
172 : struct ldb_val v;
173 : int ret;
174 0 : if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
175 : /* Perhaps not a string after all */
176 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
177 : }
178 0 : ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
179 0 : talloc_free(v.data);
180 0 : return ret;
181 : }
182 1455604 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
183 : }
184 :
185 : /*
186 : canonicalise a objectSid
187 : */
188 4898418 : static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
189 : const struct ldb_val *in, struct ldb_val *out)
190 : {
191 4898418 : if (ldif_comparision_objectSid_isString(in)) {
192 136145 : if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
193 : /* Perhaps not a string after all */
194 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
195 : }
196 136145 : return 0;
197 : }
198 4762273 : return ldb_handler_copy(ldb, mem_ctx, in, out);
199 : }
200 :
201 4765607 : static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
202 : const struct ldb_val *in, struct ldb_val *out)
203 : {
204 : struct dom_sid sid;
205 : enum ndr_err_code ndr_err;
206 4765607 : if (ldif_comparision_objectSid_isString(in)) {
207 4761347 : if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
208 4761347 : return 0;
209 : }
210 : }
211 :
212 : /* Perhaps not a string after all */
213 4260 : *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
214 :
215 4260 : if (!out->data) {
216 0 : return -1;
217 : }
218 :
219 8520 : (*out).length = strhex_to_str((char *)out->data, out->length,
220 4260 : (const char *)in->data, in->length);
221 :
222 : /* Check it looks like a SID */
223 4260 : ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
224 : (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
225 4260 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
226 0 : return -1;
227 : }
228 4260 : return 0;
229 : }
230 :
231 : /*
232 : convert a ldif formatted objectGUID to a NDR formatted blob
233 : */
234 66288341 : static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
235 : const struct ldb_val *in, struct ldb_val *out)
236 : {
237 : struct GUID guid;
238 : NTSTATUS status;
239 :
240 66288341 : status = GUID_from_data_blob(in, &guid);
241 66288341 : if (!NT_STATUS_IS_OK(status)) {
242 0 : return -1;
243 : }
244 :
245 66288341 : status = GUID_to_ndr_blob(&guid, mem_ctx, out);
246 66288341 : if (!NT_STATUS_IS_OK(status)) {
247 0 : return -1;
248 : }
249 66288341 : return 0;
250 : }
251 :
252 : /*
253 : convert a NDR formatted blob to a ldif formatted objectGUID
254 : */
255 6861128 : static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
256 : const struct ldb_val *in, struct ldb_val *out)
257 : {
258 : struct GUID guid;
259 : NTSTATUS status;
260 :
261 6861128 : status = GUID_from_ndr_blob(in, &guid);
262 6861128 : if (!NT_STATUS_IS_OK(status)) {
263 0 : return -1;
264 : }
265 6861128 : out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
266 6861128 : if (out->data == NULL) {
267 0 : return -1;
268 : }
269 6861128 : out->length = strlen((const char *)out->data);
270 6861128 : return 0;
271 : }
272 :
273 113997436 : static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
274 : {
275 113997436 : if (v->length != 36 && v->length != 38) return false;
276 :
277 : /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
278 55802429 : return true;
279 : }
280 :
281 18250864 : static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
282 : const struct ldb_val *in, struct ldb_val *out)
283 : {
284 :
285 18250864 : if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
286 17918551 : return 0;
287 : }
288 :
289 : /* Try as 'hex' form */
290 332313 : if (in->length != 32) {
291 1 : return -1;
292 : }
293 :
294 332312 : *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
295 :
296 332312 : if (!out->data) {
297 0 : return -1;
298 : }
299 :
300 664624 : (*out).length = strhex_to_str((char *)out->data, out->length,
301 332312 : (const char *)in->data, in->length);
302 :
303 : /* Check it looks like a GUID */
304 332312 : if ((*out).length != 16) {
305 0 : data_blob_free(out);
306 0 : return -1;
307 : }
308 :
309 332312 : return 0;
310 : }
311 :
312 : /*
313 : compare two objectGUIDs
314 : */
315 13729835 : static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
316 : const struct ldb_val *v1, const struct ldb_val *v2)
317 : {
318 13729835 : if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
319 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
320 13729835 : } else if (ldif_comparision_objectGUID_isString(v1)
321 8884187 : && !ldif_comparision_objectGUID_isString(v2)) {
322 : struct ldb_val v;
323 : int ret;
324 8884187 : if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
325 : /* Perhaps it wasn't a valid string after all */
326 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
327 : }
328 8884187 : ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
329 8884187 : talloc_free(v.data);
330 8884187 : return ret;
331 4845648 : } else if (!ldif_comparision_objectGUID_isString(v1)
332 4845648 : && ldif_comparision_objectGUID_isString(v2)) {
333 : struct ldb_val v;
334 : int ret;
335 0 : if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
336 : /* Perhaps it wasn't a valid string after all */
337 0 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
338 : }
339 0 : ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
340 0 : talloc_free(v.data);
341 0 : return ret;
342 : }
343 4845648 : return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
344 : }
345 :
346 : /*
347 : canonicalise a objectGUID
348 : */
349 59078096 : static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
350 : const struct ldb_val *in, struct ldb_val *out)
351 : {
352 59078096 : if (ldif_comparision_objectGUID_isString(in)) {
353 38034055 : if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
354 : /* Perhaps it wasn't a valid string after all */
355 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
356 : }
357 38034055 : return 0;
358 : }
359 21044041 : return ldb_handler_copy(ldb, mem_ctx, in, out);
360 : }
361 :
362 :
363 : /*
364 : convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
365 : */
366 2512 : static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
367 : const struct ldb_val *in, struct ldb_val *out)
368 : {
369 : struct security_descriptor *sd;
370 : enum ndr_err_code ndr_err;
371 :
372 2512 : sd = talloc(mem_ctx, struct security_descriptor);
373 2512 : if (sd == NULL) {
374 0 : return -1;
375 : }
376 :
377 2512 : ndr_err = ndr_pull_struct_blob(in, sd, sd,
378 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
379 2512 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
380 : /* If this does not parse, then it is probably SDDL, and we should try it that way */
381 :
382 233 : const struct dom_sid *sid = samdb_domain_sid(ldb);
383 233 : talloc_free(sd);
384 233 : sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
385 233 : if (sd == NULL) {
386 0 : return -1;
387 : }
388 : }
389 :
390 2512 : ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
391 : (ndr_push_flags_fn_t)ndr_push_security_descriptor);
392 2512 : talloc_free(sd);
393 2512 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
394 0 : return -1;
395 : }
396 :
397 2512 : return 0;
398 : }
399 :
400 : /*
401 : convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
402 : */
403 0 : static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
404 : const struct ldb_val *in, struct ldb_val *out)
405 : {
406 : struct security_descriptor *sd;
407 : enum ndr_err_code ndr_err;
408 :
409 0 : if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
410 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
411 : sizeof(struct security_descriptor),
412 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
413 : (ndr_print_fn_t)ndr_print_security_descriptor,
414 : true);
415 :
416 : }
417 :
418 0 : sd = talloc(mem_ctx, struct security_descriptor);
419 0 : if (sd == NULL) {
420 0 : return -1;
421 : }
422 : /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
423 0 : ndr_err = ndr_pull_struct_blob(in, sd, sd,
424 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
425 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
426 0 : talloc_free(sd);
427 0 : return -1;
428 : }
429 0 : out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
430 0 : talloc_free(sd);
431 0 : if (out->data == NULL) {
432 0 : return -1;
433 : }
434 0 : out->length = strlen((const char *)out->data);
435 0 : return 0;
436 : }
437 :
438 : /*
439 : convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
440 : */
441 692 : static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
442 : const struct ldb_val *in, struct ldb_val *out)
443 : {
444 692 : if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
445 : struct security_descriptor *sd;
446 0 : const struct dom_sid *sid = samdb_domain_sid(ldb);
447 :
448 0 : sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
449 0 : out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
450 : (ndr_print_fn_t)ndr_print_security_descriptor,
451 : "SDDL", sd);
452 0 : out->length = strlen((const char *)out->data);
453 0 : talloc_free(sd);
454 0 : return 0;
455 : }
456 :
457 692 : return ldb_handler_copy(ldb, mem_ctx, in, out);
458 : }
459 :
460 : /*
461 : canonicalise an objectCategory. We use the long form as the canonical form:
462 : 'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
463 :
464 : Also any short name of an objectClass that points to a different
465 : class (such as user) has the canonical form of the class it's
466 : defaultObjectCategory points to (eg
467 : cn=Person,cn=Schema,cn=Configuration,<basedn>)
468 : */
469 :
470 1808012 : static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
471 : const struct ldb_val *in, struct ldb_val *out)
472 : {
473 1808012 : struct ldb_dn *dn1 = NULL;
474 1808012 : const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
475 : const struct dsdb_class *sclass;
476 1808012 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
477 1808012 : if (!tmp_ctx) {
478 0 : return LDB_ERR_OPERATIONS_ERROR;
479 : }
480 :
481 1808012 : if (!schema) {
482 2 : talloc_free(tmp_ctx);
483 2 : *out = data_blob_talloc(mem_ctx, in->data, in->length);
484 2 : if (in->data && !out->data) {
485 0 : return LDB_ERR_OPERATIONS_ERROR;
486 : }
487 2 : return LDB_SUCCESS;
488 : }
489 1808010 : dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
490 1808010 : if ( ! ldb_dn_validate(dn1)) {
491 11822 : const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
492 11822 : sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
493 11822 : if (sclass) {
494 11822 : struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
495 11822 : sclass->defaultObjectCategory);
496 11822 : if (dn == NULL) {
497 0 : talloc_free(tmp_ctx);
498 0 : return LDB_ERR_OPERATIONS_ERROR;
499 : }
500 :
501 11822 : *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
502 11822 : talloc_free(tmp_ctx);
503 :
504 11822 : if (!out->data) {
505 0 : return LDB_ERR_OPERATIONS_ERROR;
506 : }
507 11822 : return LDB_SUCCESS;
508 : } else {
509 0 : *out = data_blob_talloc(mem_ctx, in->data, in->length);
510 0 : talloc_free(tmp_ctx);
511 :
512 0 : if (in->data && !out->data) {
513 0 : return LDB_ERR_OPERATIONS_ERROR;
514 : }
515 0 : return LDB_SUCCESS;
516 : }
517 : }
518 1796188 : *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
519 1796188 : talloc_free(tmp_ctx);
520 :
521 1796188 : if (!out->data) {
522 0 : return LDB_ERR_OPERATIONS_ERROR;
523 : }
524 1796188 : return LDB_SUCCESS;
525 : }
526 :
527 70741 : static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
528 : const struct ldb_val *v1,
529 : const struct ldb_val *v2)
530 : {
531 70741 : return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
532 : v1, v2);
533 : }
534 :
535 : /*
536 : convert a NDR formatted blob to a ldif formatted schemaInfo
537 : */
538 17 : static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
539 : const struct ldb_val *in, struct ldb_val *out)
540 : {
541 17 : return ldif_write_NDR(ldb, mem_ctx, in, out,
542 : sizeof(struct repsFromToBlob),
543 : (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
544 : (ndr_print_fn_t)ndr_print_schemaInfoBlob,
545 : true);
546 : }
547 :
548 : /*
549 : convert a ldif formatted prefixMap to a NDR formatted blob
550 : */
551 328 : static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
552 : const struct ldb_val *in, struct ldb_val *out)
553 : {
554 : struct prefixMapBlob *blob;
555 : enum ndr_err_code ndr_err;
556 : char *string, *line, *p, *oid;
557 : DATA_BLOB oid_blob;
558 :
559 328 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
560 :
561 328 : if (tmp_ctx == NULL) {
562 0 : return -1;
563 : }
564 :
565 328 : blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
566 328 : if (blob == NULL) {
567 0 : talloc_free(tmp_ctx);
568 0 : return -1;
569 : }
570 :
571 : /* use the switch value to detect if this is in the binary
572 : * format
573 : */
574 328 : if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
575 72 : ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
576 : (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
577 72 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
578 72 : ndr_err = ndr_push_struct_blob(out, mem_ctx,
579 : blob,
580 : (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
581 72 : talloc_free(tmp_ctx);
582 72 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
583 0 : return -1;
584 : }
585 72 : return 0;
586 : }
587 : }
588 :
589 : /* If this does not parse, then it is probably the text version, and we should try it that way */
590 256 : blob->version = PREFIX_MAP_VERSION_DSDB;
591 :
592 256 : string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
593 256 : if (string == NULL) {
594 0 : talloc_free(blob);
595 0 : return -1;
596 : }
597 :
598 256 : line = string;
599 10752 : while (line && line[0]) {
600 10496 : int error = 0;
601 :
602 10496 : p=strchr(line, ';');
603 10496 : if (p) {
604 120 : p[0] = '\0';
605 : } else {
606 10376 : p=strchr(line, '\n');
607 10376 : if (p) {
608 10373 : p[0] = '\0';
609 : }
610 : }
611 : /* allow a trailing separator */
612 10496 : if (line == p) {
613 0 : break;
614 : }
615 :
616 10496 : blob->ctr.dsdb.mappings = talloc_realloc(blob,
617 : blob->ctr.dsdb.mappings,
618 : struct drsuapi_DsReplicaOIDMapping,
619 : blob->ctr.dsdb.num_mappings+1);
620 10496 : if (!blob->ctr.dsdb.mappings) {
621 0 : talloc_free(tmp_ctx);
622 0 : return -1;
623 : }
624 :
625 10496 : blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
626 10496 : smb_strtoul(line, &oid, 10, &error, SMB_STR_STANDARD);
627 :
628 10496 : if (oid[0] != ':' || error != 0) {
629 0 : talloc_free(tmp_ctx);
630 0 : return -1;
631 : }
632 :
633 : /* we know there must be at least ":" */
634 10496 : oid++;
635 :
636 10496 : if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
637 0 : talloc_free(tmp_ctx);
638 0 : return -1;
639 : }
640 10496 : blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
641 10496 : blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
642 :
643 10496 : blob->ctr.dsdb.num_mappings++;
644 :
645 : /* Now look past the terminator we added above */
646 10496 : if (p) {
647 10493 : line = p + 1;
648 : } else {
649 3 : line = NULL;
650 : }
651 : }
652 :
653 256 : ndr_err = ndr_push_struct_blob(out, mem_ctx,
654 : blob,
655 : (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
656 256 : talloc_free(tmp_ctx);
657 256 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
658 0 : return -1;
659 : }
660 256 : return 0;
661 : }
662 :
663 : /*
664 : convert a NDR formatted blob to a ldif formatted prefixMap
665 : */
666 3 : static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
667 : const struct ldb_val *in, struct ldb_val *out)
668 : {
669 : struct prefixMapBlob *blob;
670 : enum ndr_err_code ndr_err;
671 : char *string;
672 : uint32_t i;
673 :
674 3 : if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
675 : int err;
676 : /* try to decode the blob as S4 prefixMap */
677 0 : err = ldif_write_NDR(ldb, mem_ctx, in, out,
678 : sizeof(struct prefixMapBlob),
679 : (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
680 : (ndr_print_fn_t)ndr_print_prefixMapBlob,
681 : false);
682 0 : if (0 == err) {
683 0 : return err;
684 : }
685 : /* try parsing it as Windows PrefixMap value */
686 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
687 : sizeof(struct drsuapi_MSPrefixMap_Ctr),
688 : (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
689 : (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
690 : true);
691 : }
692 :
693 3 : blob = talloc(mem_ctx, struct prefixMapBlob);
694 3 : if (blob == NULL) {
695 0 : return -1;
696 : }
697 3 : ndr_err = ndr_pull_struct_blob_all(in, blob,
698 : blob,
699 : (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
700 3 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
701 0 : goto failed;
702 : }
703 3 : if (blob->version != PREFIX_MAP_VERSION_DSDB) {
704 0 : goto failed;
705 : }
706 3 : string = talloc_strdup(mem_ctx, "");
707 3 : if (string == NULL) {
708 0 : goto failed;
709 : }
710 :
711 126 : for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
712 : DATA_BLOB oid_blob;
713 123 : char *partial_oid = NULL;
714 :
715 123 : if (i > 0) {
716 120 : talloc_asprintf_addbuf(&string, ";");
717 : }
718 :
719 123 : oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
720 123 : blob->ctr.dsdb.mappings[i].oid.length);
721 123 : if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
722 0 : DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
723 : blob->ctr.dsdb.mappings[i].id_prefix));
724 0 : goto failed;
725 : }
726 123 : talloc_asprintf_addbuf(&string, "%u:%s",
727 123 : blob->ctr.dsdb.mappings[i].id_prefix,
728 : partial_oid);
729 123 : talloc_free(discard_const(partial_oid));
730 : }
731 :
732 3 : talloc_free(blob);
733 3 : *out = data_blob_string_const(string);
734 3 : return 0;
735 :
736 0 : failed:
737 0 : talloc_free(blob);
738 0 : return -1;
739 : }
740 :
741 0 : static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
742 : {
743 0 : if (v->length < 4) {
744 0 : return true;
745 : }
746 :
747 0 : if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
748 0 : return false;
749 : }
750 :
751 0 : return true;
752 : }
753 :
754 : /*
755 : canonicalise a prefixMap
756 : */
757 0 : static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
758 : const struct ldb_val *in, struct ldb_val *out)
759 : {
760 0 : if (ldif_comparision_prefixMap_isString(in)) {
761 0 : return ldif_read_prefixMap(ldb, mem_ctx, in, out);
762 : }
763 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
764 : }
765 :
766 0 : static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
767 : const struct ldb_val *v1,
768 : const struct ldb_val *v2)
769 : {
770 0 : return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
771 : v1, v2);
772 : }
773 :
774 : /* length limited conversion of a ldb_val to a int32_t */
775 2159733 : static int val_to_int32(const struct ldb_val *in, int32_t *v)
776 : {
777 : char *end;
778 : char buf[64];
779 :
780 : /* make sure we don't read past the end of the data */
781 2159733 : if (in->length > sizeof(buf)-1) {
782 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
783 : }
784 2159733 : strncpy(buf, (char *)in->data, in->length);
785 2159733 : buf[in->length] = 0;
786 :
787 : /* We've to use "strtoll" here to have the intended overflows.
788 : * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
789 2159733 : *v = (int32_t) strtoll(buf, &end, 0);
790 2159733 : if (*end != 0) {
791 22 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
792 : }
793 2159711 : return LDB_SUCCESS;
794 : }
795 :
796 : /* length limited conversion of a ldb_val to a int64_t */
797 1379 : static int val_to_int64(const struct ldb_val *in, int64_t *v)
798 : {
799 : char *end;
800 : char buf[64];
801 :
802 : /* make sure we don't read past the end of the data */
803 1379 : if (in->length > sizeof(buf)-1) {
804 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
805 : }
806 1379 : strncpy(buf, (char *)in->data, in->length);
807 1379 : buf[in->length] = 0;
808 :
809 1379 : *v = (int64_t) strtoll(buf, &end, 0);
810 1379 : if (*end != 0) {
811 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
812 : }
813 1379 : return LDB_SUCCESS;
814 : }
815 :
816 : /* Canonicalisation of two 32-bit integers */
817 1084262 : static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
818 : const struct ldb_val *in, struct ldb_val *out)
819 : {
820 : int32_t i;
821 : int ret;
822 :
823 1084262 : ret = val_to_int32(in, &i);
824 1084262 : if (ret != LDB_SUCCESS) {
825 2 : return ret;
826 : }
827 1084260 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
828 1084260 : if (out->data == NULL) {
829 0 : ldb_oom(ldb);
830 0 : return LDB_ERR_OPERATIONS_ERROR;
831 : }
832 1084260 : out->length = strlen((char *)out->data);
833 1084260 : return 0;
834 : }
835 :
836 : /*
837 : * Lexicographically sorted representation for a 32-bit integer
838 : *
839 : * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
840 : * n o p
841 : *
842 : * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
843 : * corresponding documentation for 64-bit integers.
844 : *
845 : * The same rules apply but use INT32_MIN and INT32_MAX.
846 : *
847 : * String representation padding is done to 10 characters.
848 : *
849 : * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
850 : *
851 : */
852 491087 : static int ldif_index_format_int32(struct ldb_context *ldb,
853 : void *mem_ctx,
854 : const struct ldb_val *in,
855 : struct ldb_val *out)
856 : {
857 : int32_t i;
858 : int ret;
859 : char prefix;
860 : size_t len;
861 :
862 491087 : ret = val_to_int32(in, &i);
863 491087 : if (ret != LDB_SUCCESS) {
864 0 : return ret;
865 : }
866 :
867 491087 : if (i < 0) {
868 : /*
869 : * i is negative, so this is subtraction rather than
870 : * wrap-around.
871 : */
872 45550 : prefix = 'n';
873 45550 : i = INT32_MAX + i + 1;
874 445537 : } else if (i > 0) {
875 445525 : prefix = 'p';
876 : } else {
877 12 : prefix = 'o';
878 : }
879 :
880 491087 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
881 491087 : if (out->data == NULL) {
882 0 : ldb_oom(ldb);
883 0 : return LDB_ERR_OPERATIONS_ERROR;
884 : }
885 :
886 491087 : len = talloc_array_length(out->data) - 1;
887 491087 : if (len != 11) {
888 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
889 : __location__ ": expected index format str %s to"
890 : " have length 11 but got %zu",
891 0 : (char*)out->data, len);
892 0 : return LDB_ERR_OPERATIONS_ERROR;
893 : }
894 :
895 491087 : out->length = 11;
896 491087 : return 0;
897 : }
898 :
899 : /* Comparison of two 32-bit integers */
900 292192 : static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
901 : const struct ldb_val *v1, const struct ldb_val *v2)
902 : {
903 292192 : int32_t i1=0, i2=0;
904 292192 : val_to_int32(v1, &i1);
905 292192 : val_to_int32(v2, &i2);
906 292192 : if (i1 == i2) return 0;
907 187373 : return i1 > i2? 1 : -1;
908 : }
909 :
910 : /* Canonicalisation of two 64-bit integers */
911 795 : static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
912 : const struct ldb_val *in, struct ldb_val *out)
913 : {
914 : int64_t i;
915 : int ret;
916 :
917 795 : ret = val_to_int64(in, &i);
918 795 : if (ret != LDB_SUCCESS) {
919 0 : return ret;
920 : }
921 795 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
922 795 : if (out->data == NULL) {
923 0 : ldb_oom(ldb);
924 0 : return LDB_ERR_OPERATIONS_ERROR;
925 : }
926 795 : out->length = strlen((char *)out->data);
927 795 : return 0;
928 : }
929 :
930 : /* Comparison of two 64-bit integers */
931 214 : static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
932 : const struct ldb_val *v1, const struct ldb_val *v2)
933 : {
934 214 : int64_t i1=0, i2=0;
935 214 : val_to_int64(v1, &i1);
936 214 : val_to_int64(v2, &i2);
937 214 : if (i1 == i2) return 0;
938 0 : return i1 > i2? 1 : -1;
939 : }
940 :
941 : /*
942 : convert a NDR formatted blob to a ldif formatted repsFromTo
943 : */
944 1 : static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
945 : const struct ldb_val *in, struct ldb_val *out)
946 : {
947 1 : return ldif_write_NDR(ldb, mem_ctx, in, out,
948 : sizeof(struct repsFromToBlob),
949 : (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
950 : (ndr_print_fn_t)ndr_print_repsFromToBlob,
951 : true);
952 : }
953 :
954 : /*
955 : convert a NDR formatted blob to a ldif formatted replPropertyMetaData
956 : */
957 12 : static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
958 : const struct ldb_val *in, struct ldb_val *out)
959 : {
960 12 : return ldif_write_NDR(ldb, mem_ctx, in, out,
961 : sizeof(struct replPropertyMetaDataBlob),
962 : (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
963 : (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
964 : true);
965 : }
966 :
967 : /*
968 : convert a NDR formatted blob to a ldif formatted replUpToDateVector
969 : */
970 1 : static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
971 : const struct ldb_val *in, struct ldb_val *out)
972 : {
973 1 : return ldif_write_NDR(ldb, mem_ctx, in, out,
974 : sizeof(struct replUpToDateVectorBlob),
975 : (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
976 : (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
977 : true);
978 : }
979 :
980 0 : static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
981 : const struct ldb_val *in, struct ldb_val *out,
982 : size_t struct_size,
983 : ndr_pull_flags_fn_t pull_fn,
984 : ndr_print_fn_t print_fn,
985 : bool mask_errors)
986 : {
987 0 : uint8_t *p = NULL;
988 : enum ndr_err_code err;
989 0 : struct dsdb_dn *dsdb_dn = NULL;
990 0 : char *dn_str = NULL;
991 0 : char *str = NULL;
992 :
993 0 : if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
994 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
995 : }
996 :
997 0 : dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
998 0 : if (dsdb_dn == NULL) {
999 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1000 : }
1001 :
1002 0 : p = talloc_size(dsdb_dn, struct_size);
1003 0 : if (p == NULL) {
1004 0 : TALLOC_FREE(dsdb_dn);
1005 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1006 : }
1007 :
1008 0 : err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
1009 0 : if (err != NDR_ERR_SUCCESS) {
1010 : /* fail in not in mask_error mode */
1011 0 : if (!mask_errors) {
1012 0 : return -1;
1013 : }
1014 0 : TALLOC_FREE(dsdb_dn);
1015 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1016 : }
1017 :
1018 0 : dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
1019 0 : if (dn_str == NULL) {
1020 0 : TALLOC_FREE(dsdb_dn);
1021 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1022 : }
1023 :
1024 0 : str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
1025 0 : TALLOC_FREE(dsdb_dn);
1026 0 : if (str == NULL) {
1027 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1028 : }
1029 :
1030 0 : *out = data_blob_string_const(str);
1031 0 : return 0;
1032 : }
1033 :
1034 0 : static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
1035 : const struct ldb_val *in, struct ldb_val *out)
1036 : {
1037 0 : return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
1038 : sizeof(struct replPropertyMetaData1),
1039 : (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
1040 : (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
1041 : true);
1042 : }
1043 :
1044 : /*
1045 : convert a NDR formatted blob to a ldif formatted dnsRecord
1046 : */
1047 572 : static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
1048 : const struct ldb_val *in, struct ldb_val *out)
1049 : {
1050 572 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1051 : sizeof(struct dnsp_DnssrvRpcRecord),
1052 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
1053 : (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
1054 : true);
1055 : }
1056 :
1057 : /*
1058 : convert a NDR formatted blob to a ldif formatted dnsProperty
1059 : */
1060 154 : static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
1061 : const struct ldb_val *in, struct ldb_val *out)
1062 : {
1063 154 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1064 : sizeof(struct dnsp_DnsProperty),
1065 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
1066 : (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
1067 : true);
1068 : }
1069 :
1070 : /*
1071 : convert a NDR formatted blob of a supplementalCredentials into text
1072 : */
1073 45 : static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
1074 : const struct ldb_val *in, struct ldb_val *out)
1075 : {
1076 45 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1077 : sizeof(struct supplementalCredentialsBlob),
1078 : (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
1079 : (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
1080 : true);
1081 : }
1082 :
1083 : /*
1084 : convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
1085 : */
1086 0 : static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
1087 : const struct ldb_val *in, struct ldb_val *out)
1088 : {
1089 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1090 : sizeof(struct trustAuthInOutBlob),
1091 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
1092 : (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
1093 : true);
1094 : }
1095 :
1096 : /*
1097 : convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
1098 : */
1099 0 : static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
1100 : const struct ldb_val *in, struct ldb_val *out)
1101 : {
1102 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1103 : sizeof(struct ForestTrustInfo),
1104 : (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
1105 : (ndr_print_fn_t)ndr_print_ForestTrustInfo,
1106 : true);
1107 : }
1108 : /*
1109 : convert a NDR formatted blob of a partialAttributeSet into text
1110 : */
1111 0 : static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
1112 : const struct ldb_val *in, struct ldb_val *out)
1113 : {
1114 0 : return ldif_write_NDR(ldb, mem_ctx, in, out,
1115 : sizeof(struct partialAttributeSetBlob),
1116 : (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
1117 : (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
1118 : true);
1119 : }
1120 :
1121 :
1122 6551221 : static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
1123 : const struct ldb_val *in, struct ldb_val *out)
1124 : {
1125 6551221 : *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
1126 6551221 : if (!out->data) {
1127 0 : return -1;
1128 : }
1129 6551221 : return 0;
1130 : }
1131 :
1132 : /*
1133 : compare two dns
1134 : */
1135 0 : static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
1136 : const struct ldb_val *v1, const struct ldb_val *v2)
1137 : {
1138 0 : struct ldb_dn *dn1 = NULL, *dn2 = NULL;
1139 : int ret;
1140 :
1141 0 : if (dsdb_dn_is_deleted_val(v1)) {
1142 : /* If the DN is deleted, then we can't search for it */
1143 0 : return -1;
1144 : }
1145 :
1146 0 : if (dsdb_dn_is_deleted_val(v2)) {
1147 : /* If the DN is deleted, then we can't search for it */
1148 0 : return -1;
1149 : }
1150 :
1151 0 : dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
1152 0 : if ( ! ldb_dn_validate(dn1)) return -1;
1153 :
1154 0 : dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
1155 0 : if ( ! ldb_dn_validate(dn2)) {
1156 0 : talloc_free(dn1);
1157 0 : return -1;
1158 : }
1159 :
1160 0 : ret = ldb_dn_compare(dn1, dn2);
1161 :
1162 0 : talloc_free(dn1);
1163 0 : talloc_free(dn2);
1164 0 : return ret;
1165 : }
1166 :
1167 14052 : static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
1168 : const struct ldb_val *in, struct ldb_val *out)
1169 : {
1170 : struct ldb_dn *dn;
1171 14052 : int ret = -1;
1172 :
1173 14052 : out->length = 0;
1174 14052 : out->data = NULL;
1175 :
1176 14052 : dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
1177 14052 : if ( ! ldb_dn_validate(dn)) {
1178 0 : return LDB_ERR_INVALID_DN_SYNTAX;
1179 : }
1180 :
1181 : /* By including the RMD_FLAGS of a deleted DN, we ensure it
1182 : * does not casually match a not deleted DN */
1183 14052 : if (dsdb_dn_is_deleted_val(in)) {
1184 0 : out->data = (uint8_t *)talloc_asprintf(mem_ctx,
1185 : "<RMD_FLAGS=%u>%s",
1186 : dsdb_dn_val_rmd_flags(in),
1187 : ldb_dn_get_casefold(dn));
1188 : } else {
1189 14052 : out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
1190 : }
1191 :
1192 14052 : if (out->data == NULL) {
1193 0 : goto done;
1194 : }
1195 14052 : out->length = strlen((char *)out->data);
1196 :
1197 14052 : ret = 0;
1198 :
1199 14052 : done:
1200 14052 : talloc_free(dn);
1201 :
1202 14052 : return ret;
1203 : }
1204 :
1205 :
1206 : /*
1207 : write a 64 bit 2-part range
1208 : */
1209 156 : static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
1210 : const struct ldb_val *in, struct ldb_val *out)
1211 : {
1212 : int64_t v;
1213 : int ret;
1214 156 : ret = val_to_int64(in, &v);
1215 156 : if (ret != LDB_SUCCESS) {
1216 0 : return ret;
1217 : }
1218 312 : out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
1219 156 : (unsigned long)(v&0xFFFFFFFF),
1220 156 : (unsigned long)(v>>32));
1221 156 : if (out->data == NULL) {
1222 0 : ldb_oom(ldb);
1223 0 : return LDB_ERR_OPERATIONS_ERROR;
1224 : }
1225 156 : out->length = strlen((char *)out->data);
1226 156 : return LDB_SUCCESS;
1227 : }
1228 :
1229 : /*
1230 : read a 64 bit 2-part range
1231 : */
1232 229 : static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
1233 : const struct ldb_val *in, struct ldb_val *out)
1234 : {
1235 : unsigned long high, low;
1236 : char buf[64];
1237 :
1238 229 : if (memchr(in->data, '-', in->length) == NULL) {
1239 0 : return ldb_handler_copy(ldb, mem_ctx, in, out);
1240 : }
1241 :
1242 229 : if (in->length > sizeof(buf)-1) {
1243 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1244 : }
1245 229 : strncpy(buf, (const char *)in->data, in->length);
1246 229 : buf[in->length] = 0;
1247 :
1248 229 : if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
1249 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1250 : }
1251 :
1252 458 : out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
1253 229 : (unsigned long long)(((uint64_t)high)<<32) | (low));
1254 :
1255 229 : if (out->data == NULL) {
1256 0 : ldb_oom(ldb);
1257 0 : return LDB_ERR_OPERATIONS_ERROR;
1258 : }
1259 229 : out->length = strlen((char *)out->data);
1260 229 : return LDB_SUCCESS;
1261 : }
1262 :
1263 : /*
1264 : when this operator_fn is set for a syntax, the backend calls is in
1265 : preference to the comparison function. We are told the exact
1266 : comparison operation that is needed, and we can return errors
1267 : */
1268 14606733 : static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1269 : const struct ldb_schema_attribute *a,
1270 : const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1271 : {
1272 14606733 : switch (operation) {
1273 0 : case LDB_OP_AND:
1274 : case LDB_OP_OR:
1275 : case LDB_OP_NOT:
1276 : case LDB_OP_SUBSTRING:
1277 : case LDB_OP_APPROX:
1278 : case LDB_OP_EXTENDED:
1279 : /* handled in the backends */
1280 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
1281 :
1282 14464522 : case LDB_OP_GREATER:
1283 : case LDB_OP_LESS:
1284 : case LDB_OP_EQUALITY:
1285 : {
1286 14464522 : TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1287 : int ret;
1288 14464522 : if (tmp_ctx == NULL) {
1289 0 : return ldb_oom(ldb);
1290 : }
1291 14464522 : ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
1292 14464522 : talloc_free(tmp_ctx);
1293 14464522 : if (operation == LDB_OP_GREATER) {
1294 188 : *matched = (ret >= 0);
1295 14464334 : } else if (operation == LDB_OP_LESS) {
1296 146 : *matched = (ret <= 0);
1297 : } else {
1298 14464188 : *matched = (ret == 0);
1299 : }
1300 14464522 : return LDB_SUCCESS;
1301 : }
1302 :
1303 142211 : case LDB_OP_PRESENT:
1304 142211 : *matched = true;
1305 142211 : return LDB_SUCCESS;
1306 : }
1307 :
1308 : /* we shouldn't get here */
1309 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
1310 : }
1311 :
1312 : /*
1313 : compare two binary objects. This is correct for sorting as the sort order is:
1314 :
1315 : a
1316 : aa
1317 : b
1318 : bb
1319 :
1320 : rather than ldb_comparison_binary() which is:
1321 :
1322 : a
1323 : b
1324 : aa
1325 : bb
1326 :
1327 : */
1328 67513 : static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
1329 : const struct ldb_val *v1, const struct ldb_val *v2)
1330 : {
1331 67513 : return data_blob_cmp(v1, v2);
1332 : }
1333 :
1334 : /*
1335 : when this operator_fn is set for a syntax, the backend calls is in
1336 : preference to the comparison function. We are told the exact
1337 : comparison operation that is needed, and we can return errors.
1338 :
1339 : This mode optimises for ldb_comparison_binary() if we need equality,
1340 : as this should be faster as it can do a length-check first.
1341 : */
1342 31 : static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
1343 : const struct ldb_schema_attribute *a,
1344 : const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1345 : {
1346 31 : if (operation == LDB_OP_EQUALITY) {
1347 25 : *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
1348 25 : return LDB_SUCCESS;
1349 : }
1350 6 : return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1351 : }
1352 :
1353 : /*
1354 : see if two DNs match, comparing first by GUID, then by SID, and
1355 : finally by string components
1356 : */
1357 247919 : static int samba_dn_extended_match(struct ldb_context *ldb,
1358 : const struct ldb_val *v1,
1359 : const struct ldb_val *v2,
1360 : bool *matched)
1361 : {
1362 : TALLOC_CTX *tmp_ctx;
1363 : struct ldb_dn *dn1, *dn2;
1364 : const struct ldb_val *guid1, *guid2, *sid1, *sid2;
1365 : uint32_t rmd_flags1, rmd_flags2;
1366 :
1367 247919 : tmp_ctx = talloc_new(ldb);
1368 :
1369 247919 : dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
1370 247919 : dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
1371 247919 : if (!dn1 || !dn2) {
1372 : /* couldn't parse as DN's */
1373 0 : talloc_free(tmp_ctx);
1374 0 : (*matched) = false;
1375 0 : return LDB_SUCCESS;
1376 : }
1377 :
1378 247919 : rmd_flags1 = dsdb_dn_rmd_flags(dn1);
1379 247919 : rmd_flags2 = dsdb_dn_rmd_flags(dn2);
1380 :
1381 247919 : if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
1382 : (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
1383 : /* only match if they have the same deletion status */
1384 1079 : talloc_free(tmp_ctx);
1385 1079 : (*matched) = false;
1386 1079 : return LDB_SUCCESS;
1387 : }
1388 :
1389 :
1390 246840 : guid1 = ldb_dn_get_extended_component(dn1, "GUID");
1391 246840 : guid2 = ldb_dn_get_extended_component(dn2, "GUID");
1392 246840 : if (guid1 && guid2) {
1393 199668 : (*matched) = (data_blob_cmp(guid1, guid2) == 0);
1394 199668 : talloc_free(tmp_ctx);
1395 199668 : return LDB_SUCCESS;
1396 : }
1397 :
1398 47172 : sid1 = ldb_dn_get_extended_component(dn1, "SID");
1399 47172 : sid2 = ldb_dn_get_extended_component(dn2, "SID");
1400 47172 : if (sid1 && sid2) {
1401 8694 : (*matched) = (data_blob_cmp(sid1, sid2) == 0);
1402 8694 : talloc_free(tmp_ctx);
1403 8694 : return LDB_SUCCESS;
1404 : }
1405 :
1406 38478 : (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
1407 :
1408 38478 : talloc_free(tmp_ctx);
1409 38478 : return LDB_SUCCESS;
1410 : }
1411 :
1412 : /*
1413 : special operation for DNs, to take account of the RMD_FLAGS deleted bit
1414 : */
1415 248363 : static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
1416 : const struct ldb_schema_attribute *a,
1417 : const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
1418 : {
1419 248363 : if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
1420 : /* If the DN is deleted, then we can't search for it */
1421 :
1422 : /* should this be for equality too? */
1423 0 : *matched = false;
1424 0 : return LDB_SUCCESS;
1425 : }
1426 :
1427 496282 : if (operation == LDB_OP_EQUALITY &&
1428 247919 : samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
1429 247919 : return LDB_SUCCESS;
1430 : }
1431 :
1432 444 : return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
1433 : }
1434 :
1435 :
1436 : static const struct ldb_schema_syntax samba_syntaxes[] = {
1437 : {
1438 : .name = LDB_SYNTAX_SAMBA_SID,
1439 : .ldif_read_fn = ldif_read_objectSid,
1440 : .ldif_write_fn = ldif_write_objectSid,
1441 : .canonicalise_fn = ldif_canonicalise_objectSid,
1442 : .comparison_fn = ldif_comparison_objectSid,
1443 : .operator_fn = samba_syntax_operator_fn
1444 : },{
1445 : .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1446 : .ldif_read_fn = ldif_read_ntSecurityDescriptor,
1447 : .ldif_write_fn = ldif_write_ntSecurityDescriptor,
1448 : .canonicalise_fn = ldb_handler_copy,
1449 : .comparison_fn = samba_ldb_comparison_binary,
1450 : .operator_fn = samba_syntax_binary_operator_fn
1451 : },{
1452 : .name = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
1453 : .ldif_read_fn = ldb_handler_copy,
1454 : .ldif_write_fn = ldif_write_sddlSecurityDescriptor,
1455 : .canonicalise_fn = ldb_handler_fold,
1456 : .comparison_fn = ldb_comparison_fold,
1457 : .operator_fn = samba_syntax_operator_fn
1458 : },{
1459 : .name = LDB_SYNTAX_SAMBA_GUID,
1460 : .ldif_read_fn = ldif_read_objectGUID,
1461 : .ldif_write_fn = ldif_write_objectGUID,
1462 : .canonicalise_fn = ldif_canonicalise_objectGUID,
1463 : .comparison_fn = ldif_comparison_objectGUID,
1464 : .operator_fn = samba_syntax_operator_fn
1465 : },{
1466 : .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
1467 : .ldif_read_fn = ldb_handler_copy,
1468 : .ldif_write_fn = ldb_handler_copy,
1469 : .canonicalise_fn = ldif_canonicalise_objectCategory,
1470 : .comparison_fn = ldif_comparison_objectCategory,
1471 : .operator_fn = samba_syntax_operator_fn
1472 : },{
1473 : .name = LDB_SYNTAX_SAMBA_SCHEMAINFO,
1474 : .ldif_read_fn = ldb_handler_copy,
1475 : .ldif_write_fn = ldif_write_schemaInfo,
1476 : .canonicalise_fn = ldb_handler_copy,
1477 : .comparison_fn = samba_ldb_comparison_binary,
1478 : .operator_fn = samba_syntax_binary_operator_fn
1479 : },{
1480 : .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
1481 : .ldif_read_fn = ldif_read_prefixMap,
1482 : .ldif_write_fn = ldif_write_prefixMap,
1483 : .canonicalise_fn = ldif_canonicalise_prefixMap,
1484 : .comparison_fn = ldif_comparison_prefixMap,
1485 : .operator_fn = samba_syntax_operator_fn
1486 : },{
1487 : .name = LDB_SYNTAX_SAMBA_INT32,
1488 : .ldif_read_fn = ldb_handler_copy,
1489 : .ldif_write_fn = ldb_handler_copy,
1490 : .canonicalise_fn = ldif_canonicalise_int32,
1491 : .index_format_fn = ldif_index_format_int32,
1492 : .comparison_fn = ldif_comparison_int32,
1493 : .operator_fn = samba_syntax_operator_fn
1494 : },{
1495 : .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
1496 : .ldif_read_fn = ldb_handler_copy,
1497 : .ldif_write_fn = ldif_write_repsFromTo,
1498 : .canonicalise_fn = ldb_handler_copy,
1499 : .comparison_fn = samba_ldb_comparison_binary,
1500 : .operator_fn = samba_syntax_binary_operator_fn
1501 : },{
1502 : .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
1503 : .ldif_read_fn = ldb_handler_copy,
1504 : .ldif_write_fn = ldif_write_replPropertyMetaData,
1505 : .canonicalise_fn = ldb_handler_copy,
1506 : .comparison_fn = samba_ldb_comparison_binary,
1507 : .operator_fn = samba_syntax_binary_operator_fn
1508 : },{
1509 : .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
1510 : .ldif_read_fn = ldb_handler_copy,
1511 : .ldif_write_fn = ldif_write_replUpToDateVector,
1512 : .canonicalise_fn = ldb_handler_copy,
1513 : .comparison_fn = samba_ldb_comparison_binary,
1514 : .operator_fn = samba_syntax_binary_operator_fn
1515 : },{
1516 : .name = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
1517 : .ldif_read_fn = ldb_handler_copy,
1518 : .ldif_write_fn = ldif_write_msDS_RevealedUsers,
1519 : .canonicalise_fn = dsdb_dn_binary_canonicalise,
1520 : .comparison_fn = dsdb_dn_binary_comparison,
1521 : .operator_fn = samba_syntax_operator_fn
1522 : },{
1523 : .name = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
1524 : .ldif_read_fn = ldb_handler_copy,
1525 : .ldif_write_fn = ldif_write_trustAuthInOutBlob,
1526 : .canonicalise_fn = ldb_handler_copy,
1527 : .comparison_fn = samba_ldb_comparison_binary,
1528 : .operator_fn = samba_syntax_binary_operator_fn
1529 : },{
1530 : .name = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
1531 : .ldif_read_fn = ldb_handler_copy,
1532 : .ldif_write_fn = ldif_write_ForestTrustInfo,
1533 : .canonicalise_fn = ldb_handler_copy,
1534 : .comparison_fn = samba_ldb_comparison_binary,
1535 : .operator_fn = samba_syntax_binary_operator_fn
1536 : },{
1537 : .name = DSDB_SYNTAX_BINARY_DN,
1538 : .ldif_read_fn = ldb_handler_copy,
1539 : .ldif_write_fn = ldb_handler_copy,
1540 : .canonicalise_fn = dsdb_dn_binary_canonicalise,
1541 : .comparison_fn = dsdb_dn_binary_comparison,
1542 : .operator_fn = samba_syntax_operator_fn
1543 : },{
1544 : .name = DSDB_SYNTAX_STRING_DN,
1545 : .ldif_read_fn = ldb_handler_copy,
1546 : .ldif_write_fn = ldb_handler_copy,
1547 : .canonicalise_fn = dsdb_dn_string_canonicalise,
1548 : .comparison_fn = dsdb_dn_string_comparison,
1549 : .operator_fn = samba_syntax_operator_fn
1550 : },{
1551 : .name = LDB_SYNTAX_DN,
1552 : .ldif_read_fn = ldb_handler_copy,
1553 : .ldif_write_fn = ldb_handler_copy,
1554 : .canonicalise_fn = samba_ldb_dn_link_canonicalise,
1555 : .comparison_fn = samba_ldb_dn_link_comparison,
1556 : .operator_fn = samba_syntax_operator_dn
1557 : },{
1558 : .name = LDB_SYNTAX_SAMBA_RANGE64,
1559 : .ldif_read_fn = ldif_read_range64,
1560 : .ldif_write_fn = ldif_write_range64,
1561 : .canonicalise_fn = ldif_canonicalise_int64,
1562 : .comparison_fn = ldif_comparison_int64,
1563 : .operator_fn = samba_syntax_operator_fn
1564 : },{
1565 : .name = LDB_SYNTAX_SAMBA_DNSRECORD,
1566 : .ldif_read_fn = ldb_handler_copy,
1567 : .ldif_write_fn = ldif_write_dnsRecord,
1568 : .canonicalise_fn = ldb_handler_copy,
1569 : .comparison_fn = samba_ldb_comparison_binary,
1570 : .operator_fn = samba_syntax_binary_operator_fn
1571 : },{
1572 : .name = LDB_SYNTAX_SAMBA_DNSPROPERTY,
1573 : .ldif_read_fn = ldb_handler_copy,
1574 : .ldif_write_fn = ldif_write_dnsProperty,
1575 : .canonicalise_fn = ldb_handler_copy,
1576 : .comparison_fn = samba_ldb_comparison_binary,
1577 : .operator_fn = samba_syntax_binary_operator_fn
1578 : },{
1579 : .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
1580 : .ldif_read_fn = ldb_handler_copy,
1581 : .ldif_write_fn = ldif_write_supplementalCredentialsBlob,
1582 : .canonicalise_fn = ldb_handler_copy,
1583 : .comparison_fn = samba_ldb_comparison_binary,
1584 : .operator_fn = samba_syntax_binary_operator_fn
1585 : },{
1586 : .name = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
1587 : .ldif_read_fn = ldb_handler_copy,
1588 : .ldif_write_fn = ldif_write_partialAttributeSet,
1589 : .canonicalise_fn = ldb_handler_copy,
1590 : .comparison_fn = samba_ldb_comparison_binary,
1591 : .operator_fn = samba_syntax_binary_operator_fn
1592 : },{
1593 : .name = LDB_SYNTAX_SAMBA_OCTET_STRING,
1594 : .ldif_read_fn = ldb_handler_copy,
1595 : .ldif_write_fn = ldb_handler_copy,
1596 : .canonicalise_fn = ldb_handler_copy,
1597 : .comparison_fn = samba_ldb_comparison_binary,
1598 : .operator_fn = samba_syntax_binary_operator_fn
1599 : }
1600 : };
1601 :
1602 : static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
1603 : {
1604 : .name = "SID",
1605 : .read_fn = extended_dn_read_SID,
1606 : .write_clear_fn = ldif_write_objectSid,
1607 : .write_hex_fn = extended_dn_write_hex
1608 : },{
1609 : .name = "GUID",
1610 : .read_fn = extended_dn_read_GUID,
1611 : .write_clear_fn = ldif_write_objectGUID,
1612 : .write_hex_fn = extended_dn_write_hex
1613 : },{
1614 : .name = "WKGUID",
1615 : .read_fn = ldb_handler_copy,
1616 : .write_clear_fn = ldb_handler_copy,
1617 : .write_hex_fn = ldb_handler_copy
1618 : },{
1619 : .name = "RMD_INVOCID",
1620 : .read_fn = extended_dn_read_GUID,
1621 : .write_clear_fn = ldif_write_objectGUID,
1622 : .write_hex_fn = extended_dn_write_hex
1623 : },{
1624 : .name = "RMD_FLAGS",
1625 : .read_fn = ldb_handler_copy,
1626 : .write_clear_fn = ldb_handler_copy,
1627 : .write_hex_fn = ldb_handler_copy
1628 : },{
1629 : .name = "RMD_ADDTIME",
1630 : .read_fn = ldb_handler_copy,
1631 : .write_clear_fn = ldb_handler_copy,
1632 : .write_hex_fn = ldb_handler_copy
1633 : },{
1634 : .name = "RMD_CHANGETIME",
1635 : .read_fn = ldb_handler_copy,
1636 : .write_clear_fn = ldb_handler_copy,
1637 : .write_hex_fn = ldb_handler_copy
1638 : },{
1639 : .name = "RMD_LOCAL_USN",
1640 : .read_fn = ldb_handler_copy,
1641 : .write_clear_fn = ldb_handler_copy,
1642 : .write_hex_fn = ldb_handler_copy
1643 : },{
1644 : .name = "RMD_ORIGINATING_USN",
1645 : .read_fn = ldb_handler_copy,
1646 : .write_clear_fn = ldb_handler_copy,
1647 : .write_hex_fn = ldb_handler_copy
1648 : },{
1649 : .name = "RMD_VERSION",
1650 : .read_fn = ldb_handler_copy,
1651 : .write_clear_fn = ldb_handler_copy,
1652 : .write_hex_fn = ldb_handler_copy
1653 : }
1654 : };
1655 :
1656 : /* TODO: Should be dynamic at some point */
1657 : static const struct {
1658 : const char *name;
1659 : const char *syntax;
1660 : } samba_attributes[] = {
1661 : { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
1662 : { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 },
1663 : { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
1664 : { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO },
1665 : { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
1666 : { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
1667 : { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
1668 : { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
1669 : { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
1670 : { "msDS-RevealedUsers", LDB_SYNTAX_SAMBA_REVEALEDUSERS },
1671 : { "trustAuthIncoming", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1672 : { "trustAuthOutgoing", LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
1673 : { "msDS-TrustForestTrustInfo", LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
1674 : { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1675 : { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 },
1676 : { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 },
1677 : { "defaultSecurityDescriptor", LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
1678 :
1679 : /*
1680 : * these are extracted by searching
1681 : * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
1682 : *
1683 : * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
1684 : * adminDescription: For a Central Access Policy, this attribute defines a GUID t
1685 : * hat can be used to identify the set of policies when applied to a resource.
1686 : * Until we see a msAuthz-CentralAccessPolicyID value on a windows
1687 : * server, we ignore it here.
1688 : */
1689 : { "mS-DS-CreatorSID", LDB_SYNTAX_SAMBA_SID },
1690 : { "msDS-QuotaTrustee", LDB_SYNTAX_SAMBA_SID },
1691 : { "objectSid", LDB_SYNTAX_SAMBA_SID },
1692 : { "tokenGroups", LDB_SYNTAX_SAMBA_SID },
1693 : { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
1694 : { "tokenGroupsNoGCAcceptable", LDB_SYNTAX_SAMBA_SID },
1695 : { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
1696 : { "sIDHistory", LDB_SYNTAX_SAMBA_SID },
1697 : { "syncWithSID", LDB_SYNTAX_SAMBA_SID },
1698 :
1699 : /*
1700 : * these are extracted by searching
1701 : * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
1702 : */
1703 : { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
1704 : { "categoryId", LDB_SYNTAX_SAMBA_GUID },
1705 : { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID },
1706 : { "currMachineId", LDB_SYNTAX_SAMBA_GUID },
1707 : { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
1708 : { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
1709 : { "implementedCategories", LDB_SYNTAX_SAMBA_GUID },
1710 : { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID },
1711 : { "msDS-GenerationId", LDB_SYNTAX_SAMBA_GUID },
1712 : { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID },
1713 : { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID },
1714 : { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID },
1715 : { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID },
1716 : { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID },
1717 : { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID },
1718 : { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID },
1719 : { "mSMQSites", LDB_SYNTAX_SAMBA_GUID },
1720 : { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
1721 : { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
1722 : { "pKTGuid", LDB_SYNTAX_SAMBA_GUID },
1723 : { "requiredCategories", LDB_SYNTAX_SAMBA_GUID },
1724 : { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
1725 : { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
1726 : { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1727 : { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1728 : { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID },
1729 : { "msSPP-CSVLKSkuId", LDB_SYNTAX_SAMBA_GUID },
1730 : { "msSPP-KMSIds", LDB_SYNTAX_SAMBA_GUID },
1731 :
1732 : /*
1733 : * these are known to be GUIDs
1734 : */
1735 : { "invocationId", LDB_SYNTAX_SAMBA_GUID },
1736 : { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
1737 :
1738 : /* These NDR encoded things we want to be able to read with --show-binary */
1739 : { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD },
1740 : { "dNSProperty", LDB_SYNTAX_SAMBA_DNSPROPERTY },
1741 : { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
1742 : { "partialAttributeSet", LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
1743 : };
1744 :
1745 43835550 : const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
1746 : {
1747 : unsigned int j;
1748 43835550 : const struct ldb_schema_syntax *s = NULL;
1749 :
1750 665929568 : for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
1751 650713426 : if (strcmp(name, samba_syntaxes[j].name) == 0) {
1752 28619408 : s = &samba_syntaxes[j];
1753 28619408 : break;
1754 : }
1755 : }
1756 43835550 : return s;
1757 : }
1758 :
1759 30044550 : const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
1760 : {
1761 : unsigned int j;
1762 30044550 : const struct ldb_schema_syntax *s = NULL;
1763 :
1764 1795058374 : for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
1765 1766248655 : if (strcmp(samba_attributes[j].name, name) == 0) {
1766 1234831 : s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
1767 1234831 : break;
1768 : }
1769 : }
1770 :
1771 30044550 : return s;
1772 : }
1773 :
1774 : static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
1775 : "priorSecret", NULL};
1776 :
1777 : /*
1778 : register the samba ldif handlers
1779 : */
1780 347311 : int ldb_register_samba_handlers(struct ldb_context *ldb)
1781 : {
1782 : unsigned int i;
1783 : int ret;
1784 :
1785 347311 : if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
1786 117461 : return LDB_SUCCESS;
1787 : }
1788 :
1789 229850 : ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
1790 229850 : if (ret != LDB_SUCCESS) {
1791 0 : return ret;
1792 : }
1793 :
1794 14020850 : for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
1795 13791000 : const struct ldb_schema_syntax *s = NULL;
1796 :
1797 13791000 : s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
1798 :
1799 13791000 : if (!s) {
1800 0 : s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
1801 : }
1802 :
1803 13791000 : if (!s) {
1804 0 : return LDB_ERR_OPERATIONS_ERROR;
1805 : }
1806 :
1807 13791000 : ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
1808 13791000 : if (ret != LDB_SUCCESS) {
1809 0 : return ret;
1810 : }
1811 : }
1812 :
1813 2528350 : for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
1814 2298500 : ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
1815 2298500 : if (ret != LDB_SUCCESS) {
1816 0 : return ret;
1817 : }
1818 :
1819 : }
1820 :
1821 229850 : ret = ldb_register_samba_matching_rules(ldb);
1822 229850 : if (ret != LDB_SUCCESS) {
1823 0 : talloc_free(ldb);
1824 0 : return LDB_SUCCESS;
1825 : }
1826 :
1827 229850 : ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
1828 229850 : if (ret != LDB_SUCCESS) {
1829 0 : return ret;
1830 : }
1831 :
1832 229850 : return LDB_SUCCESS;
1833 : }
|