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