1 /*	$NetBSD: slapi_dn.c,v 1.1.1.3 2010/12/12 15:23:51 adam Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/servers/slapd/slapi/slapi_dn.c,v 1.5.2.5 2010/04/13 20:23:50 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2005-2010 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Luke Howard for inclusion
19  * in OpenLDAP Software.
20  */
21 
22 #include "portable.h"
23 
24 #include <ac/string.h>
25 #include <ac/stdarg.h>
26 #include <ac/ctype.h>
27 #include <ac/unistd.h>
28 #include <ldap_pvt.h>
29 
30 #include <slap.h>
31 #include <slapi.h>
32 
33 #ifdef LDAP_SLAPI
34 #define FLAG_DN 0x1
35 #define FLAG_NDN 0x2
36 
37 void slapi_sdn_init( Slapi_DN *sdn )
38 {
39 	sdn->flag = 0;
40 	BER_BVZERO( &sdn->dn );
41 	BER_BVZERO( &sdn->ndn );
42 }
43 
44 Slapi_DN *slapi_sdn_new( void )
45 {
46 	Slapi_DN *sdn;
47 
48 	sdn = (Slapi_DN *)slapi_ch_malloc( sizeof(*sdn ));
49 	slapi_sdn_init( sdn );
50 
51 	return sdn;
52 }
53 
54 void slapi_sdn_done( Slapi_DN *sdn )
55 {
56 	if ( sdn == NULL )
57 		return;
58 
59 	if ( sdn->flag & FLAG_DN ) {
60 		slapi_ch_free_string( &sdn->dn.bv_val );
61 	}
62 	if ( sdn->flag & FLAG_NDN ) {
63 		slapi_ch_free_string( &sdn->ndn.bv_val );
64 	}
65 
66 	slapi_sdn_init( sdn );
67 }
68 
69 void slapi_sdn_free( Slapi_DN **sdn )
70 {
71 	slapi_sdn_done( *sdn );
72 	slapi_ch_free( (void **)sdn );
73 }
74 
75 const char *slapi_sdn_get_dn( const Slapi_DN *sdn )
76 {
77 	if ( !BER_BVISNULL( &sdn->dn ) )
78 		return sdn->dn.bv_val;
79 	else
80 		return sdn->ndn.bv_val;
81 }
82 
83 const char *slapi_sdn_get_ndn( const Slapi_DN *sdn )
84 {
85 	if ( BER_BVISNULL( &sdn->ndn ) ) {
86 		dnNormalize( 0, NULL, NULL,
87 			(struct berval *)&sdn->dn, (struct berval *)&sdn->ndn, NULL );
88 		((Slapi_DN *)sdn)->flag |= FLAG_NDN;
89 	}
90 
91 	return sdn->ndn.bv_val;
92 }
93 
94 Slapi_DN *slapi_sdn_new_dn_byval( const char *dn )
95 {
96 	Slapi_DN *sdn;
97 
98 	sdn = slapi_sdn_new();
99 	return slapi_sdn_set_dn_byval( sdn, dn );
100 }
101 
102 Slapi_DN *slapi_sdn_new_ndn_byval( const char *ndn )
103 {
104 	Slapi_DN *sdn;
105 
106 	sdn = slapi_sdn_new();
107 	return slapi_sdn_set_ndn_byval( sdn, ndn );
108 }
109 
110 Slapi_DN *slapi_sdn_new_dn_byref( const char *dn )
111 {
112 	Slapi_DN *sdn;
113 
114 	sdn = slapi_sdn_new();
115 	return slapi_sdn_set_dn_byref( sdn, dn );
116 }
117 
118 Slapi_DN *slapi_sdn_new_ndn_byref( const char *ndn )
119 {
120 	Slapi_DN *sdn;
121 
122 	sdn = slapi_sdn_new();
123 	return slapi_sdn_set_ndn_byref( sdn, ndn );
124 }
125 
126 Slapi_DN *slapi_sdn_new_dn_passin( const char *dn )
127 {
128 	Slapi_DN *sdn;
129 
130 	sdn = slapi_sdn_new();
131 	return slapi_sdn_set_dn_passin( sdn, dn );
132 }
133 
134 Slapi_DN *slapi_sdn_set_dn_byval( Slapi_DN *sdn, const char *dn )
135 {
136 	if ( sdn == NULL ) {
137 		return NULL;
138 	}
139 
140 	slapi_sdn_done( sdn );
141 	if ( dn != NULL ) {
142 		sdn->dn.bv_val = slapi_ch_strdup( dn );
143 		sdn->dn.bv_len = strlen( dn );
144 	}
145 	sdn->flag |= FLAG_DN;
146 
147 	return sdn;
148 }
149 
150 Slapi_DN *slapi_sdn_set_dn_byref( Slapi_DN *sdn, const char *dn )
151 {
152 	if ( sdn == NULL )
153 		return NULL;
154 
155 	slapi_sdn_done( sdn );
156 	if ( dn != NULL ) {
157 		sdn->dn.bv_val = (char *)dn;
158 		sdn->dn.bv_len = strlen( dn );
159 	}
160 
161 	return sdn;
162 }
163 
164 Slapi_DN *slapi_sdn_set_dn_passin( Slapi_DN *sdn, const char *dn )
165 {
166 	if ( sdn == NULL )
167 		return NULL;
168 
169 	slapi_sdn_set_dn_byref( sdn, dn );
170 	sdn->flag |= FLAG_DN;
171 
172 	return sdn;
173 }
174 
175 Slapi_DN *slapi_sdn_set_ndn_byval( Slapi_DN *sdn, const char *ndn )
176 {
177 	if ( sdn == NULL ) {
178 		return NULL;
179 	}
180 
181 	slapi_sdn_done( sdn );
182 	if ( ndn != NULL ) {
183 		sdn->ndn.bv_val = slapi_ch_strdup( ndn );
184 		sdn->ndn.bv_len = strlen( ndn );
185 	}
186 	sdn->flag |= FLAG_NDN;
187 
188 	return sdn;
189 }
190 
191 Slapi_DN *slapi_sdn_set_ndn_byref( Slapi_DN *sdn, const char *ndn )
192 {
193 	if ( sdn == NULL )
194 		return NULL;
195 
196 	slapi_sdn_done( sdn );
197 	if ( ndn != NULL ) {
198 		sdn->ndn.bv_val = (char *)ndn;
199 		sdn->ndn.bv_len = strlen( ndn );
200 	}
201 
202 	return sdn;
203 }
204 
205 Slapi_DN *slapi_sdn_set_ndn_passin( Slapi_DN *sdn, const char *ndn )
206 {
207 	if ( sdn == NULL )
208 		return NULL;
209 
210 	slapi_sdn_set_ndn_byref( sdn, ndn );
211 	sdn->flag |= FLAG_NDN;
212 
213 	return sdn;
214 }
215 
216 void slapi_sdn_get_parent( const Slapi_DN *sdn, Slapi_DN *sdn_parent )
217 {
218 	struct berval parent_dn;
219 
220 	if ( !(sdn->flag & FLAG_DN) ) {
221 		dnParent( (struct berval *)&sdn->ndn, &parent_dn );
222 		slapi_sdn_set_ndn_byval( sdn_parent, parent_dn.bv_val );
223 	} else {
224 		dnParent( (struct berval *)&sdn->dn, &parent_dn );
225 		slapi_sdn_set_dn_byval( sdn_parent, parent_dn.bv_val );
226 	}
227 }
228 
229 void slapi_sdn_get_backend_parent( const Slapi_DN *sdn,
230 	Slapi_DN *sdn_parent,
231 	const Slapi_Backend *backend )
232 {
233 	slapi_sdn_get_ndn( sdn );
234 
235 	if ( backend == NULL ||
236 	     be_issuffix( (Slapi_Backend *)backend, (struct berval *)&sdn->ndn ) == 0 ) {
237 		slapi_sdn_get_parent( sdn, sdn_parent );
238 	}
239 
240 }
241 
242 Slapi_DN * slapi_sdn_dup( const Slapi_DN *sdn )
243 {
244 	Slapi_DN *new_sdn;
245 
246 	new_sdn = slapi_sdn_new();
247 	slapi_sdn_copy( sdn, new_sdn );
248 
249 	return new_sdn;
250 }
251 
252 void slapi_sdn_copy( const Slapi_DN *from, Slapi_DN *to )
253 {
254 	slapi_sdn_set_dn_byval( to, from->dn.bv_val );
255 }
256 
257 int slapi_sdn_compare( const Slapi_DN *sdn1, const Slapi_DN *sdn2 )
258 {
259 	int match = -1;
260 
261 	slapi_sdn_get_ndn( sdn1 );
262 	slapi_sdn_get_ndn( sdn2 );
263 
264 	dnMatch( &match, 0, slap_schema.si_syn_distinguishedName, NULL,
265 		(struct berval *)&sdn1->ndn, (void *)&sdn2->ndn );
266 
267 	return match;
268 }
269 
270 int slapi_sdn_isempty( const Slapi_DN *sdn)
271 {
272 	return ( BER_BVISEMPTY( &sdn->dn ) && BER_BVISEMPTY( &sdn->ndn ) );
273 }
274 
275 int slapi_sdn_issuffix( const Slapi_DN *sdn, const Slapi_DN *suffix_sdn )
276 {
277 	slapi_sdn_get_ndn( sdn );
278 	slapi_sdn_get_ndn( suffix_sdn );
279 
280 	return dnIsSuffix( &sdn->ndn, &suffix_sdn->ndn );
281 }
282 
283 int slapi_sdn_isparent( const Slapi_DN *parent, const Slapi_DN *child )
284 {
285 	Slapi_DN child_parent;
286 
287 	slapi_sdn_get_ndn( child );
288 
289 	slapi_sdn_init( &child_parent );
290 	dnParent( (struct berval *)&child->ndn, &child_parent.ndn );
291 
292 	return ( slapi_sdn_compare( parent, &child_parent ) == 0 );
293 }
294 
295 int slapi_sdn_isgrandparent( const Slapi_DN *parent, const Slapi_DN *child )
296 {
297 	Slapi_DN child_grandparent;
298 
299 	slapi_sdn_get_ndn( child );
300 
301 	slapi_sdn_init( &child_grandparent );
302 	dnParent( (struct berval *)&child->ndn, &child_grandparent.ndn );
303 	if ( child_grandparent.ndn.bv_len == 0 ) {
304 		return 0;
305 	}
306 
307 	dnParent( &child_grandparent.ndn, &child_grandparent.ndn );
308 
309 	return ( slapi_sdn_compare( parent, &child_grandparent ) == 0 );
310 }
311 
312 int slapi_sdn_get_ndn_len( const Slapi_DN *sdn )
313 {
314 	slapi_sdn_get_ndn( sdn );
315 
316 	return sdn->ndn.bv_len;
317 }
318 
319 int slapi_sdn_scope_test( const Slapi_DN *dn, const Slapi_DN *base, int scope )
320 {
321 	int rc;
322 
323 	switch ( scope ) {
324 	case LDAP_SCOPE_BASE:
325 		rc = ( slapi_sdn_compare( dn, base ) == 0 );
326 		break;
327 	case LDAP_SCOPE_ONELEVEL:
328 		rc = slapi_sdn_isparent( base, dn );
329 		break;
330 	case LDAP_SCOPE_SUBTREE:
331 		rc = slapi_sdn_issuffix( dn, base );
332 		break;
333 	default:
334 		rc = 0;
335 		break;
336 	}
337 
338 	return rc;
339 }
340 
341 void slapi_rdn_init( Slapi_RDN *rdn )
342 {
343 	rdn->flag = 0;
344 	BER_BVZERO( &rdn->bv );
345 	rdn->rdn = NULL;
346 }
347 
348 Slapi_RDN *slapi_rdn_new( void )
349 {
350 	Slapi_RDN *rdn;
351 
352 	rdn = (Slapi_RDN *)slapi_ch_malloc( sizeof(*rdn ));
353 	slapi_rdn_init( rdn );
354 
355 	return rdn;
356 }
357 
358 Slapi_RDN *slapi_rdn_new_dn( const char *dn )
359 {
360 	Slapi_RDN *rdn;
361 
362 	rdn = slapi_rdn_new();
363 	slapi_rdn_init_dn( rdn, dn );
364 	return rdn;
365 }
366 
367 Slapi_RDN *slapi_rdn_new_sdn( const Slapi_DN *sdn )
368 {
369 	return slapi_rdn_new_dn( slapi_sdn_get_dn( sdn ) );
370 }
371 
372 Slapi_RDN *slapi_rdn_new_rdn( const Slapi_RDN *fromrdn )
373 {
374 	return slapi_rdn_new_dn( fromrdn->bv.bv_val );
375 }
376 
377 void slapi_rdn_init_dn( Slapi_RDN *rdn, const char *dn )
378 {
379 	slapi_rdn_init( rdn );
380 	slapi_rdn_set_dn( rdn, dn );
381 }
382 
383 void slapi_rdn_init_sdn( Slapi_RDN *rdn, const Slapi_DN *sdn )
384 {
385 	slapi_rdn_init( rdn );
386 	slapi_rdn_set_sdn( rdn, sdn );
387 }
388 
389 void slapi_rdn_init_rdn( Slapi_RDN *rdn, const Slapi_RDN *fromrdn )
390 {
391 	slapi_rdn_init( rdn );
392 	slapi_rdn_set_rdn( rdn, fromrdn );
393 }
394 
395 void slapi_rdn_set_dn( Slapi_RDN *rdn, const char *dn )
396 {
397 	struct berval bv;
398 
399 	slapi_rdn_done( rdn );
400 
401 	BER_BVZERO( &bv );
402 
403 	if ( dn != NULL ) {
404 		bv.bv_val = (char *)dn;
405 		bv.bv_len = strlen( dn );
406 	}
407 
408 	dnExtractRdn( &bv, &rdn->bv, NULL );
409 	rdn->flag |= FLAG_DN;
410 }
411 
412 void slapi_rdn_set_sdn( Slapi_RDN *rdn, const Slapi_DN *sdn )
413 {
414 	slapi_rdn_set_dn( rdn, slapi_sdn_get_dn( sdn ) );
415 }
416 
417 void slapi_rdn_set_rdn( Slapi_RDN *rdn, const Slapi_RDN *fromrdn )
418 {
419 	slapi_rdn_set_dn( rdn, fromrdn->bv.bv_val );
420 }
421 
422 void slapi_rdn_free( Slapi_RDN **rdn )
423 {
424 	slapi_rdn_done( *rdn );
425 	slapi_ch_free( (void **)rdn );
426 }
427 
428 void slapi_rdn_done( Slapi_RDN *rdn )
429 {
430 	if ( rdn->rdn != NULL ) {
431 		ldap_rdnfree( rdn->rdn );
432 		rdn->rdn = NULL;
433 	}
434 	slapi_ch_free_string( &rdn->bv.bv_val );
435 	slapi_rdn_init( rdn );
436 }
437 
438 const char *slapi_rdn_get_rdn( const Slapi_RDN *rdn )
439 {
440 	return rdn->bv.bv_val;
441 }
442 
443 static int slapi_int_rdn_explode( Slapi_RDN *rdn )
444 {
445 	char *next;
446 
447 	if ( rdn->rdn != NULL ) {
448 		return LDAP_SUCCESS;
449 	}
450 
451 	return ldap_bv2rdn( &rdn->bv, &rdn->rdn, &next, LDAP_DN_FORMAT_LDAP );
452 }
453 
454 static int slapi_int_rdn_implode( Slapi_RDN *rdn )
455 {
456 	struct berval bv;
457 	int rc;
458 
459 	if ( rdn->rdn == NULL ) {
460 		return LDAP_SUCCESS;
461 	}
462 
463 	rc = ldap_rdn2bv( rdn->rdn, &bv, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
464 	if ( rc != LDAP_SUCCESS ) {
465 		return rc;
466 	}
467 
468 	slapi_ch_free_string( &rdn->bv.bv_val );
469 	rdn->bv = bv;
470 
471 	return 0;
472 }
473 
474 int slapi_rdn_get_num_components( Slapi_RDN *rdn )
475 {
476 	int i;
477 
478 	if ( slapi_int_rdn_explode( rdn ) != LDAP_SUCCESS )
479 		return 0;
480 
481 	for ( i = 0; rdn->rdn[i] != NULL; i++ )
482 		;
483 
484 	return i;
485 }
486 
487 int slapi_rdn_get_first( Slapi_RDN *rdn, char **type, char **value )
488 {
489 	return slapi_rdn_get_next( rdn, 0, type, value );
490 }
491 
492 int slapi_rdn_get_next( Slapi_RDN *rdn, int index, char **type, char **value )
493 {
494 	slapi_int_rdn_explode( rdn );
495 
496 	if ( rdn->rdn == NULL || rdn->rdn[index] == NULL )
497 		return -1;
498 
499 	*type = rdn->rdn[index]->la_attr.bv_val;
500 	*value = rdn->rdn[index]->la_value.bv_val;
501 
502 	return index + 1;
503 }
504 
505 int slapi_rdn_get_index( Slapi_RDN *rdn, const char *type, const char *value, size_t length )
506 {
507 	int i, match;
508 	struct berval bv;
509 	AttributeDescription *ad = NULL;
510 	const char *text;
511 
512 	slapi_int_rdn_explode( rdn );
513 
514 	if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
515 		return -1;
516 	}
517 
518 	bv.bv_val = (char *)value;
519 	bv.bv_len = length;
520 
521 	for ( i = 0; rdn->rdn[i] != NULL; i++ ) {
522 		if ( !slapi_attr_types_equivalent( ad->ad_cname.bv_val, type ))
523 			continue;
524 
525 		if ( value_match( &match, ad, ad->ad_type->sat_equality, 0,
526 			&rdn->rdn[i]->la_value, (void *)&bv, &text ) != LDAP_SUCCESS )
527 			match = -1;
528 
529 		if ( match == 0 )
530 			return i;
531 	}
532 
533 	return -1;
534 }
535 
536 int slapi_rdn_get_index_attr( Slapi_RDN *rdn, const char *type, char **value )
537 {
538 	int i;
539 
540 	for ( i = 0; rdn->rdn[i] != NULL; i++ ) {
541 		if ( slapi_attr_types_equivalent( rdn->rdn[i]->la_attr.bv_val, type ) ) {
542 			*value = rdn->rdn[i]->la_value.bv_val;
543 			return i;
544 		}
545 	}
546 
547 	return -1;
548 }
549 
550 int slapi_rdn_contains( Slapi_RDN *rdn, const char *type, const char *value, size_t length )
551 {
552 	return ( slapi_rdn_get_index( rdn, type, value, length ) != -1 );
553 }
554 
555 int slapi_rdn_contains_attr( Slapi_RDN *rdn, const char *type, char **value )
556 {
557 	return ( slapi_rdn_get_index_attr( rdn, type, value ) != -1 );
558 }
559 
560 int slapi_rdn_compare( Slapi_RDN *rdn1, Slapi_RDN *rdn2 )
561 {
562 	struct berval nrdn1 = BER_BVNULL;
563 	struct berval nrdn2 = BER_BVNULL;
564 	int match;
565 
566 	rdnNormalize( 0, NULL, NULL, (struct berval *)&rdn1->bv, &nrdn1, NULL );
567 	rdnNormalize( 0, NULL, NULL, (struct berval *)&rdn2->bv, &nrdn2, NULL );
568 
569 	if ( rdnMatch( &match, 0, NULL, NULL, &nrdn1, (void *)&nrdn2 ) != LDAP_SUCCESS) {
570 		match = -1;
571 	}
572 
573 	return match;
574 }
575 
576 int slapi_rdn_isempty( const Slapi_RDN *rdn )
577 {
578 	return ( BER_BVISEMPTY( &rdn->bv ) );
579 }
580 
581 int slapi_rdn_add( Slapi_RDN *rdn, const char *type, const char *value )
582 {
583 	char *s;
584 	size_t len;
585 
586 	len = strlen(type) + 1 + strlen( value );
587 	if ( !BER_BVISEMPTY( &rdn->bv ) ) {
588 		len += 1 + rdn->bv.bv_len;
589 	}
590 
591 	s = slapi_ch_malloc( len + 1 );
592 
593 	if ( BER_BVISEMPTY( &rdn->bv ) ) {
594 		snprintf( s, len + 1, "%s=%s", type, value );
595 	} else {
596 		snprintf( s, len + 1, "%s=%s+%s", type, value, rdn->bv.bv_val );
597 	}
598 
599 	slapi_rdn_done( rdn );
600 
601 	rdn->bv.bv_len = len;
602 	rdn->bv.bv_val = s;
603 
604 	return 1;
605 }
606 
607 int slapi_rdn_remove_index( Slapi_RDN *rdn, int atindex )
608 {
609 	int count, i;
610 
611 	count = slapi_rdn_get_num_components( rdn );
612 
613 	if ( atindex < 0 || atindex >= count )
614 		return 0;
615 
616 	if ( rdn->rdn == NULL )
617 		return 0;
618 
619 	slapi_ch_free_string( &rdn->rdn[atindex]->la_attr.bv_val );
620 	slapi_ch_free_string( &rdn->rdn[atindex]->la_value.bv_val );
621 
622 	for ( i = atindex; i < count; i++ ) {
623 		rdn->rdn[i] = rdn->rdn[i + 1];
624 	}
625 
626 	if ( slapi_int_rdn_implode( rdn ) != LDAP_SUCCESS )
627 		return 0;
628 
629 	return 1;
630 }
631 
632 int slapi_rdn_remove( Slapi_RDN *rdn, const char *type, const char *value, size_t length )
633 {
634 	int index = slapi_rdn_get_index( rdn, type, value, length );
635 
636 	return slapi_rdn_remove_index( rdn, index );
637 }
638 
639 int slapi_rdn_remove_attr( Slapi_RDN *rdn, const char *type )
640 {
641 	char *value;
642 	int index = slapi_rdn_get_index_attr( rdn, type, &value );
643 
644 	return slapi_rdn_remove_index( rdn, index );
645 }
646 
647 Slapi_DN *slapi_sdn_add_rdn( Slapi_DN *sdn, const Slapi_RDN *rdn )
648 {
649 	struct berval bv;
650 
651 	build_new_dn( &bv, &sdn->dn, (struct berval *)&rdn->bv, NULL );
652 
653 	slapi_sdn_done( sdn );
654 	sdn->dn = bv;
655 
656 	return sdn;
657 }
658 
659 Slapi_DN *slapi_sdn_set_parent( Slapi_DN *sdn, const Slapi_DN *parentdn )
660 {
661 	Slapi_RDN rdn;
662 
663 	slapi_rdn_init_sdn( &rdn, sdn );
664 	slapi_sdn_set_dn_byref( sdn, slapi_sdn_get_dn( parentdn ) );
665 	slapi_sdn_add_rdn( sdn, &rdn );
666 	slapi_rdn_done( &rdn );
667 
668 	return sdn;
669 }
670 
671 #endif /* LDAP_SLAPI */
672