LCOV - code coverage report
Current view: top level - lib/ldb/common - ldb_msg.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 556 689 80.7 %
Date: 2024-06-13 04:01:37 Functions: 60 66 90.9 %

          Line data    Source code
       1             : /*
       2             :    ldb database library
       3             : 
       4             :    Copyright (C) Andrew Tridgell  2004
       5             : 
       6             :      ** NOTE! The following LGPL license applies to the ldb
       7             :      ** library. This does NOT imply that all of Samba is released
       8             :      ** under the LGPL
       9             : 
      10             :    This library is free software; you can redistribute it and/or
      11             :    modify it under the terms of the GNU Lesser General Public
      12             :    License as published by the Free Software Foundation; either
      13             :    version 3 of the License, or (at your option) any later version.
      14             : 
      15             :    This library is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :    Lesser General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU Lesser General Public
      21             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : /*
      25             :  *  Name: ldb
      26             :  *
      27             :  *  Component: ldb message component utility functions
      28             :  *
      29             :  *  Description: functions for manipulating ldb_message structures
      30             :  *
      31             :  *  Author: Andrew Tridgell
      32             :  */
      33             : 
      34             : #include "ldb_private.h"
      35             : 
      36             : /*
      37             :   create a new ldb_message in a given memory context (NULL for top level)
      38             : */
      39   519776392 : struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
      40             : {
      41   519776392 :         return talloc_zero(mem_ctx, struct ldb_message);
      42             : }
      43             : 
      44             : /*
      45             :   find an element in a message by attribute name
      46             : */
      47  6511418974 : struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
      48             :                                                  const char *attr_name)
      49             : {
      50             :         unsigned int i;
      51 91734938130 :         for (i=0;i<msg->num_elements;i++) {
      52 87139854316 :                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
      53  1916335160 :                         return &msg->elements[i];
      54             :                 }
      55             :         }
      56  4595083814 :         return NULL;
      57             : }
      58             : 
      59             : /*
      60             :   see if two ldb_val structures contain exactly the same data
      61             :   return 1 for a match, 0 for a mis-match
      62             : */
      63   228056592 : int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
      64             : {
      65   228056592 :         if (v1->length != v2->length) return 0;
      66    39438347 :         if (v1->data == v2->data) return 1;
      67    39360803 :         if (v1->length == 0) return 1;
      68             : 
      69    39360803 :         if (memcmp(v1->data, v2->data, v1->length) == 0) {
      70    24127634 :                 return 1;
      71             :         }
      72             : 
      73    15233169 :         return 0;
      74             : }
      75             : 
      76             : /*
      77             :   find a value in an element
      78             :   assumes case sensitive comparison
      79             : */
      80    18029656 : struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
      81             :                                  struct ldb_val *val)
      82             : {
      83             :         unsigned int i;
      84   211426101 :         for (i=0;i<el->num_values;i++) {
      85   211177075 :                 if (ldb_val_equal_exact(val, &el->values[i])) {
      86    17780630 :                         return &el->values[i];
      87             :                 }
      88             :         }
      89      249026 :         return NULL;
      90             : }
      91             : 
      92             : 
      93     6441402 : static int ldb_val_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
      94             : {
      95     6441402 :         if (v1->length != v2->length) {
      96     5384452 :                 return v1->length - v2->length;
      97             :         }
      98     1056950 :         return memcmp(v1->data, v2->data, v1->length);
      99             : }
     100             : 
     101             : 
     102             : /*
     103             :   ldb_msg_find_duplicate_val() will set the **duplicate pointer to the first
     104             :   duplicate value it finds. It does a case sensitive comparison (memcmp).
     105             : 
     106             :   LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown
     107             :   options flag, otherwise LDB_SUCCESS.
     108             : */
     109             : #define LDB_DUP_QUADRATIC_THRESHOLD 10
     110             : 
     111    21920806 : int ldb_msg_find_duplicate_val(struct ldb_context *ldb,
     112             :                                TALLOC_CTX *mem_ctx,
     113             :                                const struct ldb_message_element *el,
     114             :                                struct ldb_val **duplicate,
     115             :                                uint32_t options)
     116             : {
     117             :         unsigned int i, j;
     118             :         struct ldb_val *val;
     119             : 
     120    21920806 :         if (options != 0) {
     121           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     122             :         }
     123             : 
     124    21920806 :         *duplicate = NULL;
     125             : 
     126             :         /*
     127             :            If there are not many values, it is best to avoid the talloc
     128             :            overhead and just do a brute force search.
     129             :          */
     130    21920806 :         if (el->num_values < LDB_DUP_QUADRATIC_THRESHOLD) {
     131    45646658 :                 for (j = 0; j < el->num_values; j++) {
     132    23767527 :                         val = &el->values[j];
     133    27427791 :                         for ( i = j + 1; i < el->num_values; i++) {
     134     3660267 :                                 if (ldb_val_equal_exact(val, &el->values[i])) {
     135           3 :                                         *duplicate = val;
     136           3 :                                         return LDB_SUCCESS;
     137             :                                 }
     138             :                         }
     139             :                 }
     140             :         } else {
     141             :                 struct ldb_val *values;
     142       41672 :                 values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
     143       41672 :                 if (values == NULL) {
     144           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     145             :                 }
     146             : 
     147       41672 :                 memcpy(values, el->values,
     148       41672 :                        el->num_values * sizeof(struct ldb_val));
     149       41672 :                 TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
     150     1495819 :                 for (i = 1; i < el->num_values; i++) {
     151     1454148 :                         if (ldb_val_equal_exact(&values[i],
     152     1454148 :                                                 &values[i - 1])) {
     153             :                                 /* find the original location */
     154           3 :                                 for (j = 0; j < el->num_values; j++) {
     155           3 :                                         if (ldb_val_equal_exact(&values[i],
     156           3 :                                                                 &el->values[j])
     157             :                                                 ) {
     158           1 :                                                 *duplicate = &el->values[j];
     159           1 :                                                 break;
     160             :                                         }
     161             :                                 }
     162           1 :                                 talloc_free(values);
     163           1 :                                 if (*duplicate == NULL) {
     164             :                                         /* how we got here, I don't know */
     165           0 :                                         return LDB_ERR_OPERATIONS_ERROR;
     166             :                                 }
     167           1 :                                 return LDB_SUCCESS;
     168             :                         }
     169             :                 }
     170       41671 :                 talloc_free(values);
     171             :         }
     172    21920802 :         return LDB_SUCCESS;
     173             : }
     174             : 
     175             : 
     176             : /*
     177             :   Determine whether the values in an element are also in another element.
     178             : 
     179             :   Without any flags, return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS if the elements
     180             :   share values, or LDB_SUCCESS if they don't. In this case, the function
     181             :   simply determines the set intersection and it doesn't matter in which order
     182             :   the elements are provided.
     183             : 
     184             :   With the LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES flag, any values in common are
     185             :   removed from the first element and LDB_SUCCESS is returned.
     186             : 
     187             :   LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown option.
     188             :   LDB_ERR_INAPPROPRIATE_MATCHING is returned if the elements differ in name.
     189             : */
     190             : 
     191        3472 : int ldb_msg_find_common_values(struct ldb_context *ldb,
     192             :                                TALLOC_CTX *mem_ctx,
     193             :                                struct ldb_message_element *el,
     194             :                                struct ldb_message_element *el2,
     195             :                                uint32_t options)
     196             : {
     197             :         struct ldb_val *values;
     198             :         struct ldb_val *values2;
     199             :         unsigned int i, j, k, n_values;
     200             : 
     201        3472 :         bool remove_duplicates = options & LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES;
     202             : 
     203        3472 :         if ((options & ~LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES) != 0) {
     204           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     205             :         }
     206             : 
     207        3472 :         if (strcmp(el->name, el2->name) != 0) {
     208           1 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     209             :         }
     210        3471 :         if (el->num_values == 0 || el2->num_values == 0) {
     211          12 :                 return LDB_SUCCESS;
     212             :         }
     213             :         /*
     214             :            With few values, it is better to do the brute-force search than the
     215             :            clever search involving tallocs, memcpys, sorts, etc.
     216             :         */
     217        3591 :         if (MIN(el->num_values, el2->num_values) == 1 ||
     218         157 :             MAX(el->num_values, el2->num_values) < LDB_DUP_QUADRATIC_THRESHOLD) {
     219       15396 :                 for (i = 0; i < el2->num_values; i++) {
     220       24592 :                         for (j = 0; j < el->num_values; j++) {
     221       12555 :                                 if (ldb_val_equal_exact(&el->values[j],
     222       12555 :                                                         &el2->values[i])) {
     223           8 :                                         if (! remove_duplicates) {
     224             :                                             return                      \
     225           6 :                                               LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     226             :                                         }
     227             :                                         /*
     228             :                                           With the remove_duplicates flag, we
     229             :                                           resolve the intersection by removing
     230             :                                           the offending one from el.
     231             :                                         */
     232           2 :                                         el->num_values--;
     233           3 :                                         for (k = j; k < el->num_values; k++) {
     234           1 :                                                 el->values[k] = \
     235           1 :                                                         el->values[k + 1];
     236             :                                         }
     237           2 :                                         j--; /* rewind */
     238             :                                 }
     239             :                         }
     240             :                 }
     241        3353 :                 return LDB_SUCCESS;
     242             :         }
     243             : 
     244         100 :         values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
     245         100 :         if (values == NULL) {
     246           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     247             :         }
     248         100 :         values2 = talloc_array(mem_ctx, struct ldb_val,
     249             :                                     el2->num_values);
     250         100 :         if (values2 == NULL) {
     251           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     252             :         }
     253             : 
     254         100 :         memcpy(values, el->values,
     255         100 :                el->num_values * sizeof(struct ldb_val));
     256         100 :         memcpy(values2, el2->values,
     257         100 :                el2->num_values * sizeof(struct ldb_val));
     258         100 :         TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
     259         100 :         TYPESAFE_QSORT(values2, el2->num_values, ldb_val_cmp);
     260             : 
     261             :         /*
     262             :            el->n_values may diverge from the number of values in the sorted
     263             :            list when the remove_duplicates flag is used.
     264             :         */
     265         100 :         n_values = el->num_values;
     266         100 :         i = 0;
     267         100 :         j = 0;
     268        3380 :         while (i != n_values && j < el2->num_values) {
     269        3196 :                 int ret = ldb_val_cmp(&values[i], &values2[j]);
     270        3196 :                 if (ret < 0) {
     271         721 :                         i++;
     272        2475 :                 } else if (ret > 0) {
     273        2457 :                         j++;
     274             :                 } else {
     275             :                         /* we have a collision */
     276          18 :                         if (! remove_duplicates) {
     277           4 :                                 TALLOC_FREE(values);
     278           4 :                                 TALLOC_FREE(values2);
     279           4 :                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     280             :                         }
     281             :                         /*
     282             :                            With the remove_duplicates flag we need to find
     283             :                            this in the original list and remove it, which is
     284             :                            inefficient but hopefully rare.
     285             :                         */
     286          23 :                         for (k = 0; k < el->num_values; k++) {
     287          23 :                                 if (ldb_val_equal_exact(&el->values[k],
     288          23 :                                                         &values[i])) {
     289          14 :                                         break;
     290             :                                 }
     291             :                         }
     292          14 :                         el->num_values--;
     293          76 :                         for (; k < el->num_values; k++) {
     294          62 :                                 el->values[k] = el->values[k + 1];
     295             :                         }
     296          14 :                         i++;
     297             :                 }
     298             :         }
     299          96 :         TALLOC_FREE(values);
     300          96 :         TALLOC_FREE(values2);
     301             : 
     302          96 :         return LDB_SUCCESS;
     303             : }
     304             : 
     305             : /*
     306             :   duplicate a ldb_val structure
     307             : */
     308  2135242436 : struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
     309             : {
     310             :         struct ldb_val v2;
     311  2135242436 :         v2.length = v->length;
     312  2135242436 :         if (v->data == NULL) {
     313       93122 :                 v2.data = NULL;
     314       93122 :                 return v2;
     315             :         }
     316             : 
     317             :         /* the +1 is to cope with buggy C library routines like strndup
     318             :            that look one byte beyond */
     319  2135149314 :         v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
     320  2135149314 :         if (!v2.data) {
     321           0 :                 v2.length = 0;
     322           0 :                 return v2;
     323             :         }
     324             : 
     325  2135149314 :         memcpy(v2.data, v->data, v->length);
     326  2135149314 :         ((char *)v2.data)[v->length] = 0;
     327  2135149314 :         return v2;
     328             : }
     329             : 
     330             : /**
     331             :  * Adds new empty element to msg->elements
     332             :  */
     333   168174511 : static int _ldb_msg_add_el(struct ldb_message *msg,
     334             :                            struct ldb_message_element **return_el)
     335             : {
     336             :         struct ldb_message_element *els;
     337             : 
     338             :         /*
     339             :          * TODO: Find out a way to assert on input parameters.
     340             :          * msg and return_el must be valid
     341             :          */
     342             : 
     343   168174511 :         els = talloc_realloc(msg, msg->elements,
     344             :                              struct ldb_message_element, msg->num_elements + 1);
     345   168174511 :         if (!els) {
     346           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     347             :         }
     348             : 
     349   168174511 :         ZERO_STRUCT(els[msg->num_elements]);
     350             : 
     351   168174511 :         msg->elements = els;
     352   168174511 :         msg->num_elements++;
     353             : 
     354   168174511 :         *return_el = &els[msg->num_elements-1];
     355             : 
     356   168174511 :         return LDB_SUCCESS;
     357             : }
     358             : 
     359             : /**
     360             :  * Add an empty element with a given name to a message
     361             :  */
     362   166590904 : int ldb_msg_add_empty(struct ldb_message *msg,
     363             :                       const char *attr_name,
     364             :                       int flags,
     365             :                       struct ldb_message_element **return_el)
     366             : {
     367             :         int ret;
     368             :         struct ldb_message_element *el;
     369             : 
     370   166590904 :         ret = _ldb_msg_add_el(msg, &el);
     371   166590904 :         if (ret != LDB_SUCCESS) {
     372           0 :                 return ret;
     373             :         }
     374             : 
     375             :         /* initialize newly added element */
     376   166590904 :         el->flags = flags;
     377   166590904 :         el->name = talloc_strdup(msg->elements, attr_name);
     378   166590904 :         if (!el->name) {
     379           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     380             :         }
     381             : 
     382   166590904 :         if (return_el) {
     383   166250677 :                 *return_el = el;
     384             :         }
     385             : 
     386   166590904 :         return LDB_SUCCESS;
     387             : }
     388             : 
     389             : /**
     390             :  * Adds an element to a message.
     391             :  *
     392             :  * NOTE: Ownership of ldb_message_element fields
     393             :  *       is NOT transferred. Thus, if *el pointer
     394             :  *       is invalidated for some reason, this will
     395             :  *       corrupt *msg contents also
     396             :  */
     397     1583607 : int ldb_msg_add(struct ldb_message *msg,
     398             :                 const struct ldb_message_element *el,
     399             :                 int flags)
     400             : {
     401             :         int ret;
     402             :         struct ldb_message_element *el_new;
     403             :         /* We have to copy this, just in case *el is a pointer into
     404             :          * what ldb_msg_add_empty() is about to realloc() */
     405     1583607 :         struct ldb_message_element el_copy = *el;
     406             : 
     407     1583607 :         ret = _ldb_msg_add_el(msg, &el_new);
     408     1583607 :         if (ret != LDB_SUCCESS) {
     409           0 :                 return ret;
     410             :         }
     411             : 
     412     1583607 :         el_new->flags      = flags;
     413     1583607 :         el_new->name       = el_copy.name;
     414     1583607 :         el_new->num_values = el_copy.num_values;
     415     1583607 :         el_new->values     = el_copy.values;
     416             : 
     417     1583607 :         return LDB_SUCCESS;
     418             : }
     419             : 
     420             : /*
     421             :  * add a value to a message element
     422             :  */
     423   160770533 : int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx,
     424             :                               struct ldb_message_element *el,
     425             :                               const struct ldb_val *val)
     426             : {
     427             :         struct ldb_val *vals;
     428             : 
     429   160770533 :         if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) {
     430             :                 /*
     431             :                  * Another message is using this message element's values array,
     432             :                  * so we don't want to make any modifications to the original
     433             :                  * message, or potentially invalidate its own values by calling
     434             :                  * talloc_realloc(). Make a copy instead.
     435             :                  */
     436          26 :                 el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
     437             : 
     438          26 :                 vals = talloc_array(mem_ctx, struct ldb_val,
     439             :                                     el->num_values + 1);
     440          26 :                 if (vals == NULL) {
     441           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     442             :                 }
     443             : 
     444          26 :                 if (el->values != NULL) {
     445          26 :                         memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val));
     446             :                 }
     447             :         } else {
     448   160770507 :                 vals = talloc_realloc(mem_ctx, el->values, struct ldb_val,
     449             :                                       el->num_values + 1);
     450   160770507 :                 if (vals == NULL) {
     451           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     452             :                 }
     453             :         }
     454   160770533 :         el->values = vals;
     455   160770533 :         el->values[el->num_values] = *val;
     456   160770533 :         el->num_values++;
     457             : 
     458   160770533 :         return LDB_SUCCESS;
     459             : }
     460             : 
     461             : /*
     462             :   add a value to a message
     463             : */
     464   160595918 : int ldb_msg_add_value(struct ldb_message *msg,
     465             :                       const char *attr_name,
     466             :                       const struct ldb_val *val,
     467             :                       struct ldb_message_element **return_el)
     468             : {
     469             :         struct ldb_message_element *el;
     470             :         int ret;
     471             : 
     472   160595918 :         el = ldb_msg_find_element(msg, attr_name);
     473   160595918 :         if (!el) {
     474   156791235 :                 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
     475   156791235 :                 if (ret != LDB_SUCCESS) {
     476           0 :                         return ret;
     477             :                 }
     478             :         }
     479             : 
     480   160595918 :         ret = ldb_msg_element_add_value(msg->elements, el, val);
     481   160595918 :         if (ret != LDB_SUCCESS) {
     482           0 :                 return ret;
     483             :         }
     484             : 
     485   160595918 :         if (return_el) {
     486   158888465 :                 *return_el = el;
     487             :         }
     488             : 
     489   160595918 :         return LDB_SUCCESS;
     490             : }
     491             : 
     492             : 
     493             : /*
     494             :   add a value to a message, stealing it into the 'right' place
     495             : */
     496   135777396 : int ldb_msg_add_steal_value(struct ldb_message *msg,
     497             :                             const char *attr_name,
     498             :                             struct ldb_val *val)
     499             : {
     500             :         int ret;
     501             :         struct ldb_message_element *el;
     502             : 
     503   135777396 :         ret = ldb_msg_add_value(msg, attr_name, val, &el);
     504   135777396 :         if (ret == LDB_SUCCESS) {
     505   135777396 :                 talloc_steal(el->values, val->data);
     506             :         }
     507   135777396 :         return ret;
     508             : }
     509             : 
     510             : 
     511             : /*
     512             :   add a string element to a message, specifying flags
     513             : */
     514    22710281 : int ldb_msg_add_string_flags(struct ldb_message *msg,
     515             :                              const char *attr_name, const char *str,
     516             :                              int flags)
     517             : {
     518             :         struct ldb_val val;
     519             :         int ret;
     520    22710281 :         struct ldb_message_element *el = NULL;
     521             : 
     522    22710281 :         val.data = discard_const_p(uint8_t, str);
     523    22710281 :         val.length = strlen(str);
     524             : 
     525    22710281 :         if (val.length == 0) {
     526             :                 /* allow empty strings as non-existent attributes */
     527         266 :                 return LDB_SUCCESS;
     528             :         }
     529             : 
     530    22710015 :         ret = ldb_msg_add_value(msg, attr_name, &val, &el);
     531    22710015 :         if (ret != LDB_SUCCESS) {
     532           0 :                 return ret;
     533             :         }
     534             : 
     535    22710015 :         if (flags != 0) {
     536       62237 :                 el->flags = flags;
     537             :         }
     538             : 
     539    22710015 :         return LDB_SUCCESS;
     540             : }
     541             : 
     542             : /*
     543             :   add a string element to a message
     544             : */
     545    22648044 : int ldb_msg_add_string(struct ldb_message *msg,
     546             :                        const char *attr_name, const char *str)
     547             : {
     548    22648044 :         return ldb_msg_add_string_flags(msg, attr_name, str, 0);
     549             : }
     550             : 
     551             : /*
     552             :   add a string element to a message, stealing it into the 'right' place
     553             : */
     554   121895787 : int ldb_msg_add_steal_string(struct ldb_message *msg,
     555             :                              const char *attr_name, char *str)
     556             : {
     557             :         struct ldb_val val;
     558             : 
     559   121895787 :         val.data = (uint8_t *)str;
     560   121895787 :         val.length = strlen(str);
     561             : 
     562   121895787 :         if (val.length == 0) {
     563             :                 /* allow empty strings as non-existent attributes */
     564           0 :                 return LDB_SUCCESS;
     565             :         }
     566             : 
     567   121895787 :         return ldb_msg_add_steal_value(msg, attr_name, &val);
     568             : }
     569             : 
     570             : /*
     571             :   add a DN element to a message
     572             :   WARNING: this uses the linearized string from the dn, and does not
     573             :   copy the string.
     574             : */
     575        1600 : int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
     576             :                               struct ldb_dn *dn)
     577             : {
     578        1600 :         char *str = ldb_dn_alloc_linearized(msg, dn);
     579             : 
     580        1600 :         if (str == NULL) {
     581             :                 /* we don't want to have unknown DNs added */
     582           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     583             :         }
     584             : 
     585        1600 :         return ldb_msg_add_steal_string(msg, attr_name, str);
     586             : }
     587             : 
     588             : /*
     589             :   add a printf formatted element to a message
     590             : */
     591     7763844 : int ldb_msg_add_fmt(struct ldb_message *msg,
     592             :                     const char *attr_name, const char *fmt, ...)
     593             : {
     594             :         struct ldb_val val;
     595             :         va_list ap;
     596             :         char *str;
     597             : 
     598     7763844 :         va_start(ap, fmt);
     599     7763844 :         str = talloc_vasprintf(msg, fmt, ap);
     600     7763844 :         va_end(ap);
     601             : 
     602     7763844 :         if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
     603             : 
     604     7763844 :         val.data   = (uint8_t *)str;
     605     7763844 :         val.length = strlen(str);
     606             : 
     607     7763844 :         return ldb_msg_add_steal_value(msg, attr_name, &val);
     608             : }
     609             : 
     610      174187 : static int ldb_msg_append_value_impl(struct ldb_message *msg,
     611             :                                      const char *attr_name,
     612             :                                      const struct ldb_val *val,
     613             :                                      int flags,
     614             :                                      struct ldb_message_element **return_el)
     615             : {
     616      174187 :         struct ldb_message_element *el = NULL;
     617             :         int ret;
     618             : 
     619      174187 :         ret = ldb_msg_add_empty(msg, attr_name, flags, &el);
     620      174187 :         if (ret != LDB_SUCCESS) {
     621           0 :                 return ret;
     622             :         }
     623             : 
     624      174187 :         ret = ldb_msg_element_add_value(msg->elements, el, val);
     625      174187 :         if (ret != LDB_SUCCESS) {
     626           0 :                 return ret;
     627             :         }
     628             : 
     629      174187 :         if (return_el != NULL) {
     630        1542 :                 *return_el = el;
     631             :         }
     632             : 
     633      174187 :         return LDB_SUCCESS;
     634             : }
     635             : 
     636             : /*
     637             :   append a value to a message
     638             : */
     639      172645 : int ldb_msg_append_value(struct ldb_message *msg,
     640             :                          const char *attr_name,
     641             :                          const struct ldb_val *val,
     642             :                          int flags)
     643             : {
     644      172645 :         return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL);
     645             : }
     646             : 
     647             : /*
     648             :   append a value to a message, stealing it into the 'right' place
     649             : */
     650        1542 : int ldb_msg_append_steal_value(struct ldb_message *msg,
     651             :                                const char *attr_name,
     652             :                                struct ldb_val *val,
     653             :                                int flags)
     654             : {
     655             :         int ret;
     656        1542 :         struct ldb_message_element *el = NULL;
     657             : 
     658        1542 :         ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el);
     659        1542 :         if (ret == LDB_SUCCESS) {
     660        1542 :                 talloc_steal(el->values, val->data);
     661             :         }
     662        1542 :         return ret;
     663             : }
     664             : 
     665             : /*
     666             :   append a string element to a message, stealing it into the 'right' place
     667             : */
     668         696 : int ldb_msg_append_steal_string(struct ldb_message *msg,
     669             :                                 const char *attr_name, char *str,
     670             :                                 int flags)
     671             : {
     672             :         struct ldb_val val;
     673             : 
     674         696 :         val.data = (uint8_t *)str;
     675         696 :         val.length = strlen(str);
     676             : 
     677         696 :         if (val.length == 0) {
     678             :                 /* allow empty strings as non-existent attributes */
     679           0 :                 return LDB_SUCCESS;
     680             :         }
     681             : 
     682         696 :         return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
     683             : }
     684             : 
     685             : /*
     686             :   append a string element to a message
     687             : */
     688       45659 : int ldb_msg_append_string(struct ldb_message *msg,
     689             :                           const char *attr_name, const char *str, int flags)
     690             : {
     691             :         struct ldb_val val;
     692             : 
     693       45659 :         val.data = discard_const_p(uint8_t, str);
     694       45659 :         val.length = strlen(str);
     695             : 
     696       45659 :         if (val.length == 0) {
     697             :                 /* allow empty strings as non-existent attributes */
     698           0 :                 return LDB_SUCCESS;
     699             :         }
     700             : 
     701       45659 :         return ldb_msg_append_value(msg, attr_name, &val, flags);
     702             : }
     703             : 
     704             : /*
     705             :   append a DN element to a message
     706             :   WARNING: this uses the linearized string from the dn, and does not
     707             :   copy the string.
     708             : */
     709           0 : int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name,
     710             :                                  struct ldb_dn *dn, int flags)
     711             : {
     712           0 :         char *str = ldb_dn_alloc_linearized(msg, dn);
     713             : 
     714           0 :         if (str == NULL) {
     715             :                 /* we don't want to have unknown DNs added */
     716           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     717             :         }
     718             : 
     719           0 :         return ldb_msg_append_steal_string(msg, attr_name, str, flags);
     720             : }
     721             : 
     722             : /*
     723             :   append a printf formatted element to a message
     724             : */
     725         846 : int ldb_msg_append_fmt(struct ldb_message *msg, int flags,
     726             :                        const char *attr_name, const char *fmt, ...)
     727             : {
     728             :         struct ldb_val val;
     729             :         va_list ap;
     730         846 :         char *str = NULL;
     731             : 
     732         846 :         va_start(ap, fmt);
     733         846 :         str = talloc_vasprintf(msg, fmt, ap);
     734         846 :         va_end(ap);
     735             : 
     736         846 :         if (str == NULL) {
     737           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     738             :         }
     739             : 
     740         846 :         val.data   = (uint8_t *)str;
     741         846 :         val.length = strlen(str);
     742             : 
     743         846 :         return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
     744             : }
     745             : 
     746             : /*
     747             :   compare two ldb_message_element structures
     748             :   assumes case sensitive comparison
     749             : */
     750    13656510 : int ldb_msg_element_compare(struct ldb_message_element *el1,
     751             :                             struct ldb_message_element *el2)
     752             : {
     753             :         unsigned int i;
     754             : 
     755    13656510 :         if (el1->num_values != el2->num_values) {
     756          95 :                 return el1->num_values - el2->num_values;
     757             :         }
     758             : 
     759    30203098 :         for (i=0;i<el1->num_values;i++) {
     760    16601136 :                 if (!ldb_msg_find_val(el2, &el1->values[i])) {
     761       54453 :                         return -1;
     762             :                 }
     763             :         }
     764             : 
     765    13601962 :         return 0;
     766             : }
     767             : 
     768             : /*
     769             :   compare two ldb_message_element structures.
     770             :   Different ordering is considered a mismatch
     771             : */
     772     8687952 : bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
     773             :                                    const struct ldb_message_element *el2)
     774             : {
     775             :         unsigned i;
     776     8687952 :         if (el1->num_values != el2->num_values) {
     777      824538 :                 return false;
     778             :         }
     779    11938582 :         for (i=0;i<el1->num_values;i++) {
     780     8319822 :                 if (ldb_val_equal_exact(&el1->values[i],
     781     8319822 :                                         &el2->values[i]) != 1) {
     782     4244654 :                         return false;
     783             :                 }
     784             :         }
     785     3618760 :         return true;
     786             : }
     787             : 
     788             : /*
     789             :   compare two ldb_message_element structures
     790             :   comparing by element name
     791             : */
     792   167410995 : int ldb_msg_element_compare_name(struct ldb_message_element *el1,
     793             :                                  struct ldb_message_element *el2)
     794             : {
     795   167410995 :         return ldb_attr_cmp(el1->name, el2->name);
     796             : }
     797             : 
     798     4571470 : void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el)
     799             : {
     800     4571470 :         el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
     801     4571470 : }
     802             : 
     803   149915925 : bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el)
     804             : {
     805   149915925 :         return (el->flags & LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE) != 0;
     806             : }
     807             : 
     808     1306591 : void ldb_msg_remove_inaccessible(struct ldb_message *msg)
     809             : {
     810             :         unsigned i;
     811     1306591 :         unsigned num_del = 0;
     812             : 
     813     9261278 :         for (i = 0; i < msg->num_elements; ++i) {
     814     7954687 :                 if (ldb_msg_element_is_inaccessible(&msg->elements[i])) {
     815     4566818 :                         ++num_del;
     816     3387869 :                 } else if (num_del) {
     817     2473033 :                         msg->elements[i - num_del] = msg->elements[i];
     818             :                 }
     819             :         }
     820             : 
     821     1306591 :         msg->num_elements -= num_del;
     822     1306591 : }
     823             : 
     824             : /*
     825             :   convenience functions to return common types from a message
     826             :   these return the first value if the attribute is multi-valued
     827             : */
     828  2267134604 : const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
     829             :                                            const char *attr_name)
     830             : {
     831  2267134604 :         struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
     832  2267134604 :         if (!el || el->num_values == 0) {
     833  1007832003 :                 return NULL;
     834             :         }
     835  1259302601 :         return &el->values[0];
     836             : }
     837             : 
     838    99200037 : int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
     839             :                              const char *attr_name,
     840             :                              int default_value)
     841             : {
     842    99200037 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     843             :         char buf[sizeof("-2147483648")];
     844    99200037 :         char *end = NULL;
     845             :         int ret;
     846             : 
     847    99200037 :         if (!v || !v->data) {
     848     1336648 :                 return default_value;
     849             :         }
     850             : 
     851    97863389 :         ZERO_STRUCT(buf);
     852    97863389 :         if (v->length >= sizeof(buf)) {
     853          66 :                 return default_value;
     854             :         }
     855             : 
     856    97863323 :         memcpy(buf, v->data, v->length);
     857    97863323 :         errno = 0;
     858    97863323 :         ret = (int) strtoll(buf, &end, 10);
     859    97863323 :         if (errno != 0) {
     860           0 :                 return default_value;
     861             :         }
     862    97863323 :         if (end && end[0] != '\0') {
     863           0 :                 return default_value;
     864             :         }
     865    97863323 :         return ret;
     866             : }
     867             : 
     868   406199237 : unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
     869             :                                        const char *attr_name,
     870             :                                        unsigned int default_value)
     871             : {
     872   406199237 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     873             :         char buf[sizeof("-2147483648")];
     874   406199237 :         char *end = NULL;
     875             :         unsigned int ret;
     876             : 
     877   406199237 :         if (!v || !v->data) {
     878   202149852 :                 return default_value;
     879             :         }
     880             : 
     881   204049385 :         ZERO_STRUCT(buf);
     882   204049385 :         if (v->length >= sizeof(buf)) {
     883          50 :                 return default_value;
     884             :         }
     885             : 
     886   204049335 :         memcpy(buf, v->data, v->length);
     887   204049335 :         errno = 0;
     888   204049335 :         ret = (unsigned int) strtoll(buf, &end, 10);
     889   204049335 :         if (errno != 0) {
     890           0 :                 errno = 0;
     891           0 :                 ret = (unsigned int) strtoull(buf, &end, 10);
     892           0 :                 if (errno != 0) {
     893           0 :                         return default_value;
     894             :                 }
     895             :         }
     896   204049335 :         if (end && end[0] != '\0') {
     897          39 :                 return default_value;
     898             :         }
     899   204049296 :         return ret;
     900             : }
     901             : 
     902     1826150 : int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
     903             :                                    const char *attr_name,
     904             :                                    int64_t default_value)
     905             : {
     906     1826150 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     907             :         char buf[sizeof("-9223372036854775808")];
     908     1826150 :         char *end = NULL;
     909             :         int64_t ret;
     910             : 
     911     1826150 :         if (!v || !v->data) {
     912      396461 :                 return default_value;
     913             :         }
     914             : 
     915     1429689 :         ZERO_STRUCT(buf);
     916     1429689 :         if (v->length >= sizeof(buf)) {
     917           0 :                 return default_value;
     918             :         }
     919             : 
     920     1429689 :         memcpy(buf, v->data, v->length);
     921     1429689 :         errno = 0;
     922     1429689 :         ret = (int64_t) strtoll(buf, &end, 10);
     923     1429689 :         if (errno != 0) {
     924           0 :                 return default_value;
     925             :         }
     926     1429689 :         if (end && end[0] != '\0') {
     927           0 :                 return default_value;
     928             :         }
     929     1429689 :         return ret;
     930             : }
     931             : 
     932   159187020 : uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
     933             :                                      const char *attr_name,
     934             :                                      uint64_t default_value)
     935             : {
     936   159187020 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     937             :         char buf[sizeof("-9223372036854775808")];
     938   159187020 :         char *end = NULL;
     939             :         uint64_t ret;
     940             : 
     941   159187020 :         if (!v || !v->data) {
     942    78963658 :                 return default_value;
     943             :         }
     944             : 
     945    80223362 :         ZERO_STRUCT(buf);
     946    80223362 :         if (v->length >= sizeof(buf)) {
     947           0 :                 return default_value;
     948             :         }
     949             : 
     950    80223362 :         memcpy(buf, v->data, v->length);
     951    80223362 :         errno = 0;
     952    80223362 :         ret = (uint64_t) strtoll(buf, &end, 10);
     953    80223362 :         if (errno != 0) {
     954           0 :                 errno = 0;
     955           0 :                 ret = (uint64_t) strtoull(buf, &end, 10);
     956           0 :                 if (errno != 0) {
     957           0 :                         return default_value;
     958             :                 }
     959             :         }
     960    80223362 :         if (end && end[0] != '\0') {
     961           0 :                 return default_value;
     962             :         }
     963    80223362 :         return ret;
     964             : }
     965             : 
     966           0 : double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
     967             :                                    const char *attr_name,
     968             :                                    double default_value)
     969             : {
     970           0 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     971             :         char *buf;
     972           0 :         char *end = NULL;
     973             :         double ret;
     974             : 
     975           0 :         if (!v || !v->data) {
     976           0 :                 return default_value;
     977             :         }
     978           0 :         buf = talloc_strndup(msg, (const char *)v->data, v->length);
     979           0 :         if (buf == NULL) {
     980           0 :                 return default_value;
     981             :         }
     982             : 
     983           0 :         errno = 0;
     984           0 :         ret = strtod(buf, &end);
     985           0 :         talloc_free(buf);
     986           0 :         if (errno != 0) {
     987           0 :                 return default_value;
     988             :         }
     989           0 :         if (end && end[0] != '\0') {
     990           0 :                 return default_value;
     991             :         }
     992           0 :         return ret;
     993             : }
     994             : 
     995     6671959 : int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
     996             :                               const char *attr_name,
     997             :                               int default_value)
     998             : {
     999     6671959 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
    1000     6671959 :         if (!v || !v->data) {
    1001     2634959 :                 return default_value;
    1002             :         }
    1003     4037000 :         if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
    1004       69770 :                 return 0;
    1005             :         }
    1006     3967230 :         if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
    1007     3967230 :                 return 1;
    1008             :         }
    1009           0 :         return default_value;
    1010             : }
    1011             : 
    1012   529167844 : const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
    1013             :                                         const char *attr_name,
    1014             :                                         const char *default_value)
    1015             : {
    1016   529167844 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
    1017   529167844 :         if (!v || !v->data) {
    1018   337198418 :                 return default_value;
    1019             :         }
    1020   191969426 :         if (v->data[v->length] != '\0') {
    1021           0 :                 return default_value;
    1022             :         }
    1023   191969426 :         return (const char *)v->data;
    1024             : }
    1025             : 
    1026     4193612 : struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
    1027             :                                        TALLOC_CTX *mem_ctx,
    1028             :                                        const struct ldb_message *msg,
    1029             :                                        const char *attr_name)
    1030             : {
    1031             :         struct ldb_dn *res_dn;
    1032             :         const struct ldb_val *v;
    1033             : 
    1034     4193612 :         v = ldb_msg_find_ldb_val(msg, attr_name);
    1035     4193612 :         if (!v || !v->data) {
    1036      838625 :                 return NULL;
    1037             :         }
    1038     3354987 :         res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
    1039     3354987 :         if ( ! ldb_dn_validate(res_dn)) {
    1040           0 :                 talloc_free(res_dn);
    1041           0 :                 return NULL;
    1042             :         }
    1043     3354987 :         return res_dn;
    1044             : }
    1045             : 
    1046             : /*
    1047             :   sort the elements of a message by name
    1048             : */
    1049     1193426 : void ldb_msg_sort_elements(struct ldb_message *msg)
    1050             : {
    1051     1193426 :         TYPESAFE_QSORT(msg->elements, msg->num_elements,
    1052             :                        ldb_msg_element_compare_name);
    1053     1193426 : }
    1054             : 
    1055     6552207 : static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx,
    1056             :                                          const struct ldb_message *msg)
    1057             : {
    1058             :         struct ldb_message *msg2;
    1059             :         unsigned int i;
    1060             : 
    1061     6552207 :         msg2 = talloc(mem_ctx, struct ldb_message);
    1062     6552207 :         if (msg2 == NULL) return NULL;
    1063             : 
    1064     6552207 :         *msg2 = *msg;
    1065             : 
    1066     6552207 :         msg2->elements = talloc_array(msg2, struct ldb_message_element,
    1067             :                                       msg2->num_elements);
    1068     6552207 :         if (msg2->elements == NULL) goto failed;
    1069             : 
    1070    69776288 :         for (i=0;i<msg2->num_elements;i++) {
    1071    63224081 :                 msg2->elements[i] = msg->elements[i];
    1072             :         }
    1073             : 
    1074     6552207 :         return msg2;
    1075             : 
    1076           0 : failed:
    1077           0 :         talloc_free(msg2);
    1078           0 :         return NULL;
    1079             : }
    1080             : 
    1081             : /*
    1082             :   shallow copy a message - copying only the elements array so that the caller
    1083             :   can safely add new elements without changing the message
    1084             : */
    1085     5226811 : struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
    1086             :                                          const struct ldb_message *msg)
    1087             : {
    1088             :         struct ldb_message *msg2;
    1089             :         unsigned int i;
    1090             : 
    1091     5226811 :         msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
    1092     5226811 :         if (msg2 == NULL) {
    1093           0 :                 return NULL;
    1094             :         }
    1095             : 
    1096    40666641 :         for (i = 0; i < msg2->num_elements; ++i) {
    1097             :                 /*
    1098             :                  * Mark this message's elements as sharing their values with the
    1099             :                  * original message, so that we don't inadvertently modify or
    1100             :                  * free them. We don't mark the original message element as
    1101             :                  * shared, so the original message element should not be
    1102             :                  * modified or freed while the shallow copy lives.
    1103             :                  */
    1104    35439830 :                 struct ldb_message_element *el = &msg2->elements[i];
    1105    35439830 :                 el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
    1106             :         }
    1107             : 
    1108     5226811 :         return msg2;
    1109             : }
    1110             : 
    1111             : /*
    1112             :   copy a message, allocating new memory for all parts
    1113             : */
    1114     1325396 : struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
    1115             :                                  const struct ldb_message *msg)
    1116             : {
    1117             :         struct ldb_message *msg2;
    1118             :         unsigned int i, j;
    1119             : 
    1120     1325396 :         msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
    1121     1325396 :         if (msg2 == NULL) return NULL;
    1122             : 
    1123     1325396 :         if (msg2->dn != NULL) {
    1124     1325384 :                 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
    1125     1325384 :                 if (msg2->dn == NULL) goto failed;
    1126             :         }
    1127             : 
    1128    29109647 :         for (i=0;i<msg2->num_elements;i++) {
    1129    27784251 :                 struct ldb_message_element *el = &msg2->elements[i];
    1130    27784251 :                 struct ldb_val *values = el->values;
    1131    27784251 :                 el->name = talloc_strdup(msg2->elements, el->name);
    1132    27784251 :                 if (el->name == NULL) goto failed;
    1133    27784251 :                 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
    1134    27784251 :                 if (el->values == NULL) goto failed;
    1135    61398669 :                 for (j=0;j<el->num_values;j++) {
    1136    33614418 :                         el->values[j] = ldb_val_dup(el->values, &values[j]);
    1137    33614418 :                         if (el->values[j].data == NULL && values[j].length != 0) {
    1138           0 :                                 goto failed;
    1139             :                         }
    1140             :                 }
    1141             : 
    1142             :                 /*
    1143             :                  * Since we copied this element's values, we can mark them as
    1144             :                  * not shared.
    1145             :                  */
    1146    27784251 :                 el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
    1147             :         }
    1148             : 
    1149     1325396 :         return msg2;
    1150             : 
    1151           0 : failed:
    1152           0 :         talloc_free(msg2);
    1153           0 :         return NULL;
    1154             : }
    1155             : 
    1156             : 
    1157             : /**
    1158             :  * Canonicalize a message, merging elements of the same name
    1159             :  */
    1160           0 : struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
    1161             :                                          const struct ldb_message *msg)
    1162             : {
    1163             :         int ret;
    1164             :         struct ldb_message *msg2;
    1165             : 
    1166             :         /*
    1167             :          * Preserve previous behavior and allocate
    1168             :          * *msg2 into *ldb context
    1169             :          */
    1170           0 :         ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
    1171           0 :         if (ret != LDB_SUCCESS) {
    1172           0 :                 return NULL;
    1173             :         }
    1174             : 
    1175           0 :         return msg2;
    1176             : }
    1177             : 
    1178             : /**
    1179             :  * Canonicalize a message, merging elements of the same name
    1180             :  */
    1181     1193251 : int ldb_msg_normalize(struct ldb_context *ldb,
    1182             :                       TALLOC_CTX *mem_ctx,
    1183             :                       const struct ldb_message *msg,
    1184             :                       struct ldb_message **_msg_out)
    1185             : {
    1186             :         unsigned int i;
    1187             :         struct ldb_message *msg2;
    1188             : 
    1189     1193251 :         msg2 = ldb_msg_copy(mem_ctx, msg);
    1190     1193251 :         if (msg2 == NULL) {
    1191           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1192             :         }
    1193             : 
    1194     1193251 :         ldb_msg_sort_elements(msg2);
    1195             : 
    1196    26704237 :         for (i=1; i < msg2->num_elements; i++) {
    1197    25510986 :                 struct ldb_message_element *el1 = &msg2->elements[i-1];
    1198    25510986 :                 struct ldb_message_element *el2 = &msg2->elements[i];
    1199             : 
    1200    25510986 :                 if (ldb_msg_element_compare_name(el1, el2) == 0) {
    1201        5377 :                         el1->values = talloc_realloc(msg2->elements,
    1202             :                                                      el1->values, struct ldb_val,
    1203             :                                                      el1->num_values + el2->num_values);
    1204        5377 :                         if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
    1205           0 :                                 talloc_free(msg2);
    1206           0 :                                 return LDB_ERR_OPERATIONS_ERROR;
    1207             :                         }
    1208       10495 :                         memcpy(el1->values + el1->num_values,
    1209        5377 :                                el2->values,
    1210        5377 :                                sizeof(struct ldb_val) * el2->num_values);
    1211        5377 :                         el1->num_values += el2->num_values;
    1212        5377 :                         talloc_free(discard_const_p(char, el2->name));
    1213        5377 :                         if ((i+1) < msg2->num_elements) {
    1214           0 :                                 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
    1215           0 :                                         (msg2->num_elements - (i+1)));
    1216             :                         }
    1217        5377 :                         msg2->num_elements--;
    1218        5377 :                         i--;
    1219             :                 }
    1220             :         }
    1221             : 
    1222     1193251 :         *_msg_out = msg2;
    1223     1193251 :         return LDB_SUCCESS;
    1224             : }
    1225             : 
    1226             : 
    1227             : /**
    1228             :  * return a ldb_message representing the differences between msg1 and msg2.
    1229             :  * If you then use this in a ldb_modify() call,
    1230             :  * it can be used to save edits to a message
    1231             :  */
    1232           0 : struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
    1233             :                                  struct ldb_message *msg1,
    1234             :                                  struct ldb_message *msg2)
    1235             : {
    1236             :         int ldb_ret;
    1237             :         struct ldb_message *mod;
    1238             : 
    1239           0 :         ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
    1240           0 :         if (ldb_ret != LDB_SUCCESS) {
    1241           0 :                 return NULL;
    1242             :         }
    1243             : 
    1244           0 :         return mod;
    1245             : }
    1246             : 
    1247             : /**
    1248             :  * return a ldb_message representing the differences between msg1 and msg2.
    1249             :  * If you then use this in a ldb_modify() call it can be used to save edits to a message
    1250             :  *
    1251             :  * Result message is constructed as follows:
    1252             :  * - LDB_FLAG_MOD_ADD     - elements found only in msg2
    1253             :  * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
    1254             :  *                          Value for msg2 element is used
    1255             :  * - LDB_FLAG_MOD_DELETE  - elements found only in msg2
    1256             :  *
    1257             :  * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
    1258             :  */
    1259       64914 : int ldb_msg_difference(struct ldb_context *ldb,
    1260             :                        TALLOC_CTX *mem_ctx,
    1261             :                        struct ldb_message *msg1,
    1262             :                        struct ldb_message *msg2,
    1263             :                        struct ldb_message **_msg_out)
    1264             : {
    1265             :         int ldb_res;
    1266             :         unsigned int i;
    1267             :         struct ldb_message *mod;
    1268             :         struct ldb_message_element *el;
    1269             :         TALLOC_CTX *temp_ctx;
    1270             : 
    1271       64914 :         temp_ctx = talloc_new(mem_ctx);
    1272       64914 :         if (!temp_ctx) {
    1273           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1274             :         }
    1275             : 
    1276       64914 :         mod = ldb_msg_new(temp_ctx);
    1277       64914 :         if (mod == NULL) {
    1278           0 :                 goto failed;
    1279             :         }
    1280             : 
    1281       64914 :         mod->dn = msg1->dn;
    1282       64914 :         mod->num_elements = 0;
    1283       64914 :         mod->elements = NULL;
    1284             : 
    1285             :         /*
    1286             :          * Canonicalize *msg2 so we have no repeated elements
    1287             :          * Resulting message is allocated in *mod's mem context,
    1288             :          * as we are going to move some elements from *msg2 to
    1289             :          * *mod object later
    1290             :          */
    1291       64914 :         ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
    1292       64914 :         if (ldb_res != LDB_SUCCESS) {
    1293           0 :                 goto failed;
    1294             :         }
    1295             : 
    1296             :         /* look in msg2 to find elements that need to be added or modified */
    1297    13715880 :         for (i=0;i<msg2->num_elements;i++) {
    1298    13650966 :                 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
    1299             : 
    1300    13650966 :                 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
    1301    13595230 :                         continue;
    1302             :                 }
    1303             : 
    1304      111326 :                 ldb_res = ldb_msg_add(mod,
    1305       55736 :                                       &msg2->elements[i],
    1306             :                                       el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
    1307       55736 :                 if (ldb_res != LDB_SUCCESS) {
    1308           0 :                         goto failed;
    1309             :                 }
    1310             :         }
    1311             : 
    1312             :         /* look in msg1 to find elements that need to be deleted */
    1313    13715254 :         for (i=0;i<msg1->num_elements;i++) {
    1314    13650340 :                 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
    1315    13650340 :                 if (el == NULL) {
    1316         575 :                         ldb_res = ldb_msg_add_empty(mod,
    1317         575 :                                                     msg1->elements[i].name,
    1318             :                                                     LDB_FLAG_MOD_DELETE, NULL);
    1319         575 :                         if (ldb_res != LDB_SUCCESS) {
    1320           0 :                                 goto failed;
    1321             :                         }
    1322             :                 }
    1323             :         }
    1324             : 
    1325             :         /* steal resulting message into supplied context */
    1326       64914 :         talloc_steal(mem_ctx, mod);
    1327       64914 :         *_msg_out = mod;
    1328             : 
    1329       64914 :         talloc_free(temp_ctx);
    1330       64914 :         return LDB_SUCCESS;
    1331             : 
    1332           0 : failed:
    1333           0 :         talloc_free(temp_ctx);
    1334           0 :         return LDB_ERR_OPERATIONS_ERROR;
    1335             : }
    1336             : 
    1337             : 
    1338      932473 : int ldb_msg_sanity_check(struct ldb_context *ldb,
    1339             :                          const struct ldb_message *msg)
    1340             : {
    1341             :         unsigned int i, j;
    1342             : 
    1343             :         /* basic check on DN */
    1344      932473 :         if (msg->dn == NULL) {
    1345           0 :                 ldb_set_errstring(ldb, "ldb message lacks a DN!");
    1346           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
    1347             :         }
    1348             : 
    1349             :         /* basic syntax checks */
    1350     5222268 :         for (i = 0; i < msg->num_elements; i++) {
    1351    10103104 :                 for (j = 0; j < msg->elements[i].num_values; j++) {
    1352     5813309 :                         if (msg->elements[i].values[j].length == 0) {
    1353             :                                 /* an attribute cannot be empty */
    1354           4 :                                 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
    1355           2 :                                                             msg->elements[i].name,
    1356           0 :                                                             ldb_dn_get_linearized(msg->dn));
    1357           2 :                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1358             :                         }
    1359             :                 }
    1360             :         }
    1361             : 
    1362      932471 :         return LDB_SUCCESS;
    1363             : }
    1364             : 
    1365             : 
    1366             : 
    1367             : 
    1368             : /*
    1369             :   copy an attribute list. This only copies the array, not the elements
    1370             :   (ie. the elements are left as the same pointers)
    1371             : */
    1372     8010365 : const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
    1373             : {
    1374             :         const char **ret;
    1375             :         unsigned int i;
    1376             : 
    1377    15377791 :         for (i=0;attrs && attrs[i];i++) /* noop */ ;
    1378     8010365 :         ret = talloc_array(mem_ctx, const char *, i+1);
    1379     8010365 :         if (ret == NULL) {
    1380           0 :                 return NULL;
    1381             :         }
    1382   214715127 :         for (i=0;attrs && attrs[i];i++) {
    1383   206704762 :                 ret[i] = attrs[i];
    1384             :         }
    1385     8010365 :         ret[i] = attrs[i];
    1386     8010365 :         return ret;
    1387             : }
    1388             : 
    1389             : 
    1390             : /*
    1391             :   copy an attribute list. This only copies the array, not the elements
    1392             :   (ie. the elements are left as the same pointers).  The new attribute is added to the list.
    1393             : */
    1394     8314060 : const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
    1395             : {
    1396             :         const char **ret;
    1397             :         unsigned int i;
    1398     8314060 :         bool found = false;
    1399             : 
    1400   191473450 :         for (i=0;attrs && attrs[i];i++) {
    1401   183159390 :                 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
    1402     5770423 :                         found = true;
    1403             :                 }
    1404             :         }
    1405     8314060 :         if (found) {
    1406     5141689 :                 return ldb_attr_list_copy(mem_ctx, attrs);
    1407             :         }
    1408     3172371 :         ret = talloc_array(mem_ctx, const char *, i+2);
    1409     3172371 :         if (ret == NULL) {
    1410           0 :                 return NULL;
    1411             :         }
    1412    26330142 :         for (i=0;attrs && attrs[i];i++) {
    1413    23157771 :                 ret[i] = attrs[i];
    1414             :         }
    1415     3172371 :         ret[i] = new_attr;
    1416     3172371 :         ret[i+1] = NULL;
    1417     3172371 :         return ret;
    1418             : }
    1419             : 
    1420             : 
    1421             : /*
    1422             :   return 1 if an attribute is in a list of attributes, or 0 otherwise
    1423             : */
    1424  1437996920 : int ldb_attr_in_list(const char * const *attrs, const char *attr)
    1425             : {
    1426             :         unsigned int i;
    1427  4104338148 :         for (i=0;attrs && attrs[i];i++) {
    1428  2738548174 :                 if (ldb_attr_cmp(attrs[i], attr) == 0) {
    1429    72206946 :                         return 1;
    1430             :                 }
    1431             :         }
    1432  1365789974 :         return 0;
    1433             : }
    1434             : 
    1435             : 
    1436             : /*
    1437             :   rename the specified attribute in a search result
    1438             : */
    1439           3 : int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
    1440             : {
    1441           3 :         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
    1442           3 :         if (el == NULL) {
    1443           0 :                 return LDB_SUCCESS;
    1444             :         }
    1445           3 :         el->name = talloc_strdup(msg->elements, replace);
    1446           3 :         if (el->name == NULL) {
    1447           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1448             :         }
    1449           3 :         return LDB_SUCCESS;
    1450             : }
    1451             : 
    1452             : 
    1453             : /*
    1454             :   copy the specified attribute in a search result to a new attribute
    1455             : */
    1456           3 : int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
    1457             : {
    1458           3 :         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
    1459             :         int ret;
    1460             : 
    1461           3 :         if (el == NULL) {
    1462           0 :                 return LDB_SUCCESS;
    1463             :         }
    1464           3 :         ret = ldb_msg_add(msg, el, 0);
    1465           3 :         if (ret != LDB_SUCCESS) {
    1466           0 :                 return ret;
    1467             :         }
    1468           3 :         return ldb_msg_rename_attr(msg, attr, replace);
    1469             : }
    1470             : 
    1471             : /*
    1472             :   remove the specified element in a search result
    1473             : */
    1474    44166363 : void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
    1475             : {
    1476    44166363 :         ptrdiff_t n = (el - msg->elements);
    1477    44166363 :         if (n >= msg->num_elements || n < 0) {
    1478             :                 /* the element is not in the list. the caller is crazy. */
    1479           0 :                 return;
    1480             :         }
    1481    44166363 :         msg->num_elements--;
    1482    44166363 :         if (n != msg->num_elements) {
    1483    21365756 :                 memmove(el, el+1, (msg->num_elements - n)*sizeof(*el));
    1484             :         }
    1485             : }
    1486             : 
    1487             : 
    1488             : /*
    1489             :   remove the specified attribute in a search result
    1490             : */
    1491  1770211138 : void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
    1492             : {
    1493             :         struct ldb_message_element *el;
    1494             : 
    1495  3196055405 :         while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
    1496    37784538 :                 ldb_msg_remove_element(msg, el);
    1497             :         }
    1498  1770211138 : }
    1499             : 
    1500             : /* Reallocate elements to drop any excess capacity. */
    1501   117671531 : void ldb_msg_shrink_to_fit(struct ldb_message *msg)
    1502             : {
    1503   117671531 :         if (msg->num_elements > 0) {
    1504   104617933 :                 struct ldb_message_element *elements = talloc_realloc(msg,
    1505             :                                                                       msg->elements,
    1506             :                                                                       struct ldb_message_element,
    1507             :                                                                       msg->num_elements);
    1508   104617933 :                 if (elements != NULL) {
    1509   104617933 :                         msg->elements = elements;
    1510             :                 }
    1511             :         } else {
    1512    13053598 :                 TALLOC_FREE(msg->elements);
    1513             :         }
    1514   117671531 : }
    1515             : 
    1516             : /*
    1517             :   return a LDAP formatted GeneralizedTime string
    1518             : */
    1519     4447878 : char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
    1520             : {
    1521     4447878 :         struct tm *tm = gmtime(&t);
    1522             :         char *ts;
    1523             :         int r;
    1524             : 
    1525     4447878 :         if (!tm) {
    1526           2 :                 return NULL;
    1527             :         }
    1528             : 
    1529             :         /* we now excatly how long this string will be */
    1530     4447876 :         ts = talloc_array(mem_ctx, char, 18);
    1531             : 
    1532             :         /* formatted like: 20040408072012.0Z */
    1533    12424644 :         r = snprintf(ts, 18,
    1534             :                         "%04u%02u%02u%02u%02u%02u.0Z",
    1535     8436260 :                         tm->tm_year+1900, tm->tm_mon+1,
    1536             :                         tm->tm_mday, tm->tm_hour, tm->tm_min,
    1537             :                         tm->tm_sec);
    1538             : 
    1539     4447876 :         if (r != 17) {
    1540           4 :                 talloc_free(ts);
    1541           4 :                 errno = EOVERFLOW;
    1542           4 :                 return NULL;
    1543             :         }
    1544             : 
    1545     4447872 :         return ts;
    1546             : }
    1547             : 
    1548             : /*
    1549             :   convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
    1550             : */
    1551       19972 : time_t ldb_string_to_time(const char *s)
    1552             : {
    1553             :         struct tm tm;
    1554             : 
    1555       19972 :         if (s == NULL) return 0;
    1556             : 
    1557       19946 :         memset(&tm, 0, sizeof(tm));
    1558       19946 :         if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
    1559             :                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    1560             :                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    1561           0 :                 return 0;
    1562             :         }
    1563       19946 :         tm.tm_year -= 1900;
    1564       19946 :         tm.tm_mon -= 1;
    1565             : 
    1566       19946 :         return timegm(&tm);
    1567             : }
    1568             : 
    1569             : /*
    1570             :   convert a LDAP GeneralizedTime string in ldb_val format to a
    1571             :   time_t.
    1572             : */
    1573     4029438 : int ldb_val_to_time(const struct ldb_val *v, time_t *t)
    1574             : {
    1575     4029438 :         char val[15] = {0};
    1576     4029438 :         struct tm tm = {
    1577             :                 .tm_year = 0,
    1578             :         };
    1579             : 
    1580     4029438 :         if (v == NULL) {
    1581           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1582             :         }
    1583             : 
    1584     4029438 :         if (v->data == NULL) {
    1585           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1586             :         }
    1587             : 
    1588     4029438 :         if (v->length < 16 && v->length != 13) {
    1589           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1590             :         }
    1591             : 
    1592     4029438 :         if (v->data[v->length - 1] != 'Z') {
    1593           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1594             :         }
    1595             : 
    1596     4029438 :         if (v->length == 13) {
    1597         426 :                 memcpy(val, v->data, 12);
    1598             : 
    1599         426 :                 if (sscanf(val, "%02u%02u%02u%02u%02u%02u",
    1600             :                         &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    1601             :                         &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    1602           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1603             :                 }
    1604         426 :                 if (tm.tm_year < 50) {
    1605         426 :                         tm.tm_year += 100;
    1606             :                 }
    1607             :         } else {
    1608             : 
    1609             :                 /*
    1610             :                  * anything between '.' and 'Z' is silently ignored.
    1611             :                  */
    1612     4029012 :                 if (v->data[14] != '.') {
    1613           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1614             :                 }
    1615             : 
    1616     4029012 :                 memcpy(val, v->data, 14);
    1617             : 
    1618     4029012 :                 if (sscanf(val, "%04u%02u%02u%02u%02u%02u",
    1619             :                         &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    1620             :                         &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    1621           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1622             :                 }
    1623     4029012 :                 tm.tm_year -= 1900;
    1624             :         }
    1625     4029438 :         tm.tm_mon -= 1;
    1626             : 
    1627     4029438 :         *t = timegm(&tm);
    1628             : 
    1629     4029438 :         return LDB_SUCCESS;
    1630             : }
    1631             : 
    1632             : /*
    1633             :   return a LDAP formatted UTCTime string
    1634             : */
    1635          49 : char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
    1636             : {
    1637          49 :         struct tm *tm = gmtime(&t);
    1638             :         char *ts;
    1639             :         int r;
    1640             : 
    1641          49 :         if (!tm) {
    1642           0 :                 return NULL;
    1643             :         }
    1644             : 
    1645             :         /* we now excatly how long this string will be */
    1646          49 :         ts = talloc_array(mem_ctx, char, 14);
    1647             : 
    1648             :         /* formatted like: 20040408072012.0Z => 040408072012Z */
    1649         123 :         r = snprintf(ts, 14,
    1650             :                         "%02u%02u%02u%02u%02u%02uZ",
    1651          86 :                         (tm->tm_year+1900)%100, tm->tm_mon+1,
    1652             :                         tm->tm_mday, tm->tm_hour, tm->tm_min,
    1653             :                         tm->tm_sec);
    1654             : 
    1655          49 :         if (r != 13) {
    1656           0 :                 talloc_free(ts);
    1657           0 :                 return NULL;
    1658             :         }
    1659             : 
    1660          49 :         return ts;
    1661             : }
    1662             : 
    1663             : /*
    1664             :   convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
    1665             : */
    1666           0 : time_t ldb_string_utc_to_time(const char *s)
    1667             : {
    1668             :         struct tm tm;
    1669             : 
    1670           0 :         if (s == NULL) return 0;
    1671             : 
    1672           0 :         memset(&tm, 0, sizeof(tm));
    1673           0 :         if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
    1674             :                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    1675             :                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    1676           0 :                 return 0;
    1677             :         }
    1678           0 :         if (tm.tm_year < 50) {
    1679           0 :                 tm.tm_year += 100;
    1680             :         }
    1681           0 :         tm.tm_mon -= 1;
    1682             : 
    1683           0 :         return timegm(&tm);
    1684             : }
    1685             : 
    1686             : 
    1687             : /*
    1688             :   dump a set of results to a file. Useful from within gdb
    1689             : */
    1690           0 : void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
    1691             : {
    1692             :         unsigned int i;
    1693             : 
    1694           0 :         for (i = 0; i < result->count; i++) {
    1695             :                 struct ldb_ldif ldif;
    1696           0 :                 fprintf(f, "# record %d\n", i+1);
    1697           0 :                 ldif.changetype = LDB_CHANGETYPE_NONE;
    1698           0 :                 ldif.msg = result->msgs[i];
    1699           0 :                 ldb_ldif_write_file(ldb, f, &ldif);
    1700             :         }
    1701           0 : }
    1702             : 
    1703             : /*
    1704             :   checks for a string attribute. Returns "1" on match and otherwise "0".
    1705             : */
    1706     2491368 : int ldb_msg_check_string_attribute(const struct ldb_message *msg,
    1707             :                                    const char *name, const char *value)
    1708             : {
    1709             :         struct ldb_message_element *el;
    1710             :         struct ldb_val val;
    1711             : 
    1712     2491368 :         el = ldb_msg_find_element(msg, name);
    1713     2491368 :         if (el == NULL) {
    1714     1288752 :                 return 0;
    1715             :         }
    1716             : 
    1717     1202616 :         val.data = discard_const_p(uint8_t, value);
    1718     1202616 :         val.length = strlen(value);
    1719             : 
    1720     1202616 :         if (ldb_msg_find_val(el, &val)) {
    1721     1201887 :                 return 1;
    1722             :         }
    1723             : 
    1724         729 :         return 0;
    1725             : }
    1726             : 
    1727             : 
    1728             : /*
    1729             :   compare a ldb_val to a string
    1730             : */
    1731     2783922 : int ldb_val_string_cmp(const struct ldb_val *v, const char *str)
    1732             : {
    1733     2783922 :         size_t len = strlen(str);
    1734     2783922 :         if (len != v->length) {
    1735           0 :                 return len - v->length;
    1736             :         }
    1737     2783922 :         return strncmp((const char *)v->data, str, len);
    1738             : }

Generated by: LCOV version 1.13