LCOV - code coverage report
Current view: top level - lib/ldb/common - ldb_ldif.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 466 579 80.5 %
Date: 2024-05-31 13:13:24 Functions: 24 25 96.0 %

          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: ldif routines
      28             :  *
      29             :  *  Description: ldif pack/unpack routines
      30             :  *
      31             :  *  Author: Andrew Tridgell
      32             :  */
      33             : 
      34             : /*
      35             :   see RFC2849 for the LDIF format definition
      36             : */
      37             : 
      38             : #include "ldb_private.h"
      39             : #include "system/locale.h"
      40             : 
      41             : /*
      42             : 
      43             : */
      44           3 : static int ldb_read_data_file(TALLOC_CTX *mem_ctx, struct ldb_val *value)
      45             : {
      46           1 :         struct stat statbuf;
      47           1 :         char *buf;
      48           1 :         size_t count, size;
      49           1 :         ssize_t bytes;
      50           1 :         int ret;
      51           1 :         int f;
      52           3 :         const char *fname = (const char *)value->data;
      53             : 
      54           3 :         if (strncmp(fname, "file://", 7) != 0) {
      55           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
      56             :         }
      57           3 :         fname += 7;
      58             : 
      59           3 :         f = open(fname, O_RDONLY);
      60           3 :         if (f == -1) {
      61           0 :                 return -1;
      62             :         }
      63             : 
      64           3 :         if (fstat(f, &statbuf) != 0) {
      65           0 :                 ret = -1;
      66           0 :                 goto done;
      67             :         }
      68             : 
      69           3 :         if (statbuf.st_size == 0) {
      70           0 :                 ret = -1;
      71           0 :                 goto done;
      72             :         }
      73             : 
      74           3 :         value->data = (uint8_t *)talloc_size(mem_ctx, statbuf.st_size + 1);
      75           3 :         if (value->data == NULL) {
      76           0 :                 ret = -1;
      77           0 :                 goto done;
      78             :         }
      79           3 :         value->data[statbuf.st_size] = 0;
      80             : 
      81           3 :         count = 0;
      82           3 :         size = statbuf.st_size;
      83           3 :         buf = (char *)value->data;
      84           6 :         while (count < statbuf.st_size) {
      85           3 :                 bytes = read(f, buf, size);
      86           3 :                 if (bytes == -1) {
      87           0 :                         talloc_free(value->data);
      88           0 :                         ret = -1;
      89           0 :                         goto done;
      90             :                 }
      91           3 :                 count += bytes;
      92           3 :                 buf += bytes;
      93           3 :                 size -= bytes;
      94             :         }
      95             : 
      96           3 :         value->length = statbuf.st_size;
      97           3 :         ret = statbuf.st_size;
      98             : 
      99           3 : done:
     100           3 :         close(f);
     101           3 :         return ret;
     102             : }
     103             : 
     104             : /*
     105             :   this base64 decoder was taken from jitterbug (written by tridge).
     106             :   we might need to replace it with a new version
     107             : */
     108     2042396 : int ldb_base64_decode(char *s)
     109             : {
     110     2042396 :         const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     111     2042396 :         int bit_offset=0, byte_offset, idx, i, n;
     112     2042396 :         uint8_t *d = (uint8_t *)s;
     113     2042396 :         char *p=NULL;
     114             : 
     115     2042396 :         n=i=0;
     116             : 
     117    66141036 :         while (*s && (p=strchr(b64,*s))) {
     118    64098640 :                 idx = (int)(p - b64);
     119    64098640 :                 byte_offset = (i*6)/8;
     120    64098640 :                 bit_offset = (i*6)%8;
     121    64098640 :                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
     122    64098640 :                 if (bit_offset < 3) {
     123    31900325 :                         d[byte_offset] |= (idx << (2-bit_offset));
     124    31900325 :                         n = byte_offset+1;
     125             :                 } else {
     126    32198315 :                         d[byte_offset] |= (idx >> (bit_offset-2));
     127    32198315 :                         d[byte_offset+1] = 0;
     128    32198315 :                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
     129    32198315 :                         n = byte_offset+2;
     130             :                 }
     131    64098640 :                 s++; i++;
     132             :         }
     133     2042396 :         if (bit_offset >= 3) {
     134     1626341 :                 n--;
     135             :         }
     136             : 
     137     2042396 :         if (*s && !p) {
     138             :                 /* the only termination allowed */
     139     1626340 :                 if (*s != '=') {
     140           0 :                         return -1;
     141             :                 }
     142             :         }
     143             : 
     144             :         /* null terminate */
     145     2042396 :         d[n] = 0;
     146     2042396 :         return n;
     147             : }
     148             : 
     149             : 
     150             : /*
     151             :   encode as base64
     152             :   caller frees
     153             : */
     154    17359349 : char *ldb_base64_encode(TALLOC_CTX *mem_ctx, const char *buf, int len)
     155             : {
     156    17359349 :         const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     157      484585 :         int bit_offset, byte_offset, idx, i;
     158    17359349 :         const uint8_t *d = (const uint8_t *)buf;
     159    17359349 :         int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
     160      484585 :         char *out;
     161             : 
     162    17359349 :         out = talloc_array(mem_ctx, char, bytes+pad_bytes+1);
     163    17359349 :         if (!out) return NULL;
     164             : 
     165   611741603 :         for (i=0;i<bytes;i++) {
     166   594382254 :                 byte_offset = (i*6)/8;
     167   594382254 :                 bit_offset = (i*6)%8;
     168   594382254 :                 if (bit_offset < 3) {
     169   297022751 :                         idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
     170             :                 } else {
     171   297359503 :                         idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
     172   297359503 :                         if (byte_offset+1 < len) {
     173   283930336 :                                 idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
     174             :                         }
     175             :                 }
     176   594382254 :                 out[i] = b64[idx];
     177             :         }
     178             : 
     179    43880931 :         for (;i<bytes+pad_bytes;i++)
     180    26521582 :                 out[i] = '=';
     181    17359349 :         out[i] = 0;
     182             : 
     183    17359349 :         return out;
     184             : }
     185             : 
     186             : /*
     187             :   see if a buffer should be base64 encoded
     188             : */
     189    44948276 : int ldb_should_b64_encode(struct ldb_context *ldb, const struct ldb_val *val)
     190             : {
     191     2982039 :         unsigned int i;
     192    44948276 :         uint8_t *p = val->data;
     193             : 
     194    44948276 :         if (val->length == 0) {
     195        5592 :                 return 0;
     196             :         }
     197             : 
     198    44942586 :         if (p[0] == ' ' || p[0] == ':') {
     199        1559 :                 return 1;
     200             :         }
     201             : 
     202  1484978169 :         for (i=0; i<val->length; i++) {
     203  1457339519 :                 if (!isprint(p[i]) || p[i] == '\n') {
     204    16817866 :                         return 1;
     205             :                 }
     206             :         }
     207    25141220 :         return 0;
     208             : }
     209             : 
     210             : /* this macro is used to handle the return checking on fprintf_fn() */
     211             : #define CHECK_RET do { if (ret < 0) return ret; total += ret; } while (0)
     212             : 
     213             : /*
     214             :   write a line folded string onto a file
     215             : */
     216      863758 : static int fold_string(int (*fprintf_fn)(void *, const char *, ...), void *private_data,
     217             :                         const char *buf, size_t length, int start_pos)
     218             : {
     219      579926 :         size_t i;
     220      863758 :         size_t total = 0;
     221      579926 :         int ret;
     222             : 
     223    46212614 :         for (i=0;i<length;i++) {
     224    45348856 :                 ret = fprintf_fn(private_data, "%c", buf[i]);
     225    45348856 :                 CHECK_RET;
     226    45348856 :                 if (i != (length-1) && (i + start_pos) % 77 == 0) {
     227      419548 :                         ret = fprintf_fn(private_data, "\n ");
     228    38396581 :                         CHECK_RET;
     229             :                 }
     230             :         }
     231             : 
     232      863758 :         return total;
     233             : }
     234             : 
     235             : #undef CHECK_RET
     236             : 
     237             : /*
     238             :   encode as base64 to a file
     239             : */
     240       95073 : static int base64_encode_f(struct ldb_context *ldb,
     241             :                            int (*fprintf_fn)(void *, const char *, ...),
     242             :                            void *private_data,
     243             :                            const char *buf, int len, int start_pos)
     244             : {
     245       95073 :         char *b = ldb_base64_encode(ldb, buf, len);
     246       92165 :         int ret;
     247             : 
     248       95073 :         if (!b) {
     249           0 :                 return -1;
     250             :         }
     251             : 
     252       95073 :         ret = fold_string(fprintf_fn, private_data, b, strlen(b), start_pos);
     253             : 
     254       95073 :         talloc_free(b);
     255       95073 :         return ret;
     256             : }
     257             : 
     258             : 
     259             : static const struct {
     260             :         const char *name;
     261             :         enum ldb_changetype changetype;
     262             : } ldb_changetypes[] = {
     263             :         {"add",    LDB_CHANGETYPE_ADD},
     264             :         {"delete", LDB_CHANGETYPE_DELETE},
     265             :         {"modify", LDB_CHANGETYPE_MODIFY},
     266             :         {"modrdn", LDB_CHANGETYPE_MODRDN},
     267             :         {"moddn",  LDB_CHANGETYPE_MODRDN},
     268             :         {NULL, 0}
     269             : };
     270             : 
     271             : /* this macro is used to handle the return checking on fprintf_fn() */
     272             : #define CHECK_RET do { if (ret < 0) { talloc_free(mem_ctx); return ret; } total += ret; } while (0)
     273             : 
     274             : /*
     275             :   write to ldif, using a caller supplied write method, and only printing secrets if we are not in a trace
     276             : */
     277      112605 : static int ldb_ldif_write_trace(struct ldb_context *ldb,
     278             :                                 int (*fprintf_fn)(void *, const char *, ...),
     279             :                                 void *private_data,
     280             :                                 const struct ldb_ldif *ldif,
     281             :                                 bool in_trace)
     282             : {
     283       90796 :         TALLOC_CTX *mem_ctx;
     284       90796 :         unsigned int i, j;
     285      112605 :         size_t total = 0;
     286       90796 :         int ret;
     287       90796 :         char *p;
     288       90796 :         const struct ldb_message *msg;
     289      112605 :         const char * const * secret_attributes = ldb_get_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE);
     290             : 
     291      112605 :         mem_ctx = talloc_named_const(NULL, 0, "ldb_ldif_write");
     292             : 
     293      112605 :         msg = ldif->msg;
     294      112605 :         p = ldb_dn_get_extended_linearized(mem_ctx, msg->dn, 1);
     295      112605 :         ret = fprintf_fn(private_data, "dn: %s\n", p);
     296      112605 :         talloc_free(p);
     297      112605 :         CHECK_RET;
     298             : 
     299      112605 :         if (ldif->changetype != LDB_CHANGETYPE_NONE) {
     300          74 :                 for (i=0;ldb_changetypes[i].name;i++) {
     301          74 :                         if (ldb_changetypes[i].changetype == ldif->changetype) {
     302           0 :                                 break;
     303             :                         }
     304             :                 }
     305          74 :                 if (!ldb_changetypes[i].name) {
     306           0 :                         ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Invalid ldif changetype %d",
     307           0 :                                   ldif->changetype);
     308           0 :                         talloc_free(mem_ctx);
     309           0 :                         return -1;
     310             :                 }
     311          74 :                 ret = fprintf_fn(private_data, "changetype: %s\n", ldb_changetypes[i].name);
     312          74 :                 CHECK_RET;
     313             :         }
     314             : 
     315      860172 :         for (i=0;i<msg->num_elements;i++) {
     316      483193 :                 const struct ldb_schema_attribute *a;
     317      483193 :                 size_t namelen;
     318             : 
     319      747567 :                 if (msg->elements[i].name == NULL) {
     320           0 :                         ldb_debug(ldb, LDB_DEBUG_ERROR,
     321             :                                         "Error: Invalid element name (NULL) at position %d", i);
     322           0 :                         talloc_free(mem_ctx);
     323           0 :                         return -1;
     324             :                 }
     325             : 
     326      747567 :                 namelen = strlen(msg->elements[i].name);
     327      747567 :                 a = ldb_schema_attribute_by_name(ldb, msg->elements[i].name);
     328             : 
     329      747567 :                 if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
     330           0 :                         switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
     331           0 :                         case LDB_FLAG_MOD_ADD:
     332           0 :                                 fprintf_fn(private_data, "add: %s\n",
     333           0 :                                            msg->elements[i].name);
     334           0 :                                 break;
     335           0 :                         case LDB_FLAG_MOD_DELETE:
     336           0 :                                 fprintf_fn(private_data, "delete: %s\n",
     337           0 :                                            msg->elements[i].name);
     338           0 :                                 break;
     339           0 :                         case LDB_FLAG_MOD_REPLACE:
     340           0 :                                 fprintf_fn(private_data, "replace: %s\n",
     341           0 :                                            msg->elements[i].name);
     342           0 :                                 break;
     343             :                         }
     344             :                 }
     345             : 
     346      747567 :                 if (in_trace && secret_attributes && ldb_attr_in_list(secret_attributes, msg->elements[i].name)) {
     347             :                         /* Deliberately skip printing this password */
     348          74 :                         ret = fprintf_fn(private_data, "# %s::: REDACTED SECRET ATTRIBUTE\n",
     349          37 :                                          msg->elements[i].name);
     350          37 :                         CHECK_RET;
     351          37 :                         continue;
     352             :                 }
     353     1616931 :                 for (j=0;j<msg->elements[i].num_values;j++) {
     354      579927 :                         struct ldb_val v;
     355      869401 :                         bool use_b64_encode = false;
     356      869401 :                         bool copy_raw_bytes = false;
     357             : 
     358      869401 :                         ret = a->syntax->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v);
     359      869401 :                         if (ret != LDB_SUCCESS) {
     360          72 :                                 v = msg->elements[i].values[j];
     361             :                         }
     362             : 
     363      869401 :                         if (ldb->flags & LDB_FLG_SHOW_BINARY) {
     364         240 :                                 use_b64_encode = false;
     365         240 :                                 copy_raw_bytes = true;
     366      869160 :                         } else if (a->flags & LDB_ATTR_FLAG_FORCE_BASE64_LDIF) {
     367         548 :                                 use_b64_encode = true;
     368      868612 :                         } else if (msg->elements[i].flags &
     369             :                                    LDB_FLAG_FORCE_NO_BASE64_LDIF) {
     370        5402 :                                 use_b64_encode = false;
     371        5402 :                                 copy_raw_bytes = true;
     372             :                         } else {
     373      863210 :                                 use_b64_encode = ldb_should_b64_encode(ldb, &v);
     374             :                         }
     375             : 
     376      869401 :                         if (ret != LDB_SUCCESS || use_b64_encode) {
     377      187238 :                                 ret = fprintf_fn(private_data, "%s:: ",
     378       95073 :                                                  msg->elements[i].name);
     379       95073 :                                 CHECK_RET;
     380      187238 :                                 ret = base64_encode_f(ldb, fprintf_fn, private_data,
     381       95073 :                                                       (char *)v.data, v.length,
     382       95073 :                                                       namelen + 3);
     383       95073 :                                 CHECK_RET;
     384       95073 :                                 ret = fprintf_fn(private_data, "\n");
     385       95073 :                                 CHECK_RET;
     386             :                         } else {
     387      774328 :                                 ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name);
     388      774328 :                                 CHECK_RET;
     389      774328 :                                 if (copy_raw_bytes) {
     390        5643 :                                         ret = fprintf_fn(private_data, "%*.*s",
     391        5643 :                                                          v.length, v.length, (char *)v.data);
     392             :                                 } else {
     393      768685 :                                         ret = fold_string(fprintf_fn, private_data,
     394      768685 :                                                           (char *)v.data, v.length,
     395      768685 :                                                           namelen + 2);
     396             :                                 }
     397      774328 :                                 CHECK_RET;
     398      774328 :                                 ret = fprintf_fn(private_data, "\n");
     399      774328 :                                 CHECK_RET;
     400             :                         }
     401      869401 :                         if (v.data != msg->elements[i].values[j].data) {
     402      869329 :                                 talloc_free(v.data);
     403             :                         }
     404             :                 }
     405      747530 :                 if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
     406           0 :                         fprintf_fn(private_data, "-\n");
     407             :                 }
     408             :         }
     409      112605 :         ret = fprintf_fn(private_data,"\n");
     410      112605 :         CHECK_RET;
     411             : 
     412      112605 :         talloc_free(mem_ctx);
     413             : 
     414      112605 :         return total;
     415             : }
     416             : 
     417             : #undef CHECK_RET
     418             : 
     419             : 
     420             : /*
     421             :   write to ldif, using a caller supplied write method
     422             : */
     423      112568 : int ldb_ldif_write(struct ldb_context *ldb,
     424             :                    int (*fprintf_fn)(void *, const char *, ...),
     425             :                    void *private_data,
     426             :                    const struct ldb_ldif *ldif)
     427             : {
     428      112568 :         return ldb_ldif_write_trace(ldb, fprintf_fn, private_data, ldif, false);
     429             : }
     430             : 
     431             : 
     432             : /*
     433             :   pull a ldif chunk, which is defined as a piece of data ending in \n\n or EOF
     434             :   this routine removes any RFC2849 continuations and comments
     435             : 
     436             :   caller frees
     437             : */
     438     1209740 : static char *next_chunk(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
     439             :                         int (*fgetc_fn)(void *), void *private_data)
     440             : {
     441     1209740 :         size_t alloc_size=0, chunk_size = 0;
     442     1209740 :         char *chunk = NULL;
     443      132371 :         int c;
     444     1209740 :         int in_comment = 0;
     445             : 
     446   794167526 :         while ((c = fgetc_fn(private_data)) != EOF) {
     447   794110282 :                 if (chunk_size+1 >= alloc_size) {
     448      149725 :                         char *c2;
     449     1344284 :                         alloc_size += 1024;
     450     1344284 :                         c2 = talloc_realloc(mem_ctx, chunk, char, alloc_size);
     451     1344284 :                         if (!c2) {
     452           0 :                                 talloc_free(chunk);
     453           0 :                                 errno = ENOMEM;
     454           0 :                                 return NULL;
     455             :                         }
     456     1194559 :                         chunk = c2;
     457             :                 }
     458             : 
     459   794110282 :                 if (in_comment) {
     460     1540299 :                         if (c == '\n') {
     461       34113 :                                 in_comment = 0;
     462             :                         }
     463     1540299 :                         continue;
     464             :                 }
     465             : 
     466             :                 /* handle continuation lines - see RFC2849 */
     467   792569983 :                 if (c == ' ' && chunk_size > 1 && chunk[chunk_size-1] == '\n') {
     468      294982 :                         chunk_size--;
     469      294982 :                         continue;
     470             :                 }
     471             : 
     472             :                 /* chunks are terminated by a double line-feed */
     473   792275001 :                 if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') {
     474     1152496 :                         chunk[chunk_size-1] = 0;
     475     1152496 :                         return chunk;
     476             :                 }
     477             : 
     478   791122505 :                 if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) {
     479       34113 :                         in_comment = 1;
     480       34113 :                         continue;
     481             :                 }
     482             : 
     483             :                 /* ignore leading blank lines */
     484   791088392 :                 if (chunk_size == 0 && c == '\n') {
     485       43846 :                         continue;
     486             :                 }
     487             : 
     488   791044546 :                 chunk[chunk_size++] = c;
     489             :         }
     490             : 
     491       57244 :         if (chunk) {
     492       54980 :                 chunk[chunk_size] = 0;
     493             :         }
     494             : 
     495       52814 :         return chunk;
     496             : }
     497             : 
     498             : 
     499             : /* simple ldif attribute parser */
     500    22439769 : static int next_attr(TALLOC_CTX *mem_ctx, char **s, const char **attr, struct ldb_val *value)
     501             : {
     502     2337243 :         char *p;
     503    22439769 :         int base64_encoded = 0;
     504    22439769 :         int binary_file = 0;
     505             : 
     506    22439769 :         if (strncmp(*s, "-\n", 2) == 0) {
     507       16008 :                 value->length = 0;
     508       16008 :                 *attr = "-";
     509       16008 :                 *s += 2;
     510       16008 :                 return 0;
     511             :         }
     512             : 
     513    22423761 :         p = strchr(*s, ':');
     514    22423761 :         if (!p) {
     515     1076485 :                 return -1;
     516             :         }
     517             : 
     518    21216285 :         *p++ = 0;
     519             : 
     520    21216285 :         if (*p == ':') {
     521     1996898 :                 base64_encoded = 1;
     522     1996898 :                 p++;
     523             :         }
     524             : 
     525    21216285 :         if (*p == '<') {
     526           3 :                 binary_file = 1;
     527           3 :                 p++;
     528             :         }
     529             : 
     530    21216285 :         *attr = *s;
     531             : 
     532    42417059 :         while (*p == ' ' || *p == '\t') {
     533    21200774 :                 p++;
     534             :         }
     535             : 
     536    21216285 :         value->data = (uint8_t *)p;
     537             : 
     538    21216285 :         p = strchr(p, '\n');
     539             : 
     540    21216285 :         if (!p) {
     541     1139347 :                 value->length = strlen((char *)value->data);
     542     1139347 :                 *s = ((char *)value->data) + value->length;
     543             :         } else {
     544    20076938 :                 value->length = p - (char *)value->data;
     545    20076938 :                 *s = p+1;
     546    20076938 :                 *p = 0;
     547             :         }
     548             : 
     549    21216285 :         if (base64_encoded) {
     550     1996898 :                 int len = ldb_base64_decode((char *)value->data);
     551     1996898 :                 if (len == -1) {
     552             :                         /* it wasn't valid base64 data */
     553           0 :                         return -1;
     554             :                 }
     555     1996898 :                 value->length = len;
     556             :         }
     557             : 
     558    21216285 :         if (binary_file) {
     559           3 :                 int len = ldb_read_data_file(mem_ctx, value);
     560           3 :                 if (len == -1) {
     561             :                         /* an error occurred while trying to retrieve the file */
     562           0 :                         return -1;
     563             :                 }
     564             :         }
     565             : 
     566    19012645 :         return 0;
     567             : }
     568             : 
     569             : 
     570             : /*
     571             :   free a message from a ldif_read
     572             : */
     573        5649 : void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif)
     574             : {
     575        5649 :         talloc_free(ldif);
     576        5649 : }
     577             : 
     578          12 : int ldb_ldif_parse_modrdn(struct ldb_context *ldb,
     579             :                           const struct ldb_ldif *ldif,
     580             :                           TALLOC_CTX *mem_ctx,
     581             :                           struct ldb_dn **_olddn,
     582             :                           struct ldb_dn **_newrdn,
     583             :                           bool *_deleteoldrdn,
     584             :                           struct ldb_dn **_newsuperior,
     585             :                           struct ldb_dn **_newdn)
     586             : {
     587          12 :         struct ldb_message *msg = ldif->msg;
     588          12 :         struct ldb_val _newrdn_val = {};
     589          12 :         struct ldb_val *newrdn_val = NULL;
     590          12 :         struct ldb_val *deleteoldrdn_val = NULL;
     591          12 :         struct ldb_val *newsuperior_val = NULL;
     592          12 :         struct ldb_dn *olddn = NULL;
     593          12 :         struct ldb_dn *newrdn = NULL;
     594          12 :         bool deleteoldrdn = true;
     595          12 :         struct ldb_dn *newsuperior = NULL;
     596          12 :         struct ldb_dn *newdn = NULL;
     597           6 :         struct ldb_val tmp_false;
     598           6 :         struct ldb_val tmp_true;
     599           6 :         bool ok;
     600          12 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     601             : 
     602          12 :         if (tmp_ctx == NULL) {
     603           0 :                 ldb_debug(ldb, LDB_DEBUG_FATAL,
     604             :                           "Error: talloc_new() failed");
     605           0 :                 goto err_op;
     606             :         }
     607             : 
     608          12 :         if (ldif->changetype != LDB_CHANGETYPE_MODRDN) {
     609           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     610             :                           "Error: invalid changetype '%d'",
     611           0 :                           ldif->changetype);
     612           0 :                 goto err_other;
     613             :         }
     614             : 
     615          12 :         if (msg->num_elements < 2) {
     616           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     617             :                           "Error: num_elements[%u] < 2",
     618             :                           msg->num_elements);
     619           0 :                 goto err_other;
     620             :         }
     621             : 
     622          12 :         if (msg->num_elements > 3) {
     623           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     624             :                           "Error: num_elements[%u] > 3",
     625             :                           msg->num_elements);
     626           0 :                 goto err_other;
     627             :         }
     628             : 
     629             : #define CHECK_ELEMENT(i, _name, v, needed) do { \
     630             :         v = NULL; \
     631             :         if (msg->num_elements < (i + 1)) { \
     632             :                 if (needed) { \
     633             :                         ldb_debug(ldb, LDB_DEBUG_ERROR, \
     634             :                                   "Error: num_elements[%u] < (%u + 1)", \
     635             :                                   msg->num_elements, i); \
     636             :                         goto err_other; \
     637             :                 } \
     638             :         } else if (ldb_attr_cmp(msg->elements[i].name, _name) != 0) { \
     639             :                 ldb_debug(ldb, LDB_DEBUG_ERROR, \
     640             :                           "Error: elements[%u].name[%s] != [%s]", \
     641             :                           i, msg->elements[i].name, _name); \
     642             :                 goto err_other; \
     643             :         } else if (msg->elements[i].flags != 0) { \
     644             :                 ldb_debug(ldb, LDB_DEBUG_ERROR, \
     645             :                           "Error: elements[%u].flags[0x%X} != [0x0]", \
     646             :                           i, msg->elements[i].flags); \
     647             :                 goto err_other; \
     648             :         } else if (msg->elements[i].num_values != 1) { \
     649             :                 ldb_debug(ldb, LDB_DEBUG_ERROR, \
     650             :                           "Error: elements[%u].num_values[%u] != 1", \
     651             :                           i, msg->elements[i].num_values); \
     652             :                 goto err_other; \
     653             :         } else { \
     654             :                 v = &msg->elements[i].values[0]; \
     655             :         } \
     656             : } while (0)
     657             : 
     658          12 :         CHECK_ELEMENT(0, "newrdn", newrdn_val, true);
     659          12 :         CHECK_ELEMENT(1, "deleteoldrdn", deleteoldrdn_val, true);
     660          12 :         CHECK_ELEMENT(2, "newsuperior", newsuperior_val, false);
     661             : 
     662             : #undef CHECK_ELEMENT
     663             : 
     664          12 :         olddn = ldb_dn_copy(tmp_ctx, msg->dn);
     665          12 :         if (olddn == NULL) {
     666           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     667             :                           "Error: failed to copy olddn '%s'",
     668             :                           ldb_dn_get_linearized(msg->dn));
     669           0 :                 goto err_op;
     670             :         }
     671             : 
     672          12 :         if (newrdn_val->length != 0 && strchr((const char *)newrdn_val->data, '=') == NULL) {
     673           4 :                 const char *rdn_name = ldb_dn_get_rdn_name(olddn);
     674           4 :                 char *new_rdn = NULL;
     675             : 
     676           4 :                 new_rdn = talloc_asprintf(tmp_ctx,
     677             :                                           "%s=%s",
     678             :                                           rdn_name,
     679           4 :                                           (const char *)newrdn_val->data);
     680           4 :                 if (new_rdn == NULL) {
     681           0 :                         ldb_debug(ldb, LDB_DEBUG_ERROR,
     682             :                                   "Error: failed to allocate '%s=%s'",
     683           0 :                                   rdn_name, (char *)newrdn_val->data);
     684           0 :                         goto err_op;
     685             :                 }
     686           4 :                 _newrdn_val.data = (uint8_t *)new_rdn;
     687           4 :                 _newrdn_val.length = strlen(new_rdn);
     688           4 :                 newrdn_val = &_newrdn_val;
     689             :         }
     690             : 
     691          12 :         newrdn = ldb_dn_from_ldb_val(tmp_ctx, ldb, newrdn_val);
     692          12 :         if (!ldb_dn_validate(newrdn)) {
     693           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     694             :                           "Error: Unable to parse dn '%s'",
     695           0 :                           (char *)newrdn_val->data);
     696           0 :                 goto err_dn;
     697             :         }
     698             : 
     699          12 :         tmp_false.length = 1;
     700          12 :         tmp_false.data = discard_const_p(uint8_t, "0");
     701          12 :         tmp_true.length = 1;
     702          12 :         tmp_true.data = discard_const_p(uint8_t, "1");
     703          12 :         if (ldb_val_equal_exact(deleteoldrdn_val, &tmp_false) == 1) {
     704           0 :                 deleteoldrdn = false;
     705          12 :         } else if (ldb_val_equal_exact(deleteoldrdn_val, &tmp_true) == 1) {
     706           6 :                 deleteoldrdn = true;
     707             :         } else {
     708           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     709             :                           "Error: deleteoldrdn value invalid '%s' not '0'/'1'",
     710           0 :                           (char *)deleteoldrdn_val->data);
     711           0 :                 goto err_attr;
     712             :         }
     713             : 
     714          12 :         if (newsuperior_val) {
     715           2 :                 newsuperior = ldb_dn_from_ldb_val(tmp_ctx, ldb, newsuperior_val);
     716           2 :                 if (!ldb_dn_validate(newsuperior)) {
     717           0 :                         ldb_debug(ldb, LDB_DEBUG_ERROR,
     718             :                                   "Error: Unable to parse dn '%s'",
     719           0 :                                   (char *)newsuperior_val->data);
     720           0 :                         goto err_dn;
     721             :                 }
     722             :         } else {
     723          10 :                 newsuperior = ldb_dn_get_parent(tmp_ctx, msg->dn);
     724          10 :                 if (newsuperior == NULL) {
     725           0 :                         ldb_debug(ldb, LDB_DEBUG_ERROR,
     726             :                                   "Error: Unable to get parent dn '%s'",
     727             :                                   ldb_dn_get_linearized(msg->dn));
     728           0 :                         goto err_dn;
     729             :                 }
     730             :         }
     731             : 
     732          12 :         newdn = ldb_dn_copy(tmp_ctx, newrdn);
     733          12 :         if (newdn == NULL) {
     734           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     735             :                           "Error: failed to copy newrdn '%s'",
     736             :                           ldb_dn_get_linearized(newrdn));
     737           0 :                 goto err_op;
     738             :         }
     739             : 
     740          12 :         ok = ldb_dn_add_base(newdn, newsuperior);
     741          12 :         if (!ok) {
     742           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     743             :                           "Error: failed to base '%s' to newdn '%s'",
     744             :                           ldb_dn_get_linearized(newsuperior),
     745             :                           ldb_dn_get_linearized(newdn));
     746           0 :                 goto err_op;
     747             :         }
     748             : 
     749          12 :         if (_olddn) {
     750           6 :                 *_olddn = talloc_move(mem_ctx, &olddn);
     751             :         }
     752          12 :         if (_newrdn) {
     753           0 :                 *_newrdn = talloc_move(mem_ctx, &newrdn);
     754             :         }
     755          12 :         if (_deleteoldrdn) {
     756           6 :                 *_deleteoldrdn = deleteoldrdn;
     757             :         }
     758          12 :         if (_newsuperior != NULL && _newrdn != NULL) {
     759           0 :                 if (newsuperior_val) {
     760           0 :                         *_newrdn = talloc_move(mem_ctx, &newrdn);
     761             :                 } else {
     762           0 :                         *_newrdn = NULL;
     763             :                 }
     764             :         }
     765          12 :         if (_newdn) {
     766           6 :                 *_newdn = talloc_move(mem_ctx, &newdn);
     767             :         }
     768             : 
     769          12 :         talloc_free(tmp_ctx);
     770          12 :         return LDB_SUCCESS;
     771           0 : err_other:
     772           0 :         talloc_free(tmp_ctx);
     773           0 :         return LDB_ERR_OTHER;
     774           0 : err_op:
     775           0 :         talloc_free(tmp_ctx);
     776           0 :         return LDB_ERR_OPERATIONS_ERROR;
     777           0 : err_attr:
     778           0 :         talloc_free(tmp_ctx);
     779           0 :         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     780           0 : err_dn:
     781           0 :         talloc_free(tmp_ctx);
     782           0 :         return LDB_ERR_INVALID_DN_SYNTAX;
     783             : }
     784             : 
     785             : /*
     786             :  read from a LDIF source, creating a ldb_message
     787             : */
     788     1209740 : struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
     789             :                                int (*fgetc_fn)(void *), void *private_data)
     790             : {
     791      132371 :         struct ldb_ldif *ldif;
     792      132371 :         struct ldb_message *msg;
     793     1209740 :         const char *attr=NULL;
     794     1209740 :         char *chunk=NULL, *s;
     795      132371 :         struct ldb_val value;
     796     1209740 :         unsigned flags = 0;
     797     1209740 :         value.data = NULL;
     798             : 
     799     1209740 :         ldif = talloc(ldb, struct ldb_ldif);
     800     1209740 :         if (!ldif) return NULL;
     801             : 
     802     1209740 :         ldif->msg = ldb_msg_new(ldif);
     803     1209740 :         if (ldif->msg == NULL) {
     804           0 :                 talloc_free(ldif);
     805           0 :                 return NULL;
     806             :         }
     807             : 
     808     1209740 :         ldif->changetype = LDB_CHANGETYPE_NONE;
     809     1209740 :         msg = ldif->msg;
     810             : 
     811     1209740 :         chunk = next_chunk(ldb, ldif, fgetc_fn, private_data);
     812     1209740 :         if (!chunk) {
     813        2264 :                 goto failed;
     814             :         }
     815             : 
     816     1207476 :         s = chunk;
     817             : 
     818     1207476 :         if (next_attr(ldif, &s, &attr, &value) != 0) {
     819         425 :                 goto failed;
     820             :         }
     821             : 
     822             :         /* first line must be a dn */
     823     1207051 :         if (ldb_attr_cmp(attr, "dn") != 0) {
     824           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'",
     825             :                           attr);
     826           0 :                 goto failed;
     827             :         }
     828             : 
     829     1207051 :         msg->dn = ldb_dn_from_ldb_val(msg, ldb, &value);
     830             : 
     831     1207051 :         if ( ! ldb_dn_validate(msg->dn)) {
     832           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'",
     833           0 :                           (char *)value.data);
     834           0 :                 goto failed;
     835             :         }
     836             : 
     837    21232293 :         while (next_attr(ldif, &s, &attr, &value) == 0) {
     838     2075686 :                 const struct ldb_schema_attribute *a;
     839     2075686 :                 struct ldb_message_element *el;
     840    20025242 :                 int ret, empty = 0;
     841             : 
     842    20025242 :                 if (ldb_attr_cmp(attr, "changetype") == 0) {
     843             :                         int i;
     844      159561 :                         for (i=0;ldb_changetypes[i].name;i++) {
     845      159561 :                                 if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) {
     846       58950 :                                         ldif->changetype = ldb_changetypes[i].changetype;
     847       58950 :                                         break;
     848             :                                 }
     849             :                         }
     850       58950 :                         if (!ldb_changetypes[i].name) {
     851           0 :                                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     852           0 :                                           "Error: Bad ldif changetype '%s'",(char *)value.data);
     853             :                         }
     854       58950 :                         flags = 0;
     855       58950 :                         continue;
     856             :                 }
     857             : 
     858    19966292 :                 if (ldb_attr_cmp(attr, "add") == 0) {
     859       28477 :                         flags = LDB_FLAG_MOD_ADD;
     860       28477 :                         empty = 1;
     861             :                 }
     862    19966292 :                 if (ldb_attr_cmp(attr, "delete") == 0) {
     863       16338 :                         flags = LDB_FLAG_MOD_DELETE;
     864       16338 :                         empty = 1;
     865             :                 }
     866    19966292 :                 if (ldb_attr_cmp(attr, "replace") == 0) {
     867       31846 :                         flags = LDB_FLAG_MOD_REPLACE;
     868       31846 :                         empty = 1;
     869             :                 }
     870    19966292 :                 if (ldb_attr_cmp(attr, "-") == 0) {
     871       16008 :                         flags = 0;
     872       16008 :                         continue;
     873             :                 }
     874             : 
     875    19950284 :                 if (empty) {
     876       76661 :                         if (ldb_msg_add_empty(msg, (char *)value.data, flags, NULL) != 0) {
     877           0 :                                 goto failed;
     878             :                         }
     879       76661 :                         continue;
     880             :                 }
     881             : 
     882    19873623 :                 a = ldb_schema_attribute_by_name(ldb, attr);
     883    41189502 :                 el = (msg->num_elements > 0
     884    18718120 :                       ? &msg->elements[msg->num_elements - 1]
     885    19873623 :                       : NULL);
     886             : 
     887    19745521 :                 if (el && ldb_attr_cmp(attr, el->name) == 0 && flags == el->flags) {
     888             :                         /* its a continuation */
     889     4283268 :                         el->values =
     890     3787342 :                                 talloc_realloc(msg->elements, el->values,
     891             :                                                  struct ldb_val, el->num_values+1);
     892     3787342 :                         if (!el->values) {
     893           0 :                                 goto failed;
     894             :                         }
     895     3787342 :                         ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[el->num_values]);
     896     3787342 :                         if (ret != 0) {
     897           0 :                                 goto failed;
     898             :                         }
     899     3787342 :                         if (value.length == 0) {
     900           0 :                                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     901             :                                           "Error: Attribute value cannot be empty for attribute '%s'", el->name);
     902           0 :                                 goto failed;
     903             :                         }
     904     3787342 :                         if (value.data != el->values[el->num_values].data) {
     905     3787342 :                                 talloc_steal(el->values, el->values[el->num_values].data);
     906             :                         }
     907     3787342 :                         el->num_values++;
     908             :                 } else {
     909             :                         /* its a new attribute */
     910    16086281 :                         msg->elements = talloc_realloc(msg, msg->elements,
     911             :                                                          struct ldb_message_element,
     912             :                                                          msg->num_elements+1);
     913    16086281 :                         if (!msg->elements) {
     914           0 :                                 goto failed;
     915             :                         }
     916    16086281 :                         el = &msg->elements[msg->num_elements];
     917    16086281 :                         el->flags = flags;
     918    16086281 :                         el->name = talloc_strdup(msg->elements, attr);
     919    16086281 :                         el->values = talloc(msg->elements, struct ldb_val);
     920    16086281 :                         if (!el->values || !el->name) {
     921           0 :                                 goto failed;
     922             :                         }
     923    16086281 :                         el->num_values = 1;
     924    16086281 :                         ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[0]);
     925    16086281 :                         if (ret != 0) {
     926           0 :                                 goto failed;
     927             :                         }
     928    16086281 :                         if (value.data != el->values[0].data) {
     929    16086281 :                                 talloc_steal(el->values, el->values[0].data);
     930             :                         }
     931    16086281 :                         msg->num_elements++;
     932             :                 }
     933             :         }
     934             : 
     935     1207051 :         if (ldif->changetype == LDB_CHANGETYPE_MODRDN) {
     936           3 :                 int ret;
     937             : 
     938           6 :                 ret = ldb_ldif_parse_modrdn(ldb, ldif, ldif,
     939             :                                             NULL, NULL, NULL, NULL, NULL);
     940           6 :                 if (ret != LDB_SUCCESS) {
     941           0 :                         goto failed;
     942             :                 }
     943             :         }
     944             : 
     945     1076485 :         return ldif;
     946             : 
     947        2689 : failed:
     948        2689 :         talloc_free(ldif);
     949        2689 :         return NULL;
     950             : }
     951             : 
     952             : 
     953             : 
     954             : /*
     955             :   a wrapper around ldif_read() for reading from FILE*
     956             : */
     957             : 
     958      703533 : static int fgetc_file(void *private_data)
     959             : {
     960       47294 :         int c;
     961      703533 :         struct ldif_read_file_state *state =
     962             :                 (struct ldif_read_file_state *)private_data;
     963      703533 :         c = fgetc(state->f);
     964      703533 :         if (c == '\n') {
     965       24342 :                 state->line_no++;
     966             :         }
     967      703533 :         return c;
     968             : }
     969             : 
     970        6212 : struct ldb_ldif *ldb_ldif_read_file_state(struct ldb_context *ldb,
     971             :                                           struct ldif_read_file_state *state)
     972             : {
     973        6212 :         return ldb_ldif_read(ldb, fgetc_file, state);
     974             : }
     975             : 
     976           0 : struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f)
     977             : {
     978           0 :         struct ldif_read_file_state state;
     979           0 :         state.f = f;
     980           0 :         return ldb_ldif_read_file_state(ldb, &state);
     981             : }
     982             : 
     983             : /*
     984             :   a wrapper around ldif_read() for reading from const char*
     985             : */
     986             : struct ldif_read_string_state {
     987             :         const char *s;
     988             : };
     989             : 
     990   793463993 : static int fgetc_string(void *private_data)
     991             : {
     992   793463993 :         struct ldif_read_string_state *state =
     993             :                 (struct ldif_read_string_state *)private_data;
     994   793463993 :         if (state->s[0] != 0) {
     995   793407902 :                 return *state->s++;
     996             :         }
     997       51791 :         return EOF;
     998             : }
     999             : 
    1000     1203528 : struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s)
    1001             : {
    1002      132169 :         struct ldif_read_string_state state;
    1003      132169 :         struct ldb_ldif *ldif;
    1004     1203528 :         state.s = *s;
    1005     1203528 :         ldif = ldb_ldif_read(ldb, fgetc_string, &state);
    1006     1203528 :         *s = state.s;
    1007     1203528 :         return ldif;
    1008             : }
    1009             : 
    1010             : 
    1011             : /*
    1012             :   wrapper around ldif_write() for a file
    1013             : */
    1014             : struct ldif_write_file_state {
    1015             :         FILE *f;
    1016             : };
    1017             : 
    1018             : static int fprintf_file(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
    1019             : 
    1020    43156307 : static int fprintf_file(void *private_data, const char *fmt, ...)
    1021             : {
    1022    43156307 :         struct ldif_write_file_state *state =
    1023             :                 (struct ldif_write_file_state *)private_data;
    1024    40026901 :         int ret;
    1025    40026901 :         va_list ap;
    1026             : 
    1027    43156307 :         va_start(ap, fmt);
    1028    43156307 :         ret = vfprintf(state->f, fmt, ap);
    1029    43156307 :         va_end(ap);
    1030    43156307 :         return ret;
    1031             : }
    1032             : 
    1033       97863 : int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif)
    1034             : {
    1035       90635 :         struct ldif_write_file_state state;
    1036       97863 :         state.f = f;
    1037       97863 :         return ldb_ldif_write(ldb, fprintf_file, &state, ldif);
    1038             : }
    1039             : 
    1040             : /*
    1041             :   wrapper around ldif_write() for a string
    1042             : */
    1043             : struct ldif_write_string_state {
    1044             :         char *string;
    1045             : };
    1046             : 
    1047             : static int ldif_printf_string(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
    1048             : 
    1049     4581863 : static int ldif_printf_string(void *private_data, const char *fmt, ...)
    1050             : {
    1051     4581863 :         struct ldif_write_string_state *state =
    1052             :                 (struct ldif_write_string_state *)private_data;
    1053       41838 :         va_list ap;
    1054     4581863 :         size_t oldlen = talloc_get_size(state->string);
    1055     4581863 :         va_start(ap, fmt);
    1056             : 
    1057     4581863 :         state->string = talloc_vasprintf_append(state->string, fmt, ap);
    1058     4581863 :         va_end(ap);
    1059     4581863 :         if (!state->string) {
    1060           0 :                 return -1;
    1061             :         }
    1062             : 
    1063     4581863 :         return talloc_get_size(state->string) - oldlen;
    1064             : }
    1065             : 
    1066          37 : char *ldb_ldif_write_redacted_trace_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
    1067             :                                            const struct ldb_ldif *ldif)
    1068             : {
    1069          37 :         struct ldif_write_string_state state;
    1070          37 :         state.string = talloc_strdup(mem_ctx, "");
    1071          37 :         if (!state.string) {
    1072           0 :                 return NULL;
    1073             :         }
    1074          37 :         if (ldb_ldif_write_trace(ldb, ldif_printf_string, &state, ldif, true) == -1) {
    1075           0 :                 return NULL;
    1076             :         }
    1077          37 :         return state.string;
    1078             : }
    1079             : 
    1080       14705 : char *ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
    1081             :                             const struct ldb_ldif *ldif)
    1082             : {
    1083         124 :         struct ldif_write_string_state state;
    1084       14705 :         state.string = talloc_strdup(mem_ctx, "");
    1085       14705 :         if (!state.string) {
    1086           0 :                 return NULL;
    1087             :         }
    1088       14705 :         if (ldb_ldif_write(ldb, ldif_printf_string, &state, ldif) == -1) {
    1089           0 :                 return NULL;
    1090             :         }
    1091       14705 :         return state.string;
    1092             : }
    1093             : 
    1094             : /*
    1095             :   convenient function to turn a ldb_message into a string. Useful for
    1096             :   debugging
    1097             :  */
    1098          37 : char *ldb_ldif_message_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
    1099             :                               enum ldb_changetype changetype,
    1100             :                               const struct ldb_message *msg)
    1101             : {
    1102          37 :         struct ldb_ldif ldif;
    1103             : 
    1104          37 :         ldif.changetype = changetype;
    1105          37 :         ldif.msg = discard_const_p(struct ldb_message, msg);
    1106             : 
    1107          37 :         return ldb_ldif_write_string(ldb, mem_ctx, &ldif);
    1108             : }
    1109             : 
    1110             : /*
    1111             :  * convenient function to turn a ldb_message into a string. Useful for
    1112             :  * debugging but also safer if some of the LDIF could be sensitive.
    1113             :  *
    1114             :  * The secret attributes are specified in a 'const char * const *' within
    1115             :  * the LDB_SECRET_ATTRIBUTE_LIST opaque set on the ldb
    1116             :  *
    1117             :  */
    1118          37 : char *ldb_ldif_message_redacted_string(struct ldb_context *ldb,
    1119             :                                        TALLOC_CTX *mem_ctx,
    1120             :                                        enum ldb_changetype changetype,
    1121             :                                        const struct ldb_message *msg)
    1122             : {
    1123          37 :         struct ldb_ldif ldif;
    1124             : 
    1125          37 :         ldif.changetype = changetype;
    1126          37 :         ldif.msg = discard_const_p(struct ldb_message, msg);
    1127             : 
    1128          37 :         return ldb_ldif_write_redacted_trace_string(ldb, mem_ctx, &ldif);
    1129             : }

Generated by: LCOV version 1.14