]> git.sur5r.net Git - openldap/blob - servers/slapd/dn.c
be68d02a08c939f8b97032c7b16eedce783c2c33
[openldap] / servers / slapd / dn.c
1 /* dn.c - routines for dealing with distinguished names */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 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/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16
17 #include "ldap_pvt.h"
18
19 #include "slap.h"
20
21 #define B4LEADTYPE              0
22 #define B4TYPE                  1
23 #define INOIDTYPE               2
24 #define INKEYTYPE               3
25 #define B4EQUAL                 4
26 #define B4VALUE                 5
27 #define INVALUE                 6
28 #define INQUOTEDVALUE   7
29 #define B4SEPARATOR             8
30
31 #if 0
32 /*
33  * dn_pretty - "pretty" the DN
34  */
35 char *dn_pretty( const char *dn_in )
36 {
37         /*
38          * dn_validate based implementation (for now)
39          *      likely better just to zap this, dn_validate, dn_normalize
40          */
41         char *dn, *dn_out;
42
43         dn = ch_strdup( dn_in );
44         dn_out = dn_validate( dn );
45         if( dn_out == NULL ) free( dn );
46         return dn_out;
47 }
48 #endif
49
50 /*
51  * dn_validate - validate and compress dn.  the dn is
52  * compressed in place are returned if valid.
53  */
54
55 char *
56 dn_validate( char *dn_in )
57 {
58         struct berval   val, *normalized;
59         int             rc;
60
61         if ( dn_in == NULL || dn_in[ 0 ] == '\0' ) {
62                 return( dn_in );
63         }
64
65         val.bv_val = dn_in;
66         val.bv_len = strlen( dn_in );
67
68         rc = dnPretty( NULL, &val, &normalized );
69         if ( rc != LDAP_SUCCESS ) {
70                 return( NULL );
71         }
72
73         if ( val.bv_len < normalized->bv_len ) {
74                 ber_bvfree( normalized );
75                 return( NULL );
76         }
77
78         AC_MEMCPY( dn_in, normalized->bv_val, normalized->bv_len + 1 );
79         ber_bvfree( normalized );
80
81         return( dn_in );
82 }
83
84 /*
85  * dn_normalize - put dn into a canonical form suitable for storing
86  * in a hash database.  this involves normalizing the case as well as
87  * the format.  the dn is normalized in place as well as returned if valid.
88  */
89
90 char *
91 dn_normalize( char *dn )
92 {
93         struct berval   val, *normalized;
94         int             rc;
95
96         if ( dn == NULL || dn[ 0 ] == '\0' ) {
97                 return( dn );
98         }
99
100         val.bv_val = dn;
101         val.bv_len = strlen( dn );
102
103         rc = dnNormalize( NULL, &val, &normalized );
104         if ( rc != LDAP_SUCCESS ) {
105                 return( NULL );
106         }
107
108         if ( val.bv_len < normalized->bv_len ) {
109                 ber_bvfree( normalized );
110                 return( NULL );
111         }
112
113         AC_MEMCPY( dn, normalized->bv_val, normalized->bv_len + 1 );
114         ber_bvfree( normalized );
115
116         return( dn );
117 }
118
119 int
120 dn_match( const char *val, const char *asserted )
121 {
122         struct berval   bval, basserted;
123
124         if ( val == NULL || asserted == NULL ) {
125                 return 0;
126         }
127
128         bval.bv_val = ( char * )val;
129         bval.bv_len = strlen( val );
130
131         basserted.bv_val = ( char * )asserted;
132         basserted.bv_len = strlen( asserted);
133
134         return dnMatch( NULL, 0, NULL, NULL, &bval, &basserted);
135 }
136
137 /*
138  * dn_parent - return the dn's parent, in-place
139  */
140
141 char *
142 dn_parent(
143         Backend *be,
144         const char      *dn )
145 {
146         const char      *s;
147         int     inquote;
148
149         if( dn == NULL ) {
150                 return NULL;
151         }
152
153         while(*dn != '\0' && ASCII_SPACE(*dn)) {
154                 dn++;
155         }
156
157         if( *dn == '\0' ) {
158                 return NULL;
159         }
160
161         if ( be != NULL && be_issuffix( be, dn ) ) {
162                 return NULL;
163         }
164
165         /*
166          * assume it is an X.500-style name, which looks like
167          * foo=bar,sha=baz,...
168          */
169
170         inquote = 0;
171         for ( s = dn; *s; s++ ) {
172                 if ( *s == '\\' ) {
173                         if ( *(s + 1) ) {
174                                 s++;
175                         }
176                         continue;
177                 }
178                 if ( inquote ) {
179                         if ( *s == '"' ) {
180                                 inquote = 0;
181                         }
182                 } else {
183                         if ( *s == '"' ) {
184                                 inquote = 1;
185                         } else if ( DN_SEPARATOR( *s ) ) {
186                                 return (char *)s + 1;
187                         }
188                 }
189         }
190
191         return "";
192 }
193
194 int dn_rdnlen(
195         Backend *be,
196         const char      *dn_in )
197 {
198         char    *s;
199         int     inquote;
200
201         if( dn_in == NULL ) {
202                 return 0;
203         }
204
205         while(*dn_in && ASCII_SPACE(*dn_in)) {
206                 dn_in++;
207         }
208
209         if( *dn_in == '\0' ) {
210                 return( 0 );
211         }
212
213         if ( be != NULL && be_issuffix( be, dn_in ) ) {
214                 return( 0 );
215         }
216
217         inquote = 0;
218
219         for ( s = (char *)dn_in; *s; s++ ) {
220                 if ( *s == '\\' ) {
221                         if ( *(s + 1) ) {
222                                 s++;
223                         }
224                         continue;
225                 }
226                 if ( inquote ) {
227                         if ( *s == '"' ) {
228                                 inquote = 0;
229                         }
230                 } else {
231                         if ( *s == '"' ) {
232                                 inquote = 1;
233                         } else if ( DN_SEPARATOR( *s ) ) {
234                                 break;
235                         }
236                 }
237         }
238
239         return( s - dn_in );
240 }
241
242 char * dn_rdn(
243         Backend *be,
244         const char      *dn_in )
245 {
246         char *rdn;
247         int i = dn_rdnlen( be, dn_in );
248
249         rdn = ch_malloc( i + 1 );
250         strncpy(rdn, dn_in, i);
251         rdn[i] = '\0';
252         return rdn;
253 }
254
255 /*
256  * return a charray of all subtrees to which the DN resides in
257  */
258 char **dn_subtree(
259         Backend *be,
260         const char      *dn )
261 {
262         char **subtree = NULL;
263         
264         do {
265                 charray_add( &subtree, dn );
266
267                 dn = dn_parent( be, dn );
268
269         } while ( dn != NULL );
270
271         return subtree;
272 }
273
274
275 int
276 dn_issuffixbv(
277         const struct berval *dn,
278         const struct berval *suffix
279 )
280 {
281         int     d = dn->bv_len - suffix->bv_len;
282
283         assert( dn );
284         assert( suffix );
285
286         /* empty suffix matches any dn */
287         if ( suffix->bv_len == 0 ) {
288                 return 1;
289         }
290
291         /* suffix longer than dn */
292         if ( d < 0 ) {
293                 return 0;
294         }
295
296         /* no rdn separator or escaped rdn separator */
297         if ( d > 1 && ( !DN_SEPARATOR( dn->bv_val[ d - 1 ] ) 
298                                 || DN_ESCAPE( dn->bv_val[ d - 2 ] ) ) ) {
299                 return 0;
300         }
301
302         /* no possible match or malformed dn */
303         if ( d == 1 ) {
304                 return 0;
305         }
306
307         /* compare */
308         return( strcmp( dn->bv_val + d, suffix->bv_val ) == 0 );
309 }
310
311 /*
312  * dn_issuffix - tells whether suffix is a suffix of dn. Both dn
313  * and suffix must be normalized.
314  */
315
316 int
317 dn_issuffix(
318         const char      *dn,
319         const char      *suffix
320 )
321 {
322         struct berval   bvdn, bvsuffix;
323
324         assert( dn );
325         assert( suffix );
326
327         bvdn.bv_val = (char *) dn;
328         bvdn.bv_len = strlen( dn );
329         bvsuffix.bv_val = (char *) suffix;
330         bvsuffix.bv_len = strlen( suffix );
331
332         return dn_issuffixbv( &bvdn, &bvsuffix );
333 }
334
335 /*
336  * get_next_substring(), rdn_attr_type(), rdn_attr_value(), and
337  * build_new_dn().
338  *
339  * Copyright 1999, Juan C. Gomez, All rights reserved.
340  * This software is not subject to any license of Silicon Graphics
341  * Inc. or Purdue University.
342  *
343  * Redistribution and use in source and binary forms are permitted
344  * without restriction or fee of any kind as long as this notice
345  * is preserved.
346  *
347  */
348
349 /* get_next_substring:
350  *
351  * Gets next substring in s, using d (or the end of the string '\0') as a
352  * string delimiter, and places it in a duplicated memory space. Leading
353  * spaces are ignored. String s **must** be null-terminated.
354  */
355
356 static char *
357 get_next_substring( const char * s, char d )
358 {
359
360         char    *str, *r;
361
362         r = str = ch_malloc( strlen(s) + 1 );
363
364         /* Skip leading spaces */
365         
366         while ( *s && ASCII_SPACE(*s) ) {
367                 s++;
368         }
369         
370         /* Copy word */
371
372         while ( *s && (*s != d) ) {
373
374                 /* Don't stop when you see trailing spaces may be a multi-word
375                 * string, i.e. name=John Doe!
376                 */
377
378                 *str++ = *s++;
379         }
380         
381         *str = '\0';
382         
383         return r;
384         
385 }
386
387
388 /* rdn_attr_type:
389  *
390  * Given a string (i.e. an rdn) of the form:
391  *       "attribute_type = attribute_value"
392  * this function returns the type of an attribute, that is the
393  * string "attribute_type" which is placed in newly allocated
394  * memory. The returned string will be null-terminated.
395  */
396
397 char * rdn_attr_type( const char * s )
398 {
399         return get_next_substring( s, '=' );
400 }
401
402
403 /* rdn_attr_value:
404  *
405  * Given a string (i.e. an rdn) of the form:
406  *       "attribute_type = attribute_value"
407  * this function returns "attribute_type" which is placed in newly allocated
408  * memory. The returned string will be null-terminated and may contain
409  * spaces (i.e. "John Doe\0").
410  */
411
412 char *
413 rdn_attr_value( const char * rdn )
414 {
415
416         const char      *str;
417
418         if ( (str = strchr( rdn, '=' )) != NULL ) {
419                 return get_next_substring(++str, '\0');
420         }
421
422         return NULL;
423
424 }
425
426
427 /* rdn_attrs:
428  *
429  * Given a string (i.e. an rdn) of the form:
430  *   "attribute_type=attribute_value[+attribute_type=attribute_value[...]]"
431  * this function stores the types of the attributes in ptypes, that is the
432  * array of strings "attribute_type" which is placed in newly allocated
433  * memory, and the values of the attributes in pvalues, that is the
434  * array of strings "attribute_value" which is placed in newly allocated
435  * memory. Returns 0 on success, -1 on failure.
436  *
437  * note: got part of the code from dn_validate
438  */
439
440 int
441 rdn_attrs( const char * rdn_in, char ***ptypes, char ***pvalues)
442 {
443         char **parts, **p;
444
445         *ptypes = NULL;
446         *pvalues = NULL;
447
448         /*
449          * explode the rdn in parts
450          */
451         parts = ldap_explode_rdn( rdn_in, 0 );
452
453         if ( parts == NULL ) {
454                 return( -1 );
455         }
456
457         for ( p = parts; p[0]; p++ ) {
458                 char *s, *e, *d;
459                 
460                 /* split each rdn part in type value */
461                 s = strchr( p[0], '=' );
462                 if ( s == NULL ) {
463                         charray_free( *ptypes );
464                         charray_free( *pvalues );
465                         charray_free( parts );
466                         return( -1 );
467                 }
468                 
469                 /* type should be fine */
470                 charray_add_n( ptypes, p[0], ( s-p[0] ) );
471
472                 /* value needs to be unescaped
473                  * (maybe this should be moved to ldap_explode_rdn?) */
474                 for ( e = d = s + 1; e[0]; e++ ) {
475                         if ( *e != '\\' ) {
476                                 *d++ = *e;
477                         }
478                 }
479                 d[0] = '\0';
480                 charray_add( pvalues, s + 1 );
481         }
482
483         /* free array */
484         charray_free( parts );
485
486         return( 0 );
487 }
488
489
490 /* rdn_validate:
491  *
492  * 1 if rdn is a legal rdn;
493  * 0 otherwise (including a sequence of rdns)
494  *
495  * note: got it from dn_rdn; it should be rewritten
496  * according to dn_validate
497  */
498 int
499 rdn_validate( const char * rdn )
500 {
501         int     inquote;
502
503         if ( rdn == NULL ) {
504                 return( 0 );
505         }
506
507         if ( strchr( rdn, '=' ) == NULL ) {
508                 return( 0 );
509         }
510
511         while ( *rdn && ASCII_SPACE( *rdn ) ) {
512                 rdn++;
513         }
514
515         if( *rdn == '\0' ) {
516                 return( 0 );
517         }
518
519         inquote = 0;
520
521         for ( ; *rdn; rdn++ ) {
522                 if ( *rdn == '\\' ) {
523                         if ( *(rdn + 1) ) {
524                                 rdn++;
525                         }
526                         continue;
527                 }
528                 if ( inquote ) {
529                         if ( *rdn == '"' ) {
530                                 inquote = 0;
531                         }
532                 } else {
533                         if ( *rdn == '"' ) {
534                                 inquote = 1;
535                         } else if ( DN_SEPARATOR( *rdn ) ) {
536                                 return( 0 );
537                         }
538                 }
539         }
540
541         return( 1 );
542 }
543
544
545 /* build_new_dn:
546  *
547  * Used by ldbm/bdb2 back_modrdn to create the new dn of entries being
548  * renamed.
549  *
550  * new_dn = parent (p_dn) + separator(s) + rdn (newrdn) + null.
551  */
552
553 void
554 build_new_dn( char ** new_dn,
555         const char *e_dn,
556         const char * p_dn,
557         const char * newrdn )
558 {
559
560         if ( p_dn == NULL ) {
561                 *new_dn = ch_strdup( newrdn );
562                 return;
563         }
564
565         *new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn ) + 3 );
566
567         strcpy( *new_dn, newrdn );
568         strcat( *new_dn, "," );
569         strcat( *new_dn, p_dn );
570 }