Line data Source code
1 : /*
2 : ldb database library
3 :
4 : Copyright (C) Andrew Tridgell 2005
5 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2009
6 :
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 : attribute handlers for well known attribute types, selected by syntax OID
26 : see rfc2252
27 : */
28 :
29 : #include "ldb_private.h"
30 : #include "system/locale.h"
31 : #include "ldb_handlers.h"
32 :
33 : /*
34 : default handler that just copies a ldb_val.
35 : */
36 126761361 : int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx,
37 : const struct ldb_val *in, struct ldb_val *out)
38 : {
39 126761361 : *out = ldb_val_dup(mem_ctx, in);
40 126761361 : if (in->length > 0 && out->data == NULL) {
41 0 : ldb_oom(ldb);
42 0 : return -1;
43 : }
44 121873568 : return 0;
45 : }
46 :
47 : /*
48 : a case folding copy handler, removing leading and trailing spaces and
49 : multiple internal spaces
50 :
51 : We exploit the fact that utf8 never uses the space octet except for
52 : the space itself
53 : */
54 760378894 : int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
55 : const struct ldb_val *in, struct ldb_val *out)
56 : {
57 13035954 : char *s, *t, *start;
58 13035954 : bool in_space;
59 :
60 760378894 : if (!in || !out || !(in->data)) {
61 0 : return -1;
62 : }
63 :
64 760378894 : out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
65 760378894 : if (out->data == NULL) {
66 0 : ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%.*s]", (int)in->length, (const char *)in->data);
67 0 : return -1;
68 : }
69 :
70 747342940 : start = (char *)(out->data);
71 747342940 : in_space = true;
72 747342940 : t = start;
73 11307568696 : for (s = start; *s != '\0'; s++) {
74 10547189802 : if (*s == ' ') {
75 108820044 : if (in_space) {
76 : /*
77 : * We already have one (or this is the start)
78 : * and we don't want to add more
79 : */
80 2233 : continue;
81 : }
82 108024401 : in_space = true;
83 : } else {
84 10319754115 : in_space = false;
85 : }
86 10547187569 : *t = *s;
87 10547187569 : t++;
88 : }
89 :
90 760378894 : if (in_space && t != start) {
91 : /* the loop will have left a single trailing space */
92 13 : t--;
93 : }
94 760378894 : *t = '\0';
95 :
96 760378894 : out->length = t - start;
97 760378894 : return 0;
98 : }
99 :
100 : /* length limited conversion of a ldb_val to an int64_t */
101 32284614 : static int val_to_int64(const struct ldb_val *in, int64_t *v)
102 : {
103 2615838 : char *end;
104 2615838 : char buf[64];
105 :
106 : /* make sure we don't read past the end of the data */
107 32284614 : if (in->length > sizeof(buf)-1) {
108 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
109 : }
110 32284614 : strncpy(buf, (char *)in->data, in->length);
111 32284614 : buf[in->length] = 0;
112 :
113 32284614 : *v = (int64_t) strtoll(buf, &end, 0);
114 32284614 : if (*end != 0) {
115 37 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
116 : }
117 29668741 : return LDB_SUCCESS;
118 : }
119 :
120 :
121 : /*
122 : canonicalise a ldap Integer
123 : rfc2252 specifies it should be in decimal form
124 : */
125 276997 : static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
126 : const struct ldb_val *in, struct ldb_val *out)
127 : {
128 25813 : int64_t i;
129 25813 : int ret;
130 :
131 276997 : ret = val_to_int64(in, &i);
132 276997 : if (ret != LDB_SUCCESS) {
133 3 : return ret;
134 : }
135 276994 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
136 276994 : if (out->data == NULL) {
137 0 : ldb_oom(ldb);
138 0 : return LDB_ERR_OPERATIONS_ERROR;
139 : }
140 276994 : out->length = strlen((char *)out->data);
141 276994 : return 0;
142 : }
143 :
144 : /*
145 : * Lexicographically ordered format for a ldap Integer
146 : *
147 : * [ INT64_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT64_MAX ]
148 : * n o p
149 : *
150 : * For human readability sake, we continue to format the key as a string
151 : * (like the canonicalize) rather than store as a fixed binary representation.
152 : *
153 : * In order to sort the integers in the correct string order, there are three
154 : * techniques we use:
155 : *
156 : * 1. Zero padding
157 : * 2. Negative integer inversion
158 : * 3. 1-byte prefixes: 'n' < 'o' < 'p'
159 : *
160 : * 1. To have a fixed-width representation so that 10 sorts after 2 rather than
161 : * after 1, we zero pad, like this 4-byte width example:
162 : *
163 : * 0001, 0002, 0010
164 : *
165 : * INT64_MAX = 2^63 - 1 = 9223372036854775807 (19 characters long)
166 : *
167 : * Meaning we need to pad to 19 characters.
168 : *
169 : * 2. This works for positive integers, but negative integers will still be
170 : * sorted backwards, for example:
171 : *
172 : * -9223372036854775808 ..., -0000000000000000002, -0000000000000000001
173 : * INT64_MIN -2 -1
174 : *
175 : * gets sorted based on string as:
176 : *
177 : * -0000000000000000001, -0000000000000000002, ... -9223372036854775808
178 : *
179 : * In order to fix this, we invert the negative integer range, so that they
180 : * get sorted the same way as positive numbers. INT64_MIN becomes the lowest
181 : * possible non-negative number (zero), and -1 becomes the highest (INT64_MAX).
182 : *
183 : * The actual conversion applied to negative number 'x' is:
184 : * INT64_MAX - abs(x) + 1
185 : * (The +1 is needed because abs(INT64_MIN) is one greater than INT64_MAX)
186 : *
187 : * 3. Finally, we now have two different numbers that map to the same key, e.g.
188 : * INT64_MIN maps to -0000000000000000000 and zero maps to 0000000000000000000.
189 : * In order to avoid confusion, we give every number a prefix representing its
190 : * sign: 'n' for negative numbers, 'o' for zero, and 'p' for positive. (Note
191 : * that '+' and '-' weren't used because they sort the wrong way).
192 : *
193 : * The result is a range of key values that look like this:
194 : *
195 : * n0000000000000000000, ... n9223372036854775807,
196 : * INT64_MIN -1
197 : *
198 : * o0000000000000000000,
199 : * ZERO
200 : *
201 : * p0000000000000000001, ... p9223372036854775807
202 : * +1 INT64_MAX
203 : */
204 5558669 : static int ldb_index_format_Integer(struct ldb_context *ldb,
205 : void *mem_ctx,
206 : const struct ldb_val *in,
207 : struct ldb_val *out)
208 : {
209 399005 : int64_t i;
210 399005 : int ret;
211 399005 : char prefix;
212 399005 : size_t len;
213 :
214 5558669 : ret = val_to_int64(in, &i);
215 5558669 : if (ret != LDB_SUCCESS) {
216 0 : return ret;
217 : }
218 :
219 5558669 : if (i < 0) {
220 : /*
221 : * i is negative, so this is subtraction rather than
222 : * wrap-around.
223 : */
224 92 : prefix = 'n';
225 92 : i = INT64_MAX + i + 1;
226 5558577 : } else if (i > 0) {
227 5159560 : prefix = 'p';
228 : } else {
229 12 : prefix = 'o';
230 : }
231 :
232 5558669 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%019lld", prefix, (long long)i);
233 5558669 : if (out->data == NULL) {
234 0 : ldb_oom(ldb);
235 0 : return LDB_ERR_OPERATIONS_ERROR;
236 : }
237 :
238 5558669 : len = talloc_array_length(out->data) - 1;
239 5558669 : if (len != 20) {
240 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
241 : __location__ ": expected index format str %s to"
242 : " have length 20 but got %zu",
243 0 : (char*)out->data, len);
244 0 : return LDB_ERR_OPERATIONS_ERROR;
245 : }
246 :
247 5558669 : out->length = 20;
248 5558669 : return 0;
249 : }
250 :
251 : /*
252 : compare two Integers
253 : */
254 13224474 : static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx,
255 : const struct ldb_val *v1, const struct ldb_val *v2)
256 : {
257 13224474 : int64_t i1=0, i2=0;
258 13224474 : val_to_int64(v1, &i1);
259 13224474 : val_to_int64(v2, &i2);
260 13224474 : if (i1 == i2) return 0;
261 13004254 : return i1 > i2? 1 : -1;
262 : }
263 :
264 : /*
265 : canonicalise a ldap Boolean
266 : rfc2252 specifies it should be either "TRUE" or "FALSE"
267 : */
268 2808364 : static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx,
269 : const struct ldb_val *in, struct ldb_val *out)
270 : {
271 2808364 : if (in->length >= 4 && strncasecmp((char *)in->data, "TRUE", in->length) == 0) {
272 2520659 : out->data = (uint8_t *)talloc_strdup(mem_ctx, "TRUE");
273 2520659 : out->length = 4;
274 287705 : } else if (in->length >= 5 && strncasecmp((char *)in->data, "FALSE", in->length) == 0) {
275 287705 : out->data = (uint8_t *)talloc_strdup(mem_ctx, "FALSE");
276 287705 : out->length = 5;
277 : } else {
278 0 : return -1;
279 : }
280 2445581 : return 0;
281 : }
282 :
283 : /*
284 : compare two Booleans
285 : */
286 5526761 : static int ldb_comparison_Boolean(struct ldb_context *ldb, void *mem_ctx,
287 : const struct ldb_val *v1, const struct ldb_val *v2)
288 : {
289 5526761 : if (v1->length != v2->length) {
290 91 : return v1->length - v2->length;
291 : }
292 5526670 : return strncasecmp((char *)v1->data, (char *)v2->data, v1->length);
293 : }
294 :
295 :
296 : /*
297 : compare two binary blobs
298 : */
299 27508629 : int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
300 : const struct ldb_val *v1, const struct ldb_val *v2)
301 : {
302 27508629 : if (v1->length != v2->length) {
303 31165 : return v1->length - v2->length;
304 : }
305 27477464 : return memcmp(v1->data, v2->data, v1->length);
306 : }
307 :
308 : /*
309 : compare two case insensitive strings, ignoring multiple whitespaces
310 : and leading and trailing whitespaces
311 : see rfc2252 section 8.1
312 :
313 : try to optimize for the ascii case,
314 : but if we find out an utf8 codepoint revert to slower but correct function
315 : */
316 229142461 : int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
317 : const struct ldb_val *v1, const struct ldb_val *v2)
318 : {
319 229142461 : const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
320 229142461 : size_t n1 = v1->length, n2 = v2->length;
321 5306459 : char *b1, *b2;
322 5306459 : const char *u1, *u2;
323 5306459 : int ret;
324 :
325 229143491 : while (n1 && *s1 == ' ') { s1++; n1--; };
326 229142678 : while (n2 && *s2 == ' ') { s2++; n2--; };
327 :
328 1636511145 : while (n1 && n2 && *s1 && *s2) {
329 : /* the first 127 (0x7F) chars are ascii and utf8 guarantees they
330 : * never appear in multibyte sequences */
331 1540286305 : if (((unsigned char)s1[0]) & 0x80) goto utf8str;
332 1540235756 : if (((unsigned char)s2[0]) & 0x80) goto utf8str;
333 1540234312 : if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
334 129903514 : break;
335 1407368684 : if (*s1 == ' ') {
336 7885 : while (n1 > 1 && s1[0] == s1[1]) { s1++; n1--; }
337 7882 : while (n2 > 1 && s2[0] == s2[1]) { s2++; n2--; }
338 : }
339 1407368684 : s1++; s2++;
340 1407368684 : n1--; n2--;
341 : }
342 :
343 : /* check for trailing spaces only if the other pointers has
344 : * reached the end of the strings otherwise we can
345 : * mistakenly match. ex. "domain users" <->
346 : * "domainUpdates"
347 : */
348 229090468 : if (n1 && *s1 == ' ' && (!n2 || !*s2)) {
349 494 : while (n1 && *s1 == ' ') { s1++; n1--; }
350 : }
351 229090468 : if (n2 && *s2 == ' ' && (!n1 || !*s1)) {
352 22 : while (n2 && *s2 == ' ') { s2++; n2--; }
353 : }
354 229090468 : if (n1 == 0 && n2 != 0) {
355 48444 : return -(int)ldb_ascii_toupper(*s2);
356 : }
357 229042024 : if (n2 == 0 && n1 != 0) {
358 24880 : return (int)ldb_ascii_toupper(*s1);
359 : }
360 229017144 : if (n1 == 0 && n2 == 0) {
361 93807994 : return 0;
362 : }
363 132865629 : return (int)ldb_ascii_toupper(*s1) - (int)ldb_ascii_toupper(*s2);
364 :
365 51993 : utf8str:
366 : /*
367 : * No need to recheck from the start, just from the first utf8 charu
368 : * found. Note that the callback of ldb_casefold() needs to be ascii
369 : * compatible.
370 : */
371 51993 : b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
372 51993 : b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
373 :
374 51993 : if (!b1 || !b2) {
375 : /* One of the strings was not UTF8, so we have no
376 : * options but to do a binary compare */
377 0 : talloc_free(b1);
378 0 : talloc_free(b2);
379 0 : ret = memcmp(s1, s2, MIN(n1, n2));
380 0 : if (ret == 0) {
381 0 : if (n1 == n2) return 0;
382 0 : if (n1 > n2) {
383 0 : return (int)ldb_ascii_toupper(s1[n2]);
384 : } else {
385 0 : return -(int)ldb_ascii_toupper(s2[n1]);
386 : }
387 : }
388 0 : return ret;
389 : }
390 :
391 51993 : u1 = b1;
392 51993 : u2 = b2;
393 :
394 475275 : while (*u1 & *u2) {
395 427633 : if (*u1 != *u2)
396 4351 : break;
397 423282 : if (*u1 == ' ') {
398 0 : while (u1[0] == u1[1]) u1++;
399 0 : while (u2[0] == u2[1]) u2++;
400 : }
401 423282 : u1++; u2++;
402 : }
403 51993 : if (! (*u1 && *u2)) {
404 47191 : while (*u1 == ' ') u1++;
405 47010 : while (*u2 == ' ') u2++;
406 : }
407 51993 : ret = (int)(*u1 - *u2);
408 :
409 51993 : talloc_free(b1);
410 51993 : talloc_free(b2);
411 :
412 51993 : return ret;
413 : }
414 :
415 :
416 : /*
417 : canonicalise a attribute in DN format
418 : */
419 6 : static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
420 : const struct ldb_val *in, struct ldb_val *out)
421 : {
422 6 : struct ldb_dn *dn;
423 6 : int ret = -1;
424 :
425 6 : out->length = 0;
426 6 : out->data = NULL;
427 :
428 6 : dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
429 6 : if ( ! ldb_dn_validate(dn)) {
430 0 : return LDB_ERR_INVALID_DN_SYNTAX;
431 : }
432 :
433 6 : out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
434 6 : if (out->data == NULL) {
435 0 : goto done;
436 : }
437 6 : out->length = strlen((char *)out->data);
438 :
439 6 : ret = 0;
440 :
441 6 : done:
442 6 : talloc_free(dn);
443 :
444 6 : return ret;
445 : }
446 :
447 : /*
448 : compare two dns
449 : */
450 0 : static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
451 : const struct ldb_val *v1, const struct ldb_val *v2)
452 : {
453 0 : struct ldb_dn *dn1 = NULL, *dn2 = NULL;
454 0 : int ret;
455 :
456 0 : dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
457 0 : if ( ! ldb_dn_validate(dn1)) return -1;
458 :
459 0 : dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
460 0 : if ( ! ldb_dn_validate(dn2)) {
461 0 : talloc_free(dn1);
462 0 : return -1;
463 : }
464 :
465 0 : ret = ldb_dn_compare(dn1, dn2);
466 :
467 0 : talloc_free(dn1);
468 0 : talloc_free(dn2);
469 0 : return ret;
470 : }
471 :
472 : /*
473 : compare two utc time values. 1 second resolution
474 : */
475 585372 : static int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx,
476 : const struct ldb_val *v1, const struct ldb_val *v2)
477 : {
478 585372 : time_t t1=0, t2=0;
479 585372 : ldb_val_to_time(v1, &t1);
480 585372 : ldb_val_to_time(v2, &t2);
481 585372 : if (t1 == t2) return 0;
482 270900 : return t1 > t2? 1 : -1;
483 : }
484 :
485 : /*
486 : canonicalise a utc time
487 : */
488 0 : static int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx,
489 : const struct ldb_val *in, struct ldb_val *out)
490 : {
491 0 : time_t t;
492 0 : int ret;
493 0 : ret = ldb_val_to_time(in, &t);
494 0 : if (ret != LDB_SUCCESS) {
495 0 : return ret;
496 : }
497 0 : out->data = (uint8_t *)ldb_timestring_utc(mem_ctx, t);
498 0 : if (out->data == NULL) {
499 0 : ldb_oom(ldb);
500 0 : return LDB_ERR_OPERATIONS_ERROR;
501 : }
502 0 : out->length = strlen((char *)out->data);
503 0 : return 0;
504 : }
505 :
506 : /*
507 : canonicalise a generalized time
508 : */
509 10948 : static int ldb_canonicalise_generalizedtime(struct ldb_context *ldb, void *mem_ctx,
510 : const struct ldb_val *in, struct ldb_val *out)
511 : {
512 0 : time_t t;
513 0 : int ret;
514 10948 : ret = ldb_val_to_time(in, &t);
515 10948 : if (ret != LDB_SUCCESS) {
516 0 : return ret;
517 : }
518 10948 : out->data = (uint8_t *)ldb_timestring(mem_ctx, t);
519 10948 : if (out->data == NULL) {
520 0 : ldb_oom(ldb);
521 0 : return LDB_ERR_OPERATIONS_ERROR;
522 : }
523 10948 : out->length = strlen((char *)out->data);
524 10948 : return 0;
525 : }
526 :
527 : /*
528 : table of standard attribute handlers
529 : */
530 : static const struct ldb_schema_syntax ldb_standard_syntaxes[] = {
531 : {
532 : .name = LDB_SYNTAX_INTEGER,
533 : .ldif_read_fn = ldb_handler_copy,
534 : .ldif_write_fn = ldb_handler_copy,
535 : .canonicalise_fn = ldb_canonicalise_Integer,
536 : .comparison_fn = ldb_comparison_Integer
537 : },
538 : {
539 : .name = LDB_SYNTAX_ORDERED_INTEGER,
540 : .ldif_read_fn = ldb_handler_copy,
541 : .ldif_write_fn = ldb_handler_copy,
542 : .canonicalise_fn = ldb_canonicalise_Integer,
543 : .index_format_fn = ldb_index_format_Integer,
544 : .comparison_fn = ldb_comparison_Integer
545 : },
546 : {
547 : .name = LDB_SYNTAX_OCTET_STRING,
548 : .ldif_read_fn = ldb_handler_copy,
549 : .ldif_write_fn = ldb_handler_copy,
550 : .canonicalise_fn = ldb_handler_copy,
551 : .comparison_fn = ldb_comparison_binary
552 : },
553 : {
554 : .name = LDB_SYNTAX_DIRECTORY_STRING,
555 : .ldif_read_fn = ldb_handler_copy,
556 : .ldif_write_fn = ldb_handler_copy,
557 : .canonicalise_fn = ldb_handler_fold,
558 : .comparison_fn = ldb_comparison_fold
559 : },
560 : {
561 : .name = LDB_SYNTAX_DN,
562 : .ldif_read_fn = ldb_handler_copy,
563 : .ldif_write_fn = ldb_handler_copy,
564 : .canonicalise_fn = ldb_canonicalise_dn,
565 : .comparison_fn = ldb_comparison_dn
566 : },
567 : {
568 : .name = LDB_SYNTAX_OBJECTCLASS,
569 : .ldif_read_fn = ldb_handler_copy,
570 : .ldif_write_fn = ldb_handler_copy,
571 : .canonicalise_fn = ldb_handler_fold,
572 : .comparison_fn = ldb_comparison_fold
573 : },
574 : {
575 : .name = LDB_SYNTAX_UTC_TIME,
576 : .ldif_read_fn = ldb_handler_copy,
577 : .ldif_write_fn = ldb_handler_copy,
578 : .canonicalise_fn = ldb_canonicalise_utctime,
579 : .comparison_fn = ldb_comparison_utctime
580 : },
581 : {
582 : .name = LDB_SYNTAX_GENERALIZED_TIME,
583 : .ldif_read_fn = ldb_handler_copy,
584 : .ldif_write_fn = ldb_handler_copy,
585 : .canonicalise_fn = ldb_canonicalise_generalizedtime,
586 : .comparison_fn = ldb_comparison_utctime
587 : },
588 : {
589 : .name = LDB_SYNTAX_BOOLEAN,
590 : .ldif_read_fn = ldb_handler_copy,
591 : .ldif_write_fn = ldb_handler_copy,
592 : .canonicalise_fn = ldb_canonicalise_Boolean,
593 : .comparison_fn = ldb_comparison_Boolean
594 : },
595 : };
596 :
597 :
598 : /*
599 : return the attribute handlers for a given syntax name
600 : */
601 161804672 : const struct ldb_schema_syntax *ldb_standard_syntax_by_name(struct ldb_context *ldb,
602 : const char *syntax)
603 : {
604 5273398 : unsigned int i;
605 161804672 : unsigned num_handlers = sizeof(ldb_standard_syntaxes)/sizeof(ldb_standard_syntaxes[0]);
606 : /* TODO: should be replaced with a binary search */
607 631973569 : for (i=0;i<num_handlers;i++) {
608 631973569 : if (strcmp(ldb_standard_syntaxes[i].name, syntax) == 0) {
609 161804672 : return &ldb_standard_syntaxes[i];
610 : }
611 : }
612 0 : return NULL;
613 : }
614 :
615 78068 : int ldb_any_comparison(struct ldb_context *ldb, void *mem_ctx,
616 : ldb_attr_handler_t canonicalise_fn,
617 : const struct ldb_val *v1,
618 : const struct ldb_val *v2)
619 : {
620 1841 : int ret, ret1, ret2;
621 1841 : struct ldb_val v1_canon, v2_canon;
622 78068 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
623 :
624 : /* I could try and bail if tmp_ctx was NULL, but what return
625 : * value would I use?
626 : *
627 : * It seems easier to continue on the NULL context
628 : */
629 78068 : ret1 = canonicalise_fn(ldb, tmp_ctx, v1, &v1_canon);
630 78068 : ret2 = canonicalise_fn(ldb, tmp_ctx, v2, &v2_canon);
631 :
632 78068 : if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
633 78044 : ret = ldb_comparison_binary(ldb, mem_ctx, &v1_canon, &v2_canon);
634 : } else {
635 24 : ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
636 : }
637 78068 : talloc_free(tmp_ctx);
638 78068 : return ret;
639 : }
|