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 4 : 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 4 : const char *fname = (const char *)value->data;
52 :
53 4 : if (strncmp(fname, "file://", 7) != 0) {
54 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
55 : }
56 4 : fname += 7;
57 :
58 4 : f = open(fname, O_RDONLY);
59 4 : if (f == -1) {
60 0 : return -1;
61 : }
62 :
63 4 : if (fstat(f, &statbuf) != 0) {
64 0 : ret = -1;
65 0 : goto done;
66 : }
67 :
68 4 : if (statbuf.st_size == 0) {
69 0 : ret = -1;
70 0 : goto done;
71 : }
72 :
73 4 : value->data = (uint8_t *)talloc_size(mem_ctx, statbuf.st_size + 1);
74 4 : if (value->data == NULL) {
75 0 : ret = -1;
76 0 : goto done;
77 : }
78 4 : value->data[statbuf.st_size] = 0;
79 :
80 4 : count = 0;
81 4 : size = statbuf.st_size;
82 4 : buf = (char *)value->data;
83 8 : while (count < statbuf.st_size) {
84 4 : bytes = read(f, buf, size);
85 4 : if (bytes == -1) {
86 0 : talloc_free(value->data);
87 0 : ret = -1;
88 0 : goto done;
89 : }
90 4 : count += bytes;
91 4 : buf += bytes;
92 4 : size -= bytes;
93 : }
94 :
95 4 : value->length = statbuf.st_size;
96 4 : ret = statbuf.st_size;
97 :
98 4 : done:
99 4 : close(f);
100 4 : 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 2042295 : int ldb_base64_decode(char *s)
108 : {
109 2042295 : const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
110 2042295 : int bit_offset=0, byte_offset, idx, i, n;
111 2042295 : uint8_t *d = (uint8_t *)s;
112 2042295 : char *p=NULL;
113 :
114 2042295 : n=i=0;
115 :
116 66147273 : while (*s && (p=strchr(b64,*s))) {
117 64104978 : idx = (int)(p - b64);
118 64104978 : byte_offset = (i*6)/8;
119 64104978 : bit_offset = (i*6)%8;
120 64104978 : d[byte_offset] &= ~((1<<(8-bit_offset))-1);
121 64104978 : if (bit_offset < 3) {
122 31903503 : d[byte_offset] |= (idx << (2-bit_offset));
123 31903503 : n = byte_offset+1;
124 : } else {
125 32201475 : d[byte_offset] |= (idx >> (bit_offset-2));
126 32201475 : d[byte_offset+1] = 0;
127 32201475 : d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
128 32201475 : n = byte_offset+2;
129 : }
130 64104978 : s++; i++;
131 : }
132 2042295 : if (bit_offset >= 3) {
133 1626323 : n--;
134 : }
135 :
136 2042295 : if (*s && !p) {
137 : /* the only termination allowed */
138 1626321 : if (*s != '=') {
139 0 : return -1;
140 : }
141 : }
142 :
143 : /* null terminate */
144 2042295 : d[n] = 0;
145 2042295 : return n;
146 : }
147 :
148 :
149 : /*
150 : encode as base64
151 : caller frees
152 : */
153 17714030 : char *ldb_base64_encode(TALLOC_CTX *mem_ctx, const char *buf, int len)
154 : {
155 17714030 : const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
156 480256 : int bit_offset, byte_offset, idx, i;
157 17714030 : const uint8_t *d = (const uint8_t *)buf;
158 17714030 : int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
159 480256 : char *out;
160 :
161 17714030 : out = talloc_array(mem_ctx, char, bytes+pad_bytes+1);
162 17714030 : if (!out) return NULL;
163 :
164 625622605 : for (i=0;i<bytes;i++) {
165 607908575 : byte_offset = (i*6)/8;
166 607908575 : bit_offset = (i*6)%8;
167 607908575 : if (bit_offset < 3) {
168 303763278 : idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
169 : } else {
170 304145297 : idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
171 304145297 : if (byte_offset+1 < len) {
172 290467923 : idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
173 : }
174 : }
175 607908575 : out[i] = b64[idx];
176 : }
177 :
178 44686759 : for (;i<bytes+pad_bytes;i++)
179 26972729 : out[i] = '=';
180 17714030 : out[i] = 0;
181 :
182 17714030 : return out;
183 : }
184 :
185 : /*
186 : see if a buffer should be base64 encoded
187 : */
188 45386900 : int ldb_should_b64_encode(struct ldb_context *ldb, const struct ldb_val *val)
189 : {
190 2990435 : unsigned int i;
191 45386900 : uint8_t *p = val->data;
192 :
193 45386900 : if (val->length == 0) {
194 5925 : return 0;
195 : }
196 :
197 45380941 : if (p[0] == ' ' || p[0] == ':') {
198 3258 : return 1;
199 : }
200 :
201 1484459257 : for (i=0; i<val->length; i++) {
202 1456737061 : if (!isprint(p[i]) || p[i] == '\n') {
203 17175305 : return 1;
204 : }
205 : }
206 25211977 : 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 864681 : 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 578358 : size_t i;
219 864681 : size_t total = 0;
220 578358 : int ret;
221 :
222 46246997 : for (i=0;i<length;i++) {
223 45382316 : ret = fprintf_fn(private_data, "%c", buf[i]);
224 45382316 : CHECK_RET;
225 45382316 : if (i != (length-1) && (i + start_pos) % 77 == 0) {
226 419781 : ret = fprintf_fn(private_data, "\n ");
227 38363697 : CHECK_RET;
228 : }
229 : }
230 :
231 864681 : return total;
232 : }
233 :
234 : #undef CHECK_RET
235 :
236 : /*
237 : encode as base64 to a file
238 : */
239 95005 : 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 95005 : char *b = ldb_base64_encode(ldb, buf, len);
245 92051 : int ret;
246 :
247 95005 : if (!b) {
248 0 : return -1;
249 : }
250 :
251 95005 : ret = fold_string(fprintf_fn, private_data, b, strlen(b), start_pos);
252 :
253 95005 : talloc_free(b);
254 95005 : 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 113018 : 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 90124 : TALLOC_CTX *mem_ctx;
283 90124 : unsigned int i, j;
284 113018 : size_t total = 0;
285 90124 : int ret;
286 90124 : char *p;
287 90124 : const struct ldb_message *msg;
288 113018 : const char * const * secret_attributes = ldb_get_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE);
289 :
290 113018 : mem_ctx = talloc_named_const(NULL, 0, "ldb_ldif_write");
291 :
292 113018 : msg = ldif->msg;
293 113018 : p = ldb_dn_get_extended_linearized(mem_ctx, msg->dn, 1);
294 113018 : ret = fprintf_fn(private_data, "dn: %s\n", p);
295 113018 : talloc_free(p);
296 113018 : CHECK_RET;
297 :
298 113018 : if (ldif->changetype != LDB_CHANGETYPE_NONE) {
299 48 : for (i=0;ldb_changetypes[i].name;i++) {
300 48 : if (ldb_changetypes[i].changetype == ldif->changetype) {
301 48 : break;
302 : }
303 : }
304 48 : 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 48 : ret = fprintf_fn(private_data, "changetype: %s\n", ldb_changetypes[i].name);
311 48 : CHECK_RET;
312 : }
313 :
314 861334 : for (i=0;i<msg->num_elements;i++) {
315 481722 : const struct ldb_schema_attribute *a;
316 481722 : size_t namelen;
317 :
318 748316 : 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 748316 : namelen = strlen(msg->elements[i].name);
326 748316 : a = ldb_schema_attribute_by_name(ldb, msg->elements[i].name);
327 :
328 748316 : 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 748316 : if (in_trace && secret_attributes && ldb_attr_in_list(secret_attributes, msg->elements[i].name)) {
346 : /* Deliberately skip printing this password */
347 24 : ret = fprintf_fn(private_data, "# %s::: REDACTED SECRET ATTRIBUTE\n",
348 24 : msg->elements[i].name);
349 24 : CHECK_RET;
350 24 : continue;
351 : }
352 1618619 : for (j=0;j<msg->elements[i].num_values;j++) {
353 578359 : struct ldb_val v;
354 870327 : bool use_b64_encode = false;
355 870327 : bool copy_raw_bytes = false;
356 :
357 870327 : ret = a->syntax->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v);
358 870327 : if (ret != LDB_SUCCESS) {
359 72 : v = msg->elements[i].values[j];
360 : }
361 :
362 870327 : if (ldb->flags & LDB_FLG_SHOW_BINARY) {
363 241 : use_b64_encode = false;
364 241 : copy_raw_bytes = true;
365 870085 : } else if (a->flags & LDB_ATTR_FLAG_FORCE_BASE64_LDIF) {
366 540 : use_b64_encode = true;
367 869545 : } else if (msg->elements[i].flags &
368 : LDB_FLAG_FORCE_NO_BASE64_LDIF) {
369 5404 : use_b64_encode = false;
370 5404 : copy_raw_bytes = true;
371 : } else {
372 864141 : use_b64_encode = ldb_should_b64_encode(ldb, &v);
373 : }
374 :
375 870327 : if (ret != LDB_SUCCESS || use_b64_encode) {
376 187056 : ret = fprintf_fn(private_data, "%s:: ",
377 95005 : msg->elements[i].name);
378 95005 : CHECK_RET;
379 187056 : ret = base64_encode_f(ldb, fprintf_fn, private_data,
380 95005 : (char *)v.data, v.length,
381 95005 : namelen + 3);
382 95005 : CHECK_RET;
383 95005 : ret = fprintf_fn(private_data, "\n");
384 95005 : CHECK_RET;
385 : } else {
386 775322 : ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name);
387 775322 : CHECK_RET;
388 775322 : if (copy_raw_bytes) {
389 5646 : ret = fprintf_fn(private_data, "%*.*s",
390 5646 : v.length, v.length, (char *)v.data);
391 : } else {
392 769676 : ret = fold_string(fprintf_fn, private_data,
393 769676 : (char *)v.data, v.length,
394 769676 : namelen + 2);
395 : }
396 775322 : CHECK_RET;
397 775322 : ret = fprintf_fn(private_data, "\n");
398 775322 : CHECK_RET;
399 : }
400 870327 : if (v.data != msg->elements[i].values[j].data) {
401 870255 : talloc_free(v.data);
402 : }
403 : }
404 748292 : if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
405 0 : fprintf_fn(private_data, "-\n");
406 : }
407 : }
408 113018 : ret = fprintf_fn(private_data,"\n");
409 113018 : CHECK_RET;
410 :
411 113018 : talloc_free(mem_ctx);
412 :
413 113018 : return total;
414 : }
415 :
416 : #undef CHECK_RET
417 :
418 :
419 : /*
420 : write to ldif, using a caller supplied write method
421 : */
422 112994 : 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 112994 : 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 1208289 : static char *next_chunk(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
438 : int (*fgetc_fn)(void *), void *private_data)
439 : {
440 1208289 : size_t alloc_size=0, chunk_size = 0;
441 1208289 : char *chunk = NULL;
442 129369 : int c;
443 1208289 : int in_comment = 0;
444 :
445 794099019 : while ((c = fgetc_fn(private_data)) != EOF) {
446 794042619 : if (chunk_size+1 >= alloc_size) {
447 148014 : char *c2;
448 1343462 : alloc_size += 1024;
449 1343462 : c2 = talloc_realloc(mem_ctx, chunk, char, alloc_size);
450 1343462 : if (!c2) {
451 0 : talloc_free(chunk);
452 0 : errno = ENOMEM;
453 0 : return NULL;
454 : }
455 1195448 : chunk = c2;
456 : }
457 :
458 794042619 : if (in_comment) {
459 1540381 : if (c == '\n') {
460 34117 : in_comment = 0;
461 : }
462 1540381 : continue;
463 : }
464 :
465 : /* handle continuation lines - see RFC2849 */
466 792502238 : if (c == ' ' && chunk_size > 1 && chunk[chunk_size-1] == '\n') {
467 295139 : chunk_size--;
468 295139 : continue;
469 : }
470 :
471 : /* chunks are terminated by a double line-feed */
472 792207099 : if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') {
473 1151889 : chunk[chunk_size-1] = 0;
474 1151889 : return chunk;
475 : }
476 :
477 791055210 : if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) {
478 34117 : in_comment = 1;
479 34117 : continue;
480 : }
481 :
482 : /* ignore leading blank lines */
483 791021093 : if (chunk_size == 0 && c == '\n') {
484 43652 : continue;
485 : }
486 :
487 790977441 : chunk[chunk_size++] = c;
488 : }
489 :
490 56400 : if (chunk) {
491 54751 : chunk[chunk_size] = 0;
492 : }
493 :
494 53683 : return chunk;
495 : }
496 :
497 :
498 : /* simple ldif attribute parser */
499 22436052 : static int next_attr(TALLOC_CTX *mem_ctx, char **s, const char **attr, struct ldb_val *value)
500 : {
501 2331755 : char *p;
502 22436052 : int base64_encoded = 0;
503 22436052 : int binary_file = 0;
504 :
505 22436052 : if (strncmp(*s, "-\n", 2) == 0) {
506 16014 : value->length = 0;
507 16014 : *attr = "-";
508 16014 : *s += 2;
509 16014 : return 0;
510 : }
511 :
512 22420038 : p = strchr(*s, ':');
513 22420038 : if (!p) {
514 1077362 : return -1;
515 : }
516 :
517 21213398 : *p++ = 0;
518 :
519 21213398 : if (*p == ':') {
520 1996797 : base64_encoded = 1;
521 1996797 : p++;
522 : }
523 :
524 21213398 : if (*p == '<') {
525 4 : binary_file = 1;
526 4 : p++;
527 : }
528 :
529 21213398 : *attr = *s;
530 :
531 42411285 : while (*p == ' ' || *p == '\t') {
532 21197887 : p++;
533 : }
534 :
535 21213398 : value->data = (uint8_t *)p;
536 :
537 21213398 : p = strchr(p, '\n');
538 :
539 21213398 : if (!p) {
540 1138741 : value->length = strlen((char *)value->data);
541 1138741 : *s = ((char *)value->data) + value->length;
542 : } else {
543 20074657 : value->length = p - (char *)value->data;
544 20074657 : *s = p+1;
545 20074657 : *p = 0;
546 : }
547 :
548 21213398 : if (base64_encoded) {
549 1996797 : int len = ldb_base64_decode((char *)value->data);
550 1996797 : if (len == -1) {
551 : /* it wasn't valid base64 data */
552 0 : return -1;
553 : }
554 1996797 : value->length = len;
555 : }
556 :
557 21213398 : if (binary_file) {
558 4 : int len = ldb_read_data_file(mem_ctx, value);
559 4 : if (len == -1) {
560 : /* an error occurred while trying to retrieve the file */
561 0 : return -1;
562 : }
563 : }
564 :
565 19013533 : return 0;
566 : }
567 :
568 :
569 : /*
570 : free a message from a ldif_read
571 : */
572 5710 : void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif)
573 : {
574 5710 : talloc_free(ldif);
575 5710 : }
576 :
577 16 : 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 16 : struct ldb_message *msg = ldif->msg;
587 16 : struct ldb_val _newrdn_val = {};
588 16 : struct ldb_val *newrdn_val = NULL;
589 16 : struct ldb_val *deleteoldrdn_val = NULL;
590 16 : struct ldb_val *newsuperior_val = NULL;
591 16 : struct ldb_dn *olddn = NULL;
592 16 : struct ldb_dn *newrdn = NULL;
593 16 : bool deleteoldrdn = true;
594 16 : struct ldb_dn *newsuperior = NULL;
595 16 : struct ldb_dn *newdn = NULL;
596 6 : struct ldb_val tmp_false;
597 6 : struct ldb_val tmp_true;
598 6 : bool ok;
599 16 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
600 :
601 16 : 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 16 : 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 16 : 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 16 : 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 16 : CHECK_ELEMENT(0, "newrdn", newrdn_val, true);
658 16 : CHECK_ELEMENT(1, "deleteoldrdn", deleteoldrdn_val, true);
659 16 : CHECK_ELEMENT(2, "newsuperior", newsuperior_val, false);
660 :
661 : #undef CHECK_ELEMENT
662 :
663 16 : olddn = ldb_dn_copy(tmp_ctx, msg->dn);
664 16 : 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 16 : 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 16 : newrdn = ldb_dn_from_ldb_val(tmp_ctx, ldb, newrdn_val);
691 16 : 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 16 : tmp_false.length = 1;
699 16 : tmp_false.data = discard_const_p(uint8_t, "0");
700 16 : tmp_true.length = 1;
701 16 : tmp_true.data = discard_const_p(uint8_t, "1");
702 16 : if (ldb_val_equal_exact(deleteoldrdn_val, &tmp_false) == 1) {
703 0 : deleteoldrdn = false;
704 16 : } else if (ldb_val_equal_exact(deleteoldrdn_val, &tmp_true) == 1) {
705 10 : 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 16 : if (newsuperior_val) {
714 4 : newsuperior = ldb_dn_from_ldb_val(tmp_ctx, ldb, newsuperior_val);
715 4 : 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 12 : newsuperior = ldb_dn_get_parent(tmp_ctx, msg->dn);
723 12 : 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 16 : newdn = ldb_dn_copy(tmp_ctx, newrdn);
732 16 : 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 16 : ok = ldb_dn_add_base(newdn, newsuperior);
740 16 : 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 16 : if (_olddn) {
749 8 : *_olddn = talloc_move(mem_ctx, &olddn);
750 : }
751 16 : if (_newrdn) {
752 0 : *_newrdn = talloc_move(mem_ctx, &newrdn);
753 : }
754 16 : if (_deleteoldrdn) {
755 8 : *_deleteoldrdn = deleteoldrdn;
756 : }
757 16 : 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 16 : if (_newdn) {
765 8 : *_newdn = talloc_move(mem_ctx, &newdn);
766 : }
767 :
768 16 : talloc_free(tmp_ctx);
769 16 : 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 1208289 : struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
788 : int (*fgetc_fn)(void *), void *private_data)
789 : {
790 129369 : struct ldb_ldif *ldif;
791 129369 : struct ldb_message *msg;
792 1208289 : const char *attr=NULL;
793 1208289 : char *chunk=NULL, *s;
794 129369 : struct ldb_val value;
795 1208289 : unsigned flags = 0;
796 1208289 : value.data = NULL;
797 :
798 1208289 : ldif = talloc(ldb, struct ldb_ldif);
799 1208289 : if (!ldif) return NULL;
800 :
801 1208289 : ldif->msg = ldb_msg_new(ldif);
802 1208289 : if (ldif->msg == NULL) {
803 0 : talloc_free(ldif);
804 0 : return NULL;
805 : }
806 :
807 1208289 : ldif->changetype = LDB_CHANGETYPE_NONE;
808 1208289 : msg = ldif->msg;
809 :
810 1208289 : chunk = next_chunk(ldb, ldif, fgetc_fn, private_data);
811 1208289 : if (!chunk) {
812 1649 : goto failed;
813 : }
814 :
815 1206640 : s = chunk;
816 :
817 1206640 : if (next_attr(ldif, &s, &attr, &value) != 0) {
818 426 : goto failed;
819 : }
820 :
821 : /* first line must be a dn */
822 1206214 : 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 1206214 : msg->dn = ldb_dn_from_ldb_val(msg, ldb, &value);
829 :
830 1206214 : 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 21229412 : while (next_attr(ldif, &s, &attr, &value) == 0) {
837 2073200 : const struct ldb_schema_attribute *a;
838 2073200 : struct ldb_message_element *el;
839 20023198 : int ret, empty = 0;
840 :
841 20023198 : if (ldb_attr_cmp(attr, "changetype") == 0) {
842 : int i;
843 159007 : for (i=0;ldb_changetypes[i].name;i++) {
844 159007 : if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) {
845 58763 : ldif->changetype = ldb_changetypes[i].changetype;
846 58763 : break;
847 : }
848 : }
849 58763 : 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 58763 : flags = 0;
854 58763 : continue;
855 : }
856 :
857 19964435 : if (ldb_attr_cmp(attr, "add") == 0) {
858 28291 : flags = LDB_FLAG_MOD_ADD;
859 28291 : empty = 1;
860 : }
861 19964435 : if (ldb_attr_cmp(attr, "delete") == 0) {
862 16266 : flags = LDB_FLAG_MOD_DELETE;
863 16266 : empty = 1;
864 : }
865 19964435 : if (ldb_attr_cmp(attr, "replace") == 0) {
866 31747 : flags = LDB_FLAG_MOD_REPLACE;
867 31747 : empty = 1;
868 : }
869 19964435 : if (ldb_attr_cmp(attr, "-") == 0) {
870 16014 : flags = 0;
871 16014 : continue;
872 : }
873 :
874 19948421 : if (empty) {
875 76304 : if (ldb_msg_add_empty(msg, (char *)value.data, flags, NULL) != 0) {
876 0 : goto failed;
877 : }
878 76304 : continue;
879 : }
880 :
881 19872117 : a = ldb_schema_attribute_by_name(ldb, attr);
882 41185293 : el = (msg->num_elements > 0
883 18717270 : ? &msg->elements[msg->num_elements - 1]
884 19872117 : : NULL);
885 :
886 19745304 : if (el && ldb_attr_cmp(attr, el->name) == 0 && flags == el->flags) {
887 : /* its a continuation */
888 4282959 : el->values =
889 3787033 : talloc_realloc(msg->elements, el->values,
890 : struct ldb_val, el->num_values+1);
891 3787033 : if (!el->values) {
892 0 : goto failed;
893 : }
894 3787033 : ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[el->num_values]);
895 3787033 : if (ret != 0) {
896 0 : goto failed;
897 : }
898 3787033 : 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 3787033 : if (value.data != el->values[el->num_values].data) {
904 3787033 : talloc_steal(el->values, el->values[el->num_values].data);
905 : }
906 3787033 : el->num_values++;
907 : } else {
908 : /* its a new attribute */
909 16085084 : msg->elements = talloc_realloc(msg, msg->elements,
910 : struct ldb_message_element,
911 : msg->num_elements+1);
912 16085084 : if (!msg->elements) {
913 0 : goto failed;
914 : }
915 16085084 : el = &msg->elements[msg->num_elements];
916 16085084 : el->flags = flags;
917 16085084 : el->name = talloc_strdup(msg->elements, attr);
918 16085084 : el->values = talloc(msg->elements, struct ldb_val);
919 16085084 : if (!el->values || !el->name) {
920 0 : goto failed;
921 : }
922 16085084 : el->num_values = 1;
923 16085084 : ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[0]);
924 16085084 : if (ret != 0) {
925 0 : goto failed;
926 : }
927 16085084 : if (value.data != el->values[0].data) {
928 16085084 : talloc_steal(el->values, el->values[0].data);
929 : }
930 16085084 : msg->num_elements++;
931 : }
932 : }
933 :
934 1206214 : if (ldif->changetype == LDB_CHANGETYPE_MODRDN) {
935 3 : int ret;
936 :
937 8 : ret = ldb_ldif_parse_modrdn(ldb, ldif, ldif,
938 : NULL, NULL, NULL, NULL, NULL);
939 8 : if (ret != LDB_SUCCESS) {
940 0 : goto failed;
941 : }
942 : }
943 :
944 1076937 : return ldif;
945 :
946 2075 : failed:
947 2075 : talloc_free(ldif);
948 2075 : return NULL;
949 : }
950 :
951 :
952 :
953 : /*
954 : a wrapper around ldif_read() for reading from FILE*
955 : */
956 :
957 728544 : static int fgetc_file(void *private_data)
958 : {
959 47294 : int c;
960 728544 : struct ldif_read_file_state *state =
961 : (struct ldif_read_file_state *)private_data;
962 728544 : c = fgetc(state->f);
963 728544 : if (c == '\n') {
964 24986 : state->line_no++;
965 : }
966 728544 : return c;
967 : }
968 :
969 6302 : struct ldb_ldif *ldb_ldif_read_file_state(struct ldb_context *ldb,
970 : struct ldif_read_file_state *state)
971 : {
972 6302 : 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 793370475 : static int fgetc_string(void *private_data)
990 : {
991 793370475 : struct ldif_read_string_state *state =
992 : (struct ldif_read_string_state *)private_data;
993 793370475 : if (state->s[0] != 0) {
994 793315280 : return *state->s++;
995 : }
996 52608 : return EOF;
997 : }
998 :
999 1201987 : struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s)
1000 : {
1001 129167 : struct ldif_read_string_state state;
1002 129167 : struct ldb_ldif *ldif;
1003 1201987 : state.s = *s;
1004 1201987 : ldif = ldb_ldif_read(ldb, fgetc_string, &state);
1005 1201987 : *s = state.s;
1006 1201987 : 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 43202789 : static int fprintf_file(void *private_data, const char *fmt, ...)
1020 : {
1021 43202789 : struct ldif_write_file_state *state =
1022 : (struct ldif_write_file_state *)private_data;
1023 39990288 : int ret;
1024 39990288 : va_list ap;
1025 :
1026 43202789 : va_start(ap, fmt);
1027 43202789 : ret = vfprintf(state->f, fmt, ap);
1028 43202789 : va_end(ap);
1029 43202789 : return ret;
1030 : }
1031 :
1032 98423 : int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif)
1033 : {
1034 90037 : struct ldif_write_file_state state;
1035 98423 : state.f = f;
1036 98423 : 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 4571716 : static int ldif_printf_string(void *private_data, const char *fmt, ...)
1049 : {
1050 4571716 : struct ldif_write_string_state *state =
1051 : (struct ldif_write_string_state *)private_data;
1052 40395 : va_list ap;
1053 4571716 : size_t oldlen = talloc_get_size(state->string);
1054 4571716 : va_start(ap, fmt);
1055 :
1056 4571716 : state->string = talloc_vasprintf_append(state->string, fmt, ap);
1057 4571716 : va_end(ap);
1058 4571716 : if (!state->string) {
1059 0 : return -1;
1060 : }
1061 :
1062 4571716 : return talloc_get_size(state->string) - oldlen;
1063 : }
1064 :
1065 24 : char *ldb_ldif_write_redacted_trace_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1066 : const struct ldb_ldif *ldif)
1067 : {
1068 0 : struct ldif_write_string_state state;
1069 24 : state.string = talloc_strdup(mem_ctx, "");
1070 24 : if (!state.string) {
1071 0 : return NULL;
1072 : }
1073 24 : if (ldb_ldif_write_trace(ldb, ldif_printf_string, &state, ldif, true) == -1) {
1074 0 : return NULL;
1075 : }
1076 24 : return state.string;
1077 : }
1078 :
1079 14571 : char *ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1080 : const struct ldb_ldif *ldif)
1081 : {
1082 87 : struct ldif_write_string_state state;
1083 14571 : state.string = talloc_strdup(mem_ctx, "");
1084 14571 : if (!state.string) {
1085 0 : return NULL;
1086 : }
1087 14571 : if (ldb_ldif_write(ldb, ldif_printf_string, &state, ldif) == -1) {
1088 0 : return NULL;
1089 : }
1090 14571 : return state.string;
1091 : }
1092 :
1093 : /*
1094 : convenient function to turn a ldb_message into a string. Useful for
1095 : debugging
1096 : */
1097 24 : 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 0 : struct ldb_ldif ldif;
1102 :
1103 24 : ldif.changetype = changetype;
1104 24 : ldif.msg = discard_const_p(struct ldb_message, msg);
1105 :
1106 24 : 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 24 : 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 0 : struct ldb_ldif ldif;
1123 :
1124 24 : ldif.changetype = changetype;
1125 24 : ldif.msg = discard_const_p(struct ldb_message, msg);
1126 :
1127 24 : return ldb_ldif_write_redacted_trace_string(ldb, mem_ctx, &ldif);
1128 : }
|