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