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