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 127268060 : int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx,
37 : const struct ldb_val *in, struct ldb_val *out)
38 : {
39 127268060 : *out = ldb_val_dup(mem_ctx, in);
40 127268060 : if (in->length > 0 && out->data == NULL) {
41 0 : ldb_oom(ldb);
42 0 : return -1;
43 : }
44 122399475 : 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 763590411 : int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
55 : const struct ldb_val *in, struct ldb_val *out)
56 : {
57 13118729 : char *s, *t, *start;
58 13118729 : bool in_space;
59 :
60 763590411 : if (!in || !out || !(in->data)) {
61 0 : return -1;
62 : }
63 :
64 763590411 : out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
65 763590411 : 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 750471682 : start = (char *)(out->data);
71 750471682 : in_space = true;
72 750471682 : t = start;
73 11352718048 : for (s = start; *s != '\0'; s++) {
74 10589127637 : if (*s == ' ') {
75 109159756 : 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 2230 : continue;
81 : }
82 108359593 : in_space = true;
83 : } else {
84 10360507880 : in_space = false;
85 : }
86 10589125407 : *t = *s;
87 10589125407 : t++;
88 : }
89 :
90 763590411 : if (in_space && t != start) {
91 : /* the loop will have left a single trailing space */
92 13 : t--;
93 : }
94 763590411 : *t = '\0';
95 :
96 763590411 : out->length = t - start;
97 763590411 : return 0;
98 : }
99 :
100 : /* length limited conversion of a ldb_val to an int64_t */
101 31573150 : static int val_to_int64(const struct ldb_val *in, int64_t *v)
102 : {
103 2561074 : char *end;
104 2561074 : char buf[64];
105 :
106 : /* make sure we don't read past the end of the data */
107 31573150 : if (in->length > sizeof(buf)-1) {
108 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
109 : }
110 31573150 : strncpy(buf, (char *)in->data, in->length);
111 31573150 : buf[in->length] = 0;
112 :
113 31573150 : *v = (int64_t) strtoll(buf, &end, 0);
114 31573150 : if (*end != 0) {
115 35 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
116 : }
117 29012043 : return LDB_SUCCESS;
118 : }
119 :
120 :
121 : /*
122 : canonicalise a ldap Integer
123 : rfc2252 specifies it should be in decimal form
124 : */
125 279621 : static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
126 : const struct ldb_val *in, struct ldb_val *out)
127 : {
128 25877 : int64_t i;
129 25877 : int ret;
130 :
131 279621 : ret = val_to_int64(in, &i);
132 279621 : if (ret != LDB_SUCCESS) {
133 3 : return ret;
134 : }
135 279618 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
136 279618 : if (out->data == NULL) {
137 0 : ldb_oom(ldb);
138 0 : return LDB_ERR_OPERATIONS_ERROR;
139 : }
140 279618 : out->length = strlen((char *)out->data);
141 279618 : 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 5585973 : 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 399425 : int64_t i;
210 399425 : int ret;
211 399425 : char prefix;
212 399425 : size_t len;
213 :
214 5585973 : ret = val_to_int64(in, &i);
215 5585973 : if (ret != LDB_SUCCESS) {
216 0 : return ret;
217 : }
218 :
219 5585973 : if (i < 0) {
220 : /*
221 : * i is negative, so this is subtraction rather than
222 : * wrap-around.
223 : */
224 184 : prefix = 'n';
225 184 : i = INT64_MAX + i + 1;
226 5585789 : } else if (i > 0) {
227 5186548 : prefix = 'p';
228 : } else {
229 24 : prefix = 'o';
230 : }
231 :
232 5585973 : out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%019lld", prefix, (long long)i);
233 5585973 : if (out->data == NULL) {
234 0 : ldb_oom(ldb);
235 0 : return LDB_ERR_OPERATIONS_ERROR;
236 : }
237 :
238 5585973 : len = talloc_array_length(out->data) - 1;
239 5585973 : 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 5585973 : out->length = 20;
248 5585973 : return 0;
249 : }
250 :
251 : /*
252 : compare two Integers
253 : */
254 12853778 : 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 12853778 : int64_t i1=0, i2=0;
258 12853778 : val_to_int64(v1, &i1);
259 12853778 : val_to_int64(v2, &i2);
260 12853778 : if (i1 == i2) return 0;
261 12852006 : 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 2809394 : static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx,
269 : const struct ldb_val *in, struct ldb_val *out)
270 : {
271 2809394 : if (in->length >= 4 && strncasecmp((char *)in->data, "TRUE", in->length) == 0) {
272 2521559 : out->data = (uint8_t *)talloc_strdup(mem_ctx, "TRUE");
273 2521559 : out->length = 4;
274 287835 : } else if (in->length >= 5 && strncasecmp((char *)in->data, "FALSE", in->length) == 0) {
275 287835 : out->data = (uint8_t *)talloc_strdup(mem_ctx, "FALSE");
276 287835 : out->length = 5;
277 : } else {
278 0 : return -1;
279 : }
280 2446563 : return 0;
281 : }
282 :
283 : /*
284 : * compare two Booleans.
285 : *
286 : * According to RFC4517 4.2.2, "the booleanMatch rule is an equality matching
287 : * rule", meaning it isn't used for ordering.
288 : *
289 : * However, it seems conceivable that Samba could be coerced into sorting on a
290 : * field with Boolean syntax, so we might as well have consistent behaviour in
291 : * that case.
292 : *
293 : * The most probably values are {"FALSE", 5} and {"TRUE", 4}. To save time we
294 : * compare first by length, which makes FALSE > TRUE. This is somewhat
295 : * contrary to convention, but is how Samba has worked forever.
296 : *
297 : * If somehow we are comparing incompletely normalised values where the length
298 : * is the same (for example {"false", 5} and {"TRUE\0", 5}), the length is the
299 : * same, and we fall back to a strncasecmp. In this case, since "FALSE" is
300 : * alphabetically lower, we swap the order, so that "TRUE\0" again comes
301 : * before "FALSE".
302 : *
303 : * ldb_canonicalise_Boolean (just above) gives us a clue as to what we might
304 : * expect to cope with by way of invalid values.
305 : */
306 5602275 : static int ldb_comparison_Boolean(struct ldb_context *ldb, void *mem_ctx,
307 : const struct ldb_val *v1, const struct ldb_val *v2)
308 : {
309 5602275 : if (v1->length != v2->length) {
310 89 : return NUMERIC_CMP(v2->length, v1->length);
311 : }
312 : /* reversed, see long comment above */
313 5602186 : return strncasecmp((char *)v2->data, (char *)v1->data, v1->length);
314 : }
315 :
316 :
317 : /*
318 : compare two binary blobs
319 : */
320 27914097 : int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
321 : const struct ldb_val *v1, const struct ldb_val *v2)
322 : {
323 27914097 : if (v1->length != v2->length) {
324 28933 : return NUMERIC_CMP(v1->length, v2->length);
325 : }
326 27885164 : return memcmp(v1->data, v2->data, v1->length);
327 : }
328 :
329 : /*
330 : * ldb_comparison_fold is a schema syntax comparison_fn for utf-8 strings that
331 : * collapse multiple spaces into one (e.g. "Directory String" syntax).
332 : *
333 : * The default comparison function only performs ASCII case-folding, and only
334 : * collapses multiple spaces, not tabs and other whitespace (contrary to
335 : * RFC4518). To change the comparison function (as Samba does), use
336 : * ldb_set_utf8_functions().
337 : */
338 232028616 : int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
339 : const struct ldb_val *v1, const struct ldb_val *v2)
340 : {
341 232028616 : return ldb->utf8_fns.casecmp(ldb->utf8_fns.context, v1, v2);
342 : }
343 :
344 :
345 : /*
346 : canonicalise a attribute in DN format
347 : */
348 6 : static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
349 : const struct ldb_val *in, struct ldb_val *out)
350 : {
351 6 : struct ldb_dn *dn;
352 6 : int ret = -1;
353 :
354 6 : out->length = 0;
355 6 : out->data = NULL;
356 :
357 6 : dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
358 6 : if ( ! ldb_dn_validate(dn)) {
359 0 : return LDB_ERR_INVALID_DN_SYNTAX;
360 : }
361 :
362 6 : out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
363 6 : if (out->data == NULL) {
364 0 : goto done;
365 : }
366 6 : out->length = strlen((char *)out->data);
367 :
368 6 : ret = 0;
369 :
370 6 : done:
371 6 : talloc_free(dn);
372 :
373 6 : return ret;
374 : }
375 :
376 : /*
377 : compare two dns
378 : */
379 0 : static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
380 : const struct ldb_val *v1, const struct ldb_val *v2)
381 : {
382 0 : struct ldb_dn *dn1 = NULL, *dn2 = NULL;
383 0 : int ret;
384 :
385 0 : dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
386 0 : if ( ! ldb_dn_validate(dn1)) return -1;
387 :
388 0 : dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
389 0 : if ( ! ldb_dn_validate(dn2)) {
390 0 : talloc_free(dn1);
391 0 : return -1;
392 : }
393 :
394 0 : ret = ldb_dn_compare(dn1, dn2);
395 :
396 0 : talloc_free(dn1);
397 0 : talloc_free(dn2);
398 0 : return ret;
399 : }
400 :
401 : /*
402 : compare two utc time values. 1 second resolution
403 : */
404 601020 : static int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx,
405 : const struct ldb_val *v1, const struct ldb_val *v2)
406 : {
407 601020 : time_t t1=0, t2=0;
408 601020 : ldb_val_to_time(v1, &t1);
409 601020 : ldb_val_to_time(v2, &t2);
410 601020 : if (t1 == t2) return 0;
411 313907 : return t1 > t2? 1 : -1;
412 : }
413 :
414 : /*
415 : canonicalise a utc time
416 : */
417 0 : static int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx,
418 : const struct ldb_val *in, struct ldb_val *out)
419 : {
420 0 : time_t t;
421 0 : int ret;
422 0 : ret = ldb_val_to_time(in, &t);
423 0 : if (ret != LDB_SUCCESS) {
424 0 : return ret;
425 : }
426 0 : out->data = (uint8_t *)ldb_timestring_utc(mem_ctx, t);
427 0 : if (out->data == NULL) {
428 0 : ldb_oom(ldb);
429 0 : return LDB_ERR_OPERATIONS_ERROR;
430 : }
431 0 : out->length = strlen((char *)out->data);
432 0 : return 0;
433 : }
434 :
435 : /*
436 : canonicalise a generalized time
437 : */
438 10948 : static int ldb_canonicalise_generalizedtime(struct ldb_context *ldb, void *mem_ctx,
439 : const struct ldb_val *in, struct ldb_val *out)
440 : {
441 0 : time_t t;
442 0 : int ret;
443 10948 : ret = ldb_val_to_time(in, &t);
444 10948 : if (ret != LDB_SUCCESS) {
445 0 : return ret;
446 : }
447 10948 : out->data = (uint8_t *)ldb_timestring(mem_ctx, t);
448 10948 : if (out->data == NULL) {
449 0 : ldb_oom(ldb);
450 0 : return LDB_ERR_OPERATIONS_ERROR;
451 : }
452 10948 : out->length = strlen((char *)out->data);
453 10948 : return 0;
454 : }
455 :
456 : /*
457 : table of standard attribute handlers
458 : */
459 : static const struct ldb_schema_syntax ldb_standard_syntaxes[] = {
460 : {
461 : .name = LDB_SYNTAX_INTEGER,
462 : .ldif_read_fn = ldb_handler_copy,
463 : .ldif_write_fn = ldb_handler_copy,
464 : .canonicalise_fn = ldb_canonicalise_Integer,
465 : .comparison_fn = ldb_comparison_Integer
466 : },
467 : {
468 : .name = LDB_SYNTAX_ORDERED_INTEGER,
469 : .ldif_read_fn = ldb_handler_copy,
470 : .ldif_write_fn = ldb_handler_copy,
471 : .canonicalise_fn = ldb_canonicalise_Integer,
472 : .index_format_fn = ldb_index_format_Integer,
473 : .comparison_fn = ldb_comparison_Integer
474 : },
475 : {
476 : .name = LDB_SYNTAX_OCTET_STRING,
477 : .ldif_read_fn = ldb_handler_copy,
478 : .ldif_write_fn = ldb_handler_copy,
479 : .canonicalise_fn = ldb_handler_copy,
480 : .comparison_fn = ldb_comparison_binary
481 : },
482 : {
483 : .name = LDB_SYNTAX_DIRECTORY_STRING,
484 : .ldif_read_fn = ldb_handler_copy,
485 : .ldif_write_fn = ldb_handler_copy,
486 : .canonicalise_fn = ldb_handler_fold,
487 : .comparison_fn = ldb_comparison_fold
488 : },
489 : {
490 : .name = LDB_SYNTAX_DN,
491 : .ldif_read_fn = ldb_handler_copy,
492 : .ldif_write_fn = ldb_handler_copy,
493 : .canonicalise_fn = ldb_canonicalise_dn,
494 : .comparison_fn = ldb_comparison_dn
495 : },
496 : {
497 : .name = LDB_SYNTAX_OBJECTCLASS,
498 : .ldif_read_fn = ldb_handler_copy,
499 : .ldif_write_fn = ldb_handler_copy,
500 : .canonicalise_fn = ldb_handler_fold,
501 : .comparison_fn = ldb_comparison_fold
502 : },
503 : {
504 : .name = LDB_SYNTAX_UTC_TIME,
505 : .ldif_read_fn = ldb_handler_copy,
506 : .ldif_write_fn = ldb_handler_copy,
507 : .canonicalise_fn = ldb_canonicalise_utctime,
508 : .comparison_fn = ldb_comparison_utctime
509 : },
510 : {
511 : .name = LDB_SYNTAX_GENERALIZED_TIME,
512 : .ldif_read_fn = ldb_handler_copy,
513 : .ldif_write_fn = ldb_handler_copy,
514 : .canonicalise_fn = ldb_canonicalise_generalizedtime,
515 : .comparison_fn = ldb_comparison_utctime
516 : },
517 : {
518 : .name = LDB_SYNTAX_BOOLEAN,
519 : .ldif_read_fn = ldb_handler_copy,
520 : .ldif_write_fn = ldb_handler_copy,
521 : .canonicalise_fn = ldb_canonicalise_Boolean,
522 : .comparison_fn = ldb_comparison_Boolean
523 : },
524 : };
525 :
526 :
527 : /*
528 : return the attribute handlers for a given syntax name
529 : */
530 163712355 : const struct ldb_schema_syntax *ldb_standard_syntax_by_name(struct ldb_context *ldb,
531 : const char *syntax)
532 : {
533 5378679 : unsigned int i;
534 163712355 : unsigned num_handlers = sizeof(ldb_standard_syntaxes)/sizeof(ldb_standard_syntaxes[0]);
535 : /* TODO: should be replaced with a binary search */
536 639339820 : for (i=0;i<num_handlers;i++) {
537 639339820 : if (strcmp(ldb_standard_syntaxes[i].name, syntax) == 0) {
538 163712355 : return &ldb_standard_syntaxes[i];
539 : }
540 : }
541 0 : return NULL;
542 : }
543 :
544 78160 : int ldb_any_comparison(struct ldb_context *ldb, void *mem_ctx,
545 : ldb_attr_handler_t canonicalise_fn,
546 : const struct ldb_val *v1,
547 : const struct ldb_val *v2)
548 : {
549 1833 : int ret, ret1, ret2;
550 1833 : struct ldb_val v1_canon, v2_canon;
551 78160 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
552 :
553 : /* I could try and bail if tmp_ctx was NULL, but what return
554 : * value would I use?
555 : *
556 : * It seems easier to continue on the NULL context
557 : */
558 78160 : ret1 = canonicalise_fn(ldb, tmp_ctx, v1, &v1_canon);
559 78160 : ret2 = canonicalise_fn(ldb, tmp_ctx, v2, &v2_canon);
560 :
561 78160 : if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
562 78136 : ret = ldb_comparison_binary(ldb, mem_ctx, &v1_canon, &v2_canon);
563 : } else {
564 24 : ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
565 : }
566 78160 : talloc_free(tmp_ctx);
567 78160 : return ret;
568 : }
|