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