r13324: From now on check attribute names obey rfc2251
[samba.git] / source / lib / ldb / common / ldb_msg.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: ldb message component utility functions
29  *
30  *  Description: functions for manipulating ldb_message structures
31  *
32  *  Author: Andrew Tridgell
33  */
34
35 #include "includes.h"
36 #include "ldb/include/includes.h"
37
38 /*
39   create a new ldb_message in a given memory context (NULL for top level)
40 */
41 struct ldb_message *ldb_msg_new(void *mem_ctx)
42 {
43         return talloc_zero(mem_ctx, struct ldb_message);
44 }
45
46 /*
47   find an element in a message by attribute name
48 */
49 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, 
50                                                  const char *attr_name)
51 {
52         unsigned int i;
53         for (i=0;i<msg->num_elements;i++) {
54                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
55                         return &msg->elements[i];
56                 }
57         }
58         return NULL;
59 }
60
61 /*
62   see if two ldb_val structures contain exactly the same data
63   return 1 for a match, 0 for a mis-match
64 */
65 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
66 {
67         if (v1->length != v2->length) return 0;
68
69         if (v1->length == 0) return 1;
70
71         if (memcmp(v1->data, v2->data, v1->length) == 0) {
72                 return 1;
73         }
74
75         return 0;
76 }
77
78 /*
79   find a value in an element
80   assumes case sensitive comparison
81 */
82 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, 
83                                  struct ldb_val *val)
84 {
85         unsigned int i;
86         for (i=0;i<el->num_values;i++) {
87                 if (ldb_val_equal_exact(val, &el->values[i])) {
88                         return &el->values[i];
89                 }
90         }
91         return NULL;
92 }
93
94 /*
95   duplicate a ldb_val structure
96 */
97 struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
98 {
99         struct ldb_val v2;
100         v2.length = v->length;
101         if (v->data == NULL) {
102                 v2.data = NULL;
103                 return v2;
104         }
105
106         /* the +1 is to cope with buggy C library routines like strndup
107            that look one byte beyond */
108         v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
109         if (!v2.data) {
110                 v2.length = 0;
111                 return v2;
112         }
113
114         memcpy(v2.data, v->data, v->length);
115         ((char *)v2.data)[v->length] = 0;
116         return v2;
117 }
118
119 /*
120   add an empty element to a message
121 */
122 int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags)
123 {
124         struct ldb_message_element *els;
125
126         if (! ldb_valid_attr_name(attr_name)) {
127                 return -1;
128         }
129
130         els = talloc_realloc(msg, msg->elements, 
131                              struct ldb_message_element, msg->num_elements+1);
132         if (!els) {
133                 errno = ENOMEM;
134                 return -1;
135         }
136
137         els[msg->num_elements].values = NULL;
138         els[msg->num_elements].num_values = 0;
139         els[msg->num_elements].flags = flags;
140         els[msg->num_elements].name = talloc_strdup(els, attr_name);
141         if (!els[msg->num_elements].name) {
142                 errno = ENOMEM;
143                 return -1;
144         }
145
146         msg->elements = els;
147         msg->num_elements++;
148
149         return 0;
150 }
151
152 /*
153   add an empty element to a message
154 */
155 int ldb_msg_add(struct ldb_message *msg, 
156                 const struct ldb_message_element *el, 
157                 int flags)
158 {
159         if (ldb_msg_add_empty(msg, el->name, flags) != 0) {
160                 return -1;
161         }
162
163         msg->elements[msg->num_elements-1] = *el;
164         msg->elements[msg->num_elements-1].flags = flags;
165
166         return 0;
167 }
168
169 /*
170   add a value to a message
171 */
172 int ldb_msg_add_value(struct ldb_message *msg, 
173                       const char *attr_name,
174                       const struct ldb_val *val)
175 {
176         struct ldb_message_element *el;
177         struct ldb_val *vals;
178
179         el = ldb_msg_find_element(msg, attr_name);
180         if (!el) {
181                 ldb_msg_add_empty(msg, attr_name, 0);
182                 el = ldb_msg_find_element(msg, attr_name);
183         }
184         if (!el) {
185                 return -1;
186         }
187
188         vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
189         if (!vals) {
190                 errno = ENOMEM;
191                 return -1;
192         }
193         el->values = vals;
194         el->values[el->num_values] = *val;
195         el->num_values++;
196
197         return 0;
198 }
199
200
201 /*
202   add a string element to a message
203 */
204 int ldb_msg_add_string(struct ldb_message *msg, 
205                        const char *attr_name, const char *str)
206 {
207         struct ldb_val val;
208
209         val.data = discard_const_p(uint8_t, str);
210         val.length = strlen(str);
211
212         return ldb_msg_add_value(msg, attr_name, &val);
213 }
214
215 /*
216   add a printf formatted element to a message
217 */
218 int ldb_msg_add_fmt(struct ldb_message *msg, 
219                     const char *attr_name, const char *fmt, ...)
220 {
221         struct ldb_val val;
222         va_list ap;
223         char *str;
224
225         va_start(ap, fmt);
226         str = talloc_vasprintf(msg, fmt, ap);
227         va_end(ap);
228
229         if (str == NULL) return -1;
230
231         val.data   = (uint8_t *)str;
232         val.length = strlen(str);
233
234         return ldb_msg_add_value(msg, attr_name, &val);
235 }
236
237 /*
238   compare two ldb_message_element structures
239   assumes case senistive comparison
240 */
241 int ldb_msg_element_compare(struct ldb_message_element *el1, 
242                             struct ldb_message_element *el2)
243 {
244         unsigned int i;
245
246         if (el1->num_values != el2->num_values) {
247                 return el1->num_values - el2->num_values;
248         }
249
250         for (i=0;i<el1->num_values;i++) {
251                 if (!ldb_msg_find_val(el2, &el1->values[i])) {
252                         return -1;
253                 }
254         }
255
256         return 0;
257 }
258
259 /*
260   compare two ldb_message_element structures
261   comparing by element name
262 */
263 int ldb_msg_element_compare_name(struct ldb_message_element *el1, 
264                                  struct ldb_message_element *el2)
265 {
266         return ldb_attr_cmp(el1->name, el2->name);
267 }
268
269 /*
270   convenience functions to return common types from a message
271   these return the first value if the attribute is multi-valued
272 */
273 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name)
274 {
275         struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
276         if (!el || el->num_values == 0) {
277                 return NULL;
278         }
279         return &el->values[0];
280 }
281
282 int ldb_msg_find_int(const struct ldb_message *msg, 
283                      const char *attr_name,
284                      int default_value)
285 {
286         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
287         if (!v || !v->data) {
288                 return default_value;
289         }
290         return strtol((const char *)v->data, NULL, 0);
291 }
292
293 unsigned int ldb_msg_find_uint(const struct ldb_message *msg, 
294                                const char *attr_name,
295                                unsigned int default_value)
296 {
297         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
298         if (!v || !v->data) {
299                 return default_value;
300         }
301         return strtoul((const char *)v->data, NULL, 0);
302 }
303
304 int64_t ldb_msg_find_int64(const struct ldb_message *msg, 
305                            const char *attr_name,
306                            int64_t default_value)
307 {
308         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
309         if (!v || !v->data) {
310                 return default_value;
311         }
312         return strtoll((const char *)v->data, NULL, 0);
313 }
314
315 uint64_t ldb_msg_find_uint64(const struct ldb_message *msg, 
316                              const char *attr_name,
317                              uint64_t default_value)
318 {
319         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
320         if (!v || !v->data) {
321                 return default_value;
322         }
323         return strtoull((const char *)v->data, NULL, 0);
324 }
325
326 double ldb_msg_find_double(const struct ldb_message *msg, 
327                            const char *attr_name,
328                            double default_value)
329 {
330         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
331         if (!v || !v->data) {
332                 return default_value;
333         }
334         return strtod((const char *)v->data, NULL);
335 }
336
337 const char *ldb_msg_find_string(const struct ldb_message *msg, 
338                                 const char *attr_name,
339                                 const char *default_value)
340 {
341         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
342         if (!v || !v->data) {
343                 return default_value;
344         }
345         return (const char *)v->data;
346 }
347
348 /*
349   sort the elements of a message by name
350 */
351 void ldb_msg_sort_elements(struct ldb_message *msg)
352 {
353         qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element), 
354               (comparison_fn_t)ldb_msg_element_compare_name);
355 }
356
357 /*
358   shallow copy a message - copying only the elements array so that the caller
359   can safely add new elements without changing the message
360 */
361 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, 
362                                          const struct ldb_message *msg)
363 {
364         struct ldb_message *msg2;
365         int i;
366
367         msg2 = talloc(mem_ctx, struct ldb_message);
368         if (msg2 == NULL) return NULL;
369
370         *msg2 = *msg;
371         msg2->private_data = NULL;
372
373         msg2->elements = talloc_array(msg2, struct ldb_message_element, 
374                                       msg2->num_elements);
375         if (msg2->elements == NULL) goto failed;
376
377         for (i=0;i<msg2->num_elements;i++) {
378                 msg2->elements[i] = msg->elements[i];
379         }
380
381         return msg2;
382
383 failed:
384         talloc_free(msg2);
385         return NULL;
386 }
387
388
389 /*
390   copy a message, allocating new memory for all parts
391 */
392 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, 
393                                  const struct ldb_message *msg)
394 {
395         struct ldb_message *msg2;
396         int i, j;
397
398         msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
399         if (msg2 == NULL) return NULL;
400
401         msg2->dn = ldb_dn_copy(msg2, msg2->dn);
402         if (msg2->dn == NULL) goto failed;
403
404         for (i=0;i<msg2->num_elements;i++) {
405                 struct ldb_message_element *el = &msg2->elements[i];
406                 struct ldb_val *values = el->values;
407                 el->name = talloc_strdup(msg2->elements, el->name);
408                 if (el->name == NULL) goto failed;
409                 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
410                 for (j=0;j<el->num_values;j++) {
411                         el->values[j] = ldb_val_dup(el->values, &values[j]);
412                         if (el->values[j].data == NULL && values[j].length != 0) {
413                                 goto failed;
414                         }
415                 }
416         }
417
418         return msg2;
419
420 failed:
421         talloc_free(msg2);
422         return NULL;
423 }
424
425
426 /*
427   canonicalise a message, merging elements of the same name
428 */
429 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, 
430                                          const struct ldb_message *msg)
431 {
432         int i;
433         struct ldb_message *msg2;
434
435         msg2 = ldb_msg_copy(ldb, msg);
436         if (msg2 == NULL) return NULL;
437
438         ldb_msg_sort_elements(msg2);
439
440         for (i=1;i<msg2->num_elements;i++) {
441                 struct ldb_message_element *el1 = &msg2->elements[i-1];
442                 struct ldb_message_element *el2 = &msg2->elements[i];
443                 if (ldb_msg_element_compare_name(el1, el2) == 0) {
444                         el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val, 
445                                                        el1->num_values + el2->num_values);
446                         if (el1->values == NULL) {
447                                 return NULL;
448                         }
449                         memcpy(el1->values + el1->num_values,
450                                el2->values,
451                                sizeof(struct ldb_val) * el2->num_values);
452                         el1->num_values += el2->num_values;
453                         talloc_free(discard_const_p(char, el2->name));
454                         if (i+1<msg2->num_elements) {
455                                 memmove(el2, el2+1, sizeof(struct ldb_message_element) * 
456                                         (msg2->num_elements - (i+1)));
457                         }
458                         msg2->num_elements--;
459                         i--;
460                 }
461         }
462
463         return msg2;
464 }
465
466
467 /*
468   return a ldb_message representing the differences between msg1 and msg2. If you
469   then use this in a ldb_modify() call it can be used to save edits to a message
470 */
471 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, 
472                                  struct ldb_message *msg1,
473                                  struct ldb_message *msg2)
474 {
475         struct ldb_message *mod;
476         struct ldb_message_element *el;
477         unsigned int i;
478
479         mod = ldb_msg_new(ldb);
480
481         mod->dn = msg1->dn;
482         mod->num_elements = 0;
483         mod->elements = NULL;
484
485         msg2 = ldb_msg_canonicalize(ldb, msg2);
486         if (msg2 == NULL) {
487                 return NULL;
488         }
489         
490         /* look in msg2 to find elements that need to be added
491            or modified */
492         for (i=0;i<msg2->num_elements;i++) {
493                 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
494
495                 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
496                         continue;
497                 }
498
499                 if (ldb_msg_add(mod, 
500                                 &msg2->elements[i],
501                                 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
502                         return NULL;
503                 }
504         }
505
506         /* look in msg1 to find elements that need to be deleted */
507         for (i=0;i<msg1->num_elements;i++) {
508                 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
509                 if (!el) {
510                         if (ldb_msg_add_empty(mod, 
511                                               msg1->elements[i].name,
512                                               LDB_FLAG_MOD_DELETE) != 0) {
513                                 return NULL;
514                         }
515                 }
516         }
517
518         return mod;
519 }
520
521 int ldb_msg_sanity_check(const struct ldb_message *msg)
522 {
523         int i, j;
524
525         /* basic check on DN */
526         if (msg->dn == NULL) {
527                 /* TODO: return also an error string */
528                 return LDB_ERR_INVALID_DN_SYNTAX;
529         }
530         if (msg->dn->comp_num == 0) {
531                 /* root dse has empty dn */
532                 /* TODO: return also an error string */
533                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
534         }
535
536         /* basic syntax checks */
537         for (i = 0; i < msg->num_elements; i++) {
538                 for (j = 0; j < msg->elements[i].num_values; j++) {
539                         if (msg->elements[i].values[j].length == 0) {
540                                 /* an attribute cannot be empty */
541                                 /* TODO: return also an error string */
542                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
543                         }
544                 }
545         }
546
547         return LDB_SUCCESS;
548 }
549
550
551
552
553 /*
554   copy an attribute list. This only copies the array, not the elements
555   (ie. the elements are left as the same pointers)
556 */
557 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
558 {
559         const char **ret;
560         int i;
561         for (i=0;attrs[i];i++) /* noop */ ;
562         ret = talloc_array(mem_ctx, const char *, i+1);
563         if (ret == NULL) {
564                 return NULL;
565         }
566         for (i=0;attrs[i];i++) {
567                 ret[i] = attrs[i];
568         }
569         ret[i] = attrs[i];
570         return ret;
571 }
572
573
574 /*
575   return 1 if an attribute is in a list of attributes, or 0 otherwise
576 */
577 int ldb_attr_in_list(const char * const *attrs, const char *attr)
578 {
579         int i;
580         for (i=0;attrs[i];i++) {
581                 if (ldb_attr_cmp(attrs[i], attr) == 0) {
582                         return 1;
583                 }
584         }
585         return 0;
586 }
587
588
589 /*
590   rename the specified attribute in a search result
591 */
592 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
593 {
594         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
595         if (el == NULL) {
596                 return 0;
597         }
598         el->name = talloc_strdup(msg->elements, replace);
599         if (el->name == NULL) {
600                 return -1;
601         }
602         return 0;
603 }
604
605
606 /*
607   copy the specified attribute in a search result to a new attribute
608 */
609 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
610 {
611         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
612         if (el == NULL) {
613                 return 0;
614         }
615         if (ldb_msg_add(msg, el, 0) != 0) {
616                 return -1;
617         }
618         return ldb_msg_rename_attr(msg, attr, replace);
619 }
620
621
622 /*
623   remove the specified attribute in a search result
624 */
625 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
626 {
627         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
628         if (el) {
629                 int n = (el - msg->elements);
630                 if (n != msg->num_elements-1) {
631                         memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
632                 }
633                 msg->num_elements--;
634         }
635 }
636
637 /*
638   return a LDAP formatted time string
639 */
640 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
641 {
642         struct tm *tm = gmtime(&t);
643
644         if (!tm) {
645                 return NULL;
646         }
647
648         /* formatted like: 20040408072012.0Z */
649         return talloc_asprintf(mem_ctx, 
650                                "%04u%02u%02u%02u%02u%02u.0Z",
651                                tm->tm_year+1900, tm->tm_mon+1,
652                                tm->tm_mday, tm->tm_hour, tm->tm_min,
653                                tm->tm_sec);
654 }
655
656
657 /*
658   convert a LDAP time string to a time_t. Return 0 if unable to convert
659 */
660 time_t ldb_string_to_time(const char *s)
661 {
662         struct tm tm;
663         
664         if (s == NULL) return 0;
665         
666         memset(&tm, 0, sizeof(tm));
667         if (sscanf(s, "%04u%02u%02u%02u%02u%02u", 
668                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
669                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
670                 return 0;
671         }
672         tm.tm_year -= 1900;
673         tm.tm_mon -= 1;
674         
675         return timegm(&tm);
676 }
677
678
679 /*
680   dump a set of results to a file. Useful from within gdb
681 */
682 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
683 {
684         int i;
685
686         for (i = 0; i < result->count; i++) {
687                 struct ldb_ldif ldif;
688                 fprintf(f, "# record %d\n", i+1);
689                 ldif.changetype = LDB_CHANGETYPE_NONE;
690                 ldif.msg = result->msgs[i];
691                 ldb_ldif_write_file(ldb, f, &ldif);
692         }
693 }
694