LCOV - code coverage report
Current view: top level - lib/ldb/common - attrib_handlers.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 163 215 75.8 %
Date: 2021-09-23 10: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    60815860 : int ldb_handler_copy(struct ldb_context *ldb, void *mem_ctx,
      37             :                      const struct ldb_val *in, struct ldb_val *out)
      38             : {
      39    60815860 :         *out = ldb_val_dup(mem_ctx, in);
      40    60815860 :         if (in->length > 0 && out->data == NULL) {
      41           0 :                 ldb_oom(ldb);
      42           0 :                 return -1;
      43             :         }
      44    57510058 :         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   656344970 : int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
      55             :                             const struct ldb_val *in, struct ldb_val *out)
      56             : {
      57             :         char *s, *t, *start;
      58             :         bool in_space;
      59             : 
      60   656344970 :         if (!in || !out || !(in->data)) {
      61           0 :                 return -1;
      62             :         }
      63             : 
      64   656344970 :         out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
      65   656344970 :         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   640102820 :         start = (char *)(out->data);
      71   640102820 :         in_space = true;
      72   640102820 :         t = start;
      73  9034921823 :         for (s = start; *s != '\0'; s++) {
      74  8394819003 :                 if (*s == ' ') {
      75    75432547 :                         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         491 :                                 continue;
      81             :                         }
      82    75019452 :                         in_space = true;
      83             :                 } else {
      84  8186160081 :                         in_space = false;
      85             :                 }
      86  8394818512 :                 *t = *s;
      87  8394818512 :                 t++;
      88             :         }
      89             : 
      90   656344970 :         if (in_space && t != start) {
      91             :                 /* the loop will have left a single trailing space */
      92           9 :                 t--;
      93             :         }
      94   656344970 :         *t = '\0';
      95             : 
      96   656344970 :         out->length = t - start;
      97   656344970 :         return 0;
      98             : }
      99             : 
     100             : /* length limited conversion of a ldb_val to an int64_t */
     101    30135522 : static int val_to_int64(const struct ldb_val *in, int64_t *v)
     102             : {
     103             :         char *end;
     104             :         char buf[64];
     105             : 
     106             :         /* make sure we don't read past the end of the data */
     107    30135522 :         if (in->length > sizeof(buf)-1) {
     108           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     109             :         }
     110    32594681 :         strncpy(buf, (char *)in->data, in->length);
     111    30135522 :         buf[in->length] = 0;
     112             : 
     113    30135522 :         *v = (int64_t) strtoll(buf, &end, 0);
     114    30135522 :         if (*end != 0) {
     115          35 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     116             :         }
     117    30135485 :         return LDB_SUCCESS;
     118             : }
     119             : 
     120             : 
     121             : /*
     122             :   canonicalise a ldap Integer
     123             :   rfc2252 specifies it should be in decimal form
     124             : */
     125      206315 : static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
     126             :                                     const struct ldb_val *in, struct ldb_val *out)
     127             : {
     128             :         int64_t i;
     129             :         int ret;
     130             : 
     131      206315 :         ret = val_to_int64(in, &i);
     132      206315 :         if (ret != LDB_SUCCESS) {
     133           3 :                 return ret;
     134             :         }
     135      206312 :         out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
     136      206312 :         if (out->data == NULL) {
     137           0 :                 ldb_oom(ldb);
     138           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     139             :         }
     140      206312 :         out->length = strlen((char *)out->data);
     141      206312 :         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     4857437 : 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             :         int64_t i;
     210             :         int ret;
     211             :         char prefix;
     212             :         size_t len;
     213             : 
     214     4857437 :         ret = val_to_int64(in, &i);
     215     4857437 :         if (ret != LDB_SUCCESS) {
     216           0 :                 return ret;
     217             :         }
     218             : 
     219     4857437 :         if (i < 0) {
     220             :                 /*
     221             :                  * i is negative, so this is subtraction rather than
     222             :                  * wrap-around.
     223             :                  */
     224          46 :                 prefix = 'n';
     225          46 :                 i = INT64_MAX + i + 1;
     226     4857391 :         } else if (i > 0) {
     227     4488493 :                 prefix = 'p';
     228             :         } else {
     229           6 :                 prefix = 'o';
     230             :         }
     231             : 
     232     4857437 :         out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%019lld", prefix, (long long)i);
     233     4857437 :         if (out->data == NULL) {
     234           0 :                 ldb_oom(ldb);
     235           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     236             :         }
     237             : 
     238     4857437 :         len = talloc_array_length(out->data) - 1;
     239     4857437 :         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     4857437 :         out->length = 20;
     248     4857437 :         return 0;
     249             : }
     250             : 
     251             : /*
     252             :   compare two Integers
     253             : */
     254    12535885 : 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    12535885 :         int64_t i1=0, i2=0;
     258    12535885 :         val_to_int64(v1, &i1);
     259    12535885 :         val_to_int64(v2, &i2);
     260    12535885 :         if (i1 == i2) return 0;
     261    12325982 :         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     2594747 : static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx,
     269             :                              const struct ldb_val *in, struct ldb_val *out)
     270             : {
     271     2594747 :         if (in->length >= 4 && strncasecmp((char *)in->data, "TRUE", in->length) == 0) {
     272     2328510 :                 out->data = (uint8_t *)talloc_strdup(mem_ctx, "TRUE");
     273     2328510 :                 out->length = 4;
     274      266237 :         } else if (in->length >= 5 && strncasecmp((char *)in->data, "FALSE", in->length) == 0) {
     275      266237 :                 out->data = (uint8_t *)talloc_strdup(mem_ctx, "FALSE");
     276      266237 :                 out->length = 5;
     277             :         } else {
     278           0 :                 return -1;
     279             :         }
     280     2259340 :         return 0;
     281             : }
     282             : 
     283             : /*
     284             :   compare two Booleans
     285             : */
     286     2098360 : 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     2098360 :         if (v1->length != v2->length) {
     290          51 :                 return v1->length - v2->length;
     291             :         }
     292     2098309 :         return strncasecmp((char *)v1->data, (char *)v2->data, v1->length);
     293             : }
     294             : 
     295             : 
     296             : /*
     297             :   compare two binary blobs
     298             : */
     299    18060180 : int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
     300             :                           const struct ldb_val *v1, const struct ldb_val *v2)
     301             : {
     302    18060180 :         if (v1->length != v2->length) {
     303       30109 :                 return v1->length - v2->length;
     304             :         }
     305    18030071 :         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   180346813 : int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
     317             :                                const struct ldb_val *v1, const struct ldb_val *v2)
     318             : {
     319   180346813 :         const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
     320   180346813 :         size_t n1 = v1->length, n2 = v2->length;
     321             :         char *b1, *b2;
     322             :         const char *u1, *u2;
     323             :         int ret;
     324   180346813 :         while (n1 && *s1 == ' ') { s1++; n1--; };
     325   176616584 :         while (n2 && *s2 == ' ') { s2++; n2--; };
     326             : 
     327  1435365352 :         while (n1 && n2 && *s1 && *s2) {
     328             :                 /* the first 127 (0x7F) chars are ascii and utf8 guarantes they
     329             :                  * never appear in multibyte sequences */
     330  1235247090 :                 if (((unsigned char)s1[0]) & 0x80) goto utf8str;
     331  1235195754 :                 if (((unsigned char)s2[0]) & 0x80) goto utf8str;
     332  1235194293 :                 if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
     333   101895059 :                         break;
     334  1131224961 :                 if (*s1 == ' ') {
     335        8624 :                         while (n1 > 1 && s1[0] == s1[1]) { s1++; n1--; }
     336        8623 :                         while (n2 > 1 && s2[0] == s2[1]) { s2++; n2--; }
     337             :                 }
     338  1131224961 :                 s1++; s2++;
     339  1131224961 :                 n1--; n2--;
     340             :         }
     341             : 
     342             :         /* check for trailing spaces only if the other pointers has
     343             :          * reached the end of the strings otherwise we can
     344             :          * mistakenly match.  ex. "domain users" <->
     345             :          * "domainUpdates"
     346             :          */
     347   180294016 :         if (n1 && *s1 == ' ' && (!n2 || !*s2)) {
     348         250 :                 while (n1 && *s1 == ' ') { s1++; n1--; }                
     349             :         }
     350   180294016 :         if (n2 && *s2 == ' ' && (!n1 || !*s1)) {
     351          10 :                 while (n2 && *s2 == ' ') { s2++; n2--; }                
     352             :         }
     353   180294016 :         if (n1 == 0 && n2 != 0) {
     354       61833 :                 return -(int)toupper(*s2);
     355             :         }
     356   180232183 :         if (n2 == 0 && n1 != 0) {
     357       22822 :                 return (int)toupper(*s1);
     358             :         }
     359   180209361 :         if (n1 == 0 && n2 == 0) {
     360    74585135 :                 return 0;
     361             :         }
     362   103969332 :         return (int)toupper(*s1) - (int)toupper(*s2);
     363             : 
     364       52797 : utf8str:
     365             :         /* no need to recheck from the start, just from the first utf8 char found */
     366       52797 :         b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
     367       52797 :         b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
     368             : 
     369       52797 :         if (!b1 || !b2) {
     370             :                 /* One of the strings was not UTF8, so we have no
     371             :                  * options but to do a binary compare */
     372           0 :                 talloc_free(b1);
     373           0 :                 talloc_free(b2);
     374           0 :                 ret = memcmp(s1, s2, MIN(n1, n2));
     375           0 :                 if (ret == 0) {
     376           0 :                         if (n1 == n2) return 0;
     377           0 :                         if (n1 > n2) {
     378           0 :                                 return (int)toupper(s1[n2]);
     379             :                         } else {
     380           0 :                                 return -(int)toupper(s2[n1]);
     381             :                         }
     382             :                 }
     383           0 :                 return ret;
     384             :         }
     385             : 
     386       52797 :         u1 = b1;
     387       52797 :         u2 = b2;
     388             : 
     389      535114 :         while (*u1 & *u2) {
     390      433975 :                 if (*u1 != *u2)
     391        4435 :                         break;
     392      429540 :                 if (*u1 == ' ') {
     393           3 :                         while (u1[0] == u1[1]) u1++;
     394           3 :                         while (u2[0] == u2[1]) u2++;
     395             :                 }
     396      429540 :                 u1++; u2++;
     397             :         }
     398       52797 :         if (! (*u1 && *u2)) {
     399       47696 :                 while (*u1 == ' ') u1++;
     400       47696 :                 while (*u2 == ' ') u2++;
     401             :         }
     402       52797 :         ret = (int)(*u1 - *u2);
     403             : 
     404       52797 :         talloc_free(b1);
     405       52797 :         talloc_free(b2);
     406             :         
     407       52797 :         return ret;
     408             : }
     409             : 
     410             : 
     411             : /*
     412             :   canonicalise a attribute in DN format
     413             : */
     414           6 : static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
     415             :                                const struct ldb_val *in, struct ldb_val *out)
     416             : {
     417             :         struct ldb_dn *dn;
     418           6 :         int ret = -1;
     419             : 
     420           6 :         out->length = 0;
     421           6 :         out->data = NULL;
     422             : 
     423           6 :         dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
     424           6 :         if ( ! ldb_dn_validate(dn)) {
     425           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     426             :         }
     427             : 
     428           6 :         out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
     429           6 :         if (out->data == NULL) {
     430           0 :                 goto done;
     431             :         }
     432           6 :         out->length = strlen((char *)out->data);
     433             : 
     434           6 :         ret = 0;
     435             : 
     436           6 : done:
     437           6 :         talloc_free(dn);
     438             : 
     439           6 :         return ret;
     440             : }
     441             : 
     442             : /*
     443             :   compare two dns
     444             : */
     445           0 : static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
     446             :                              const struct ldb_val *v1, const struct ldb_val *v2)
     447             : {
     448           0 :         struct ldb_dn *dn1 = NULL, *dn2 = NULL;
     449             :         int ret;
     450             : 
     451           0 :         dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
     452           0 :         if ( ! ldb_dn_validate(dn1)) return -1;
     453             : 
     454           0 :         dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
     455           0 :         if ( ! ldb_dn_validate(dn2)) {
     456           0 :                 talloc_free(dn1);
     457           0 :                 return -1;
     458             :         } 
     459             : 
     460           0 :         ret = ldb_dn_compare(dn1, dn2);
     461             : 
     462           0 :         talloc_free(dn1);
     463           0 :         talloc_free(dn2);
     464           0 :         return ret;
     465             : }
     466             : 
     467             : /*
     468             :   compare two utc time values. 1 second resolution
     469             : */
     470      587805 : static int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx,
     471             :                                   const struct ldb_val *v1, const struct ldb_val *v2)
     472             : {
     473      587805 :         time_t t1=0, t2=0;
     474      587805 :         ldb_val_to_time(v1, &t1);
     475      587805 :         ldb_val_to_time(v2, &t2);
     476      587805 :         if (t1 == t2) return 0;
     477      318850 :         return t1 > t2? 1 : -1;
     478             : }
     479             : 
     480             : /*
     481             :   canonicalise a utc time
     482             : */
     483           0 : static int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx,
     484             :                                     const struct ldb_val *in, struct ldb_val *out)
     485             : {
     486             :         time_t t;
     487             :         int ret;
     488           0 :         ret = ldb_val_to_time(in, &t);
     489           0 :         if (ret != LDB_SUCCESS) {
     490           0 :                 return ret;
     491             :         }
     492           0 :         out->data = (uint8_t *)ldb_timestring_utc(mem_ctx, t);
     493           0 :         if (out->data == NULL) {
     494           0 :                 ldb_oom(ldb);
     495           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     496             :         }
     497           0 :         out->length = strlen((char *)out->data);
     498           0 :         return 0;
     499             : }
     500             : 
     501             : /*
     502             :   canonicalise a generalized time
     503             : */
     504       10813 : static int ldb_canonicalise_generalizedtime(struct ldb_context *ldb, void *mem_ctx,
     505             :                                         const struct ldb_val *in, struct ldb_val *out)
     506             : {
     507             :         time_t t;
     508             :         int ret;
     509       10813 :         ret = ldb_val_to_time(in, &t);
     510       10813 :         if (ret != LDB_SUCCESS) {
     511           0 :                 return ret;
     512             :         }
     513       10813 :         out->data = (uint8_t *)ldb_timestring(mem_ctx, t);
     514       10813 :         if (out->data == NULL) {
     515           0 :                 ldb_oom(ldb);
     516           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     517             :         }
     518       10813 :         out->length = strlen((char *)out->data);
     519       10813 :         return 0;
     520             : }
     521             : 
     522             : /*
     523             :   table of standard attribute handlers
     524             : */
     525             : static const struct ldb_schema_syntax ldb_standard_syntaxes[] = {
     526             :         { 
     527             :                 .name            = LDB_SYNTAX_INTEGER,
     528             :                 .ldif_read_fn    = ldb_handler_copy,
     529             :                 .ldif_write_fn   = ldb_handler_copy,
     530             :                 .canonicalise_fn = ldb_canonicalise_Integer,
     531             :                 .comparison_fn   = ldb_comparison_Integer
     532             :         },
     533             :         {
     534             :                 .name            = LDB_SYNTAX_ORDERED_INTEGER,
     535             :                 .ldif_read_fn    = ldb_handler_copy,
     536             :                 .ldif_write_fn   = ldb_handler_copy,
     537             :                 .canonicalise_fn = ldb_canonicalise_Integer,
     538             :                 .index_format_fn = ldb_index_format_Integer,
     539             :                 .comparison_fn   = ldb_comparison_Integer
     540             :         },
     541             :         {
     542             :                 .name            = LDB_SYNTAX_OCTET_STRING,
     543             :                 .ldif_read_fn    = ldb_handler_copy,
     544             :                 .ldif_write_fn   = ldb_handler_copy,
     545             :                 .canonicalise_fn = ldb_handler_copy,
     546             :                 .comparison_fn   = ldb_comparison_binary
     547             :         },
     548             :         { 
     549             :                 .name            = LDB_SYNTAX_DIRECTORY_STRING,
     550             :                 .ldif_read_fn    = ldb_handler_copy,
     551             :                 .ldif_write_fn   = ldb_handler_copy,
     552             :                 .canonicalise_fn = ldb_handler_fold,
     553             :                 .comparison_fn   = ldb_comparison_fold
     554             :         },
     555             :         { 
     556             :                 .name            = LDB_SYNTAX_DN,
     557             :                 .ldif_read_fn    = ldb_handler_copy,
     558             :                 .ldif_write_fn   = ldb_handler_copy,
     559             :                 .canonicalise_fn = ldb_canonicalise_dn,
     560             :                 .comparison_fn   = ldb_comparison_dn
     561             :         },
     562             :         { 
     563             :                 .name            = LDB_SYNTAX_OBJECTCLASS,
     564             :                 .ldif_read_fn    = ldb_handler_copy,
     565             :                 .ldif_write_fn   = ldb_handler_copy,
     566             :                 .canonicalise_fn = ldb_handler_fold,
     567             :                 .comparison_fn   = ldb_comparison_fold
     568             :         },
     569             :         { 
     570             :                 .name            = LDB_SYNTAX_UTC_TIME,
     571             :                 .ldif_read_fn    = ldb_handler_copy,
     572             :                 .ldif_write_fn   = ldb_handler_copy,
     573             :                 .canonicalise_fn = ldb_canonicalise_utctime,
     574             :                 .comparison_fn   = ldb_comparison_utctime
     575             :         },
     576             :         { 
     577             :                 .name            = LDB_SYNTAX_GENERALIZED_TIME,
     578             :                 .ldif_read_fn    = ldb_handler_copy,
     579             :                 .ldif_write_fn   = ldb_handler_copy,
     580             :                 .canonicalise_fn = ldb_canonicalise_generalizedtime,
     581             :                 .comparison_fn   = ldb_comparison_utctime
     582             :         },
     583             :         {
     584             :                 .name            = LDB_SYNTAX_BOOLEAN,
     585             :                 .ldif_read_fn    = ldb_handler_copy,
     586             :                 .ldif_write_fn   = ldb_handler_copy,
     587             :                 .canonicalise_fn = ldb_canonicalise_Boolean,
     588             :                 .comparison_fn   = ldb_comparison_Boolean
     589             :         },
     590             : };
     591             : 
     592             : 
     593             : /*
     594             :   return the attribute handlers for a given syntax name
     595             : */
     596   131302149 : const struct ldb_schema_syntax *ldb_standard_syntax_by_name(struct ldb_context *ldb,
     597             :                                                             const char *syntax)
     598             : {
     599             :         unsigned int i;
     600   131302149 :         unsigned num_handlers = sizeof(ldb_standard_syntaxes)/sizeof(ldb_standard_syntaxes[0]);
     601             :         /* TODO: should be replaced with a binary search */
     602   512198933 :         for (i=0;i<num_handlers;i++) {
     603   512198933 :                 if (strcmp(ldb_standard_syntaxes[i].name, syntax) == 0) {
     604   131302149 :                         return &ldb_standard_syntaxes[i];
     605             :                 }
     606             :         }
     607           0 :         return NULL;
     608             : }
     609             : 
     610       72672 : int ldb_any_comparison(struct ldb_context *ldb, void *mem_ctx, 
     611             :                        ldb_attr_handler_t canonicalise_fn, 
     612             :                        const struct ldb_val *v1,
     613             :                        const struct ldb_val *v2)
     614             : {
     615             :         int ret, ret1, ret2;
     616             :         struct ldb_val v1_canon, v2_canon;
     617       72672 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     618             : 
     619             :         /* I could try and bail if tmp_ctx was NULL, but what return
     620             :          * value would I use?
     621             :          *
     622             :          * It seems easier to continue on the NULL context 
     623             :          */
     624       72672 :         ret1 = canonicalise_fn(ldb, tmp_ctx, v1, &v1_canon);
     625       72672 :         ret2 = canonicalise_fn(ldb, tmp_ctx, v2, &v2_canon);
     626             : 
     627       72672 :         if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
     628       72648 :                 ret = ldb_comparison_binary(ldb, mem_ctx, &v1_canon, &v2_canon);
     629             :         } else {
     630          24 :                 ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
     631             :         }
     632       72672 :         talloc_free(tmp_ctx);
     633       72672 :         return ret;
     634             : }

Generated by: LCOV version 1.13