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