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