1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2005-2021 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 
slapi_sdn_init(Slapi_DN * sdn)35 void slapi_sdn_init( Slapi_DN *sdn )
36 {
37 	sdn->flag = 0;
38 	BER_BVZERO( &sdn->dn );
39 	BER_BVZERO( &sdn->ndn );
40 }
41 
slapi_sdn_new(void)42 Slapi_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 
slapi_sdn_done(Slapi_DN * sdn)52 void 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 
slapi_sdn_free(Slapi_DN ** sdn)67 void slapi_sdn_free( Slapi_DN **sdn )
68 {
69 	slapi_sdn_done( *sdn );
70 	slapi_ch_free( (void **)sdn );
71 }
72 
slapi_sdn_get_dn(const Slapi_DN * sdn)73 const 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 
slapi_sdn_get_ndn(const Slapi_DN * sdn)81 const 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 
slapi_sdn_new_dn_byval(const char * dn)92 Slapi_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 
slapi_sdn_new_ndn_byval(const char * ndn)100 Slapi_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 
slapi_sdn_new_dn_byref(const char * dn)108 Slapi_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 
slapi_sdn_new_ndn_byref(const char * ndn)116 Slapi_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 
slapi_sdn_new_dn_passin(const char * dn)124 Slapi_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 
slapi_sdn_set_dn_byval(Slapi_DN * sdn,const char * dn)132 Slapi_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 
slapi_sdn_set_dn_byref(Slapi_DN * sdn,const char * dn)148 Slapi_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 
slapi_sdn_set_dn_passin(Slapi_DN * sdn,const char * dn)162 Slapi_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 
slapi_sdn_set_ndn_byval(Slapi_DN * sdn,const char * ndn)173 Slapi_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 
slapi_sdn_set_ndn_byref(Slapi_DN * sdn,const char * ndn)189 Slapi_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 
slapi_sdn_set_ndn_passin(Slapi_DN * sdn,const char * ndn)203 Slapi_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 
slapi_sdn_get_parent(const Slapi_DN * sdn,Slapi_DN * sdn_parent)214 void 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 
slapi_sdn_get_backend_parent(const Slapi_DN * sdn,Slapi_DN * sdn_parent,const Slapi_Backend * backend)227 void 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 
slapi_sdn_dup(const Slapi_DN * sdn)240 Slapi_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 
slapi_sdn_copy(const Slapi_DN * from,Slapi_DN * to)250 void slapi_sdn_copy( const Slapi_DN *from, Slapi_DN *to )
251 {
252 	slapi_sdn_set_dn_byval( to, from->dn.bv_val );
253 }
254 
slapi_sdn_compare(const Slapi_DN * sdn1,const Slapi_DN * sdn2)255 int 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 
slapi_sdn_isempty(const Slapi_DN * sdn)268 int slapi_sdn_isempty( const Slapi_DN *sdn)
269 {
270 	return ( BER_BVISEMPTY( &sdn->dn ) && BER_BVISEMPTY( &sdn->ndn ) );
271 }
272 
slapi_sdn_issuffix(const Slapi_DN * sdn,const Slapi_DN * suffix_sdn)273 int 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 
slapi_sdn_isparent(const Slapi_DN * parent,const Slapi_DN * child)281 int 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 
slapi_sdn_isgrandparent(const Slapi_DN * parent,const Slapi_DN * child)293 int 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 
slapi_sdn_get_ndn_len(const Slapi_DN * sdn)310 int 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 
slapi_sdn_scope_test(const Slapi_DN * dn,const Slapi_DN * base,int scope)317 int 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 
slapi_rdn_init(Slapi_RDN * rdn)339 void slapi_rdn_init( Slapi_RDN *rdn )
340 {
341 	rdn->flag = 0;
342 	BER_BVZERO( &rdn->bv );
343 	rdn->rdn = NULL;
344 }
345 
slapi_rdn_new(void)346 Slapi_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 
slapi_rdn_new_dn(const char * dn)356 Slapi_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 
slapi_rdn_new_sdn(const Slapi_DN * sdn)365 Slapi_RDN *slapi_rdn_new_sdn( const Slapi_DN *sdn )
366 {
367 	return slapi_rdn_new_dn( slapi_sdn_get_dn( sdn ) );
368 }
369 
slapi_rdn_new_rdn(const Slapi_RDN * fromrdn)370 Slapi_RDN *slapi_rdn_new_rdn( const Slapi_RDN *fromrdn )
371 {
372 	return slapi_rdn_new_dn( fromrdn->bv.bv_val );
373 }
374 
slapi_rdn_init_dn(Slapi_RDN * rdn,const char * dn)375 void 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 
slapi_rdn_init_sdn(Slapi_RDN * rdn,const Slapi_DN * sdn)381 void 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 
slapi_rdn_init_rdn(Slapi_RDN * rdn,const Slapi_RDN * fromrdn)387 void 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 
slapi_rdn_set_dn(Slapi_RDN * rdn,const char * dn)393 void 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 
slapi_rdn_set_sdn(Slapi_RDN * rdn,const Slapi_DN * sdn)410 void 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 
slapi_rdn_set_rdn(Slapi_RDN * rdn,const Slapi_RDN * fromrdn)415 void slapi_rdn_set_rdn( Slapi_RDN *rdn, const Slapi_RDN *fromrdn )
416 {
417 	slapi_rdn_set_dn( rdn, fromrdn->bv.bv_val );
418 }
419 
slapi_rdn_free(Slapi_RDN ** rdn)420 void slapi_rdn_free( Slapi_RDN **rdn )
421 {
422 	slapi_rdn_done( *rdn );
423 	slapi_ch_free( (void **)rdn );
424 }
425 
slapi_rdn_done(Slapi_RDN * rdn)426 void 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 
slapi_rdn_get_rdn(const Slapi_RDN * rdn)436 const char *slapi_rdn_get_rdn( const Slapi_RDN *rdn )
437 {
438 	return rdn->bv.bv_val;
439 }
440 
slapi_int_rdn_explode(Slapi_RDN * rdn)441 static 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 
slapi_int_rdn_implode(Slapi_RDN * rdn)452 static 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 
slapi_rdn_get_num_components(Slapi_RDN * rdn)472 int 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 
slapi_rdn_get_first(Slapi_RDN * rdn,char ** type,char ** value)485 int slapi_rdn_get_first( Slapi_RDN *rdn, char **type, char **value )
486 {
487 	return slapi_rdn_get_next( rdn, 0, type, value );
488 }
489 
slapi_rdn_get_next(Slapi_RDN * rdn,int index,char ** type,char ** value)490 int 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 
slapi_rdn_get_index(Slapi_RDN * rdn,const char * type,const char * value,size_t length)503 int 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 
slapi_rdn_get_index_attr(Slapi_RDN * rdn,const char * type,char ** value)534 int 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 
slapi_rdn_contains(Slapi_RDN * rdn,const char * type,const char * value,size_t length)548 int 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 
slapi_rdn_contains_attr(Slapi_RDN * rdn,const char * type,char ** value)553 int 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 
slapi_rdn_compare(Slapi_RDN * rdn1,Slapi_RDN * rdn2)558 int 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 
slapi_rdn_isempty(const Slapi_RDN * rdn)574 int slapi_rdn_isempty( const Slapi_RDN *rdn )
575 {
576 	return ( BER_BVISEMPTY( &rdn->bv ) );
577 }
578 
slapi_rdn_add(Slapi_RDN * rdn,const char * type,const char * value)579 int 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 
slapi_rdn_remove_index(Slapi_RDN * rdn,int atindex)605 int 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 
slapi_rdn_remove(Slapi_RDN * rdn,const char * type,const char * value,size_t length)630 int 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 
slapi_rdn_remove_attr(Slapi_RDN * rdn,const char * type)637 int 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 
slapi_sdn_add_rdn(Slapi_DN * sdn,const Slapi_RDN * rdn)645 Slapi_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 
slapi_sdn_set_parent(Slapi_DN * sdn,const Slapi_DN * parentdn)657 Slapi_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