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

Generated by: LCOV version 1.14