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 1 : static int ldb_read_data_file(TALLOC_CTX *mem_ctx, struct ldb_val *value)
45 : {
46 : struct stat statbuf;
47 : char *buf;
48 : int count, size, bytes;
49 : int ret;
50 : int f;
51 1 : const char *fname = (const char *)value->data;
52 :
53 1 : if (strncmp(fname, "file://", 7) != 0) {
54 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
55 : }
56 1 : fname += 7;
57 :
58 1 : f = open(fname, O_RDONLY);
59 1 : if (f == -1) {
60 0 : return -1;
61 : }
62 :
63 1 : if (fstat(f, &statbuf) != 0) {
64 0 : ret = -1;
65 0 : goto done;
66 : }
67 :
68 1 : if (statbuf.st_size == 0) {
69 0 : ret = -1;
70 0 : goto done;
71 : }
72 :
73 1 : value->data = (uint8_t *)talloc_size(mem_ctx, statbuf.st_size + 1);
74 1 : if (value->data == NULL) {
75 0 : ret = -1;
76 0 : goto done;
77 : }
78 1 : value->data[statbuf.st_size] = 0;
79 :
80 1 : count = 0;
81 1 : size = statbuf.st_size;
82 1 : buf = (char *)value->data;
83 3 : while (count < statbuf.st_size) {
84 1 : bytes = read(f, buf, size);
85 1 : if (bytes == -1) {
86 0 : talloc_free(value->data);
87 0 : ret = -1;
88 0 : goto done;
89 : }
90 1 : count += bytes;
91 1 : buf += bytes;
92 1 : size -= bytes;
93 : }
94 :
95 1 : value->length = statbuf.st_size;
96 1 : ret = statbuf.st_size;
97 :
98 1 : done:
99 1 : close(f);
100 1 : 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 1406669 : int ldb_base64_decode(char *s)
108 : {
109 1406669 : const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
110 1406669 : int bit_offset=0, byte_offset, idx, i, n;
111 1406669 : uint8_t *d = (uint8_t *)s;
112 1406669 : char *p=NULL;
113 :
114 1406669 : n=i=0;
115 :
116 44379850 : while (*s && (p=strchr(b64,*s))) {
117 41798288 : idx = (int)(p - b64);
118 41798288 : byte_offset = (i*6)/8;
119 41798288 : bit_offset = (i*6)%8;
120 41798288 : d[byte_offset] &= ~((1<<(8-bit_offset))-1);
121 41798288 : if (bit_offset < 3) {
122 20810115 : d[byte_offset] |= (idx << (2-bit_offset));
123 20810115 : n = byte_offset+1;
124 : } else {
125 20988173 : d[byte_offset] |= (idx >> (bit_offset-2));
126 20988173 : d[byte_offset+1] = 0;
127 20988173 : d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
128 20988173 : n = byte_offset+2;
129 : }
130 41798288 : s++; i++;
131 : }
132 1406669 : if (bit_offset >= 3) {
133 1142821 : n--;
134 : }
135 :
136 1406669 : if (*s && !p) {
137 : /* the only termination allowed */
138 1142820 : if (*s != '=') {
139 0 : return -1;
140 : }
141 : }
142 :
143 : /* null terminate */
144 1406669 : d[n] = 0;
145 1406669 : return n;
146 : }
147 :
148 :
149 : /*
150 : encode as base64
151 : caller frees
152 : */
153 9840547 : char *ldb_base64_encode(TALLOC_CTX *mem_ctx, const char *buf, int len)
154 : {
155 9840547 : const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
156 : int bit_offset, byte_offset, idx, i;
157 9840547 : const uint8_t *d = (const uint8_t *)buf;
158 9840547 : int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
159 : char *out;
160 :
161 9840547 : out = talloc_array(mem_ctx, char, bytes+pad_bytes+1);
162 9840547 : if (!out) return NULL;
163 :
164 350701140 : for (i=0;i<bytes;i++) {
165 340860593 : byte_offset = (i*6)/8;
166 340860593 : bit_offset = (i*6)%8;
167 340860593 : if (bit_offset < 3) {
168 170294269 : idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
169 : } else {
170 170566324 : idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
171 170566324 : if (byte_offset+1 < len) {
172 163161563 : idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
173 : }
174 : }
175 340860593 : out[i] = b64[idx];
176 : }
177 :
178 24378014 : for (;i<bytes+pad_bytes;i++)
179 14537467 : out[i] = '=';
180 9840547 : out[i] = 0;
181 :
182 9840547 : return out;
183 : }
184 :
185 : /*
186 : see if a buffer should be base64 encoded
187 : */
188 29985536 : int ldb_should_b64_encode(struct ldb_context *ldb, const struct ldb_val *val)
189 : {
190 : unsigned int i;
191 29985536 : uint8_t *p = val->data;
192 :
193 29985536 : if (val->length == 0) {
194 4905 : return 0;
195 : }
196 :
197 29980631 : if (p[0] == ' ' || p[0] == ':') {
198 1139 : return 1;
199 : }
200 :
201 1298668948 : for (i=0; i<val->length; i++) {
202 1278482307 : if (!isprint(p[i]) || p[i] == '\n') {
203 9792851 : return 1;
204 : }
205 : }
206 20186641 : 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 240488 : 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 : size_t i;
219 240488 : size_t total = 0;
220 : int ret;
221 :
222 5595468 : for (i=0;i<length;i++) {
223 5354980 : ret = fprintf_fn(private_data, "%c", buf[i]);
224 5354980 : CHECK_RET;
225 5354980 : if (i != (length-1) && (i + start_pos) % 77 == 0) {
226 30370 : ret = fprintf_fn(private_data, "\n ");
227 30370 : CHECK_RET;
228 : }
229 : }
230 :
231 240488 : return total;
232 : }
233 :
234 : #undef CHECK_RET
235 :
236 : /*
237 : encode as base64 to a file
238 : */
239 2054 : 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 2054 : char *b = ldb_base64_encode(ldb, buf, len);
245 : int ret;
246 :
247 2054 : if (!b) {
248 0 : return -1;
249 : }
250 :
251 2054 : ret = fold_string(fprintf_fn, private_data, b, strlen(b), start_pos);
252 :
253 2054 : talloc_free(b);
254 2054 : 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 13736 : 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 : TALLOC_CTX *mem_ctx;
283 : unsigned int i, j;
284 13736 : size_t total = 0;
285 : int ret;
286 : char *p;
287 : const struct ldb_message *msg;
288 13736 : const char * const * secret_attributes = ldb_get_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE);
289 :
290 13736 : mem_ctx = talloc_named_const(NULL, 0, "ldb_ldif_write");
291 :
292 13736 : msg = ldif->msg;
293 13736 : p = ldb_dn_get_extended_linearized(mem_ctx, msg->dn, 1);
294 13736 : ret = fprintf_fn(private_data, "dn: %s\n", p);
295 13736 : talloc_free(p);
296 13736 : CHECK_RET;
297 :
298 13736 : 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 233900 : for (i=0;i<msg->num_elements;i++) {
315 : const struct ldb_schema_attribute *a;
316 : size_t namelen;
317 :
318 220164 : 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 220164 : namelen = strlen(msg->elements[i].name);
326 220164 : a = ldb_schema_attribute_by_name(ldb, msg->elements[i].name);
327 :
328 220164 : 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 220164 : if (in_trace && secret_attributes && ldb_attr_in_list(secret_attributes, msg->elements[i].name)) {
346 : /* Deliberatly 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 925548 : for (j=0;j<msg->elements[i].num_values;j++) {
353 : struct ldb_val v;
354 245020 : bool use_b64_encode = false;
355 245020 : bool copy_raw_bytes = false;
356 :
357 245020 : ret = a->syntax->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v);
358 245020 : if (ret != LDB_SUCCESS) {
359 0 : v = msg->elements[i].values[j];
360 : }
361 :
362 245020 : if (ldb->flags & LDB_FLG_SHOW_BINARY) {
363 234 : use_b64_encode = false;
364 234 : copy_raw_bytes = true;
365 244786 : } else if (a->flags & LDB_ATTR_FLAG_FORCE_BASE64_LDIF) {
366 0 : use_b64_encode = true;
367 244786 : } else if (msg->elements[i].flags &
368 : LDB_FLAG_FORCE_NO_BASE64_LDIF) {
369 4298 : use_b64_encode = false;
370 4298 : copy_raw_bytes = true;
371 : } else {
372 240488 : use_b64_encode = ldb_should_b64_encode(ldb, &v);
373 : }
374 :
375 245020 : if (ret != LDB_SUCCESS || use_b64_encode) {
376 2054 : ret = fprintf_fn(private_data, "%s:: ",
377 2054 : msg->elements[i].name);
378 2054 : CHECK_RET;
379 6034 : ret = base64_encode_f(ldb, fprintf_fn, private_data,
380 4044 : (char *)v.data, v.length,
381 2054 : namelen + 3);
382 2054 : CHECK_RET;
383 2054 : ret = fprintf_fn(private_data, "\n");
384 2054 : CHECK_RET;
385 : } else {
386 242966 : ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name);
387 242966 : CHECK_RET;
388 242966 : if (copy_raw_bytes) {
389 4532 : ret = fprintf_fn(private_data, "%*.*s",
390 4532 : v.length, v.length, (char *)v.data);
391 : } else {
392 476375 : ret = fold_string(fprintf_fn, private_data,
393 238434 : (char *)v.data, v.length,
394 238434 : namelen + 2);
395 : }
396 242966 : CHECK_RET;
397 242966 : ret = fprintf_fn(private_data, "\n");
398 242966 : CHECK_RET;
399 : }
400 245020 : if (v.data != msg->elements[i].values[j].data) {
401 245020 : talloc_free(v.data);
402 : }
403 : }
404 220140 : if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
405 0 : fprintf_fn(private_data, "-\n");
406 : }
407 : }
408 13736 : ret = fprintf_fn(private_data,"\n");
409 13736 : CHECK_RET;
410 :
411 13736 : talloc_free(mem_ctx);
412 :
413 13736 : return total;
414 : }
415 :
416 : #undef CHECK_RET
417 :
418 :
419 : /*
420 : write to ldif, using a caller supplied write method
421 : */
422 13712 : 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 13712 : 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 858173 : static char *next_chunk(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
438 : int (*fgetc_fn)(void *), void *private_data)
439 : {
440 858173 : size_t alloc_size=0, chunk_size = 0;
441 858173 : char *chunk = NULL;
442 : int c;
443 858173 : int in_comment = 0;
444 :
445 567794390 : while ((c = fgetc_fn(private_data)) != EOF) {
446 567040452 : if (chunk_size+1 >= alloc_size) {
447 : char *c2;
448 948756 : alloc_size += 1024;
449 948756 : c2 = talloc_realloc(mem_ctx, chunk, char, alloc_size);
450 948756 : if (!c2) {
451 0 : talloc_free(chunk);
452 0 : errno = ENOMEM;
453 0 : return NULL;
454 : }
455 948756 : chunk = c2;
456 : }
457 :
458 567040452 : if (in_comment) {
459 961496 : if (c == '\n') {
460 21403 : in_comment = 0;
461 : }
462 961496 : continue;
463 : }
464 :
465 : /* handle continuation lines - see RFC2849 */
466 566078956 : if (c == ' ' && chunk_size > 1 && chunk[chunk_size-1] == '\n') {
467 277575 : chunk_size--;
468 277575 : continue;
469 : }
470 :
471 : /* chunks are terminated by a double line-feed */
472 565801381 : if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') {
473 825035 : chunk[chunk_size-1] = 0;
474 825035 : return chunk;
475 : }
476 :
477 564976346 : if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) {
478 21403 : in_comment = 1;
479 21403 : continue;
480 : }
481 :
482 : /* ignore leading blank lines */
483 564954943 : if (chunk_size == 0 && c == '\n') {
484 30939 : continue;
485 : }
486 :
487 564924004 : chunk[chunk_size++] = c;
488 : }
489 :
490 33138 : if (chunk) {
491 31678 : chunk[chunk_size] = 0;
492 : }
493 :
494 33138 : return chunk;
495 : }
496 :
497 :
498 : /* simple ldif attribute parser */
499 16346266 : static int next_attr(TALLOC_CTX *mem_ctx, char **s, const char **attr, struct ldb_val *value)
500 : {
501 : char *p;
502 16346266 : int base64_encoded = 0;
503 16346266 : int binary_file = 0;
504 :
505 16346266 : if (strncmp(*s, "-\n", 2) == 0) {
506 9689 : value->length = 0;
507 9689 : *attr = "-";
508 9689 : *s += 2;
509 9689 : return 0;
510 : }
511 :
512 16336577 : p = strchr(*s, ':');
513 16336577 : if (!p) {
514 856713 : return -1;
515 : }
516 :
517 15479864 : *p++ = 0;
518 :
519 15479864 : if (*p == ':') {
520 1361276 : base64_encoded = 1;
521 1361276 : p++;
522 : }
523 :
524 15479864 : if (*p == '<') {
525 1 : binary_file = 1;
526 1 : p++;
527 : }
528 :
529 15479864 : *attr = *s;
530 :
531 44061436 : while (*p == ' ' || *p == '\t') {
532 15479459 : p++;
533 : }
534 :
535 15479864 : value->data = (uint8_t *)p;
536 :
537 15479864 : p = strchr(p, '\n');
538 :
539 15479864 : if (!p) {
540 819851 : value->length = strlen((char *)value->data);
541 819851 : *s = ((char *)value->data) + value->length;
542 : } else {
543 14660013 : value->length = p - (char *)value->data;
544 14660013 : *s = p+1;
545 14660013 : *p = 0;
546 : }
547 :
548 15479864 : if (base64_encoded) {
549 1361276 : int len = ldb_base64_decode((char *)value->data);
550 1361276 : if (len == -1) {
551 : /* it wasn't valid base64 data */
552 0 : return -1;
553 : }
554 1361276 : value->length = len;
555 : }
556 :
557 15479864 : if (binary_file) {
558 1 : int len = ldb_read_data_file(mem_ctx, value);
559 1 : if (len == -1) {
560 : /* an error occurred while trying to retrieve the file */
561 0 : return -1;
562 : }
563 : }
564 :
565 15479864 : return 0;
566 : }
567 :
568 :
569 : /*
570 : free a message from a ldif_read
571 : */
572 570 : void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif)
573 : {
574 570 : talloc_free(ldif);
575 570 : }
576 :
577 6 : 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 6 : struct ldb_message *msg = ldif->msg;
587 6 : struct ldb_val *newrdn_val = NULL;
588 6 : struct ldb_val *deleteoldrdn_val = NULL;
589 6 : struct ldb_val *newsuperior_val = NULL;
590 6 : struct ldb_dn *olddn = NULL;
591 6 : struct ldb_dn *newrdn = NULL;
592 6 : bool deleteoldrdn = true;
593 6 : struct ldb_dn *newsuperior = NULL;
594 6 : struct ldb_dn *newdn = NULL;
595 : struct ldb_val tmp_false;
596 : struct ldb_val tmp_true;
597 : bool ok;
598 6 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
599 :
600 6 : if (tmp_ctx == NULL) {
601 0 : ldb_debug(ldb, LDB_DEBUG_FATAL,
602 : "Error: talloc_new() failed");
603 0 : goto err_op;
604 : }
605 :
606 6 : if (ldif->changetype != LDB_CHANGETYPE_MODRDN) {
607 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
608 : "Error: invalid changetype '%d'",
609 0 : ldif->changetype);
610 0 : goto err_other;
611 : }
612 :
613 6 : if (msg->num_elements < 2) {
614 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
615 : "Error: num_elements[%u] < 2",
616 : msg->num_elements);
617 0 : goto err_other;
618 : }
619 :
620 6 : if (msg->num_elements > 3) {
621 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
622 : "Error: num_elements[%u] > 3",
623 : msg->num_elements);
624 0 : goto err_other;
625 : }
626 :
627 : #define CHECK_ELEMENT(i, _name, v, needed) do { \
628 : v = NULL; \
629 : if (msg->num_elements < (i + 1)) { \
630 : if (needed) { \
631 : ldb_debug(ldb, LDB_DEBUG_ERROR, \
632 : "Error: num_elements[%u] < (%u + 1)", \
633 : msg->num_elements, i); \
634 : goto err_other; \
635 : } \
636 : } else if (ldb_attr_cmp(msg->elements[i].name, _name) != 0) { \
637 : ldb_debug(ldb, LDB_DEBUG_ERROR, \
638 : "Error: elements[%u].name[%s] != [%s]", \
639 : i, msg->elements[i].name, _name); \
640 : goto err_other; \
641 : } else if (msg->elements[i].flags != 0) { \
642 : ldb_debug(ldb, LDB_DEBUG_ERROR, \
643 : "Error: elements[%u].flags[0x%X} != [0x0]", \
644 : i, msg->elements[i].flags); \
645 : goto err_other; \
646 : } else if (msg->elements[i].num_values != 1) { \
647 : ldb_debug(ldb, LDB_DEBUG_ERROR, \
648 : "Error: elements[%u].num_values[%u] != 1", \
649 : i, msg->elements[i].num_values); \
650 : goto err_other; \
651 : } else { \
652 : v = &msg->elements[i].values[0]; \
653 : } \
654 : } while (0)
655 :
656 6 : CHECK_ELEMENT(0, "newrdn", newrdn_val, true);
657 6 : CHECK_ELEMENT(1, "deleteoldrdn", deleteoldrdn_val, true);
658 6 : CHECK_ELEMENT(2, "newsuperior", newsuperior_val, false);
659 :
660 : #undef CHECK_ELEMENT
661 :
662 6 : olddn = ldb_dn_copy(tmp_ctx, msg->dn);
663 6 : if (olddn == NULL) {
664 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
665 : "Error: failed to copy olddn '%s'",
666 : ldb_dn_get_linearized(msg->dn));
667 0 : goto err_op;
668 : }
669 :
670 6 : newrdn = ldb_dn_from_ldb_val(tmp_ctx, ldb, newrdn_val);
671 6 : if (!ldb_dn_validate(newrdn)) {
672 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
673 : "Error: Unable to parse dn '%s'",
674 0 : (char *)newrdn_val->data);
675 0 : goto err_dn;
676 : }
677 :
678 6 : tmp_false.length = 1;
679 6 : tmp_false.data = discard_const_p(uint8_t, "0");
680 6 : tmp_true.length = 1;
681 6 : tmp_true.data = discard_const_p(uint8_t, "1");
682 6 : if (ldb_val_equal_exact(deleteoldrdn_val, &tmp_false) == 1) {
683 0 : deleteoldrdn = false;
684 6 : } else if (ldb_val_equal_exact(deleteoldrdn_val, &tmp_true) == 1) {
685 6 : deleteoldrdn = true;
686 : } else {
687 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
688 : "Error: deleteoldrdn value invalid '%s' not '0'/'1'",
689 0 : (char *)deleteoldrdn_val->data);
690 0 : goto err_attr;
691 : }
692 :
693 6 : if (newsuperior_val) {
694 2 : newsuperior = ldb_dn_from_ldb_val(tmp_ctx, ldb, newsuperior_val);
695 2 : if (!ldb_dn_validate(newsuperior)) {
696 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
697 : "Error: Unable to parse dn '%s'",
698 0 : (char *)newsuperior_val->data);
699 0 : goto err_dn;
700 : }
701 : } else {
702 4 : newsuperior = ldb_dn_get_parent(tmp_ctx, msg->dn);
703 4 : if (newsuperior == NULL) {
704 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
705 : "Error: Unable to get parent dn '%s'",
706 : ldb_dn_get_linearized(msg->dn));
707 0 : goto err_dn;
708 : }
709 : }
710 :
711 6 : newdn = ldb_dn_copy(tmp_ctx, newrdn);
712 6 : if (newdn == NULL) {
713 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
714 : "Error: failed to copy newrdn '%s'",
715 : ldb_dn_get_linearized(newrdn));
716 0 : goto err_op;
717 : }
718 :
719 6 : ok = ldb_dn_add_base(newdn, newsuperior);
720 6 : if (!ok) {
721 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
722 : "Error: failed to base '%s' to newdn '%s'",
723 : ldb_dn_get_linearized(newsuperior),
724 : ldb_dn_get_linearized(newdn));
725 0 : goto err_op;
726 : }
727 :
728 6 : if (_olddn) {
729 3 : *_olddn = talloc_move(mem_ctx, &olddn);
730 : }
731 6 : if (_newrdn) {
732 0 : *_newrdn = talloc_move(mem_ctx, &newrdn);
733 : }
734 6 : if (_deleteoldrdn) {
735 3 : *_deleteoldrdn = deleteoldrdn;
736 : }
737 6 : if (_newsuperior != NULL && _newrdn != NULL) {
738 0 : if (newsuperior_val) {
739 0 : *_newrdn = talloc_move(mem_ctx, &newrdn);
740 : } else {
741 0 : *_newrdn = NULL;
742 : }
743 : }
744 6 : if (_newdn) {
745 3 : *_newdn = talloc_move(mem_ctx, &newdn);
746 : }
747 :
748 6 : talloc_free(tmp_ctx);
749 6 : return LDB_SUCCESS;
750 0 : err_other:
751 0 : talloc_free(tmp_ctx);
752 0 : return LDB_ERR_OTHER;
753 0 : err_op:
754 0 : talloc_free(tmp_ctx);
755 0 : return LDB_ERR_OPERATIONS_ERROR;
756 0 : err_attr:
757 0 : talloc_free(tmp_ctx);
758 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
759 0 : err_dn:
760 0 : talloc_free(tmp_ctx);
761 0 : return LDB_ERR_INVALID_DN_SYNTAX;
762 : }
763 :
764 : /*
765 : read from a LDIF source, creating a ldb_message
766 : */
767 858173 : struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
768 : int (*fgetc_fn)(void *), void *private_data)
769 : {
770 : struct ldb_ldif *ldif;
771 : struct ldb_message *msg;
772 858173 : const char *attr=NULL;
773 858173 : char *chunk=NULL, *s;
774 : struct ldb_val value;
775 858173 : unsigned flags = 0;
776 858173 : value.data = NULL;
777 :
778 858173 : ldif = talloc(ldb, struct ldb_ldif);
779 858173 : if (!ldif) return NULL;
780 :
781 858173 : ldif->msg = ldb_msg_new(ldif);
782 858173 : if (ldif->msg == NULL) {
783 0 : talloc_free(ldif);
784 0 : return NULL;
785 : }
786 :
787 858173 : ldif->changetype = LDB_CHANGETYPE_NONE;
788 858173 : msg = ldif->msg;
789 :
790 858173 : chunk = next_chunk(ldb, ldif, fgetc_fn, private_data);
791 858173 : if (!chunk) {
792 1460 : goto failed;
793 : }
794 :
795 856713 : s = chunk;
796 :
797 856713 : if (next_attr(ldif, &s, &attr, &value) != 0) {
798 425 : goto failed;
799 : }
800 :
801 : /* first line must be a dn */
802 856288 : if (ldb_attr_cmp(attr, "dn") != 0) {
803 0 : ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'",
804 : attr);
805 0 : goto failed;
806 : }
807 :
808 856288 : msg->dn = ldb_dn_from_ldb_val(msg, ldb, &value);
809 :
810 856288 : if ( ! ldb_dn_validate(msg->dn)) {
811 0 : ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'",
812 0 : (char *)value.data);
813 0 : goto failed;
814 : }
815 :
816 16208669 : while (next_attr(ldif, &s, &attr, &value) == 0) {
817 : const struct ldb_schema_attribute *a;
818 : struct ldb_message_element *el;
819 14633265 : int ret, empty = 0;
820 :
821 14633265 : if (ldb_attr_cmp(attr, "changetype") == 0) {
822 : int i;
823 100910 : for (i=0;ldb_changetypes[i].name;i++) {
824 100910 : if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) {
825 34315 : ldif->changetype = ldb_changetypes[i].changetype;
826 34315 : break;
827 : }
828 : }
829 34315 : if (!ldb_changetypes[i].name) {
830 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
831 0 : "Error: Bad ldif changetype '%s'",(char *)value.data);
832 : }
833 34315 : flags = 0;
834 34315 : continue;
835 : }
836 :
837 14598950 : if (ldb_attr_cmp(attr, "add") == 0) {
838 20032 : flags = LDB_FLAG_MOD_ADD;
839 20032 : empty = 1;
840 : }
841 14598950 : if (ldb_attr_cmp(attr, "delete") == 0) {
842 12288 : flags = LDB_FLAG_MOD_DELETE;
843 12288 : empty = 1;
844 : }
845 14598950 : if (ldb_attr_cmp(attr, "replace") == 0) {
846 20716 : flags = LDB_FLAG_MOD_REPLACE;
847 20716 : empty = 1;
848 : }
849 14598950 : if (ldb_attr_cmp(attr, "-") == 0) {
850 9689 : flags = 0;
851 9689 : continue;
852 : }
853 :
854 14589261 : if (empty) {
855 53036 : if (ldb_msg_add_empty(msg, (char *)value.data, flags, NULL) != 0) {
856 0 : goto failed;
857 : }
858 53036 : continue;
859 : }
860 :
861 14536225 : el = &msg->elements[msg->num_elements-1];
862 :
863 14536225 : a = ldb_schema_attribute_by_name(ldb, attr);
864 :
865 16676426 : if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 &&
866 2578017 : flags == el->flags) {
867 : /* its a continuation */
868 2578017 : el->values =
869 2578017 : talloc_realloc(msg->elements, el->values,
870 : struct ldb_val, el->num_values+1);
871 2578017 : if (!el->values) {
872 0 : goto failed;
873 : }
874 2578017 : ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[el->num_values]);
875 2578017 : if (ret != 0) {
876 0 : goto failed;
877 : }
878 2578017 : if (value.length == 0) {
879 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
880 : "Error: Attribute value cannot be empty for attribute '%s'", el->name);
881 0 : goto failed;
882 : }
883 2578017 : if (value.data != el->values[el->num_values].data) {
884 2578017 : talloc_steal(el->values, el->values[el->num_values].data);
885 : }
886 2578017 : el->num_values++;
887 : } else {
888 : /* its a new attribute */
889 11958208 : msg->elements = talloc_realloc(msg, msg->elements,
890 : struct ldb_message_element,
891 : msg->num_elements+1);
892 11958208 : if (!msg->elements) {
893 0 : goto failed;
894 : }
895 11958208 : el = &msg->elements[msg->num_elements];
896 11958208 : el->flags = flags;
897 11958208 : el->name = talloc_strdup(msg->elements, attr);
898 11958208 : el->values = talloc(msg->elements, struct ldb_val);
899 22140871 : if (!el->values || !el->name) {
900 0 : goto failed;
901 : }
902 11958208 : el->num_values = 1;
903 11958208 : ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[0]);
904 11958208 : if (ret != 0) {
905 0 : goto failed;
906 : }
907 11958208 : if (value.data != el->values[0].data) {
908 11958208 : talloc_steal(el->values, el->values[0].data);
909 : }
910 11958208 : msg->num_elements++;
911 : }
912 : }
913 :
914 856288 : if (ldif->changetype == LDB_CHANGETYPE_MODRDN) {
915 : int ret;
916 :
917 3 : ret = ldb_ldif_parse_modrdn(ldb, ldif, ldif,
918 : NULL, NULL, NULL, NULL, NULL);
919 3 : if (ret != LDB_SUCCESS) {
920 0 : goto failed;
921 : }
922 : }
923 :
924 856288 : return ldif;
925 :
926 1885 : failed:
927 1885 : talloc_free(ldif);
928 1885 : return NULL;
929 : }
930 :
931 :
932 :
933 : /*
934 : a wrapper around ldif_read() for reading from FILE*
935 : */
936 :
937 147992 : static int fgetc_file(void *private_data)
938 : {
939 : int c;
940 147992 : struct ldif_read_file_state *state =
941 : (struct ldif_read_file_state *)private_data;
942 147992 : c = fgetc(state->f);
943 147992 : if (c == '\n') {
944 3789 : state->line_no++;
945 : }
946 147992 : return c;
947 : }
948 :
949 1042 : struct ldb_ldif *ldb_ldif_read_file_state(struct ldb_context *ldb,
950 : struct ldif_read_file_state *state)
951 : {
952 1042 : return ldb_ldif_read(ldb, fgetc_file, state);
953 : }
954 :
955 0 : struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f)
956 : {
957 : struct ldif_read_file_state state;
958 0 : state.f = f;
959 0 : return ldb_ldif_read_file_state(ldb, &state);
960 : }
961 :
962 : /*
963 : a wrapper around ldif_read() for reading from const char*
964 : */
965 : struct ldif_read_string_state {
966 : const char *s;
967 : };
968 :
969 566925598 : static int fgetc_string(void *private_data)
970 : {
971 566925598 : struct ldif_read_string_state *state =
972 : (struct ldif_read_string_state *)private_data;
973 566925598 : if (state->s[0] != 0) {
974 566893437 : return *state->s++;
975 : }
976 32161 : return EOF;
977 : }
978 :
979 857131 : struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s)
980 : {
981 : struct ldif_read_string_state state;
982 : struct ldb_ldif *ldif;
983 857131 : state.s = *s;
984 857131 : ldif = ldb_ldif_read(ldb, fgetc_string, &state);
985 857131 : *s = state.s;
986 857131 : return ldif;
987 : }
988 :
989 :
990 : /*
991 : wrapper around ldif_write() for a file
992 : */
993 : struct ldif_write_file_state {
994 : FILE *f;
995 : };
996 :
997 : static int fprintf_file(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
998 :
999 3092746 : static int fprintf_file(void *private_data, const char *fmt, ...)
1000 : {
1001 3092746 : struct ldif_write_file_state *state =
1002 : (struct ldif_write_file_state *)private_data;
1003 : int ret;
1004 : va_list ap;
1005 :
1006 3092746 : va_start(ap, fmt);
1007 3092746 : ret = vfprintf(state->f, fmt, ap);
1008 3092746 : va_end(ap);
1009 3092746 : return ret;
1010 : }
1011 :
1012 7561 : int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif)
1013 : {
1014 : struct ldif_write_file_state state;
1015 7561 : state.f = f;
1016 7561 : return ldb_ldif_write(ldb, fprintf_file, &state, ldif);
1017 : }
1018 :
1019 : /*
1020 : wrapper around ldif_write() for a string
1021 : */
1022 : struct ldif_write_string_state {
1023 : char *string;
1024 : };
1025 :
1026 : static int ldif_printf_string(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1027 :
1028 2814720 : static int ldif_printf_string(void *private_data, const char *fmt, ...)
1029 : {
1030 2814720 : struct ldif_write_string_state *state =
1031 : (struct ldif_write_string_state *)private_data;
1032 : va_list ap;
1033 2814720 : size_t oldlen = talloc_get_size(state->string);
1034 2814720 : va_start(ap, fmt);
1035 :
1036 2814720 : state->string = talloc_vasprintf_append(state->string, fmt, ap);
1037 2814720 : va_end(ap);
1038 2814720 : if (!state->string) {
1039 0 : return -1;
1040 : }
1041 :
1042 2814720 : return talloc_get_size(state->string) - oldlen;
1043 : }
1044 :
1045 24 : char *ldb_ldif_write_redacted_trace_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1046 : const struct ldb_ldif *ldif)
1047 : {
1048 : struct ldif_write_string_state state;
1049 24 : state.string = talloc_strdup(mem_ctx, "");
1050 24 : if (!state.string) {
1051 0 : return NULL;
1052 : }
1053 24 : if (ldb_ldif_write_trace(ldb, ldif_printf_string, &state, ldif, true) == -1) {
1054 0 : return NULL;
1055 : }
1056 24 : return state.string;
1057 : }
1058 :
1059 6151 : char *ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1060 : const struct ldb_ldif *ldif)
1061 : {
1062 : struct ldif_write_string_state state;
1063 6151 : state.string = talloc_strdup(mem_ctx, "");
1064 6151 : if (!state.string) {
1065 0 : return NULL;
1066 : }
1067 6151 : if (ldb_ldif_write(ldb, ldif_printf_string, &state, ldif) == -1) {
1068 0 : return NULL;
1069 : }
1070 6151 : return state.string;
1071 : }
1072 :
1073 : /*
1074 : convenient function to turn a ldb_message into a string. Useful for
1075 : debugging
1076 : */
1077 24 : char *ldb_ldif_message_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1078 : enum ldb_changetype changetype,
1079 : const struct ldb_message *msg)
1080 : {
1081 : struct ldb_ldif ldif;
1082 :
1083 24 : ldif.changetype = changetype;
1084 24 : ldif.msg = discard_const_p(struct ldb_message, msg);
1085 :
1086 24 : return ldb_ldif_write_string(ldb, mem_ctx, &ldif);
1087 : }
1088 :
1089 : /*
1090 : * convenient function to turn a ldb_message into a string. Useful for
1091 : * debugging but also safer if some of the LDIF could be sensitive.
1092 : *
1093 : * The secret attributes are specified in a 'const char * const *' within
1094 : * the LDB_SECRET_ATTRIBUTE_LIST opaque set on the ldb
1095 : *
1096 : */
1097 24 : char *ldb_ldif_message_redacted_string(struct ldb_context *ldb,
1098 : TALLOC_CTX *mem_ctx,
1099 : enum ldb_changetype changetype,
1100 : const struct ldb_message *msg)
1101 : {
1102 : struct ldb_ldif ldif;
1103 :
1104 24 : ldif.changetype = changetype;
1105 24 : ldif.msg = discard_const_p(struct ldb_message, msg);
1106 :
1107 24 : return ldb_ldif_write_redacted_trace_string(ldb, mem_ctx, &ldif);
1108 : }
|