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