r23798: updated old Temple Place FSF addresses to new URL
[kai/samba-autobuild/.git] / source3 / lib / ldb / common / ldb_ldif.c
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 "includes.h"
39 #include "ldb/include/includes.h"
40 #include "system/locale.h"
41
42 /*
43   
44 */
45 static int ldb_read_data_file(void *mem_ctx, struct ldb_val *value)
46 {
47         struct stat statbuf;
48         char *buf;
49         int count, size, bytes;
50         int ret;
51         int f;
52         const char *fname = (const char *)value->data;
53
54         if (strncmp(fname, "file://", 7) != 0) {
55                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
56         }
57         fname += 7;
58
59         f = open(fname, O_RDONLY);
60         if (f == -1) {
61                 return -1;
62         }
63
64         if (fstat(f, &statbuf) != 0) {
65                 ret = -1;
66                 goto done;
67         }
68
69         if (statbuf.st_size == 0) {
70                 ret = -1;
71                 goto done;
72         }
73
74         value->data = (uint8_t *)talloc_size(mem_ctx, statbuf.st_size + 1);
75         if (value->data == NULL) {
76                 ret = -1;
77                 goto done;
78         }
79         value->data[statbuf.st_size] = 0;
80
81         count = 0;
82         size = statbuf.st_size;
83         buf = (char *)value->data;
84         while (count < statbuf.st_size) {
85                 bytes = read(f, buf, size);
86                 if (bytes == -1) {
87                         talloc_free(value->data);
88                         ret = -1;
89                         goto done;
90                 }
91                 count += bytes;
92                 buf += bytes;
93                 size -= bytes;
94         }
95
96         value->length = statbuf.st_size;
97         ret = statbuf.st_size;
98
99 done:
100         close(f);
101         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 int ldb_base64_decode(char *s)
109 {
110         const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
111         int bit_offset=0, byte_offset, idx, i, n;
112         uint8_t *d = (uint8_t *)s;
113         char *p=NULL;
114
115         n=i=0;
116
117         while (*s && (p=strchr(b64,*s))) {
118                 idx = (int)(p - b64);
119                 byte_offset = (i*6)/8;
120                 bit_offset = (i*6)%8;
121                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
122                 if (bit_offset < 3) {
123                         d[byte_offset] |= (idx << (2-bit_offset));
124                         n = byte_offset+1;
125                 } else {
126                         d[byte_offset] |= (idx >> (bit_offset-2));
127                         d[byte_offset+1] = 0;
128                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
129                         n = byte_offset+2;
130                 }
131                 s++; i++;
132         }
133         if (bit_offset >= 3) {
134                 n--;
135         }
136
137         if (*s && !p) {
138                 /* the only termination allowed */
139                 if (*s != '=') {
140                         return -1;
141                 }
142         }
143
144         /* null terminate */
145         d[n] = 0;
146         return n;
147 }
148
149
150 /*
151   encode as base64
152   caller frees
153 */
154 char *ldb_base64_encode(void *mem_ctx, const char *buf, int len)
155 {
156         const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
157         int bit_offset, byte_offset, idx, i;
158         const uint8_t *d = (const uint8_t *)buf;
159         int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
160         char *out;
161
162         out = talloc_array(mem_ctx, char, bytes+pad_bytes+1);
163         if (!out) return NULL;
164
165         for (i=0;i<bytes;i++) {
166                 byte_offset = (i*6)/8;
167                 bit_offset = (i*6)%8;
168                 if (bit_offset < 3) {
169                         idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
170                 } else {
171                         idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
172                         if (byte_offset+1 < len) {
173                                 idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
174                         }
175                 }
176                 out[i] = b64[idx];
177         }
178
179         for (;i<bytes+pad_bytes;i++)
180                 out[i] = '=';
181         out[i] = 0;
182
183         return out;
184 }
185
186 /*
187   see if a buffer should be base64 encoded
188 */
189 int ldb_should_b64_encode(const struct ldb_val *val)
190 {
191         unsigned int i;
192         uint8_t *p = val->data;
193
194         if (val->length == 0) {
195                 return 0;
196         }
197
198         if (p[0] == ' ' || p[0] == ':') {
199                 return 1;
200         }
201
202         for (i=0; i<val->length; i++) {
203                 if (!isprint(p[i]) || p[i] == '\n') {
204                         return 1;
205                 }
206         }
207         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 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         unsigned int i;
220         int total=0, ret;
221
222         for (i=0;i<length;i++) {
223                 ret = fprintf_fn(private_data, "%c", buf[i]);
224                 CHECK_RET;
225                 if (i != (length-1) && (i + start_pos) % 77 == 0) {
226                         ret = fprintf_fn(private_data, "\n ");
227                         CHECK_RET;
228                 }
229         }
230
231         return total;
232 }
233
234 #undef CHECK_RET
235
236 /*
237   encode as base64 to a file
238 */
239 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         char *b = ldb_base64_encode(ldb, buf, len);
245         int ret;
246
247         if (!b) {
248                 return -1;
249         }
250
251         ret = fold_string(fprintf_fn, private_data, b, strlen(b), start_pos);
252
253         talloc_free(b);
254         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         {NULL, 0}
266 };
267
268 /* this macro is used to handle the return checking on fprintf_fn() */
269 #define CHECK_RET do { if (ret < 0) { talloc_free(mem_ctx); return ret; } total += ret; } while (0)
270
271 /*
272   write to ldif, using a caller supplied write method
273 */
274 int ldb_ldif_write(struct ldb_context *ldb,
275                    int (*fprintf_fn)(void *, const char *, ...), 
276                    void *private_data,
277                    const struct ldb_ldif *ldif)
278 {
279         TALLOC_CTX *mem_ctx;
280         unsigned int i, j;
281         int total=0, ret;
282         const struct ldb_message *msg;
283
284         mem_ctx = talloc_named_const(NULL, 0, "ldb_ldif_write");
285
286         msg = ldif->msg;
287
288         ret = fprintf_fn(private_data, "dn: %s\n", ldb_dn_linearize(msg->dn, msg->dn));
289         CHECK_RET;
290
291         if (ldif->changetype != LDB_CHANGETYPE_NONE) {
292                 for (i=0;ldb_changetypes[i].name;i++) {
293                         if (ldb_changetypes[i].changetype == ldif->changetype) {
294                                 break;
295                         }
296                 }
297                 if (!ldb_changetypes[i].name) {
298                         ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Invalid ldif changetype %d\n",
299                                   ldif->changetype);
300                         talloc_free(mem_ctx);
301                         return -1;
302                 }
303                 ret = fprintf_fn(private_data, "changetype: %s\n", ldb_changetypes[i].name);
304                 CHECK_RET;
305         }
306
307         for (i=0;i<msg->num_elements;i++) {
308                 const struct ldb_attrib_handler *h;
309
310                 h = ldb_attrib_handler(ldb, msg->elements[i].name);
311
312                 if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
313                         switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
314                         case LDB_FLAG_MOD_ADD:
315                                 fprintf_fn(private_data, "add: %s\n", 
316                                            msg->elements[i].name);
317                                 break;
318                         case LDB_FLAG_MOD_DELETE:
319                                 fprintf_fn(private_data, "delete: %s\n", 
320                                            msg->elements[i].name);
321                                 break;
322                         case LDB_FLAG_MOD_REPLACE:
323                                 fprintf_fn(private_data, "replace: %s\n", 
324                                            msg->elements[i].name);
325                                 break;
326                         }
327                 }
328
329                 for (j=0;j<msg->elements[i].num_values;j++) {
330                         struct ldb_val v;
331                         ret = h->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v);
332                         CHECK_RET;
333                         if (ldb_should_b64_encode(&v)) {
334                                 ret = fprintf_fn(private_data, "%s:: ", 
335                                                  msg->elements[i].name);
336                                 CHECK_RET;
337                                 ret = base64_encode_f(ldb, fprintf_fn, private_data, 
338                                                       (char *)v.data, v.length,
339                                                       strlen(msg->elements[i].name)+3);
340                                 CHECK_RET;
341                                 ret = fprintf_fn(private_data, "\n");
342                                 CHECK_RET;
343                         } else {
344                                 ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name);
345                                 CHECK_RET;
346                                 ret = fold_string(fprintf_fn, private_data,
347                                                   (char *)v.data, v.length,
348                                                   strlen(msg->elements[i].name)+2);
349                                 CHECK_RET;
350                                 ret = fprintf_fn(private_data, "\n");
351                                 CHECK_RET;
352                         }
353                         if (v.data != msg->elements[i].values[j].data) {
354                                 talloc_free(v.data);
355                         }
356                 }
357                 if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
358                         fprintf_fn(private_data, "-\n");
359                 }
360         }
361         ret = fprintf_fn(private_data,"\n");
362         CHECK_RET;
363
364         return total;
365 }
366
367 #undef CHECK_RET
368
369
370 /*
371   pull a ldif chunk, which is defined as a piece of data ending in \n\n or EOF
372   this routine removes any RFC2849 continuations and comments
373
374   caller frees
375 */
376 static char *next_chunk(struct ldb_context *ldb, 
377                         int (*fgetc_fn)(void *), void *private_data)
378 {
379         size_t alloc_size=0, chunk_size = 0;
380         char *chunk = NULL;
381         int c;
382         int in_comment = 0;
383
384         while ((c = fgetc_fn(private_data)) != EOF) {
385                 if (chunk_size+1 >= alloc_size) {
386                         char *c2;
387                         alloc_size += 1024;
388                         c2 = talloc_realloc(ldb, chunk, char, alloc_size);
389                         if (!c2) {
390                                 talloc_free(chunk);
391                                 errno = ENOMEM;
392                                 return NULL;
393                         }
394                         chunk = c2;
395                 }
396
397                 if (in_comment) {
398                         if (c == '\n') {
399                                 in_comment = 0;
400                         }
401                         continue;                       
402                 }
403                 
404                 /* handle continuation lines - see RFC2849 */
405                 if (c == ' ' && chunk_size > 1 && chunk[chunk_size-1] == '\n') {
406                         chunk_size--;
407                         continue;
408                 }
409                 
410                 /* chunks are terminated by a double line-feed */
411                 if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') {
412                         chunk[chunk_size-1] = 0;
413                         return chunk;
414                 }
415
416                 if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) {
417                         in_comment = 1;
418                         continue;
419                 }
420
421                 /* ignore leading blank lines */
422                 if (chunk_size == 0 && c == '\n') {
423                         continue;
424                 }
425
426                 chunk[chunk_size++] = c;
427         }
428
429         if (chunk) {
430                 chunk[chunk_size] = 0;
431         }
432
433         return chunk;
434 }
435
436
437 /* simple ldif attribute parser */
438 static int next_attr(void *mem_ctx, char **s, const char **attr, struct ldb_val *value)
439 {
440         char *p;
441         int base64_encoded = 0;
442         int binary_file = 0;
443
444         if (strncmp(*s, "-\n", 2) == 0) {
445                 value->length = 0;
446                 *attr = "-";
447                 *s += 2;
448                 return 0;
449         }
450
451         p = strchr(*s, ':');
452         if (!p) {
453                 return -1;
454         }
455
456         *p++ = 0;
457
458         if (*p == ':') {
459                 base64_encoded = 1;
460                 p++;
461         }
462
463         if (*p == '<') {
464                 binary_file = 1;
465                 p++;
466         }
467
468         *attr = *s;
469
470         while (*p == ' ' || *p == '\t') {
471                 p++;
472         }
473
474         value->data = (uint8_t *)p;
475
476         p = strchr(p, '\n');
477
478         if (!p) {
479                 value->length = strlen((char *)value->data);
480                 *s = ((char *)value->data) + value->length;
481         } else {
482                 value->length = p - (char *)value->data;
483                 *s = p+1;
484                 *p = 0;
485         }
486
487         if (base64_encoded) {
488                 int len = ldb_base64_decode((char *)value->data);
489                 if (len == -1) {
490                         /* it wasn't valid base64 data */
491                         return -1;
492                 }
493                 value->length = len;
494         }
495
496         if (binary_file) {
497                 int len = ldb_read_data_file(mem_ctx, value);
498                 if (len == -1) {
499                         /* an error occured hile trying to retrieve the file */
500                         return -1;
501                 }
502         }
503
504         return 0;
505 }
506
507
508 /*
509   free a message from a ldif_read
510 */
511 void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif)
512 {
513         talloc_free(ldif);
514 }
515
516 /*
517  read from a LDIF source, creating a ldb_message
518 */
519 struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
520                                int (*fgetc_fn)(void *), void *private_data)
521 {
522         struct ldb_ldif *ldif;
523         struct ldb_message *msg;
524         const char *attr=NULL;
525         char *chunk=NULL, *s;
526         struct ldb_val value;
527         unsigned flags = 0;
528
529         value.data = NULL;
530
531         ldif = talloc(ldb, struct ldb_ldif);
532         if (!ldif) return NULL;
533
534         ldif->msg = talloc(ldif, struct ldb_message);
535         if (ldif->msg == NULL) {
536                 talloc_free(ldif);
537                 return NULL;
538         }
539
540         ldif->changetype = LDB_CHANGETYPE_NONE;
541         msg = ldif->msg;
542
543         msg->dn = NULL;
544         msg->elements = NULL;
545         msg->num_elements = 0;
546         msg->private_data = NULL;
547
548         chunk = next_chunk(ldb, fgetc_fn, private_data);
549         if (!chunk) {
550                 goto failed;
551         }
552         talloc_steal(ldif, chunk);
553
554         msg->private_data = chunk;
555         s = chunk;
556
557         if (next_attr(ldif, &s, &attr, &value) != 0) {
558                 goto failed;
559         }
560         
561         /* first line must be a dn */
562         if (ldb_attr_cmp(attr, "dn") != 0) {
563                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'\n", 
564                           attr);
565                 goto failed;
566         }
567
568         msg->dn = ldb_dn_explode(msg, (char *)value.data);
569
570         if (msg->dn == NULL) {
571                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'\n", 
572                                   value.data);
573                 goto failed;
574         }
575
576         while (next_attr(ldif, &s, &attr, &value) == 0) {
577                 const struct ldb_attrib_handler *h;             
578                 struct ldb_message_element *el;
579                 int ret, empty = 0;
580
581                 if (ldb_attr_cmp(attr, "changetype") == 0) {
582                         int i;
583                         for (i=0;ldb_changetypes[i].name;i++) {
584                                 if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) {
585                                         ldif->changetype = ldb_changetypes[i].changetype;
586                                         break;
587                                 }
588                         }
589                         if (!ldb_changetypes[i].name) {
590                                 ldb_debug(ldb, LDB_DEBUG_ERROR, 
591                                           "Error: Bad ldif changetype '%s'\n",(char *)value.data);
592                         }
593                         flags = 0;
594                         continue;
595                 }
596
597                 if (ldb_attr_cmp(attr, "add") == 0) {
598                         flags = LDB_FLAG_MOD_ADD;
599                         empty = 1;
600                 }
601                 if (ldb_attr_cmp(attr, "delete") == 0) {
602                         flags = LDB_FLAG_MOD_DELETE;
603                         empty = 1;
604                 }
605                 if (ldb_attr_cmp(attr, "replace") == 0) {
606                         flags = LDB_FLAG_MOD_REPLACE;
607                         empty = 1;
608                 }
609                 if (ldb_attr_cmp(attr, "-") == 0) {
610                         flags = 0;
611                         continue;
612                 }
613
614                 if (empty) {
615                         if (ldb_msg_add_empty(msg, (char *)value.data, flags, NULL) != 0) {
616                                 goto failed;
617                         }
618                         continue;
619                 }
620                 
621                 el = &msg->elements[msg->num_elements-1];
622
623                 h = ldb_attrib_handler(ldb, attr);
624
625                 if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 &&
626                     flags == el->flags) {
627                         /* its a continuation */
628                         el->values = 
629                                 talloc_realloc(msg->elements, el->values, 
630                                                  struct ldb_val, el->num_values+1);
631                         if (!el->values) {
632                                 goto failed;
633                         }
634                         ret = h->ldif_read_fn(ldb, ldif, &value, &el->values[el->num_values]);
635                         if (ret != 0) {
636                                 goto failed;
637                         }
638                         if (value.length == 0) {
639                                 ldb_debug(ldb, LDB_DEBUG_ERROR,
640                                           "Error: Attribute value cannot be empty for attribute '%s'\n", el->name);
641                                 goto failed;
642                         }
643                         if (value.data != el->values[el->num_values].data) {
644                                 talloc_steal(el->values, el->values[el->num_values].data);
645                         }
646                         el->num_values++;
647                 } else {
648                         /* its a new attribute */
649                         msg->elements = talloc_realloc(ldif, msg->elements, 
650                                                          struct ldb_message_element, 
651                                                          msg->num_elements+1);
652                         if (!msg->elements) {
653                                 goto failed;
654                         }
655                         el = &msg->elements[msg->num_elements];
656                         el->flags = flags;
657                         el->name = talloc_strdup(msg->elements, attr);
658                         el->values = talloc(msg->elements, struct ldb_val);
659                         if (!el->values || !el->name) {
660                                 goto failed;
661                         }
662                         el->num_values = 1;
663                         ret = h->ldif_read_fn(ldb, ldif, &value, &el->values[0]);
664                         if (ret != 0) {
665                                 goto failed;
666                         }
667                         if (value.data != el->values[0].data) {
668                                 talloc_steal(el->values, el->values[0].data);
669                         }
670                         msg->num_elements++;
671                 }
672         }
673
674         return ldif;
675
676 failed:
677         talloc_free(ldif);
678         return NULL;
679 }
680
681
682
683 /*
684   a wrapper around ldif_read() for reading from FILE*
685 */
686 struct ldif_read_file_state {
687         FILE *f;
688 };
689
690 static int fgetc_file(void *private_data)
691 {
692         struct ldif_read_file_state *state =
693                 (struct ldif_read_file_state *)private_data;
694         return fgetc(state->f);
695 }
696
697 struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f)
698 {
699         struct ldif_read_file_state state;
700         state.f = f;
701         return ldb_ldif_read(ldb, fgetc_file, &state);
702 }
703
704
705 /*
706   a wrapper around ldif_read() for reading from const char*
707 */
708 struct ldif_read_string_state {
709         const char *s;
710 };
711
712 static int fgetc_string(void *private_data)
713 {
714         struct ldif_read_string_state *state =
715                 (struct ldif_read_string_state *)private_data;
716         if (state->s[0] != 0) {
717                 return *state->s++;
718         }
719         return EOF;
720 }
721
722 struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s)
723 {
724         struct ldif_read_string_state state;
725         struct ldb_ldif *ldif;
726         state.s = *s;
727         ldif = ldb_ldif_read(ldb, fgetc_string, &state);
728         *s = state.s;
729         return ldif;
730 }
731
732
733 /*
734   wrapper around ldif_write() for a file
735 */
736 struct ldif_write_file_state {
737         FILE *f;
738 };
739
740 static int fprintf_file(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
741
742 static int fprintf_file(void *private_data, const char *fmt, ...)
743 {
744         struct ldif_write_file_state *state =
745                 (struct ldif_write_file_state *)private_data;
746         int ret;
747         va_list ap;
748
749         va_start(ap, fmt);
750         ret = vfprintf(state->f, fmt, ap);
751         va_end(ap);
752         return ret;
753 }
754
755 int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif)
756 {
757         struct ldif_write_file_state state;
758         state.f = f;
759         return ldb_ldif_write(ldb, fprintf_file, &state, ldif);
760 }