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