LCOV - code coverage report
Current view: top level - lib/ldb/common - attrib_handlers.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 180 237 75.9 %
Date: 2024-02-28 12:06:22 Functions: 15 17 88.2 %

          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   126024246 : int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx,
      37             :                      const struct ldb_val *in, struct ldb_val *out)
      38             : {
      39   126024246 :         *out = ldb_val_dup(mem_ctx, in);
      40   126024246 :         if (in->length > 0 && out->data == NULL) {
      41           0 :                 ldb_oom(ldb);
      42           0 :                 return -1;
      43             :         }
      44   121118202 :         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   757726034 : int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
      55             :                             const struct ldb_val *in, struct ldb_val *out)
      56             : {
      57    13081314 :         char *s, *t, *start;
      58    13081314 :         bool in_space;
      59             : 
      60   757726034 :         if (!in || !out || !(in->data)) {
      61           0 :                 return -1;
      62             :         }
      63             : 
      64   757726034 :         out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
      65   757726034 :         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   744644720 :         start = (char *)(out->data);
      71   744644720 :         in_space = true;
      72   744644720 :         t = start;
      73 11271119252 :         for (s = start; *s != '\0'; s++) {
      74 10513393218 :                 if (*s == ' ') {
      75   108471656 :                         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        2232 :                                 continue;
      81             :                         }
      82   107676221 :                         in_space = true;
      83             :                 } else {
      84 10285961730 :                         in_space = false;
      85             :                 }
      86 10513390986 :                 *t = *s;
      87 10513390986 :                 t++;
      88             :         }
      89             : 
      90   757726034 :         if (in_space && t != start) {
      91             :                 /* the loop will have left a single trailing space */
      92          13 :                 t--;
      93             :         }
      94   757726034 :         *t = '\0';
      95             : 
      96   757726034 :         out->length = t - start;
      97   757726034 :         return 0;
      98             : }
      99             : 
     100             : /* length limited conversion of a ldb_val to an int64_t */
     101    31485846 : static int val_to_int64(const struct ldb_val *in, int64_t *v)
     102             : {
     103     2598258 :         char *end;
     104     2598258 :         char buf[64];
     105             : 
     106             :         /* make sure we don't read past the end of the data */
     107    31485846 :         if (in->length > sizeof(buf)-1) {
     108           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     109             :         }
     110    31485846 :         strncpy(buf, (char *)in->data, in->length);
     111    31485846 :         buf[in->length] = 0;
     112             : 
     113    31485846 :         *v = (int64_t) strtoll(buf, &end, 0);
     114    31485846 :         if (*end != 0) {
     115          37 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     116             :         }
     117    28887553 :         return LDB_SUCCESS;
     118             : }
     119             : 
     120             : 
     121             : /*
     122             :   canonicalise a ldap Integer
     123             :   rfc2252 specifies it should be in decimal form
     124             : */
     125      276990 : 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      276990 :         ret = val_to_int64(in, &i);
     132      276990 :         if (ret != LDB_SUCCESS) {
     133           3 :                 return ret;
     134             :         }
     135      276987 :         out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
     136      276987 :         if (out->data == NULL) {
     137           0 :                 ldb_oom(ldb);
     138           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     139             :         }
     140      276987 :         out->length = strlen((char *)out->data);
     141      276987 :         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     5533166 : 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     5533166 :         ret = val_to_int64(in, &i);
     215     5533166 :         if (ret != LDB_SUCCESS) {
     216           0 :                 return ret;
     217             :         }
     218             : 
     219     5533166 :         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     5533074 :         } else if (i > 0) {
     227     5134057 :                 prefix = 'p';
     228             :         } else {
     229          12 :                 prefix = 'o';
     230             :         }
     231             : 
     232     5533166 :         out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%019lld", prefix, (long long)i);
     233     5533166 :         if (out->data == NULL) {
     234           0 :                 ldb_oom(ldb);
     235           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     236             :         }
     237             : 
     238     5533166 :         len = talloc_array_length(out->data) - 1;
     239     5533166 :         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     5533166 :         out->length = 20;
     248     5533166 :         return 0;
     249             : }
     250             : 
     251             : /*
     252             :   compare two Integers
     253             : */
     254    12837845 : 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    12837845 :         int64_t i1=0, i2=0;
     258    12837845 :         val_to_int64(v1, &i1);
     259    12837845 :         val_to_int64(v2, &i2);
     260    12837845 :         if (i1 == i2) return 0;
     261    12617201 :         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     2805510 : static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx,
     269             :                              const struct ldb_val *in, struct ldb_val *out)
     270             : {
     271     2805510 :         if (in->length >= 4 && strncasecmp((char *)in->data, "TRUE", in->length) == 0) {
     272     2517845 :                 out->data = (uint8_t *)talloc_strdup(mem_ctx, "TRUE");
     273     2517845 :                 out->length = 4;
     274      287665 :         } else if (in->length >= 5 && strncasecmp((char *)in->data, "FALSE", in->length) == 0) {
     275      287665 :                 out->data = (uint8_t *)talloc_strdup(mem_ctx, "FALSE");
     276      287665 :                 out->length = 5;
     277             :         } else {
     278           0 :                 return -1;
     279             :         }
     280     2442727 :         return 0;
     281             : }
     282             : 
     283             : /*
     284             :   compare two Booleans
     285             : */
     286     5513973 : 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     5513973 :         if (v1->length != v2->length) {
     290          93 :                 return v1->length - v2->length;
     291             :         }
     292     5513880 :         return strncasecmp((char *)v1->data, (char *)v2->data, v1->length);
     293             : }
     294             : 
     295             : 
     296             : /*
     297             :   compare two binary blobs
     298             : */
     299    27568854 : int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
     300             :                           const struct ldb_val *v1, const struct ldb_val *v2)
     301             : {
     302    27568854 :         if (v1->length != v2->length) {
     303       31782 :                 return v1->length - v2->length;
     304             :         }
     305    27537072 :         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   228350501 : int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
     317             :                                const struct ldb_val *v1, const struct ldb_val *v2)
     318             : {
     319   228350501 :         const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
     320   228350501 :         size_t n1 = v1->length, n2 = v2->length;
     321     5308505 :         char *b1, *b2;
     322     5308505 :         const char *u1, *u2;
     323     5308505 :         int ret;
     324             : 
     325   228351545 :         while (n1 && *s1 == ' ') { s1++; n1--; };
     326   228350691 :         while (n2 && *s2 == ' ') { s2++; n2--; };
     327             : 
     328  1631213702 :         while (n1 && n2 && *s1 && *s2) {
     329             :                 /* the first 127 (0x7F) chars are ascii and utf8 guarantees they
     330             :                  * never appear in multibyte sequences */
     331  1535355128 :                 if (((unsigned char)s1[0]) & 0x80) goto utf8str;
     332  1535304566 :                 if (((unsigned char)s2[0]) & 0x80) goto utf8str;
     333  1535303134 :                 if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
     334   129477857 :                         break;
     335  1402863201 :                 if (*s1 == ' ') {
     336        7892 :                         while (n1 > 1 && s1[0] == s1[1]) { s1++; n1--; }
     337        7889 :                         while (n2 > 1 && s2[0] == s2[1]) { s2++; n2--; }
     338             :                 }
     339  1402863201 :                 s1++; s2++;
     340  1402863201 :                 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   228298507 :         if (n1 && *s1 == ' ' && (!n2 || !*s2)) {
     349         492 :                 while (n1 && *s1 == ' ') { s1++; n1--; }
     350             :         }
     351   228298507 :         if (n2 && *s2 == ' ' && (!n1 || !*s1)) {
     352          22 :                 while (n2 && *s2 == ' ') { s2++; n2--; }
     353             :         }
     354   228298507 :         if (n1 == 0 && n2 != 0) {
     355       52721 :                 return -(int)ldb_ascii_toupper(*s2);
     356             :         }
     357   228245786 :         if (n2 == 0 && n1 != 0) {
     358       29799 :                 return (int)ldb_ascii_toupper(*s1);
     359             :         }
     360   228215987 :         if (n1 == 0 && n2 == 0) {
     361    93430449 :                 return 0;
     362             :         }
     363   132439933 :         return (int)ldb_ascii_toupper(*s1) - (int)ldb_ascii_toupper(*s2);
     364             : 
     365       51994 : 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       51994 :         b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
     372       51994 :         b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
     373             : 
     374       51994 :         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       51994 :         u1 = b1;
     392       51994 :         u2 = b2;
     393             : 
     394      475445 :         while (*u1 & *u2) {
     395      427807 :                 if (*u1 != *u2)
     396        4356 :                         break;
     397      423451 :                 if (*u1 == ' ') {
     398           2 :                         while (u1[0] == u1[1]) u1++;
     399           2 :                         while (u2[0] == u2[1]) u2++;
     400             :                 }
     401      423451 :                 u1++; u2++;
     402             :         }
     403       51994 :         if (! (*u1 && *u2)) {
     404       47209 :                 while (*u1 == ' ') u1++;
     405       47025 :                 while (*u2 == ' ') u2++;
     406             :         }
     407       51994 :         ret = (int)(*u1 - *u2);
     408             : 
     409       51994 :         talloc_free(b1);
     410       51994 :         talloc_free(b2);
     411             : 
     412       51994 :         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      648475 : 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      648475 :         time_t t1=0, t2=0;
     479      648475 :         ldb_val_to_time(v1, &t1);
     480      648475 :         ldb_val_to_time(v2, &t2);
     481      648475 :         if (t1 == t2) return 0;
     482      325339 :         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   161228275 : const struct ldb_schema_syntax *ldb_standard_syntax_by_name(struct ldb_context *ldb,
     602             :                                                             const char *syntax)
     603             : {
     604     5273284 :         unsigned int i;
     605   161228275 :         unsigned num_handlers = sizeof(ldb_standard_syntaxes)/sizeof(ldb_standard_syntaxes[0]);
     606             :         /* TODO: should be replaced with a binary search */
     607   629664799 :         for (i=0;i<num_handlers;i++) {
     608   629664799 :                 if (strcmp(ldb_standard_syntaxes[i].name, syntax) == 0) {
     609   161228275 :                         return &ldb_standard_syntaxes[i];
     610             :                 }
     611             :         }
     612           0 :         return NULL;
     613             : }
     614             : 
     615       78055 : 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        1833 :         int ret, ret1, ret2;
     621        1833 :         struct ldb_val v1_canon, v2_canon;
     622       78055 :         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       78055 :         ret1 = canonicalise_fn(ldb, tmp_ctx, v1, &v1_canon);
     630       78055 :         ret2 = canonicalise_fn(ldb, tmp_ctx, v2, &v2_canon);
     631             : 
     632       78055 :         if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
     633       78031 :                 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       78055 :         talloc_free(tmp_ctx);
     638       78055 :         return ret;
     639             : }

Generated by: LCOV version 1.14