1/* $OpenLDAP$ */
2/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 *
4 * Copyright 2002-2011 The OpenLDAP Foundation.
5 * Portions Copyright 1997,2002-2003 IBM Corporation.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
10 * Public License.
11 *
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
15 */
16/* ACKNOWLEDGEMENTS:
17 * This work was initially developed by IBM Corporation for use in
18 * IBM products and subsequently ported to OpenLDAP Software by
19 * Steve Omrani.  Additional significant contributors include:
20 *   Luke Howard
21 */
22
23#include "portable.h"
24
25#include <ac/string.h>
26#include <ac/stdarg.h>
27#include <ac/ctype.h>
28#include <ac/unistd.h>
29#include <lutil.h>
30
31#include <slap.h>
32#include <slapi.h>
33
34#include <netdb.h>
35
36#ifdef LDAP_SLAPI
37
38/*
39 * server start time (should we use a struct timeval also in slapd?
40 */
41static struct			timeval base_time;
42ldap_pvt_thread_mutex_t		slapi_hn_mutex;
43ldap_pvt_thread_mutex_t		slapi_time_mutex;
44
45struct slapi_mutex {
46	ldap_pvt_thread_mutex_t mutex;
47};
48
49struct slapi_condvar {
50	ldap_pvt_thread_cond_t cond;
51	ldap_pvt_thread_mutex_t mutex;
52};
53
54static int checkBVString(const struct berval *bv)
55{
56	ber_len_t i;
57
58	for ( i = 0; i < bv->bv_len; i++ ) {
59		if ( bv->bv_val[i] == '\0' )
60			return 0;
61	}
62	if ( bv->bv_val[i] != '\0' )
63		return 0;
64
65	return 1;
66}
67
68/*
69 * This function converts an array of pointers to berval objects to
70 * an array of berval objects.
71 */
72
73int
74bvptr2obj(
75	struct berval	**bvptr,
76	BerVarray	*bvobj,
77	unsigned *num )
78{
79	int		rc = LDAP_SUCCESS;
80	int		i;
81	BerVarray	tmpberval;
82
83	if ( bvptr == NULL || *bvptr == NULL ) {
84		return LDAP_OTHER;
85	}
86
87	for ( i = 0; bvptr != NULL && bvptr[i] != NULL; i++ ) {
88		; /* EMPTY */
89	}
90	if ( num )
91		*num = i;
92
93	tmpberval = (BerVarray)slapi_ch_malloc( (i + 1)*sizeof(struct berval));
94	if ( tmpberval == NULL ) {
95		return LDAP_NO_MEMORY;
96	}
97
98	for ( i = 0; bvptr[i] != NULL; i++ ) {
99		tmpberval[i].bv_val = bvptr[i]->bv_val;
100		tmpberval[i].bv_len = bvptr[i]->bv_len;
101	}
102	tmpberval[i].bv_val = NULL;
103	tmpberval[i].bv_len = 0;
104
105	if ( rc == LDAP_SUCCESS ) {
106		*bvobj = tmpberval;
107	}
108
109	return rc;
110}
111
112Slapi_Entry *
113slapi_str2entry(
114	char		*s,
115	int		flags )
116{
117	return str2entry( s );
118}
119
120char *
121slapi_entry2str(
122	Slapi_Entry	*e,
123	int		*len )
124{
125	char		*ret = NULL;
126	char		*s;
127
128	ldap_pvt_thread_mutex_lock( &entry2str_mutex );
129	s = entry2str( e, len );
130	if ( s != NULL )
131		ret = slapi_ch_strdup( s );
132	ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
133
134	return ret;
135}
136
137char *
138slapi_entry_get_dn( Slapi_Entry *e )
139{
140	return e->e_name.bv_val;
141}
142
143int
144slapi_x_entry_get_id( Slapi_Entry *e )
145{
146	return e->e_id;
147}
148
149static int
150slapi_int_dn_pretty( struct berval *in, struct berval *out )
151{
152	Syntax		*syntax = slap_schema.si_syn_distinguishedName;
153
154	assert( syntax != NULL );
155
156	return (syntax->ssyn_pretty)( syntax, in, out, NULL );
157}
158
159static int
160slapi_int_dn_normalize( struct berval *in, struct berval *out )
161{
162	MatchingRule	*mr = slap_schema.si_mr_distinguishedNameMatch;
163	Syntax		*syntax = slap_schema.si_syn_distinguishedName;
164
165	assert( mr != NULL );
166
167	return (mr->smr_normalize)( 0, syntax, mr, in, out, NULL );
168}
169
170void
171slapi_entry_set_dn(
172	Slapi_Entry	*e,
173	char		*ldn )
174{
175	struct berval	dn = BER_BVNULL;
176
177	dn.bv_val = ldn;
178	dn.bv_len = strlen( ldn );
179
180	slapi_int_dn_pretty( &dn, &e->e_name );
181	slapi_int_dn_normalize( &dn, &e->e_nname );
182}
183
184Slapi_Entry *
185slapi_entry_dup( Slapi_Entry *e )
186{
187	return entry_dup( e );
188}
189
190int
191slapi_entry_attr_delete(
192	Slapi_Entry	*e,
193	char		*type )
194{
195	AttributeDescription	*ad = NULL;
196	const char		*text;
197
198	if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
199		return 1;	/* LDAP_NO_SUCH_ATTRIBUTE */
200	}
201
202	if ( attr_delete( &e->e_attrs, ad ) == LDAP_SUCCESS ) {
203		return 0;	/* attribute is deleted */
204	} else {
205		return -1;	/* something went wrong */
206	}
207}
208
209Slapi_Entry *
210slapi_entry_alloc( void )
211{
212	return (Slapi_Entry *)entry_alloc();
213}
214
215void
216slapi_entry_free( Slapi_Entry *e )
217{
218	if ( e != NULL )
219		entry_free( e );
220}
221
222int
223slapi_entry_attr_merge(
224	Slapi_Entry	*e,
225	char		*type,
226	struct berval	**vals )
227{
228	AttributeDescription	*ad = NULL;
229	const char		*text;
230	BerVarray		bv;
231	int			rc;
232
233	rc = slap_str2ad( type, &ad, &text );
234	if ( rc != LDAP_SUCCESS ) {
235		return -1;
236	}
237
238	rc = bvptr2obj( vals, &bv, NULL );
239	if ( rc != LDAP_SUCCESS ) {
240		return -1;
241	}
242
243	rc = attr_merge_normalize( e, ad, bv, NULL );
244	ch_free( bv );
245
246	return rc;
247}
248
249int
250slapi_entry_attr_find(
251	Slapi_Entry	*e,
252	char		*type,
253	Slapi_Attr	**attr )
254{
255	AttributeDescription	*ad = NULL;
256	const char		*text;
257	int			rc;
258
259	rc = slap_str2ad( type, &ad, &text );
260	if ( rc != LDAP_SUCCESS ) {
261		return -1;
262	}
263
264	*attr = attr_find( e->e_attrs, ad );
265	if ( *attr == NULL ) {
266		return -1;
267	}
268
269	return 0;
270}
271
272char *
273slapi_entry_attr_get_charptr( const Slapi_Entry *e, const char *type )
274{
275	AttributeDescription *ad = NULL;
276	const char *text;
277	int rc;
278	Attribute *attr;
279
280	rc = slap_str2ad( type, &ad, &text );
281	if ( rc != LDAP_SUCCESS ) {
282		return NULL;
283	}
284
285	attr = attr_find( e->e_attrs, ad );
286	if ( attr == NULL ) {
287		return NULL;
288	}
289
290	if ( attr->a_vals != NULL && attr->a_vals[0].bv_len != 0 ) {
291		const char *p;
292
293		p = slapi_value_get_string( &attr->a_vals[0] );
294		if ( p != NULL ) {
295			return slapi_ch_strdup( p );
296		}
297	}
298
299	return NULL;
300}
301
302int
303slapi_entry_attr_get_int( const Slapi_Entry *e, const char *type )
304{
305	AttributeDescription *ad = NULL;
306	const char *text;
307	int rc;
308	Attribute *attr;
309
310	rc = slap_str2ad( type, &ad, &text );
311	if ( rc != LDAP_SUCCESS ) {
312		return 0;
313	}
314
315	attr = attr_find( e->e_attrs, ad );
316	if ( attr == NULL ) {
317		return 0;
318	}
319
320	return slapi_value_get_int( attr->a_vals );
321}
322
323long
324slapi_entry_attr_get_long( const Slapi_Entry *e, const char *type )
325{
326	AttributeDescription *ad = NULL;
327	const char *text;
328	int rc;
329	Attribute *attr;
330
331	rc = slap_str2ad( type, &ad, &text );
332	if ( rc != LDAP_SUCCESS ) {
333		return 0;
334	}
335
336	attr = attr_find( e->e_attrs, ad );
337	if ( attr == NULL ) {
338		return 0;
339	}
340
341	return slapi_value_get_long( attr->a_vals );
342}
343
344unsigned int
345slapi_entry_attr_get_uint( const Slapi_Entry *e, const char *type )
346{
347	AttributeDescription *ad = NULL;
348	const char *text;
349	int rc;
350	Attribute *attr;
351
352	rc = slap_str2ad( type, &ad, &text );
353	if ( rc != LDAP_SUCCESS ) {
354		return 0;
355	}
356
357	attr = attr_find( e->e_attrs, ad );
358	if ( attr == NULL ) {
359		return 0;
360	}
361
362	return slapi_value_get_uint( attr->a_vals );
363}
364
365unsigned long
366slapi_entry_attr_get_ulong( const Slapi_Entry *e, const char *type )
367{
368	AttributeDescription *ad = NULL;
369	const char *text;
370	int rc;
371	Attribute *attr;
372
373	rc = slap_str2ad( type, &ad, &text );
374	if ( rc != LDAP_SUCCESS ) {
375		return 0;
376	}
377
378	attr = attr_find( e->e_attrs, ad );
379	if ( attr == NULL ) {
380		return 0;
381	}
382
383	return slapi_value_get_ulong( attr->a_vals );
384}
385
386int
387slapi_entry_attr_hasvalue( Slapi_Entry *e, const char *type, const char *value )
388{
389	struct berval bv;
390	AttributeDescription *ad = NULL;
391	const char *text;
392	int rc;
393	Attribute *attr;
394
395	rc = slap_str2ad( type, &ad, &text );
396	if ( rc != LDAP_SUCCESS ) {
397		return 0;
398	}
399
400	attr = attr_find( e->e_attrs, ad );
401	if ( attr == NULL ) {
402		return 0;
403	}
404
405	bv.bv_val = (char *)value;
406	bv.bv_len = strlen( value );
407
408	return ( slapi_attr_value_find( attr, &bv ) != -1 );
409}
410
411void
412slapi_entry_attr_set_charptr(Slapi_Entry* e, const char *type, const char *value)
413{
414	AttributeDescription	*ad = NULL;
415	const char		*text;
416	int			rc;
417	struct berval		bv;
418
419	rc = slap_str2ad( type, &ad, &text );
420	if ( rc != LDAP_SUCCESS ) {
421		return;
422	}
423
424	attr_delete ( &e->e_attrs, ad );
425	if ( value != NULL ) {
426		bv.bv_val = (char *)value;
427		bv.bv_len = strlen(value);
428		attr_merge_normalize_one( e, ad, &bv, NULL );
429	}
430}
431
432void
433slapi_entry_attr_set_int( Slapi_Entry* e, const char *type, int l)
434{
435	char buf[64];
436
437	snprintf( buf, sizeof( buf ), "%d", l );
438	slapi_entry_attr_set_charptr( e, type, buf );
439}
440
441void
442slapi_entry_attr_set_uint( Slapi_Entry* e, const char *type, unsigned int l)
443{
444	char buf[64];
445
446	snprintf( buf, sizeof( buf ), "%u", l );
447	slapi_entry_attr_set_charptr( e, type, buf );
448}
449
450void
451slapi_entry_attr_set_long(Slapi_Entry* e, const char *type, long l)
452{
453	char buf[64];
454
455	snprintf( buf, sizeof( buf ), "%ld", l );
456	slapi_entry_attr_set_charptr( e, type, buf );
457}
458
459void
460slapi_entry_attr_set_ulong(Slapi_Entry* e, const char *type, unsigned long l)
461{
462	char buf[64];
463
464	snprintf( buf, sizeof( buf ), "%lu", l );
465	slapi_entry_attr_set_charptr( e, type, buf );
466}
467
468int
469slapi_is_rootdse( const char *dn )
470{
471	return ( dn == NULL || dn[0] == '\0' );
472}
473
474int
475slapi_entry_has_children( const Slapi_Entry *e )
476{
477	Slapi_PBlock *pb;
478	Backend *be = select_backend( (struct berval *)&e->e_nname, 0 );
479	int rc, hasSubordinates = 0;
480
481	if ( be == NULL || be->be_has_subordinates == 0 ) {
482		return 0;
483	}
484
485	pb = slapi_pblock_new();
486	if ( pb == NULL ) {
487		return 0;
488	}
489	slapi_int_connection_init_pb( pb, LDAP_REQ_SEARCH );
490
491	rc = slapi_pblock_set( pb, SLAPI_TARGET_DN, slapi_entry_get_dn(
492		(Entry *) e ));
493	if ( rc == LDAP_SUCCESS ) {
494		pb->pb_op->o_bd = be;
495		rc = be->be_has_subordinates( pb->pb_op, (Entry *) e,
496			&hasSubordinates );
497	}
498
499	slapi_pblock_destroy( pb );
500
501	return ( rc == LDAP_SUCCESS && hasSubordinates == LDAP_COMPARE_TRUE );
502}
503
504/*
505 * Return approximate size of the entry rounded to the nearest
506 * 1K. Only the size of the attribute values are counted in the
507 * Sun implementation.
508 *
509 * http://docs.sun.com/source/816-6701-10/funcref.html#1017388
510 */
511size_t slapi_entry_size(Slapi_Entry *e)
512{
513	size_t size;
514	Attribute *a;
515	int i;
516
517	for ( size = 0, a = e->e_attrs; a != NULL; a = a->a_next ) {
518		for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
519			size += a->a_vals[i].bv_len + 1;
520		}
521	}
522
523	size += 1023;
524	size -= (size % 1024);
525
526	return size;
527}
528
529/*
530 * Add values to entry.
531 *
532 * Returns:
533 *	LDAP_SUCCESS			Values added to entry
534 *	LDAP_TYPE_OR_VALUE_EXISTS	One or more values exist in entry already
535 *	LDAP_CONSTRAINT_VIOLATION	Any other error (odd, but it's the spec)
536 */
537int
538slapi_entry_add_values( Slapi_Entry *e, const char *type, struct berval **vals )
539{
540	Modification		mod;
541	const char		*text;
542	int			rc;
543	char			textbuf[SLAP_TEXT_BUFLEN];
544
545	mod.sm_op = LDAP_MOD_ADD;
546	mod.sm_flags = 0;
547	mod.sm_desc = NULL;
548	mod.sm_type.bv_val = (char *)type;
549	mod.sm_type.bv_len = strlen( type );
550
551	rc = slap_str2ad( type, &mod.sm_desc, &text );
552	if ( rc != LDAP_SUCCESS ) {
553		return rc;
554	}
555
556	if ( vals == NULL ) {
557		/* Apparently vals can be NULL
558		 * FIXME: sm_values = NULL ? */
559		mod.sm_values = (BerVarray)ch_malloc( sizeof(struct berval) );
560		mod.sm_values->bv_val = NULL;
561		mod.sm_numvals = 0;
562
563	} else {
564		rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
565		if ( rc != LDAP_SUCCESS ) {
566			return LDAP_CONSTRAINT_VIOLATION;
567		}
568	}
569	mod.sm_nvalues = NULL;
570
571	rc = modify_add_values( e, &mod, 0, &text, textbuf, sizeof(textbuf) );
572
573	slapi_ch_free( (void **)&mod.sm_values );
574
575	return (rc == LDAP_SUCCESS) ? LDAP_SUCCESS : LDAP_CONSTRAINT_VIOLATION;
576}
577
578int
579slapi_entry_add_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
580{
581	return slapi_entry_add_values( e, type, vals );
582}
583
584int
585slapi_entry_add_valueset(Slapi_Entry *e, const char *type, Slapi_ValueSet *vs)
586{
587	AttributeDescription	*ad = NULL;
588	const char		*text;
589	int			rc;
590
591	rc = slap_str2ad( type, &ad, &text );
592	if ( rc != LDAP_SUCCESS ) {
593		return -1;
594	}
595
596	return attr_merge_normalize( e, ad, *vs, NULL );
597}
598
599int
600slapi_entry_delete_values( Slapi_Entry *e, const char *type, struct berval **vals )
601{
602	Modification		mod;
603	const char		*text;
604	int			rc;
605	char			textbuf[SLAP_TEXT_BUFLEN];
606
607	mod.sm_op = LDAP_MOD_DELETE;
608	mod.sm_flags = 0;
609	mod.sm_desc = NULL;
610	mod.sm_type.bv_val = (char *)type;
611	mod.sm_type.bv_len = strlen( type );
612
613	if ( vals == NULL ) {
614		/* If vals is NULL, this is a NOOP. */
615		return LDAP_SUCCESS;
616	}
617
618	rc = slap_str2ad( type, &mod.sm_desc, &text );
619	if ( rc != LDAP_SUCCESS ) {
620		return rc;
621	}
622
623	if ( vals[0] == NULL ) {
624		/* SLAPI doco says LDApb_opERATIONS_ERROR but LDAP_OTHER is better */
625		return attr_delete( &e->e_attrs, mod.sm_desc ) ? LDAP_OTHER : LDAP_SUCCESS;
626	}
627
628	rc = bvptr2obj( vals, &mod.sm_values, &mod.sm_numvals );
629	if ( rc != LDAP_SUCCESS ) {
630		return LDAP_CONSTRAINT_VIOLATION;
631	}
632	mod.sm_nvalues = NULL;
633
634	rc = modify_delete_values( e, &mod, 0, &text, textbuf, sizeof(textbuf) );
635
636	slapi_ch_free( (void **)&mod.sm_values );
637
638	return rc;
639}
640
641int
642slapi_entry_delete_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
643{
644	return slapi_entry_delete_values( e, type, vals );
645}
646
647int
648slapi_entry_merge_values_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
649{
650	return slapi_entry_attr_merge( e, (char *)type, vals );
651}
652
653int
654slapi_entry_add_value(Slapi_Entry *e, const char *type, const Slapi_Value *value)
655{
656	AttributeDescription	*ad = NULL;
657	int 			rc;
658	const char		*text;
659
660	rc = slap_str2ad( type, &ad, &text );
661	if ( rc != LDAP_SUCCESS ) {
662		return -1;
663	}
664
665	rc = attr_merge_normalize_one( e, ad, (Slapi_Value *)value, NULL );
666	if ( rc != LDAP_SUCCESS ) {
667		return -1;
668	}
669
670	return 0;
671}
672
673int
674slapi_entry_add_string(Slapi_Entry *e, const char *type, const char *value)
675{
676	Slapi_Value val;
677
678	val.bv_val = (char *)value;
679	val.bv_len = strlen( value );
680
681	return slapi_entry_add_value( e, type, &val );
682}
683
684int
685slapi_entry_delete_string(Slapi_Entry *e, const char *type, const char *value)
686{
687	Slapi_Value *vals[2];
688	Slapi_Value val;
689
690	val.bv_val = (char *)value;
691	val.bv_len = strlen( value );
692	vals[0] = &val;
693	vals[1] = NULL;
694
695	return slapi_entry_delete_values_sv( e, type, vals );
696}
697
698int
699slapi_entry_attr_merge_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
700{
701	return slapi_entry_attr_merge( e, (char *)type, vals );
702}
703
704int
705slapi_entry_first_attr( const Slapi_Entry *e, Slapi_Attr **attr )
706{
707	if ( e == NULL ) {
708		return -1;
709	}
710
711	*attr = e->e_attrs;
712
713	return ( *attr != NULL ) ? 0 : -1;
714}
715
716int
717slapi_entry_next_attr( const Slapi_Entry *e, Slapi_Attr *prevattr, Slapi_Attr **attr )
718{
719	if ( e == NULL ) {
720		return -1;
721	}
722
723	if ( prevattr == NULL ) {
724		return -1;
725	}
726
727	*attr = prevattr->a_next;
728
729	return ( *attr != NULL ) ? 0 : -1;
730}
731
732int
733slapi_entry_attr_replace_sv( Slapi_Entry *e, const char *type, Slapi_Value **vals )
734{
735	AttributeDescription *ad = NULL;
736	const char *text;
737	int rc;
738	BerVarray bv;
739
740	rc = slap_str2ad( type, &ad, &text );
741	if ( rc != LDAP_SUCCESS ) {
742		return 0;
743	}
744
745	attr_delete( &e->e_attrs, ad );
746
747	rc = bvptr2obj( vals, &bv, NULL );
748	if ( rc != LDAP_SUCCESS ) {
749		return -1;
750	}
751
752	rc = attr_merge_normalize( e, ad, bv, NULL );
753	slapi_ch_free( (void **)&bv );
754	if ( rc != LDAP_SUCCESS ) {
755		return -1;
756	}
757
758	return 0;
759}
760
761/*
762 * FIXME -- The caller must free the allocated memory.
763 * In Netscape they do not have to.
764 */
765int
766slapi_attr_get_values(
767	Slapi_Attr	*attr,
768	struct berval	***vals )
769{
770	int		i, j;
771	struct berval	**bv;
772
773	if ( attr == NULL ) {
774		return 1;
775	}
776
777	for ( i = 0; attr->a_vals[i].bv_val != NULL; i++ ) {
778		; /* EMPTY */
779	}
780
781	bv = (struct berval **)ch_malloc( (i + 1) * sizeof(struct berval *) );
782	for ( j = 0; j < i; j++ ) {
783		bv[j] = ber_dupbv( NULL, &attr->a_vals[j] );
784	}
785	bv[j] = NULL;
786
787	*vals = (struct berval **)bv;
788
789	return 0;
790}
791
792char *
793slapi_dn_normalize( char *dn )
794{
795	struct berval	bdn;
796	struct berval	pdn;
797
798	assert( dn != NULL );
799
800	bdn.bv_val = dn;
801	bdn.bv_len = strlen( dn );
802
803	if ( slapi_int_dn_pretty( &bdn, &pdn ) != LDAP_SUCCESS ) {
804		return NULL;
805	}
806
807	return pdn.bv_val;
808}
809
810char *
811slapi_dn_normalize_case( char *dn )
812{
813	struct berval	bdn;
814	struct berval	ndn;
815
816	assert( dn != NULL );
817
818	bdn.bv_val = dn;
819	bdn.bv_len = strlen( dn );
820
821	if ( slapi_int_dn_normalize( &bdn, &ndn ) != LDAP_SUCCESS ) {
822		return NULL;
823	}
824
825	return ndn.bv_val;
826}
827
828int
829slapi_dn_issuffix(
830	char		*dn,
831	char		*suffix )
832{
833	struct berval	bdn, ndn;
834	struct berval	bsuffix, nsuffix;
835	int rc;
836
837	assert( dn != NULL );
838	assert( suffix != NULL );
839
840	bdn.bv_val = dn;
841	bdn.bv_len = strlen( dn );
842
843	bsuffix.bv_val = suffix;
844	bsuffix.bv_len = strlen( suffix );
845
846	if ( dnNormalize( 0, NULL, NULL, &bdn, &ndn, NULL ) != LDAP_SUCCESS ) {
847		return 0;
848	}
849
850	if ( dnNormalize( 0, NULL, NULL, &bsuffix, &nsuffix, NULL )
851		!= LDAP_SUCCESS )
852	{
853		slapi_ch_free( (void **)&ndn.bv_val );
854		return 0;
855	}
856
857	rc = dnIsSuffix( &ndn, &nsuffix );
858
859	slapi_ch_free( (void **)&ndn.bv_val );
860	slapi_ch_free( (void **)&nsuffix.bv_val );
861
862	return rc;
863}
864
865int
866slapi_dn_isparent(
867	const char	*parentdn,
868	const char	*childdn )
869{
870	struct berval	assertedParentDN, normalizedAssertedParentDN;
871	struct berval	childDN, normalizedChildDN;
872	struct berval	normalizedParentDN;
873	int		match;
874
875	assert( parentdn != NULL );
876	assert( childdn != NULL );
877
878	assertedParentDN.bv_val = (char *)parentdn;
879	assertedParentDN.bv_len = strlen( parentdn );
880
881	if ( dnNormalize( 0, NULL, NULL, &assertedParentDN,
882		&normalizedAssertedParentDN, NULL ) != LDAP_SUCCESS )
883	{
884		return 0;
885	}
886
887	childDN.bv_val = (char *)childdn;
888	childDN.bv_len = strlen( childdn );
889
890	if ( dnNormalize( 0, NULL, NULL, &childDN,
891		&normalizedChildDN, NULL ) != LDAP_SUCCESS )
892	{
893		slapi_ch_free( (void **)&normalizedAssertedParentDN.bv_val );
894		return 0;
895	}
896
897	dnParent( &normalizedChildDN, &normalizedParentDN );
898
899	if ( dnMatch( &match, 0, slap_schema.si_syn_distinguishedName, NULL,
900		&normalizedParentDN, (void *)&normalizedAssertedParentDN ) != LDAP_SUCCESS )
901	{
902		match = -1;
903	}
904
905	slapi_ch_free( (void **)&normalizedAssertedParentDN.bv_val );
906	slapi_ch_free( (void **)&normalizedChildDN.bv_val );
907
908	return ( match == 0 );
909}
910
911/*
912 * Returns DN of the parent entry, or NULL if the DN is
913 * an empty string or NULL, or has no parent.
914 */
915char *
916slapi_dn_parent( const char *_dn )
917{
918	struct berval	dn, prettyDN;
919	struct berval	parentDN;
920	char		*ret;
921
922	if ( _dn == NULL ) {
923		return NULL;
924	}
925
926	dn.bv_val = (char *)_dn;
927	dn.bv_len = strlen( _dn );
928
929	if ( dn.bv_len == 0 ) {
930		return NULL;
931	}
932
933	if ( dnPretty( NULL, &dn, &prettyDN, NULL ) != LDAP_SUCCESS ) {
934		return NULL;
935	}
936
937	dnParent( &prettyDN, &parentDN ); /* in-place */
938
939	if ( parentDN.bv_len == 0 ) {
940		slapi_ch_free_string( &prettyDN.bv_val );
941		return NULL;
942	}
943
944	ret = slapi_ch_strdup( parentDN.bv_val );
945	slapi_ch_free_string( &prettyDN.bv_val );
946
947	return ret;
948}
949
950int slapi_dn_isbesuffix( Slapi_PBlock *pb, char *ldn )
951{
952	struct berval	ndn;
953	Backend		*be;
954
955	if ( slapi_is_rootdse( ldn ) ) {
956		return 0;
957	}
958
959	/* according to spec should already be normalized */
960	ndn.bv_len = strlen( ldn );
961	ndn.bv_val = ldn;
962
963	be = select_backend( &pb->pb_op->o_req_ndn, 0 );
964	if ( be == NULL ) {
965		return 0;
966	}
967
968	return be_issuffix( be, &ndn );
969}
970
971/*
972 * Returns DN of the parent entry; or NULL if the DN is
973 * an empty string, if the DN has no parent, or if the
974 * DN is the suffix of the backend database
975 */
976char *slapi_dn_beparent( Slapi_PBlock *pb, const char *ldn )
977{
978	Backend 	*be;
979	struct berval	dn, prettyDN;
980	struct berval	normalizedDN, parentDN;
981	char		*parent = NULL;
982
983	if ( pb == NULL ) {
984		return NULL;
985	}
986
987	PBLOCK_ASSERT_OP( pb, 0 );
988
989	if ( slapi_is_rootdse( ldn ) ) {
990		return NULL;
991	}
992
993	dn.bv_val = (char *)ldn;
994	dn.bv_len = strlen( ldn );
995
996	if ( dnPrettyNormal( NULL, &dn, &prettyDN, &normalizedDN, NULL ) != LDAP_SUCCESS ) {
997		return NULL;
998	}
999
1000	be = select_backend( &pb->pb_op->o_req_ndn, 0 );
1001
1002	if ( be == NULL || be_issuffix( be, &normalizedDN ) == 0 ) {
1003		dnParent( &prettyDN, &parentDN );
1004
1005		if ( parentDN.bv_len != 0 )
1006			parent = slapi_ch_strdup( parentDN.bv_val );
1007	}
1008
1009	slapi_ch_free_string( &prettyDN.bv_val );
1010	slapi_ch_free_string( &normalizedDN.bv_val );
1011
1012	return parent;
1013}
1014
1015char *
1016slapi_dn_ignore_case( char *dn )
1017{
1018	return slapi_dn_normalize_case( dn );
1019}
1020
1021char *
1022slapi_ch_malloc( unsigned long size )
1023{
1024	return ch_malloc( size );
1025}
1026
1027void
1028slapi_ch_free( void **ptr )
1029{
1030	if ( ptr == NULL || *ptr == NULL )
1031		return;
1032	ch_free( *ptr );
1033	*ptr = NULL;
1034}
1035
1036void
1037slapi_ch_free_string( char **ptr )
1038{
1039	slapi_ch_free( (void **)ptr );
1040}
1041
1042void
1043slapi_ch_array_free( char **arrayp )
1044{
1045	char **p;
1046
1047	if ( arrayp != NULL ) {
1048		for ( p = arrayp; *p != NULL; p++ ) {
1049			slapi_ch_free( (void **)p );
1050		}
1051		slapi_ch_free( (void **)&arrayp );
1052	}
1053}
1054
1055struct berval *
1056slapi_ch_bvdup(const struct berval *v)
1057{
1058	return ber_dupbv(NULL, (struct berval *)v);
1059}
1060
1061struct berval **
1062slapi_ch_bvecdup(const struct berval **v)
1063{
1064	int i;
1065	struct berval **rv;
1066
1067	if ( v == NULL ) {
1068		return NULL;
1069	}
1070
1071	for ( i = 0; v[i] != NULL; i++ )
1072		;
1073
1074	rv = (struct berval **) slapi_ch_malloc( (i + 1) * sizeof(struct berval *) );
1075
1076	for ( i = 0; v[i] != NULL; i++ ) {
1077		rv[i] = slapi_ch_bvdup( v[i] );
1078	}
1079	rv[i] = NULL;
1080
1081	return rv;
1082}
1083
1084char *
1085slapi_ch_calloc(
1086	unsigned long nelem,
1087	unsigned long size )
1088{
1089	return ch_calloc( nelem, size );
1090}
1091
1092char *
1093slapi_ch_realloc(
1094	char *block,
1095	unsigned long size )
1096{
1097	return ch_realloc( block, size );
1098}
1099
1100char *
1101slapi_ch_strdup( const char *s )
1102{
1103	return ch_strdup( s );
1104}
1105
1106size_t
1107slapi_ch_stlen( const char *s )
1108{
1109	return strlen( s );
1110}
1111
1112int
1113slapi_control_present(
1114	LDAPControl	**controls,
1115	char		*oid,
1116	struct berval	**val,
1117	int		*iscritical )
1118{
1119	int		i;
1120	int		rc = 0;
1121
1122	if ( val ) {
1123		*val = NULL;
1124	}
1125
1126	if ( iscritical ) {
1127		*iscritical = 0;
1128	}
1129
1130	for ( i = 0; controls != NULL && controls[i] != NULL; i++ ) {
1131		if ( strcmp( controls[i]->ldctl_oid, oid ) != 0 ) {
1132			continue;
1133		}
1134
1135		rc = 1;
1136		if ( controls[i]->ldctl_value.bv_len != 0 ) {
1137			if ( val ) {
1138				*val = &controls[i]->ldctl_value;
1139			}
1140		}
1141
1142		if ( iscritical ) {
1143			*iscritical = controls[i]->ldctl_iscritical;
1144		}
1145
1146		break;
1147	}
1148
1149	return rc;
1150}
1151
1152static void
1153slapControlMask2SlapiControlOp(slap_mask_t slap_mask,
1154	unsigned long *slapi_mask)
1155{
1156	*slapi_mask = SLAPI_OPERATION_NONE;
1157
1158	if ( slap_mask & SLAP_CTRL_ABANDON )
1159		*slapi_mask |= SLAPI_OPERATION_ABANDON;
1160
1161	if ( slap_mask & SLAP_CTRL_ADD )
1162		*slapi_mask |= SLAPI_OPERATION_ADD;
1163
1164	if ( slap_mask & SLAP_CTRL_BIND )
1165		*slapi_mask |= SLAPI_OPERATION_BIND;
1166
1167	if ( slap_mask & SLAP_CTRL_COMPARE )
1168		*slapi_mask |= SLAPI_OPERATION_COMPARE;
1169
1170	if ( slap_mask & SLAP_CTRL_DELETE )
1171		*slapi_mask |= SLAPI_OPERATION_DELETE;
1172
1173	if ( slap_mask & SLAP_CTRL_MODIFY )
1174		*slapi_mask |= SLAPI_OPERATION_MODIFY;
1175
1176	if ( slap_mask & SLAP_CTRL_RENAME )
1177		*slapi_mask |= SLAPI_OPERATION_MODDN;
1178
1179	if ( slap_mask & SLAP_CTRL_SEARCH )
1180		*slapi_mask |= SLAPI_OPERATION_SEARCH;
1181
1182	if ( slap_mask & SLAP_CTRL_UNBIND )
1183		*slapi_mask |= SLAPI_OPERATION_UNBIND;
1184}
1185
1186static void
1187slapiControlOp2SlapControlMask(unsigned long slapi_mask,
1188	slap_mask_t *slap_mask)
1189{
1190	*slap_mask = 0;
1191
1192	if ( slapi_mask & SLAPI_OPERATION_BIND )
1193		*slap_mask |= SLAP_CTRL_BIND;
1194
1195	if ( slapi_mask & SLAPI_OPERATION_UNBIND )
1196		*slap_mask |= SLAP_CTRL_UNBIND;
1197
1198	if ( slapi_mask & SLAPI_OPERATION_SEARCH )
1199		*slap_mask |= SLAP_CTRL_SEARCH;
1200
1201	if ( slapi_mask & SLAPI_OPERATION_MODIFY )
1202		*slap_mask |= SLAP_CTRL_MODIFY;
1203
1204	if ( slapi_mask & SLAPI_OPERATION_ADD )
1205		*slap_mask |= SLAP_CTRL_ADD;
1206
1207	if ( slapi_mask & SLAPI_OPERATION_DELETE )
1208		*slap_mask |= SLAP_CTRL_DELETE;
1209
1210	if ( slapi_mask & SLAPI_OPERATION_MODDN )
1211		*slap_mask |= SLAP_CTRL_RENAME;
1212
1213	if ( slapi_mask & SLAPI_OPERATION_COMPARE )
1214		*slap_mask |= SLAP_CTRL_COMPARE;
1215
1216	if ( slapi_mask & SLAPI_OPERATION_ABANDON )
1217		*slap_mask |= SLAP_CTRL_ABANDON;
1218
1219	*slap_mask |= SLAP_CTRL_GLOBAL;
1220}
1221
1222static int
1223slapi_int_parse_control(
1224	Operation *op,
1225	SlapReply *rs,
1226	LDAPControl *ctrl )
1227{
1228	/* Plugins must deal with controls themselves. */
1229
1230	return LDAP_SUCCESS;
1231}
1232
1233void
1234slapi_register_supported_control(
1235	char		*controloid,
1236	unsigned long	controlops )
1237{
1238	slap_mask_t controlmask;
1239
1240	slapiControlOp2SlapControlMask( controlops, &controlmask );
1241
1242	register_supported_control( controloid, controlmask, NULL, slapi_int_parse_control, NULL );
1243}
1244
1245int
1246slapi_get_supported_controls(
1247	char		***ctrloidsp,
1248	unsigned long	**ctrlopsp )
1249{
1250	int i, rc;
1251
1252	rc = get_supported_controls( ctrloidsp, (slap_mask_t **)ctrlopsp );
1253	if ( rc != LDAP_SUCCESS ) {
1254		return rc;
1255	}
1256
1257	for ( i = 0; (*ctrloidsp)[i] != NULL; i++ ) {
1258		/* In place, naughty. */
1259		slapControlMask2SlapiControlOp( (*ctrlopsp)[i], &((*ctrlopsp)[i]) );
1260	}
1261
1262	return LDAP_SUCCESS;
1263}
1264
1265LDAPControl *
1266slapi_dup_control( LDAPControl *ctrl )
1267{
1268	LDAPControl *ret;
1269
1270	ret = (LDAPControl *)slapi_ch_malloc( sizeof(*ret) );
1271	ret->ldctl_oid = slapi_ch_strdup( ctrl->ldctl_oid );
1272	ber_dupbv( &ret->ldctl_value, &ctrl->ldctl_value );
1273	ret->ldctl_iscritical = ctrl->ldctl_iscritical;
1274
1275	return ret;
1276}
1277
1278void
1279slapi_register_supported_saslmechanism( char *mechanism )
1280{
1281	/* FIXME -- can not add saslmechanism to OpenLDAP dynamically */
1282	slapi_log_error( SLAPI_LOG_FATAL, "slapi_register_supported_saslmechanism",
1283			"OpenLDAP does not support dynamic registration of SASL mechanisms\n" );
1284}
1285
1286char **
1287slapi_get_supported_saslmechanisms( void )
1288{
1289	/* FIXME -- can not get the saslmechanism without a connection. */
1290	slapi_log_error( SLAPI_LOG_FATAL, "slapi_get_supported_saslmechanisms",
1291			"can not get the SASL mechanism list "
1292			"without a connection\n" );
1293	return NULL;
1294}
1295
1296char **
1297slapi_get_supported_extended_ops( void )
1298{
1299	int		i, j, k;
1300	char		**ppExtOpOID = NULL;
1301	int		numExtOps = 0;
1302
1303	for ( i = 0; get_supported_extop( i ) != NULL; i++ ) {
1304		;
1305	}
1306
1307	for ( j = 0; slapi_int_get_supported_extop( j ) != NULL; j++ ) {
1308		;
1309	}
1310
1311	numExtOps = i + j;
1312	if ( numExtOps == 0 ) {
1313		return NULL;
1314	}
1315
1316	ppExtOpOID = (char **)slapi_ch_malloc( (numExtOps + 1) * sizeof(char *) );
1317	for ( k = 0; k < i; k++ ) {
1318		struct berval	*bv;
1319
1320		bv = get_supported_extop( k );
1321		assert( bv != NULL );
1322
1323		ppExtOpOID[ k ] = bv->bv_val;
1324	}
1325
1326	for ( ; k < j; k++ ) {
1327		struct berval	*bv;
1328
1329		bv = slapi_int_get_supported_extop( k );
1330		assert( bv != NULL );
1331
1332		ppExtOpOID[ i + k ] = bv->bv_val;
1333	}
1334	ppExtOpOID[ i + k ] = NULL;
1335
1336	return ppExtOpOID;
1337}
1338
1339void
1340slapi_send_ldap_result(
1341	Slapi_PBlock	*pb,
1342	int		err,
1343	char		*matched,
1344	char		*text,
1345	int		nentries,
1346	struct berval	**urls )
1347{
1348	SlapReply	*rs;
1349
1350	PBLOCK_ASSERT_OP( pb, 0 );
1351
1352	rs = pb->pb_rs;
1353
1354	rs->sr_err = err;
1355	rs->sr_matched = matched;
1356	rs->sr_text = text;
1357	rs->sr_ref = NULL;
1358
1359	if ( err == LDAP_SASL_BIND_IN_PROGRESS ) {
1360		send_ldap_sasl( pb->pb_op, rs );
1361	} else if ( rs->sr_rspoid != NULL ) {
1362		send_ldap_extended( pb->pb_op, rs );
1363	} else {
1364		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
1365			rs->sr_nentries = nentries;
1366		if ( urls != NULL )
1367			bvptr2obj( urls, &rs->sr_ref, NULL );
1368
1369		send_ldap_result( pb->pb_op, rs );
1370
1371		if ( urls != NULL )
1372			slapi_ch_free( (void **)&rs->sr_ref );
1373	}
1374}
1375
1376int
1377slapi_send_ldap_search_entry(
1378	Slapi_PBlock	*pb,
1379	Slapi_Entry	*e,
1380	LDAPControl	**ectrls,
1381	char		**attrs,
1382	int		attrsonly )
1383{
1384	SlapReply		rs = { REP_SEARCH };
1385	int			i = 0, j = 0;
1386	AttributeName		*an = NULL;
1387	const char		*text;
1388	int			rc;
1389
1390	assert( pb->pb_op != NULL );
1391
1392	if ( attrs != NULL ) {
1393		for ( i = 0; attrs[ i ] != NULL; i++ ) {
1394			; /* empty */
1395		}
1396	}
1397
1398	if ( i ) {
1399		an = (AttributeName *) slapi_ch_calloc( i + 1, sizeof(AttributeName) );
1400		for ( i = 0; attrs[i] != NULL; i++ ) {
1401			an[j].an_name.bv_val = attrs[i];
1402			an[j].an_name.bv_len = strlen( attrs[i] );
1403			an[j].an_desc = NULL;
1404			if ( slap_bv2ad( &an[j].an_name, &an[j].an_desc, &text ) == LDAP_SUCCESS) {
1405				j++;
1406			}
1407		}
1408		an[j].an_name.bv_len = 0;
1409		an[j].an_name.bv_val = NULL;
1410	}
1411
1412	rs.sr_err = LDAP_SUCCESS;
1413	rs.sr_matched = NULL;
1414	rs.sr_text = NULL;
1415	rs.sr_ref = NULL;
1416	rs.sr_ctrls = ectrls;
1417	rs.sr_attrs = an;
1418	rs.sr_operational_attrs = NULL;
1419	rs.sr_entry = e;
1420	rs.sr_v2ref = NULL;
1421	rs.sr_flags = 0;
1422
1423	rc = send_search_entry( pb->pb_op, &rs );
1424
1425	slapi_ch_free( (void **)&an );
1426
1427	return rc;
1428}
1429
1430int
1431slapi_send_ldap_search_reference(
1432	Slapi_PBlock	*pb,
1433	Slapi_Entry	*e,
1434	struct berval	**references,
1435	LDAPControl	**ectrls,
1436	struct berval	**v2refs
1437	)
1438{
1439	SlapReply	rs = { REP_SEARCHREF };
1440	int		rc;
1441
1442	rs.sr_err = LDAP_SUCCESS;
1443	rs.sr_matched = NULL;
1444	rs.sr_text = NULL;
1445
1446	rc = bvptr2obj( references, &rs.sr_ref, NULL );
1447	if ( rc != LDAP_SUCCESS ) {
1448		return rc;
1449	}
1450
1451	rs.sr_ctrls = ectrls;
1452	rs.sr_attrs = NULL;
1453	rs.sr_operational_attrs = NULL;
1454	rs.sr_entry = e;
1455
1456	if ( v2refs != NULL ) {
1457		rc = bvptr2obj( v2refs, &rs.sr_v2ref, NULL );
1458		if ( rc != LDAP_SUCCESS ) {
1459			slapi_ch_free( (void **)&rs.sr_ref );
1460			return rc;
1461		}
1462	} else {
1463		rs.sr_v2ref = NULL;
1464	}
1465
1466	rc = send_search_reference( pb->pb_op, &rs );
1467
1468	slapi_ch_free( (void **)&rs.sr_ref );
1469	slapi_ch_free( (void **)&rs.sr_v2ref );
1470
1471	return rc;
1472}
1473
1474Slapi_Filter *
1475slapi_str2filter( char *str )
1476{
1477	return str2filter( str );
1478}
1479
1480void
1481slapi_filter_free(
1482	Slapi_Filter	*f,
1483	int		recurse )
1484{
1485	filter_free( f );
1486}
1487
1488Slapi_Filter *
1489slapi_filter_dup( Slapi_Filter *filter )
1490{
1491	return filter_dup( filter, NULL );
1492}
1493
1494int
1495slapi_filter_get_choice( Slapi_Filter *f )
1496{
1497	int		rc;
1498
1499	if ( f != NULL ) {
1500		rc = f->f_choice;
1501	} else {
1502		rc = 0;
1503	}
1504
1505	return rc;
1506}
1507
1508int
1509slapi_filter_get_ava(
1510	Slapi_Filter	*f,
1511	char		**type,
1512	struct berval	**bval )
1513{
1514	int		ftype;
1515	int		rc = LDAP_SUCCESS;
1516
1517	assert( type != NULL );
1518	assert( bval != NULL );
1519
1520	*type = NULL;
1521	*bval = NULL;
1522
1523	ftype = f->f_choice;
1524	if ( ftype == LDAP_FILTER_EQUALITY
1525			|| ftype ==  LDAP_FILTER_GE
1526			|| ftype == LDAP_FILTER_LE
1527			|| ftype == LDAP_FILTER_APPROX ) {
1528		/*
1529		 * According to the SLAPI Reference Manual these are
1530		 * not duplicated.
1531		 */
1532		*type = f->f_un.f_un_ava->aa_desc->ad_cname.bv_val;
1533		*bval = &f->f_un.f_un_ava->aa_value;
1534	} else { /* filter type not supported */
1535		rc = -1;
1536	}
1537
1538	return rc;
1539}
1540
1541Slapi_Filter *
1542slapi_filter_list_first( Slapi_Filter *f )
1543{
1544	int		ftype;
1545
1546	if ( f == NULL ) {
1547		return NULL;
1548	}
1549
1550	ftype = f->f_choice;
1551	if ( ftype == LDAP_FILTER_AND
1552			|| ftype == LDAP_FILTER_OR
1553			|| ftype == LDAP_FILTER_NOT ) {
1554		return (Slapi_Filter *)f->f_list;
1555	} else {
1556		return NULL;
1557	}
1558}
1559
1560Slapi_Filter *
1561slapi_filter_list_next(
1562	Slapi_Filter	*f,
1563	Slapi_Filter	*fprev )
1564{
1565	int		ftype;
1566
1567	if ( f == NULL ) {
1568		return NULL;
1569	}
1570
1571	ftype = f->f_choice;
1572	if ( ftype == LDAP_FILTER_AND
1573			|| ftype == LDAP_FILTER_OR
1574			|| ftype == LDAP_FILTER_NOT )
1575	{
1576		return fprev->f_next;
1577	}
1578
1579	return NULL;
1580}
1581
1582int
1583slapi_filter_get_attribute_type( Slapi_Filter *f, char **type )
1584{
1585	if ( f == NULL ) {
1586		return -1;
1587	}
1588
1589	switch ( f->f_choice ) {
1590	case LDAP_FILTER_GE:
1591	case LDAP_FILTER_LE:
1592	case LDAP_FILTER_EQUALITY:
1593	case LDAP_FILTER_APPROX:
1594		*type = f->f_av_desc->ad_cname.bv_val;
1595		break;
1596	case LDAP_FILTER_SUBSTRINGS:
1597		*type = f->f_sub_desc->ad_cname.bv_val;
1598		break;
1599	case LDAP_FILTER_PRESENT:
1600		*type = f->f_desc->ad_cname.bv_val;
1601		break;
1602	case LDAP_FILTER_EXT:
1603		*type = f->f_mr_desc->ad_cname.bv_val;
1604		break;
1605	default:
1606		/* Complex filters need not apply. */
1607		*type = NULL;
1608		return -1;
1609	}
1610
1611	return 0;
1612}
1613
1614int
1615slapi_x_filter_set_attribute_type( Slapi_Filter *f, const char *type )
1616{
1617	AttributeDescription **adp, *ad = NULL;
1618	const char *text;
1619	int rc;
1620
1621	if ( f == NULL ) {
1622		return -1;
1623	}
1624
1625	switch ( f->f_choice ) {
1626	case LDAP_FILTER_GE:
1627	case LDAP_FILTER_LE:
1628	case LDAP_FILTER_EQUALITY:
1629	case LDAP_FILTER_APPROX:
1630		adp = &f->f_av_desc;
1631		break;
1632	case LDAP_FILTER_SUBSTRINGS:
1633		adp = &f->f_sub_desc;
1634		break;
1635	case LDAP_FILTER_PRESENT:
1636		adp = &f->f_desc;
1637		break;
1638	case LDAP_FILTER_EXT:
1639		adp = &f->f_mr_desc;
1640		break;
1641	default:
1642		/* Complex filters need not apply. */
1643		return -1;
1644	}
1645
1646	rc = slap_str2ad( type, &ad, &text );
1647	if ( rc == LDAP_SUCCESS )
1648		*adp = ad;
1649
1650	return ( rc == LDAP_SUCCESS ) ? 0 : -1;
1651}
1652
1653int
1654slapi_filter_get_subfilt( Slapi_Filter *f, char **type, char **initial,
1655	char ***any, char **final )
1656{
1657	int i;
1658
1659	if ( f->f_choice != LDAP_FILTER_SUBSTRINGS ) {
1660		return -1;
1661	}
1662
1663	/*
1664	 * The caller shouldn't free but we can't return an
1665	 * array of char *s from an array of bervals without
1666	 * allocating memory, so we may as well be consistent.
1667	 * XXX
1668	 */
1669	*type = f->f_sub_desc->ad_cname.bv_val;
1670	*initial = f->f_sub_initial.bv_val ? slapi_ch_strdup(f->f_sub_initial.bv_val) : NULL;
1671	if ( f->f_sub_any != NULL ) {
1672		for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ )
1673			;
1674		*any = (char **)slapi_ch_malloc( (i + 1) * sizeof(char *) );
1675		for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
1676			(*any)[i] = slapi_ch_strdup(f->f_sub_any[i].bv_val);
1677		}
1678		(*any)[i] = NULL;
1679	} else {
1680		*any = NULL;
1681	}
1682	*final = f->f_sub_final.bv_val ? slapi_ch_strdup(f->f_sub_final.bv_val) : NULL;
1683
1684	return 0;
1685}
1686
1687Slapi_Filter *
1688slapi_filter_join( int ftype, Slapi_Filter *f1, Slapi_Filter *f2 )
1689{
1690	Slapi_Filter *f = NULL;
1691
1692	if ( ftype == LDAP_FILTER_AND ||
1693	     ftype == LDAP_FILTER_OR ||
1694	     ftype == LDAP_FILTER_NOT )
1695	{
1696		f = (Slapi_Filter *)slapi_ch_malloc( sizeof(*f) );
1697		f->f_choice = ftype;
1698		f->f_list = f1;
1699		f->f_list->f_next = f2;
1700		f->f_next = NULL;
1701	}
1702
1703	return f;
1704}
1705
1706int
1707slapi_x_filter_append( int ftype,
1708	Slapi_Filter **pContainingFilter, /* NULL on first call */
1709	Slapi_Filter **pNextFilter,
1710	Slapi_Filter *filterToAppend )
1711{
1712	if ( ftype == LDAP_FILTER_AND ||
1713	     ftype == LDAP_FILTER_OR ||
1714	     ftype == LDAP_FILTER_NOT )
1715	{
1716		if ( *pContainingFilter == NULL ) {
1717			*pContainingFilter = (Slapi_Filter *)slapi_ch_malloc( sizeof(Slapi_Filter) );
1718			(*pContainingFilter)->f_choice = ftype;
1719			(*pContainingFilter)->f_list = filterToAppend;
1720			(*pContainingFilter)->f_next = NULL;
1721		} else {
1722			if ( (*pContainingFilter)->f_choice != ftype ) {
1723				/* Sanity check */
1724				return -1;
1725			}
1726			(*pNextFilter)->f_next = filterToAppend;
1727		}
1728		*pNextFilter = filterToAppend;
1729
1730		return 0;
1731	}
1732	return -1;
1733}
1734
1735int
1736slapi_filter_test( Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Filter *f,
1737	int verify_access )
1738{
1739	Operation *op;
1740	int rc;
1741
1742	if ( f == NULL ) {
1743		/* spec says return zero if no filter. */
1744		return 0;
1745	}
1746
1747	if ( verify_access ) {
1748		op = pb->pb_op;
1749		if ( op == NULL )
1750			return LDAP_PARAM_ERROR;
1751	} else {
1752		op = NULL;
1753	}
1754
1755	/*
1756	 * According to acl.c it is safe to call test_filter() with
1757	 * NULL arguments...
1758	 */
1759	rc = test_filter( op, e, f );
1760	switch (rc) {
1761	case LDAP_COMPARE_TRUE:
1762		rc = 0;
1763		break;
1764	case LDAP_COMPARE_FALSE:
1765		break;
1766	case SLAPD_COMPARE_UNDEFINED:
1767		rc = LDAP_OTHER;
1768		break;
1769	case LDAP_PROTOCOL_ERROR:
1770		/* filter type unknown: spec says return -1 */
1771		rc = -1;
1772		break;
1773	}
1774
1775	return rc;
1776}
1777
1778int
1779slapi_filter_test_simple( Slapi_Entry *e, Slapi_Filter *f)
1780{
1781	return slapi_filter_test( NULL, e, f, 0 );
1782}
1783
1784int
1785slapi_filter_apply( Slapi_Filter *f, FILTER_APPLY_FN fn, void *arg, int *error_code )
1786{
1787	switch ( f->f_choice ) {
1788	case LDAP_FILTER_AND:
1789	case LDAP_FILTER_NOT:
1790	case LDAP_FILTER_OR: {
1791		int rc;
1792
1793		/*
1794		 * FIXME: altering f; should we use a temporary?
1795		 */
1796		for ( f = f->f_list; f != NULL; f = f->f_next ) {
1797			rc = slapi_filter_apply( f, fn, arg, error_code );
1798			if ( rc != 0 ) {
1799				return rc;
1800			}
1801			if ( *error_code == SLAPI_FILTER_SCAN_NOMORE ) {
1802				break;
1803			}
1804		}
1805		break;
1806	}
1807	case LDAP_FILTER_EQUALITY:
1808	case LDAP_FILTER_SUBSTRINGS:
1809	case LDAP_FILTER_GE:
1810	case LDAP_FILTER_LE:
1811	case LDAP_FILTER_PRESENT:
1812	case LDAP_FILTER_APPROX:
1813	case LDAP_FILTER_EXT:
1814		*error_code = fn( f, arg );
1815		break;
1816	default:
1817		*error_code = SLAPI_FILTER_UNKNOWN_FILTER_TYPE;
1818	}
1819
1820	if ( *error_code == SLAPI_FILTER_SCAN_NOMORE ||
1821	     *error_code == SLAPI_FILTER_SCAN_CONTINUE ) {
1822		return 0;
1823	}
1824
1825	return -1;
1826}
1827
1828int
1829slapi_pw_find(
1830	struct berval	**vals,
1831	struct berval	*v )
1832{
1833	int i;
1834
1835	if( ( vals == NULL ) || ( v == NULL ) )
1836		return 1;
1837
1838	for ( i = 0; vals[i] != NULL; i++ ) {
1839		if ( !lutil_passwd( vals[i], v, NULL, NULL ) )
1840			return 0;
1841	}
1842
1843	return 1;
1844}
1845
1846#define MAX_HOSTNAME 512
1847
1848char *
1849slapi_get_hostname( void )
1850{
1851	char		*hn = NULL;
1852	static int	been_here = 0;
1853	static char	*static_hn = NULL;
1854
1855	ldap_pvt_thread_mutex_lock( &slapi_hn_mutex );
1856	if ( !been_here ) {
1857		static_hn = (char *)slapi_ch_malloc( MAX_HOSTNAME );
1858		if ( static_hn == NULL) {
1859			slapi_log_error( SLAPI_LOG_FATAL, "slapi_get_hostname",
1860					"Cannot allocate memory for hostname\n" );
1861			static_hn = NULL;
1862			ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex );
1863
1864			return hn;
1865
1866		} else {
1867			if ( gethostname( static_hn, MAX_HOSTNAME ) != 0 ) {
1868				slapi_log_error( SLAPI_LOG_FATAL,
1869						"SLAPI",
1870						"can't get hostname\n" );
1871				slapi_ch_free( (void **)&static_hn );
1872				static_hn = NULL;
1873				ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex );
1874
1875				return hn;
1876
1877			} else {
1878				been_here = 1;
1879			}
1880		}
1881	}
1882	ldap_pvt_thread_mutex_unlock( &slapi_hn_mutex );
1883
1884	hn = ch_strdup( static_hn );
1885
1886	return hn;
1887}
1888
1889/*
1890 * FIXME: this should go in an appropriate header ...
1891 */
1892extern int slapi_int_log_error( int level, char *subsystem, char *fmt, va_list arglist );
1893
1894int
1895slapi_log_error(
1896	int		severity,
1897	char		*subsystem,
1898	char		*fmt,
1899	... )
1900{
1901	int		rc = LDAP_SUCCESS;
1902	va_list		arglist;
1903
1904	va_start( arglist, fmt );
1905	rc = slapi_int_log_error( severity, subsystem, fmt, arglist );
1906	va_end( arglist );
1907
1908	return rc;
1909}
1910
1911
1912unsigned long
1913slapi_timer_current_time( void )
1914{
1915	static int	first_time = 1;
1916#if !defined (_WIN32)
1917	struct timeval	now;
1918	unsigned long	ret;
1919
1920	ldap_pvt_thread_mutex_lock( &slapi_time_mutex );
1921	if (first_time) {
1922		first_time = 0;
1923		gettimeofday( &base_time, NULL );
1924	}
1925	gettimeofday( &now, NULL );
1926	ret = ( now.tv_sec  - base_time.tv_sec ) * 1000000 +
1927			(now.tv_usec - base_time.tv_usec);
1928	ldap_pvt_thread_mutex_unlock( &slapi_time_mutex );
1929
1930	return ret;
1931
1932	/*
1933	 * Ain't it better?
1934	return (slap_get_time() - starttime) * 1000000;
1935	 */
1936#else /* _WIN32 */
1937	LARGE_INTEGER now;
1938
1939	if ( first_time ) {
1940		first_time = 0;
1941		performance_counter_present = QueryPerformanceCounter( &base_time );
1942		QueryPerformanceFrequency( &performance_freq );
1943	}
1944
1945	if ( !performance_counter_present )
1946	     return 0;
1947
1948	QueryPerformanceCounter( &now );
1949	return (1000000*(now.QuadPart-base_time.QuadPart))/performance_freq.QuadPart;
1950#endif /* _WIN32 */
1951}
1952
1953/*
1954 * FIXME ?
1955 */
1956unsigned long
1957slapi_timer_get_time( char *label )
1958{
1959	unsigned long start = slapi_timer_current_time();
1960	printf("%10ld %10d usec %s\n", start, 0, label);
1961	return start;
1962}
1963
1964/*
1965 * FIXME ?
1966 */
1967void
1968slapi_timer_elapsed_time(
1969	char *label,
1970	unsigned long start )
1971{
1972	unsigned long stop = slapi_timer_current_time();
1973	printf ("%10ld %10ld usec %s\n", stop, stop - start, label);
1974}
1975
1976void
1977slapi_free_search_results_internal( Slapi_PBlock *pb )
1978{
1979	Slapi_Entry	**entries;
1980	int		k = 0, nEnt = 0;
1981
1982	slapi_pblock_get( pb, SLAPI_NENTRIES, &nEnt );
1983	slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries );
1984	if ( nEnt == 0 || entries == NULL ) {
1985		return;
1986	}
1987
1988	for ( k = 0; k < nEnt; k++ ) {
1989		slapi_entry_free( entries[k] );
1990		entries[k] = NULL;
1991	}
1992
1993	slapi_ch_free( (void **)&entries );
1994}
1995
1996int slapi_is_connection_ssl( Slapi_PBlock *pb, int *isSSL )
1997{
1998	if ( pb == NULL )
1999		return LDAP_PARAM_ERROR;
2000
2001	if ( pb->pb_conn == NULL )
2002		return LDAP_PARAM_ERROR;
2003
2004#ifdef HAVE_TLS
2005	*isSSL = pb->pb_conn->c_is_tls;
2006#else
2007	*isSSL = 0;
2008#endif
2009
2010	return LDAP_SUCCESS;
2011}
2012
2013/*
2014 * DS 5.x compatability API follow
2015 */
2016
2017int slapi_attr_get_flags( const Slapi_Attr *attr, unsigned long *flags )
2018{
2019	AttributeType *at;
2020
2021	if ( attr == NULL )
2022		return LDAP_PARAM_ERROR;
2023
2024	at = attr->a_desc->ad_type;
2025
2026	*flags = SLAPI_ATTR_FLAG_STD_ATTR;
2027
2028	if ( is_at_single_value( at ) )
2029		*flags |= SLAPI_ATTR_FLAG_SINGLE;
2030	if ( is_at_operational( at ) )
2031		*flags |= SLAPI_ATTR_FLAG_OPATTR;
2032	if ( is_at_obsolete( at ) )
2033		*flags |= SLAPI_ATTR_FLAG_OBSOLETE;
2034	if ( is_at_collective( at ) )
2035		*flags |= SLAPI_ATTR_FLAG_COLLECTIVE;
2036	if ( is_at_no_user_mod( at ) )
2037		*flags |= SLAPI_ATTR_FLAG_NOUSERMOD;
2038
2039	return LDAP_SUCCESS;
2040}
2041
2042int slapi_attr_flag_is_set( const Slapi_Attr *attr, unsigned long flag )
2043{
2044	unsigned long flags;
2045
2046	if ( slapi_attr_get_flags( attr, &flags ) != 0 )
2047		return 0;
2048	return (flags & flag) ? 1 : 0;
2049}
2050
2051Slapi_Attr *slapi_attr_new( void )
2052{
2053	Attribute *ad;
2054
2055	ad = (Attribute  *)slapi_ch_calloc( 1, sizeof(*ad) );
2056
2057	return ad;
2058}
2059
2060Slapi_Attr *slapi_attr_init( Slapi_Attr *a, const char *type )
2061{
2062	const char *text;
2063	AttributeDescription *ad = NULL;
2064
2065	if( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
2066		return NULL;
2067	}
2068
2069	a->a_desc = ad;
2070	a->a_vals = NULL;
2071	a->a_nvals = NULL;
2072	a->a_next = NULL;
2073	a->a_flags = 0;
2074
2075	return a;
2076}
2077
2078void slapi_attr_free( Slapi_Attr **a )
2079{
2080	attr_free( *a );
2081	*a = NULL;
2082}
2083
2084Slapi_Attr *slapi_attr_dup( const Slapi_Attr *attr )
2085{
2086	return attr_dup( (Slapi_Attr *)attr );
2087}
2088
2089int slapi_attr_add_value( Slapi_Attr *a, const Slapi_Value *v )
2090{
2091	struct berval nval;
2092	struct berval *nvalp;
2093	int rc;
2094	AttributeDescription *desc = a->a_desc;
2095
2096	if ( desc->ad_type->sat_equality &&
2097	     desc->ad_type->sat_equality->smr_normalize ) {
2098		rc = (*desc->ad_type->sat_equality->smr_normalize)(
2099			SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
2100			desc->ad_type->sat_syntax,
2101			desc->ad_type->sat_equality,
2102			(Slapi_Value *)v, &nval, NULL );
2103		if ( rc != LDAP_SUCCESS ) {
2104			return rc;
2105		}
2106		nvalp = &nval;
2107	} else {
2108		nvalp = NULL;
2109	}
2110
2111	rc = attr_valadd( a, (Slapi_Value *)v, nvalp, 1 );
2112
2113	if ( nvalp != NULL ) {
2114		slapi_ch_free_string( &nval.bv_val );
2115	}
2116
2117	return rc;
2118}
2119
2120int slapi_attr_type2plugin( const char *type, void **pi )
2121{
2122	*pi = NULL;
2123
2124	return LDAP_OTHER;
2125}
2126
2127int slapi_attr_get_type( const Slapi_Attr *attr, char **type )
2128{
2129	if ( attr == NULL ) {
2130		return LDAP_PARAM_ERROR;
2131	}
2132
2133	*type = attr->a_desc->ad_cname.bv_val;
2134
2135	return LDAP_SUCCESS;
2136}
2137
2138int slapi_attr_get_oid_copy( const Slapi_Attr *attr, char **oidp )
2139{
2140	if ( attr == NULL ) {
2141		return LDAP_PARAM_ERROR;
2142	}
2143	*oidp = attr->a_desc->ad_type->sat_oid;
2144
2145	return LDAP_SUCCESS;
2146}
2147
2148int slapi_attr_value_cmp( const Slapi_Attr *a, const struct berval *v1, const struct berval *v2 )
2149{
2150	MatchingRule *mr;
2151	int ret;
2152	int rc;
2153	const char *text;
2154
2155	mr = a->a_desc->ad_type->sat_equality;
2156	rc = value_match( &ret, a->a_desc, mr,
2157			SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
2158		(struct berval *)v1, (void *)v2, &text );
2159	if ( rc != LDAP_SUCCESS )
2160		return -1;
2161
2162	return ( ret == 0 ) ? 0 : -1;
2163}
2164
2165int slapi_attr_value_find( const Slapi_Attr *a, struct berval *v )
2166{
2167	int rc;
2168
2169	if ( a ->a_vals == NULL ) {
2170		return -1;
2171	}
2172	rc = attr_valfind( (Attribute *)a, SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, v,
2173		NULL, NULL );
2174	return rc == 0 ? 0 : -1;
2175}
2176
2177int slapi_attr_type_cmp( const char *t1, const char *t2, int opt )
2178{
2179	AttributeDescription *a1 = NULL;
2180	AttributeDescription *a2 = NULL;
2181	const char *text;
2182	int ret;
2183
2184	if ( slap_str2ad( t1, &a1, &text ) != LDAP_SUCCESS ) {
2185		return -1;
2186	}
2187
2188	if ( slap_str2ad( t2, &a2, &text ) != LDAP_SUCCESS ) {
2189		return 1;
2190	}
2191
2192#define ad_base_cmp(l,r) (((l)->ad_type->sat_cname.bv_len < (r)->ad_type->sat_cname.bv_len) \
2193	? -1 : (((l)->ad_type->sat_cname.bv_len > (r)->ad_type->sat_cname.bv_len) \
2194		? 1 : strcasecmp((l)->ad_type->sat_cname.bv_val, (r)->ad_type->sat_cname.bv_val )))
2195
2196	switch ( opt ) {
2197	case SLAPI_TYPE_CMP_EXACT:
2198		ret = ad_cmp( a1, a2 );
2199		break;
2200	case SLAPI_TYPE_CMP_BASE:
2201		ret = ad_base_cmp( a1, a2 );
2202		break;
2203	case SLAPI_TYPE_CMP_SUBTYPE:
2204		ret = is_ad_subtype( a2, a2 );
2205		break;
2206	default:
2207		ret = -1;
2208		break;
2209	}
2210
2211	return ret;
2212}
2213
2214int slapi_attr_types_equivalent( const char *t1, const char *t2 )
2215{
2216	return ( slapi_attr_type_cmp( t1, t2, SLAPI_TYPE_CMP_EXACT ) == 0 );
2217}
2218
2219int slapi_attr_first_value( Slapi_Attr *a, Slapi_Value **v )
2220{
2221	return slapi_valueset_first_value( &a->a_vals, v );
2222}
2223
2224int slapi_attr_next_value( Slapi_Attr *a, int hint, Slapi_Value **v )
2225{
2226	return slapi_valueset_next_value( &a->a_vals, hint, v );
2227}
2228
2229int slapi_attr_get_numvalues( const Slapi_Attr *a, int *numValues )
2230{
2231	*numValues = slapi_valueset_count( &a->a_vals );
2232
2233	return 0;
2234}
2235
2236int slapi_attr_get_valueset( const Slapi_Attr *a, Slapi_ValueSet **vs )
2237{
2238	*vs = &((Slapi_Attr *)a)->a_vals;
2239
2240	return 0;
2241}
2242
2243int slapi_attr_get_bervals_copy( Slapi_Attr *a, struct berval ***vals )
2244{
2245	return slapi_attr_get_values( a, vals );
2246}
2247
2248char *slapi_attr_syntax_normalize( const char *s )
2249{
2250	AttributeDescription *ad = NULL;
2251	const char *text;
2252
2253	if ( slap_str2ad( s, &ad, &text ) != LDAP_SUCCESS ) {
2254		return NULL;
2255	}
2256
2257	return ad->ad_cname.bv_val;
2258}
2259
2260Slapi_Value *slapi_value_new( void )
2261{
2262	struct berval *bv;
2263
2264	bv = (struct berval *)slapi_ch_malloc( sizeof(*bv) );
2265
2266	return bv;
2267}
2268
2269Slapi_Value *slapi_value_new_berval(const struct berval *bval)
2270{
2271	return ber_dupbv( NULL, (struct berval *)bval );
2272}
2273
2274Slapi_Value *slapi_value_new_value(const Slapi_Value *v)
2275{
2276	return slapi_value_new_berval( v );
2277}
2278
2279Slapi_Value *slapi_value_new_string(const char *s)
2280{
2281	struct berval bv;
2282
2283	bv.bv_val = (char *)s;
2284	bv.bv_len = strlen( s );
2285
2286	return slapi_value_new_berval( &bv );
2287}
2288
2289Slapi_Value *slapi_value_init(Slapi_Value *val)
2290{
2291	val->bv_val = NULL;
2292	val->bv_len = 0;
2293
2294	return val;
2295}
2296
2297Slapi_Value *slapi_value_init_berval(Slapi_Value *v, struct berval *bval)
2298{
2299	return ber_dupbv( v, bval );
2300}
2301
2302Slapi_Value *slapi_value_init_string(Slapi_Value *v, const char *s)
2303{
2304	v->bv_val = slapi_ch_strdup( s );
2305	v->bv_len = strlen( s );
2306
2307	return v;
2308}
2309
2310Slapi_Value *slapi_value_dup(const Slapi_Value *v)
2311{
2312	return slapi_value_new_value( v );
2313}
2314
2315void slapi_value_free(Slapi_Value **value)
2316{
2317	if ( value == NULL ) {
2318		return;
2319	}
2320
2321	if ( (*value) != NULL ) {
2322		slapi_ch_free( (void **)&(*value)->bv_val );
2323		slapi_ch_free( (void **)value );
2324	}
2325}
2326
2327const struct berval *slapi_value_get_berval( const Slapi_Value *value )
2328{
2329	return value;
2330}
2331
2332Slapi_Value *slapi_value_set_berval( Slapi_Value *value, const struct berval *bval )
2333{
2334	if ( value == NULL ) {
2335		return NULL;
2336	}
2337	if ( value->bv_val != NULL ) {
2338		slapi_ch_free( (void **)&value->bv_val );
2339	}
2340	slapi_value_init_berval( value, (struct berval *)bval );
2341
2342	return value;
2343}
2344
2345Slapi_Value *slapi_value_set_value( Slapi_Value *value, const Slapi_Value *vfrom)
2346{
2347	if ( value == NULL ) {
2348		return NULL;
2349	}
2350	return slapi_value_set_berval( value, vfrom );
2351}
2352
2353Slapi_Value *slapi_value_set( Slapi_Value *value, void *val, unsigned long len)
2354{
2355	if ( value == NULL ) {
2356		return NULL;
2357	}
2358	if ( value->bv_val != NULL ) {
2359		slapi_ch_free( (void **)&value->bv_val );
2360	}
2361	value->bv_val = slapi_ch_malloc( len );
2362	value->bv_len = len;
2363	AC_MEMCPY( value->bv_val, val, len );
2364
2365	return value;
2366}
2367
2368int slapi_value_set_string(Slapi_Value *value, const char *strVal)
2369{
2370	if ( value == NULL ) {
2371		return -1;
2372	}
2373	slapi_value_set( value, (void *)strVal, strlen( strVal ) );
2374	return 0;
2375}
2376
2377int slapi_value_set_int(Slapi_Value *value, int intVal)
2378{
2379	char buf[64];
2380
2381	snprintf( buf, sizeof( buf ), "%d", intVal );
2382
2383	return slapi_value_set_string( value, buf );
2384}
2385
2386const char *slapi_value_get_string(const Slapi_Value *value)
2387{
2388	if ( value == NULL ) return NULL;
2389	if ( value->bv_val == NULL ) return NULL;
2390	if ( !checkBVString( value ) ) return NULL;
2391
2392	return value->bv_val;
2393}
2394
2395int slapi_value_get_int(const Slapi_Value *value)
2396{
2397	if ( value == NULL ) return 0;
2398	if ( value->bv_val == NULL ) return 0;
2399	if ( !checkBVString( value ) ) return 0;
2400
2401	return (int)strtol( value->bv_val, NULL, 10 );
2402}
2403
2404unsigned int slapi_value_get_uint(const Slapi_Value *value)
2405{
2406	if ( value == NULL ) return 0;
2407	if ( value->bv_val == NULL ) return 0;
2408	if ( !checkBVString( value ) ) return 0;
2409
2410	return (unsigned int)strtoul( value->bv_val, NULL, 10 );
2411}
2412
2413long slapi_value_get_long(const Slapi_Value *value)
2414{
2415	if ( value == NULL ) return 0;
2416	if ( value->bv_val == NULL ) return 0;
2417	if ( !checkBVString( value ) ) return 0;
2418
2419	return strtol( value->bv_val, NULL, 10 );
2420}
2421
2422unsigned long slapi_value_get_ulong(const Slapi_Value *value)
2423{
2424	if ( value == NULL ) return 0;
2425	if ( value->bv_val == NULL ) return 0;
2426	if ( !checkBVString( value ) ) return 0;
2427
2428	return strtoul( value->bv_val, NULL, 10 );
2429}
2430
2431size_t slapi_value_get_length(const Slapi_Value *value)
2432{
2433	if ( value == NULL )
2434		return 0;
2435
2436	return (size_t) value->bv_len;
2437}
2438
2439int slapi_value_compare(const Slapi_Attr *a, const Slapi_Value *v1, const Slapi_Value *v2)
2440{
2441	return slapi_attr_value_cmp( a, v1, v2 );
2442}
2443
2444/* A ValueSet is a container for a BerVarray. */
2445Slapi_ValueSet *slapi_valueset_new( void )
2446{
2447	Slapi_ValueSet *vs;
2448
2449	vs = (Slapi_ValueSet *)slapi_ch_malloc( sizeof( *vs ) );
2450	*vs = NULL;
2451
2452	return vs;
2453}
2454
2455void slapi_valueset_free(Slapi_ValueSet *vs)
2456{
2457	if ( vs != NULL ) {
2458		BerVarray vp = *vs;
2459
2460		ber_bvarray_free( vp );
2461		vp = NULL;
2462
2463		slapi_ch_free( (void **)&vp );
2464	}
2465}
2466
2467void slapi_valueset_init(Slapi_ValueSet *vs)
2468{
2469	if ( vs != NULL && *vs == NULL ) {
2470		*vs = (Slapi_ValueSet)slapi_ch_calloc( 1, sizeof(struct berval) );
2471		(*vs)->bv_val = NULL;
2472		(*vs)->bv_len = 0;
2473	}
2474}
2475
2476void slapi_valueset_done(Slapi_ValueSet *vs)
2477{
2478	BerVarray vp;
2479
2480	if ( vs == NULL )
2481		return;
2482
2483	for ( vp = *vs; vp->bv_val != NULL; vp++ ) {
2484		vp->bv_len = 0;
2485		slapi_ch_free( (void **)&vp->bv_val );
2486	}
2487	/* but don't free *vs or vs */
2488}
2489
2490void slapi_valueset_add_value(Slapi_ValueSet *vs, const Slapi_Value *addval)
2491{
2492	struct berval bv;
2493
2494	ber_dupbv( &bv, (Slapi_Value *)addval );
2495	ber_bvarray_add( vs, &bv );
2496}
2497
2498int slapi_valueset_first_value( Slapi_ValueSet *vs, Slapi_Value **v )
2499{
2500	return slapi_valueset_next_value( vs, 0, v );
2501}
2502
2503int slapi_valueset_next_value( Slapi_ValueSet *vs, int index, Slapi_Value **v)
2504{
2505	int i;
2506	BerVarray vp;
2507
2508	if ( vs == NULL )
2509		return -1;
2510
2511	vp = *vs;
2512
2513	for ( i = 0; vp[i].bv_val != NULL; i++ ) {
2514		if ( i == index ) {
2515			*v = &vp[i];
2516			return index + 1;
2517		}
2518	}
2519
2520	return -1;
2521}
2522
2523int slapi_valueset_count( const Slapi_ValueSet *vs )
2524{
2525	int i;
2526	BerVarray vp;
2527
2528	if ( vs == NULL )
2529		return 0;
2530
2531	vp = *vs;
2532
2533	if ( vp == NULL )
2534		return 0;
2535
2536	for ( i = 0; vp[i].bv_val != NULL; i++ )
2537		;
2538
2539	return i;
2540
2541}
2542
2543void slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
2544{
2545	BerVarray vp;
2546
2547	for ( vp = *vs2; vp->bv_val != NULL; vp++ ) {
2548		slapi_valueset_add_value( vs1, vp );
2549	}
2550}
2551
2552int slapi_access_allowed( Slapi_PBlock *pb, Slapi_Entry *e, char *attr,
2553	struct berval *val, int access )
2554{
2555	int rc;
2556	slap_access_t slap_access;
2557	AttributeDescription *ad = NULL;
2558	const char *text;
2559
2560	rc = slap_str2ad( attr, &ad, &text );
2561	if ( rc != LDAP_SUCCESS ) {
2562		return rc;
2563	}
2564
2565	/*
2566	 * Whilst the SLAPI access types are arranged as a bitmask, the
2567	 * documentation indicates that they are to be used separately.
2568	 */
2569	switch ( access & SLAPI_ACL_ALL ) {
2570	case SLAPI_ACL_COMPARE:
2571		slap_access = ACL_COMPARE;
2572		break;
2573	case SLAPI_ACL_SEARCH:
2574		slap_access = ACL_SEARCH;
2575		break;
2576	case SLAPI_ACL_READ:
2577		slap_access = ACL_READ;
2578		break;
2579	case SLAPI_ACL_WRITE:
2580		slap_access = ACL_WRITE;
2581		break;
2582	case SLAPI_ACL_DELETE:
2583		slap_access = ACL_WDEL;
2584		break;
2585	case SLAPI_ACL_ADD:
2586		slap_access = ACL_WADD;
2587		break;
2588	case SLAPI_ACL_SELF:  /* not documented */
2589	case SLAPI_ACL_PROXY: /* not documented */
2590	default:
2591		return LDAP_INSUFFICIENT_ACCESS;
2592		break;
2593	}
2594
2595	assert( pb->pb_op != NULL );
2596
2597	if ( access_allowed( pb->pb_op, e, ad, val, slap_access, NULL ) ) {
2598		return LDAP_SUCCESS;
2599	}
2600
2601	return LDAP_INSUFFICIENT_ACCESS;
2602}
2603
2604int slapi_acl_check_mods(Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char **errbuf)
2605{
2606	int rc = LDAP_SUCCESS;
2607	Modifications *ml;
2608
2609	if ( pb == NULL || pb->pb_op == NULL )
2610		return LDAP_PARAM_ERROR;
2611
2612	ml = slapi_int_ldapmods2modifications( pb->pb_op, mods );
2613	if ( ml == NULL ) {
2614		return LDAP_OTHER;
2615	}
2616
2617	if ( rc == LDAP_SUCCESS ) {
2618		rc = acl_check_modlist( pb->pb_op, e, ml ) ? LDAP_SUCCESS : LDAP_INSUFFICIENT_ACCESS;
2619	}
2620
2621	slap_mods_free( ml, 1 );
2622
2623	return rc;
2624}
2625
2626/*
2627 * Synthesise an LDAPMod array from a Modifications list to pass
2628 * to SLAPI.
2629 */
2630LDAPMod **slapi_int_modifications2ldapmods( Modifications *modlist )
2631{
2632	Modifications *ml;
2633	LDAPMod **mods, *modp;
2634	int i, j;
2635
2636	for( i = 0, ml = modlist; ml != NULL; i++, ml = ml->sml_next )
2637		;
2638
2639	mods = (LDAPMod **)slapi_ch_malloc( (i + 1) * sizeof(LDAPMod *) );
2640
2641	for( i = 0, ml = modlist; ml != NULL; ml = ml->sml_next ) {
2642		mods[i] = (LDAPMod *)slapi_ch_malloc( sizeof(LDAPMod) );
2643		modp = mods[i];
2644		modp->mod_op = ml->sml_op | LDAP_MOD_BVALUES;
2645		if ( BER_BVISNULL( &ml->sml_type ) ) {
2646			/* may happen for internally generated mods */
2647			assert( ml->sml_desc != NULL );
2648			modp->mod_type = slapi_ch_strdup( ml->sml_desc->ad_cname.bv_val );
2649		} else {
2650			modp->mod_type = slapi_ch_strdup( ml->sml_type.bv_val );
2651		}
2652
2653		if ( ml->sml_values != NULL ) {
2654			for( j = 0; ml->sml_values[j].bv_val != NULL; j++ )
2655				;
2656			modp->mod_bvalues = (struct berval **)slapi_ch_malloc( (j + 1) *
2657				sizeof(struct berval *) );
2658			for( j = 0; ml->sml_values[j].bv_val != NULL; j++ ) {
2659				modp->mod_bvalues[j] = (struct berval *)slapi_ch_malloc(
2660						sizeof(struct berval) );
2661				ber_dupbv( modp->mod_bvalues[j], &ml->sml_values[j] );
2662			}
2663			modp->mod_bvalues[j] = NULL;
2664		} else {
2665			modp->mod_bvalues = NULL;
2666		}
2667		i++;
2668	}
2669
2670	mods[i] = NULL;
2671
2672	return mods;
2673}
2674
2675/*
2676 * Convert a potentially modified array of LDAPMods back to a
2677 * Modification list. Unfortunately the values need to be
2678 * duplicated because slap_mods_check() will try to free them
2679 * before prettying (and we can't easily get out of calling
2680 * slap_mods_check() because we need normalized values).
2681 */
2682Modifications *slapi_int_ldapmods2modifications ( Operation *op, LDAPMod **mods )
2683{
2684	Modifications *modlist = NULL, **modtail;
2685	LDAPMod **modp;
2686	char textbuf[SLAP_TEXT_BUFLEN];
2687	const char *text;
2688
2689	if ( mods == NULL ) {
2690		return NULL;
2691	}
2692
2693	modtail = &modlist;
2694
2695	for ( modp = mods; *modp != NULL; modp++ ) {
2696		Modifications *mod;
2697		LDAPMod *lmod = *modp;
2698		int i;
2699		const char *text;
2700		AttributeDescription *ad = NULL;
2701
2702		if ( slap_str2ad( lmod->mod_type, &ad, &text ) != LDAP_SUCCESS ) {
2703			continue;
2704		}
2705
2706		mod = (Modifications *) slapi_ch_malloc( sizeof(Modifications) );
2707		mod->sml_op = lmod->mod_op & ~(LDAP_MOD_BVALUES);
2708		mod->sml_flags = 0;
2709		mod->sml_type = ad->ad_cname;
2710		mod->sml_desc = ad;
2711		mod->sml_next = NULL;
2712
2713		i = 0;
2714		if ( lmod->mod_op & LDAP_MOD_BVALUES ) {
2715			if ( lmod->mod_bvalues != NULL ) {
2716				while ( lmod->mod_bvalues[i] != NULL )
2717					i++;
2718			}
2719		} else {
2720			if ( lmod->mod_values != NULL ) {
2721				while ( lmod->mod_values[i] != NULL )
2722					i++;
2723			}
2724		}
2725		mod->sml_numvals = i;
2726
2727		if ( i == 0 ) {
2728			mod->sml_values = NULL;
2729		} else {
2730			mod->sml_values = (BerVarray) slapi_ch_malloc( (i + 1) * sizeof(struct berval) );
2731
2732			/* NB: This implicitly trusts a plugin to return valid modifications. */
2733			if ( lmod->mod_op & LDAP_MOD_BVALUES ) {
2734				for ( i = 0; lmod->mod_bvalues[i] != NULL; i++ ) {
2735					ber_dupbv( &mod->sml_values[i], lmod->mod_bvalues[i] );
2736				}
2737			} else {
2738				for ( i = 0; lmod->mod_values[i] != NULL; i++ ) {
2739					mod->sml_values[i].bv_val = slapi_ch_strdup( lmod->mod_values[i] );
2740					mod->sml_values[i].bv_len = strlen( lmod->mod_values[i] );
2741				}
2742			}
2743			mod->sml_values[i].bv_val = NULL;
2744			mod->sml_values[i].bv_len = 0;
2745		}
2746		mod->sml_nvalues = NULL;
2747
2748		*modtail = mod;
2749		modtail = &mod->sml_next;
2750	}
2751
2752	if ( slap_mods_check( op, modlist, &text, textbuf, sizeof( textbuf ), NULL ) != LDAP_SUCCESS ) {
2753		slap_mods_free( modlist, 1 );
2754		modlist = NULL;
2755	}
2756
2757	return modlist;
2758}
2759
2760/*
2761 * Sun ONE DS 5.x computed attribute support. Computed attributes
2762 * allow for dynamically generated operational attributes, a very
2763 * useful thing indeed.
2764 */
2765
2766/*
2767 * For some reason Sun don't use the normal plugin mechanism
2768 * registration path to register an "evaluator" function (an
2769 * "evaluator" is responsible for adding computed attributes;
2770 * the nomenclature is somewhat confusing).
2771 *
2772 * As such slapi_compute_add_evaluator() registers the
2773 * function directly.
2774 */
2775int slapi_compute_add_evaluator(slapi_compute_callback_t function)
2776{
2777	Slapi_PBlock *pPlugin = NULL;
2778	int rc;
2779	int type = SLAPI_PLUGIN_OBJECT;
2780
2781	pPlugin = slapi_pblock_new();
2782	if ( pPlugin == NULL ) {
2783		rc = LDAP_NO_MEMORY;
2784		goto done;
2785	}
2786
2787	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
2788	if ( rc != LDAP_SUCCESS ) {
2789		goto done;
2790	}
2791
2792	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN, (void *)function );
2793	if ( rc != LDAP_SUCCESS ) {
2794		goto done;
2795	}
2796
2797	rc = slapi_int_register_plugin( frontendDB, pPlugin );
2798	if ( rc != 0 ) {
2799		rc = LDAP_OTHER;
2800		goto done;
2801	}
2802
2803done:
2804	if ( rc != LDAP_SUCCESS ) {
2805		if ( pPlugin != NULL ) {
2806			slapi_pblock_destroy( pPlugin );
2807		}
2808		return -1;
2809	}
2810
2811	return 0;
2812}
2813
2814/*
2815 * See notes above regarding slapi_compute_add_evaluator().
2816 */
2817int slapi_compute_add_search_rewriter(slapi_search_rewrite_callback_t function)
2818{
2819	Slapi_PBlock *pPlugin = NULL;
2820	int rc;
2821	int type = SLAPI_PLUGIN_OBJECT;
2822
2823	pPlugin = slapi_pblock_new();
2824	if ( pPlugin == NULL ) {
2825		rc = LDAP_NO_MEMORY;
2826		goto done;
2827	}
2828
2829	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
2830	if ( rc != LDAP_SUCCESS ) {
2831		goto done;
2832	}
2833
2834	rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, (void *)function );
2835	if ( rc != LDAP_SUCCESS ) {
2836		goto done;
2837	}
2838
2839	rc = slapi_int_register_plugin( frontendDB, pPlugin );
2840	if ( rc != 0 ) {
2841		rc = LDAP_OTHER;
2842		goto done;
2843	}
2844
2845done:
2846	if ( rc != LDAP_SUCCESS ) {
2847		if ( pPlugin != NULL ) {
2848			slapi_pblock_destroy( pPlugin );
2849		}
2850		return -1;
2851	}
2852
2853	return 0;
2854}
2855
2856/*
2857 * Call compute evaluators
2858 */
2859int compute_evaluator(computed_attr_context *c, char *type, Slapi_Entry *e, slapi_compute_output_t outputfn)
2860{
2861	int rc = 0;
2862	slapi_compute_callback_t *pGetPlugin, *tmpPlugin;
2863
2864	rc = slapi_int_get_plugins( frontendDB, SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN, (SLAPI_FUNC **)&tmpPlugin );
2865	if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
2866		/* Nothing to do; front-end should ignore. */
2867		return 0;
2868	}
2869
2870	for ( pGetPlugin = tmpPlugin; *pGetPlugin != NULL; pGetPlugin++ ) {
2871		/*
2872		 * -1: no attribute matched requested type
2873		 *  0: one attribute matched
2874		 * >0: error happened
2875		 */
2876		rc = (*pGetPlugin)( c, type, e, outputfn );
2877		if ( rc > 0 ) {
2878			break;
2879		}
2880	}
2881
2882	slapi_ch_free( (void **)&tmpPlugin );
2883
2884	return rc;
2885}
2886
2887int
2888compute_rewrite_search_filter( Slapi_PBlock *pb )
2889{
2890	if ( pb == NULL || pb->pb_op == NULL )
2891		return LDAP_PARAM_ERROR;
2892
2893	return slapi_int_call_plugins( pb->pb_op->o_bd, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, pb );
2894}
2895
2896/*
2897 * New API to provide the plugin with access to the search
2898 * pblock. Have informed Sun DS team.
2899 */
2900int
2901slapi_x_compute_get_pblock(computed_attr_context *c, Slapi_PBlock **pb)
2902{
2903	if ( c == NULL )
2904		return -1;
2905
2906	if ( c->cac_pb == NULL )
2907		return -1;
2908
2909	*pb = c->cac_pb;
2910
2911	return 0;
2912}
2913
2914Slapi_Mutex *slapi_new_mutex( void )
2915{
2916	Slapi_Mutex *m;
2917
2918	m = (Slapi_Mutex *)slapi_ch_malloc( sizeof(*m) );
2919	if ( ldap_pvt_thread_mutex_init( &m->mutex ) != 0 ) {
2920		slapi_ch_free( (void **)&m );
2921		return NULL;
2922	}
2923
2924	return m;
2925}
2926
2927void slapi_destroy_mutex( Slapi_Mutex *mutex )
2928{
2929	if ( mutex != NULL ) {
2930		ldap_pvt_thread_mutex_destroy( &mutex->mutex );
2931		slapi_ch_free( (void **)&mutex);
2932	}
2933}
2934
2935void slapi_lock_mutex( Slapi_Mutex *mutex )
2936{
2937	ldap_pvt_thread_mutex_lock( &mutex->mutex );
2938}
2939
2940int slapi_unlock_mutex( Slapi_Mutex *mutex )
2941{
2942	return ldap_pvt_thread_mutex_unlock( &mutex->mutex );
2943}
2944
2945Slapi_CondVar *slapi_new_condvar( Slapi_Mutex *mutex )
2946{
2947	Slapi_CondVar *cv;
2948
2949	if ( mutex == NULL ) {
2950		return NULL;
2951	}
2952
2953	cv = (Slapi_CondVar *)slapi_ch_malloc( sizeof(*cv) );
2954	if ( ldap_pvt_thread_cond_init( &cv->cond ) != 0 ) {
2955		slapi_ch_free( (void **)&cv );
2956		return NULL;
2957	}
2958
2959	cv->mutex = mutex->mutex;
2960
2961	return cv;
2962}
2963
2964void slapi_destroy_condvar( Slapi_CondVar *cvar )
2965{
2966	if ( cvar != NULL ) {
2967		ldap_pvt_thread_cond_destroy( &cvar->cond );
2968		slapi_ch_free( (void **)&cvar );
2969	}
2970}
2971
2972int slapi_wait_condvar( Slapi_CondVar *cvar, struct timeval *timeout )
2973{
2974	if ( cvar == NULL ) {
2975		return -1;
2976	}
2977
2978	return ldap_pvt_thread_cond_wait( &cvar->cond, &cvar->mutex );
2979}
2980
2981int slapi_notify_condvar( Slapi_CondVar *cvar, int notify_all )
2982{
2983	if ( cvar == NULL ) {
2984		return -1;
2985	}
2986
2987	if ( notify_all ) {
2988		return ldap_pvt_thread_cond_broadcast( &cvar->cond );
2989	}
2990
2991	return ldap_pvt_thread_cond_signal( &cvar->cond );
2992}
2993
2994int slapi_int_access_allowed( Operation *op,
2995	Entry *entry,
2996	AttributeDescription *desc,
2997	struct berval *val,
2998	slap_access_t access,
2999	AccessControlState *state )
3000{
3001	int rc, slap_access = 0;
3002	slapi_acl_callback_t *pGetPlugin, *tmpPlugin;
3003	Slapi_PBlock *pb;
3004
3005	pb = SLAPI_OPERATION_PBLOCK( op );
3006	if ( pb == NULL ) {
3007		/* internal operation */
3008		return 1;
3009	}
3010
3011	switch ( access ) {
3012	case ACL_COMPARE:
3013                slap_access |= SLAPI_ACL_COMPARE;
3014		break;
3015	case ACL_SEARCH:
3016		slap_access |= SLAPI_ACL_SEARCH;
3017		break;
3018	case ACL_READ:
3019		slap_access |= SLAPI_ACL_READ;
3020		break;
3021	case ACL_WRITE:
3022		slap_access |= SLAPI_ACL_WRITE;
3023		break;
3024	case ACL_WDEL:
3025		slap_access |= SLAPI_ACL_DELETE;
3026		break;
3027	case ACL_WADD:
3028		slap_access |= SLAPI_ACL_ADD;
3029		break;
3030	default:
3031		break;
3032        }
3033
3034	rc = slapi_int_get_plugins( frontendDB, SLAPI_PLUGIN_ACL_ALLOW_ACCESS, (SLAPI_FUNC **)&tmpPlugin );
3035	if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
3036		/* nothing to do; allowed access */
3037		return 1;
3038	}
3039
3040	rc = 1; /* default allow policy */
3041
3042	for ( pGetPlugin = tmpPlugin; *pGetPlugin != NULL; pGetPlugin++ ) {
3043		/*
3044		 * 0	access denied
3045		 * 1	access granted
3046		 */
3047		rc = (*pGetPlugin)( pb, entry, desc->ad_cname.bv_val,
3048				    val, slap_access, (void *)state );
3049		if ( rc == 0 ) {
3050			break;
3051		}
3052	}
3053
3054	slapi_ch_free( (void **)&tmpPlugin );
3055
3056	return rc;
3057}
3058
3059/*
3060 * There is no documentation for this.
3061 */
3062int slapi_rdn2typeval( char *rdn, char **type, struct berval *bv )
3063{
3064	LDAPRDN lrdn;
3065	LDAPAVA *ava;
3066	int rc;
3067	char *p;
3068
3069	*type = NULL;
3070
3071	bv->bv_len = 0;
3072	bv->bv_val = NULL;
3073
3074	rc = ldap_str2rdn( rdn, &lrdn, &p, LDAP_DN_FORMAT_LDAPV3 );
3075	if ( rc != LDAP_SUCCESS ) {
3076		return -1;
3077	}
3078
3079	if ( lrdn[1] != NULL ) {
3080		return -1; /* not single valued */
3081	}
3082
3083	ava = lrdn[0];
3084
3085	*type = slapi_ch_strdup( ava->la_attr.bv_val );
3086	ber_dupbv( bv, &ava->la_value );
3087
3088	ldap_rdnfree(lrdn);
3089
3090	return 0;
3091}
3092
3093char *slapi_dn_plus_rdn( const char *dn, const char *rdn )
3094{
3095	struct berval new_dn, parent_dn, newrdn;
3096
3097	new_dn.bv_val = NULL;
3098
3099	parent_dn.bv_val = (char *)dn;
3100	parent_dn.bv_len = strlen( dn );
3101
3102	newrdn.bv_val = (char *)rdn;
3103	newrdn.bv_len = strlen( rdn );
3104
3105	build_new_dn( &new_dn, &parent_dn, &newrdn, NULL );
3106
3107	return new_dn.bv_val;
3108}
3109
3110int slapi_entry_schema_check( Slapi_PBlock *pb, Slapi_Entry *e )
3111{
3112	Backend *be_orig;
3113	const char *text;
3114	char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
3115	size_t textlen = sizeof textbuf;
3116	int rc = LDAP_SUCCESS;
3117
3118	PBLOCK_ASSERT_OP( pb, 0 );
3119
3120	be_orig = pb->pb_op->o_bd;
3121
3122	pb->pb_op->o_bd = select_backend( &e->e_nname, 0 );
3123	if ( pb->pb_op->o_bd != NULL ) {
3124		rc = entry_schema_check( pb->pb_op, e, NULL, 0, 0, NULL,
3125			&text, textbuf, textlen );
3126	}
3127	pb->pb_op->o_bd = be_orig;
3128
3129	return ( rc == LDAP_SUCCESS ) ? 0 : 1;
3130}
3131
3132int slapi_entry_rdn_values_present( const Slapi_Entry *e )
3133{
3134	LDAPDN dn;
3135	int rc;
3136	int i = 0, match = 0;
3137
3138	rc = ldap_bv2dn( &((Entry *)e)->e_name, &dn, LDAP_DN_FORMAT_LDAPV3 );
3139	if ( rc != LDAP_SUCCESS ) {
3140		return 0;
3141	}
3142
3143	if ( dn[0] != NULL ) {
3144		LDAPRDN rdn = dn[0];
3145
3146		for ( i = 0; rdn[i] != NULL; i++ ) {
3147			LDAPAVA *ava = &rdn[0][i];
3148			Slapi_Attr *a = NULL;
3149
3150			if ( slapi_entry_attr_find( (Slapi_Entry *)e, ava->la_attr.bv_val, &a ) == 0 &&
3151			     slapi_attr_value_find( a, &ava->la_value ) == 0 )
3152				match++;
3153		}
3154	}
3155
3156	ldap_dnfree( dn );
3157
3158	return ( i == match );
3159}
3160
3161int slapi_entry_add_rdn_values( Slapi_Entry *e )
3162{
3163	LDAPDN dn;
3164	int i, rc;
3165
3166	rc = ldap_bv2dn( &e->e_name, &dn, LDAP_DN_FORMAT_LDAPV3 );
3167	if ( rc != LDAP_SUCCESS ) {
3168		return rc;
3169	}
3170
3171	if ( dn[0] != NULL ) {
3172		LDAPRDN rdn = dn[0];
3173		struct berval *vals[2];
3174
3175		for ( i = 0; rdn[i] != NULL; i++ ) {
3176			LDAPAVA *ava = &rdn[0][i];
3177			Slapi_Attr *a = NULL;
3178
3179			if ( slapi_entry_attr_find( e, ava->la_attr.bv_val, &a ) == 0 &&
3180			     slapi_attr_value_find( a, &ava->la_value ) == 0 )
3181				continue;
3182
3183			vals[0] = &ava->la_value;
3184			vals[1] = NULL;
3185
3186			slapi_entry_attr_merge( e, ava->la_attr.bv_val, vals );
3187		}
3188	}
3189
3190	ldap_dnfree( dn );
3191
3192	return LDAP_SUCCESS;
3193}
3194
3195const char *slapi_entry_get_uniqueid( const Slapi_Entry *e )
3196{
3197	Attribute *attr;
3198
3199	attr = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID );
3200	if ( attr == NULL ) {
3201		return NULL;
3202	}
3203
3204	if ( attr->a_vals != NULL && attr->a_vals[0].bv_len != 0 ) {
3205		return slapi_value_get_string( &attr->a_vals[0] );
3206	}
3207
3208	return NULL;
3209}
3210
3211void slapi_entry_set_uniqueid( Slapi_Entry *e, char *uniqueid )
3212{
3213	struct berval bv;
3214
3215	attr_delete ( &e->e_attrs, slap_schema.si_ad_entryUUID );
3216
3217	bv.bv_val = uniqueid;
3218	bv.bv_len = strlen( uniqueid );
3219	attr_merge_normalize_one( e, slap_schema.si_ad_entryUUID, &bv, NULL );
3220}
3221
3222LDAP *slapi_ldap_init( char *ldaphost, int ldapport, int secure, int shared )
3223{
3224	LDAP *ld;
3225	char *url;
3226	size_t size;
3227	int rc;
3228
3229	size = sizeof("ldap:///");
3230	if ( secure ) {
3231		size++;
3232	}
3233	size += strlen( ldaphost );
3234	if ( ldapport != 0 ) {
3235		size += 32;
3236	}
3237
3238	url = slapi_ch_malloc( size );
3239
3240	if ( ldapport != 0 ) {
3241		rc = snprintf( url, size, "ldap%s://%s:%d/", ( secure ? "s" : "" ), ldaphost, ldapport );
3242	} else {
3243		rc = snprintf( url, size, "ldap%s://%s/", ( secure ? "s" : "" ), ldaphost );
3244	}
3245
3246	if ( rc > 0 && (size_t) rc < size ) {
3247		rc = ldap_initialize( &ld, url );
3248	} else {
3249		ld = NULL;
3250	}
3251
3252	slapi_ch_free_string( &url );
3253
3254	return ( rc == LDAP_SUCCESS ) ? ld : NULL;
3255}
3256
3257void slapi_ldap_unbind( LDAP *ld )
3258{
3259	ldap_unbind_ext_s( ld, NULL, NULL );
3260}
3261
3262int slapi_x_backend_get_flags( const Slapi_Backend *be, unsigned long *flags )
3263{
3264	if ( be == NULL )
3265		return LDAP_PARAM_ERROR;
3266
3267	*flags = SLAP_DBFLAGS(be);
3268
3269	return LDAP_SUCCESS;
3270}
3271
3272int
3273slapi_int_count_controls( LDAPControl **ctrls )
3274{
3275	size_t i;
3276
3277	if ( ctrls == NULL )
3278		return 0;
3279
3280	for ( i = 0; ctrls[i] != NULL; i++ )
3281		;
3282
3283	return i;
3284}
3285
3286int
3287slapi_op_abandoned( Slapi_PBlock *pb )
3288{
3289	if ( pb->pb_op == NULL )
3290		return 0;
3291
3292	return ( pb->pb_op->o_abandon );
3293}
3294
3295char *
3296slapi_op_type_to_string(unsigned long type)
3297{
3298	char *str;
3299
3300	switch (type) {
3301	case SLAPI_OPERATION_BIND:
3302		str = "bind";
3303		break;
3304	case SLAPI_OPERATION_UNBIND:
3305		str = "unbind";
3306		break;
3307	case SLAPI_OPERATION_SEARCH:
3308		str = "search";
3309		break;
3310	case SLAPI_OPERATION_MODIFY:
3311		str = "modify";
3312		break;
3313	case SLAPI_OPERATION_ADD:
3314		str = "add";
3315		break;
3316	case SLAPI_OPERATION_DELETE:
3317		str = "delete";
3318		break;
3319	case SLAPI_OPERATION_MODDN:
3320		str = "modrdn";
3321		break;
3322	case SLAPI_OPERATION_COMPARE:
3323		str = "compare";
3324		break;
3325	case SLAPI_OPERATION_ABANDON:
3326		str = "abandon";
3327		break;
3328	case SLAPI_OPERATION_EXTENDED:
3329		str = "extended";
3330		break;
3331	default:
3332		str = "unknown operation type";
3333		break;
3334	}
3335	return str;
3336}
3337
3338unsigned long
3339slapi_op_get_type(Slapi_Operation * op)
3340{
3341	unsigned long type;
3342
3343	switch ( op->o_tag ) {
3344	case LDAP_REQ_BIND:
3345		type = SLAPI_OPERATION_BIND;
3346		break;
3347	case LDAP_REQ_UNBIND:
3348		type = SLAPI_OPERATION_UNBIND;
3349		break;
3350	case LDAP_REQ_SEARCH:
3351		type = SLAPI_OPERATION_SEARCH;
3352		break;
3353	case LDAP_REQ_MODIFY:
3354		type = SLAPI_OPERATION_MODIFY;
3355		break;
3356	case LDAP_REQ_ADD:
3357		type = SLAPI_OPERATION_ADD;
3358		break;
3359	case LDAP_REQ_DELETE:
3360		type = SLAPI_OPERATION_DELETE;
3361		break;
3362	case LDAP_REQ_MODRDN:
3363		type = SLAPI_OPERATION_MODDN;
3364		break;
3365	case LDAP_REQ_COMPARE:
3366		type = SLAPI_OPERATION_COMPARE;
3367		break;
3368	case LDAP_REQ_ABANDON:
3369		type = SLAPI_OPERATION_ABANDON;
3370		break;
3371	case LDAP_REQ_EXTENDED:
3372		type = SLAPI_OPERATION_EXTENDED;
3373		break;
3374	default:
3375		type = SLAPI_OPERATION_NONE;
3376		break;
3377	}
3378	return type;
3379}
3380
3381void slapi_be_set_readonly( Slapi_Backend *be, int readonly )
3382{
3383	if ( be == NULL )
3384		return;
3385
3386	if ( readonly )
3387		be->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
3388	else
3389		be->be_restrictops &= ~(SLAP_RESTRICT_OP_WRITES);
3390}
3391
3392int slapi_be_get_readonly( Slapi_Backend *be )
3393{
3394	if ( be == NULL )
3395		return 0;
3396
3397	return ( (be->be_restrictops & SLAP_RESTRICT_OP_WRITES) == SLAP_RESTRICT_OP_WRITES );
3398}
3399
3400const char *slapi_x_be_get_updatedn( Slapi_Backend *be )
3401{
3402	if ( be == NULL )
3403		return NULL;
3404
3405	return be->be_update_ndn.bv_val;
3406}
3407
3408Slapi_Backend *slapi_be_select( const Slapi_DN *sdn )
3409{
3410	Slapi_Backend *be;
3411
3412	slapi_sdn_get_ndn( sdn );
3413
3414	be = select_backend( (struct berval *)&sdn->ndn, 0 );
3415
3416	return be;
3417}
3418
3419#if 0
3420void
3421slapi_operation_set_flag(Slapi_Operation *op, unsigned long flag)
3422{
3423}
3424
3425void
3426slapi_operation_clear_flag(Slapi_Operation *op, unsigned long flag)
3427{
3428}
3429
3430int
3431slapi_operation_is_flag_set(Slapi_Operation *op, unsigned long flag)
3432{
3433}
3434#endif
3435
3436#endif /* LDAP_SLAPI */
3437
3438