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