]> git.sur5r.net Git - openldap/blob - servers/slapd/entry.c
Renamed BVarray to BerVarray. Moved slapd:bvarray_{add,free} to
[openldap] / servers / slapd / entry.c
1 /* entry.c - routines for dealing with entries */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/errno.h>
14 #include <ac/socket.h>
15 #include <ac/string.h>
16
17 #include "slap.h"
18 #include "ldif.h"
19
20 static unsigned char    *ebuf;  /* buf returned by entry2str             */
21 static unsigned char    *ecur;  /* pointer to end of currently used ebuf */
22 static int              emaxsize;/* max size of ebuf                     */
23
24 /*
25  * Empty root entry
26  */
27 const Entry slap_entry_root = { NOID, { 0, "" }, { 0, "" }, NULL, NULL };
28
29 int entry_destroy(void)
30 {
31         if ( ebuf ) free( ebuf );
32         ebuf = NULL;
33         ecur = NULL;
34         emaxsize = 0;
35         return 0;
36 }
37
38
39 Entry *
40 str2entry( char *s )
41 {
42         int rc;
43         Entry           *e;
44         char            *type;
45         struct berval   vals[2];
46         AttributeDescription *ad;
47         const char *text;
48         char    *next;
49
50         /*
51          * LDIF is used as the string format.
52          * An entry looks like this:
53          *
54          *      dn: <dn>\n
55          *      [<attr>:[:] <value>\n]
56          *      [<tab><continuedvalue>\n]*
57          *      ...
58          *
59          * If a double colon is used after a type, it means the
60          * following value is encoded as a base 64 string.  This
61          * happens if the value contains a non-printing character
62          * or newline.
63          */
64
65 #ifdef NEW_LOGGING
66         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
67                 "str2entry: \"%s\"\n", s ? s : "NULL" ));
68 #else
69         Debug( LDAP_DEBUG_TRACE, "=> str2entry\n",
70                 s ? s : "NULL", 0, 0 );
71 #endif
72
73         /* initialize reader/writer lock */
74         e = (Entry *) ch_malloc( sizeof(Entry) );
75
76         if( e == NULL ) {
77 #ifdef NEW_LOGGING
78                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
79                         "str2entry: entry allocation failed.\n" ));
80 #else
81                 Debug( LDAP_DEBUG_ANY,
82                     "<= str2entry NULL (entry allocation failed)\n",
83                     0, 0, 0 );
84 #endif
85                 return( NULL );
86         }
87
88         /* initialize entry */
89         e->e_id = NOID;
90         e->e_name.bv_val = NULL;
91         e->e_name.bv_len = 0;
92         e->e_nname.bv_val = NULL;
93         e->e_nname.bv_len = 0;
94         e->e_attrs = NULL;
95         e->e_private = NULL;
96
97         /* dn + attributes */
98         vals[1].bv_val = NULL;
99
100         next = s;
101         while ( (s = ldif_getline( &next )) != NULL ) {
102                 if ( *s == '\n' || *s == '\0' ) {
103                         break;
104                 }
105
106                 if ( ldif_parse_line( s, &type, &vals[0].bv_val, &vals[0].bv_len ) != 0 ) {
107 #ifdef NEW_LOGGING
108                         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
109                                    "str2entry:  NULL (parse_line)\n" ));
110 #else
111                         Debug( LDAP_DEBUG_TRACE,
112                             "<= str2entry NULL (parse_line)\n", 0, 0, 0 );
113 #endif
114                         continue;
115                 }
116
117                 if ( strcasecmp( type, "dn" ) == 0 ) {
118                         struct berval *pdn = NULL;
119
120                         free( type );
121
122                         if ( e->e_dn != NULL ) {
123 #ifdef NEW_LOGGING
124                                 LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, "str2entry: "
125                                         "entry %ld has multiple DNs \"%s\" and \"%s\"\n",
126                                         (long) e->e_id, e->e_dn,
127                                         vals[0].bv_val != NULL ? vals[0].bv_val : "" ));
128 #else
129                                 Debug( LDAP_DEBUG_ANY, "str2entry: "
130                                         "entry %ld has multiple DNs \"%s\" and \"%s\"\n",
131                                     (long) e->e_id, e->e_dn,
132                                         vals[0].bv_val != NULL ? vals[0].bv_val : "" );
133 #endif
134                                 if( vals[0].bv_val != NULL ) free( vals[0].bv_val );
135                                 entry_free( e );
136                                 return NULL;
137                         }
138
139                         rc = dnPrettyNormal( NULL, &vals[0], &e->e_name, &e->e_nname );
140                         free( vals[0].bv_val );
141                         if( rc != LDAP_SUCCESS ) {
142 #ifdef NEW_LOGGING
143                                 LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1, "str2entry: "
144                                         "entry %ld has invalid DN \"%s\"\n",
145                                         (long) e->e_id,
146                                         pdn->bv_val ? pdn->bv_val : "" ));
147 #else
148                                 Debug( LDAP_DEBUG_ANY, "str2entry: "
149                                         "entry %ld has invalid DN \"%s\"\n",
150                                         (long) e->e_id,
151                                         pdn->bv_val ? pdn->bv_val : "", 0 );
152 #endif
153                                 entry_free( e );
154                                 return NULL;
155                         }
156                         continue;
157                 }
158
159                 ad = NULL;
160                 rc = slap_str2ad( type, &ad, &text );
161
162                 if( rc != LDAP_SUCCESS ) {
163 #ifdef NEW_LOGGING
164                         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
165                                 "str2entry:  str2ad(%s): %s\n", type, text ));
166 #else
167                         Debug( slapMode & SLAP_TOOL_MODE
168                                 ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE,
169                                 "<= str2entry: str2ad(%s): %s\n", type, text, 0 );
170 #endif
171                         if( slapMode & SLAP_TOOL_MODE ) {
172                                 entry_free( e );
173                                 free( vals[0].bv_val );
174                                 free( type );
175                                 return NULL;
176                         }
177
178                         rc = slap_str2undef_ad( type, &ad, &text );
179                         if( rc != LDAP_SUCCESS ) {
180 #ifdef NEW_LOGGING
181                                 LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
182                                         "str2entry:  str2undef_ad(%s): %s\n", type, text ));
183 #else
184                                 Debug( LDAP_DEBUG_ANY,
185                                         "<= str2entry: str2undef_ad(%s): %s\n",
186                                                 type, text, 0 );
187 #endif
188                                 entry_free( e );
189                                 free( vals[0].bv_val );
190                                 free( type );
191                                 return NULL;
192                         }
193                 }
194
195                 if( slapMode & SLAP_TOOL_MODE ) {
196                         struct berval pval;
197                         slap_syntax_validate_func *validate =
198                                 ad->ad_type->sat_syntax->ssyn_validate;
199                         slap_syntax_transform_func *pretty =
200                                 ad->ad_type->sat_syntax->ssyn_pretty;
201
202                         if( pretty ) {
203                                 rc = pretty( ad->ad_type->sat_syntax,
204                                         &vals[0], &pval );
205
206                         } else if( validate ) {
207                                 /*
208                                  * validate value per syntax
209                                  */
210                                 rc = validate( ad->ad_type->sat_syntax, &vals[0] );
211
212                         } else {
213 #ifdef NEW_LOGGING
214                                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
215                                         "str2entry: no validator for syntax %s\n", 
216                                         ad->ad_type->sat_syntax->ssyn_oid ));
217 #else
218                                 Debug( LDAP_DEBUG_ANY,
219                                         "str2entry: no validator for syntax %s\n",
220                                         ad->ad_type->sat_syntax->ssyn_oid, 0, 0 );
221 #endif
222                                 entry_free( e );
223                                 free( vals[0].bv_val );
224                                 free( type );
225                                 return NULL;
226                         }
227
228                         if( rc != 0 ) {
229 #ifdef NEW_LOGGING
230                                 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
231                                         "str2entry:  invalid value for syntax %s\n",
232                                         ad->ad_type->sat_syntax->ssyn_oid ));
233 #else
234                                 Debug( LDAP_DEBUG_ANY,
235                                         "str2entry: invalid value for syntax %s\n",
236                                         ad->ad_type->sat_syntax->ssyn_oid, 0, 0 );
237 #endif
238                                 entry_free( e );
239                                 free( vals[0].bv_val );
240                                 free( type );
241                                 return NULL;
242                         }
243
244                         if( pretty ) {
245                                 free( vals[0].bv_val );
246                                 vals[0] = pval;
247                         }
248                 }
249
250                 rc = attr_merge( e, ad, vals );
251                 if( rc != 0 ) {
252 #ifdef NEW_LOGGING
253                         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
254                                 "str2entry:  NULL (attr_merge)\n" ));
255 #else
256                         Debug( LDAP_DEBUG_ANY,
257                             "<= str2entry NULL (attr_merge)\n", 0, 0, 0 );
258 #endif
259                         entry_free( e );
260                         free( vals[0].bv_val );
261                         free( type );
262                         return( NULL );
263                 }
264
265                 free( type );
266                 free( vals[0].bv_val );
267         }
268
269         /* check to make sure there was a dn: line */
270         if ( e->e_dn == NULL ) {
271 #ifdef NEW_LOGGING
272                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
273                         "str2entry:  entry %ld has no dn.\n",
274                         (long) e->e_id ));
275 #else
276                 Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n",
277                     (long) e->e_id, 0, 0 );
278 #endif
279                 entry_free( e );
280                 return( NULL );
281         }
282
283 #ifdef NEW_LOGGING
284         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL2,
285                 "str2entry(%s) -> 0x%lx\n", e->e_dn, (unsigned long)e ));
286 #else
287         Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n",
288                 e->e_dn, (unsigned long) e, 0 );
289 #endif
290         return( e );
291 }
292
293
294 #define GRABSIZE        BUFSIZ
295
296 #define MAKE_SPACE( n ) { \
297                 while ( ecur + (n) > ebuf + emaxsize ) { \
298                         ptrdiff_t       offset; \
299                         offset = (int) (ecur - ebuf); \
300                         ebuf = (unsigned char *) ch_realloc( (char *) ebuf, \
301                             emaxsize + GRABSIZE ); \
302                         emaxsize += GRABSIZE; \
303                         ecur = ebuf + offset; \
304                 } \
305         }
306
307 char *
308 entry2str(
309     Entry       *e,
310     int         *len )
311 {
312         Attribute       *a;
313         struct berval   *bv;
314         int             i;
315         ber_len_t tmplen;
316
317         /*
318          * In string format, an entry looks like this:
319          *      dn: <dn>\n
320          *      [<attr>: <value>\n]*
321          */
322
323         ecur = ebuf;
324
325         /* put the dn */
326         if ( e->e_dn != NULL ) {
327                 /* put "dn: <dn>" */
328                 tmplen = e->e_name.bv_len;
329                 MAKE_SPACE( LDIF_SIZE_NEEDED( 2, tmplen ));
330                 ldif_sput( (char **) &ecur, LDIF_PUT_VALUE, "dn", e->e_dn, tmplen );
331         }
332
333         /* put the attributes */
334         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
335                 /* put "<type>:[:] <value>" line for each value */
336                 for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
337                         bv = &a->a_vals[i];
338                         tmplen = a->a_desc->ad_cname.bv_len;
339                         MAKE_SPACE( LDIF_SIZE_NEEDED( tmplen, bv->bv_len ));
340                         ldif_sput( (char **) &ecur, LDIF_PUT_VALUE,
341                                 a->a_desc->ad_cname.bv_val,
342                             bv->bv_val, bv->bv_len );
343                 }
344         }
345         MAKE_SPACE( 1 );
346         *ecur = '\0';
347         *len = ecur - ebuf;
348
349         return( (char *) ebuf );
350 }
351
352 void
353 entry_free( Entry *e )
354 {
355         /* free an entry structure */
356         assert( e != NULL );
357
358         /* e_private must be freed by the caller */
359         assert( e->e_private == NULL );
360         e->e_private = NULL;
361
362         /* free DNs */
363         if ( e->e_dn != NULL ) {
364                 free( e->e_dn );
365                 e->e_dn = NULL;
366         }
367         if ( e->e_ndn != NULL ) {
368                 free( e->e_ndn );
369                 e->e_ndn = NULL;
370         }
371
372         /* free attributes */
373         attrs_free( e->e_attrs );
374         e->e_attrs = NULL;
375
376         free( e );
377 }
378
379 /*
380  * These routines are used only by Backend.
381  *
382  * the Entry has three entry points (ways to find things):
383  *
384  *      by entry        e.g., if you already have an entry from the cache
385  *                      and want to delete it. (really by entry ptr)
386  *      by dn           e.g., when looking for the base object of a search
387  *      by id           e.g., for search candidates
388  *
389  * these correspond to three different avl trees that are maintained.
390  */
391
392 int
393 entry_cmp( Entry *e1, Entry *e2 )
394 {
395         return( e1 < e2 ? -1 : (e1 > e2 ? 1 : 0) );
396 }
397
398 int
399 entry_dn_cmp( Entry *e1, Entry *e2 )
400 {
401         /* compare their normalized UPPERCASED dn's */
402         int rc = e1->e_nname.bv_len - e2->e_nname.bv_len;
403         if (rc) return rc;
404         return( strcmp( e1->e_ndn, e2->e_ndn ) );
405 }
406
407 int
408 entry_id_cmp( Entry *e1, Entry *e2 )
409 {
410         return( e1->e_id < e2->e_id ? -1 : (e1->e_id > e2->e_id ? 1 : 0) );
411 }
412
413 #ifdef SLAPD_BDB
414
415 /* This is like a ber_len */
416 static ber_len_t
417 entry_lenlen(ber_len_t len)
418 {
419         if (len <= 0x7f)
420                 return 1;
421         if (len <= 0xff)
422                 return 2;
423         if (len <= 0xffff)
424                 return 3;
425         if (len <= 0xffffff)
426                 return 4;
427         return 5;
428 }
429
430 static void
431 entry_putlen(unsigned char **buf, ber_len_t len)
432 {
433         ber_len_t lenlen = entry_lenlen(len);
434
435         if (lenlen == 1) {
436                 **buf = (unsigned char) len;
437         } else {
438                 int i;
439                 **buf = 0x80 | ((unsigned char) lenlen - 1);
440                 for (i=lenlen-1; i>0; i--) {
441                         (*buf)[i] = (unsigned char) len;
442                         len >>= 8;
443                 }
444         }
445         *buf += lenlen;
446 }
447
448 static ber_len_t
449 entry_getlen(unsigned char **buf)
450 {
451         ber_len_t len;
452         int i;
453
454         len = *(*buf)++;
455         if (len <= 0x7f)
456                 return len;
457         i = len & 0x7f;
458         len = 0;
459         for (;i > 0; i--) {
460                 len <<= 8;
461                 len |= *(*buf)++;
462         }
463         return len;
464 }
465
466 /* Flatten an Entry into a buffer. The buffer is filled with just the
467  * strings/bervals of all the entry components. Each field is preceded
468  * by its length, encoded the way ber_put_len works. Every field is NUL
469  * terminated.  The entire buffer size is precomputed so that a single
470  * malloc can be performed. The entry size is also recorded,
471  * to aid in entry_decode.
472  */
473 int entry_encode(Entry *e, struct berval *bv)
474 {
475         ber_len_t siz = sizeof(Entry);
476         ber_len_t len, dnlen, ndnlen;
477         int i;
478         Attribute *a;
479         unsigned char *ptr;
480
481 #ifdef NEW_LOGGING
482         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
483                 "entry_encode: id: 0x%08lx  \"%s\"\n",
484                 (long) e->e_id, e->e_dn ));
485 #else
486         Debug( LDAP_DEBUG_TRACE, "=> entry_encode(0x%08lx): %s\n",
487                 (long) e->e_id, e->e_dn, 0 );
488 #endif
489         dnlen = e->e_name.bv_len;
490         ndnlen = e->e_nname.bv_len;
491         len = dnlen + ndnlen + 2;       /* two trailing NUL bytes */
492         len += entry_lenlen(dnlen);
493         len += entry_lenlen(ndnlen);
494         for (a=e->e_attrs; a; a=a->a_next) {
495                 /* For AttributeDesc, we only store the attr name */
496                 siz += sizeof(Attribute);
497                 len += a->a_desc->ad_cname.bv_len+1;
498                 len += entry_lenlen(a->a_desc->ad_cname.bv_len);
499                 for (i=0; a->a_vals[i].bv_val; i++) {
500                         siz += sizeof(struct berval);
501                         len += a->a_vals[i].bv_len + 1;
502                         len += entry_lenlen(a->a_vals[i].bv_len);
503                 }
504                 len += entry_lenlen(i);
505                 siz += sizeof(struct berval);   /* empty berval at end */
506         }
507         len += 1;       /* NUL byte at end */
508         len += entry_lenlen(siz);
509         bv->bv_len = len;
510         bv->bv_val = ch_malloc(len);
511         ptr = (unsigned char *)bv->bv_val;
512         entry_putlen(&ptr, siz);
513         entry_putlen(&ptr, dnlen);
514         AC_MEMCPY(ptr, e->e_dn, dnlen);
515         ptr += dnlen;
516         *ptr++ = '\0';
517         entry_putlen(&ptr, ndnlen);
518         AC_MEMCPY(ptr, e->e_ndn, ndnlen);
519         ptr += ndnlen;
520         *ptr++ = '\0';
521
522         for (a=e->e_attrs; a; a=a->a_next) {
523                 entry_putlen(&ptr, a->a_desc->ad_cname.bv_len);
524                 AC_MEMCPY(ptr, a->a_desc->ad_cname.bv_val,
525                         a->a_desc->ad_cname.bv_len);
526                 ptr += a->a_desc->ad_cname.bv_len;
527                 *ptr++ = '\0';
528                 if (a->a_vals) {
529                     for (i=0; a->a_vals[i].bv_val; i++);
530                     entry_putlen(&ptr, i);
531                     for (i=0; a->a_vals[i].bv_val; i++) {
532                         entry_putlen(&ptr, a->a_vals[i].bv_len);
533                         memcpy(ptr, a->a_vals[i].bv_val,
534                                 a->a_vals[i].bv_len);
535                         ptr += a->a_vals[i].bv_len;
536                         *ptr++ = '\0';
537                     }
538                 }
539         }
540         *ptr = '\0';
541         return 0;
542 }
543
544 /* Retrieve an Entry that was stored using entry_encode above.
545  * We malloc a single block with the size stored above for the Entry
546  * and all if its Attributes. We also must lookup the stored
547  * attribute names to get AttributeDescriptions. To detect if the
548  * attributes of an Entry are later modified, we note that e->e_attr
549  * is always a constant offset from (e).
550  *
551  * Note: everything is stored in a single contiguous block, so
552  * you can not free individual attributes or names from this
553  * structure. Attempting to do so will likely corrupt memory.
554  */
555 int entry_decode(struct berval *bv, Entry **e)
556 {
557         int i, j;
558         int rc;
559         Attribute *a;
560         Entry *x;
561         const char *text;
562         AttributeDescription *ad;
563         unsigned char *ptr = (unsigned char *)bv->bv_val;
564         BerVarray bptr;
565
566         i = entry_getlen(&ptr);
567         x = ch_malloc(i);
568         i = entry_getlen(&ptr);
569         x->e_name.bv_val = ptr;
570         x->e_name.bv_len = i;
571         ptr += i+1;
572         i = entry_getlen(&ptr);
573         x->e_nname.bv_val = ptr;
574         x->e_nname.bv_len = i;
575         ptr += i+1;
576 #ifdef NEW_LOGGING
577         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL2,
578                 "entry_decode: \"%s\"\n", x->e_dn ));
579 #else
580         Debug( LDAP_DEBUG_TRACE,
581             "entry_decode: \"%s\"\n",
582             x->e_dn, 0, 0 );
583 #endif
584         x->e_private = bv->bv_val;
585
586         /* A valid entry must have at least one attr, so this
587          * pointer can never be NULL
588          */
589         x->e_attrs = (Attribute *)(x+1);
590         bptr = (BerVarray)x->e_attrs;
591         a = NULL;
592
593         while (i = entry_getlen(&ptr)) {
594                 struct berval bv = { i, ptr };
595                 if (a) {
596                         a->a_next = (Attribute *)bptr;
597                 }
598                 a = (Attribute *)bptr;
599                 ad = NULL;
600                 rc = slap_bv2ad( &bv, &ad, &text );
601
602                 if( rc != LDAP_SUCCESS ) {
603 #ifdef NEW_LOGGING
604                         LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
605                                 "entry_decode: str2ad(%s): %s\n", ptr, text ));
606 #else
607                         Debug( LDAP_DEBUG_TRACE,
608                                 "<= entry_decode: str2ad(%s): %s\n", ptr, text, 0 );
609 #endif
610                         rc = slap_bv2undef_ad( &bv, &ad, &text );
611
612                         if( rc != LDAP_SUCCESS ) {
613 #ifdef NEW_LOGGING
614                                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
615                                         "entry_decode:  str2undef_ad(%s): %s\n", ptr, text));
616 #else
617                                 Debug( LDAP_DEBUG_ANY,
618                                         "<= entry_decode: str2undef_ad(%s): %s\n",
619                                                 ptr, text, 0 );
620 #endif
621                                 return rc;
622                         }
623                 }
624                 ptr += i + 1;
625                 a->a_desc = ad;
626                 bptr = (BerVarray)(a+1);
627                 a->a_vals = bptr;
628                 a->a_flags = 0;
629                 j = entry_getlen(&ptr);
630
631                 while (j) {
632                         i = entry_getlen(&ptr);
633                         bptr->bv_len = i;
634                         bptr->bv_val = (char *)ptr;
635                         ptr += i+1;
636                         bptr++;
637                         j--;
638                 }
639                 bptr->bv_val = NULL;
640                 bptr->bv_len = 0;
641                 bptr++;
642         }
643         if (a)
644                 a->a_next = NULL;
645 #ifdef NEW_LOGGING
646         LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
647                 "entry_decode:  %s\n", x->e_dn ));
648 #else
649         Debug(LDAP_DEBUG_TRACE, "<= entry_decode(%s)\n",
650                 x->e_dn, 0, 0 );
651 #endif
652         *e = x;
653         return 0;
654 }
655 #endif