1/*	$NetBSD$	*/
2
3/* backend.c - routines for dealing with back-end databases */
4/* OpenLDAP: pkg/ldap/servers/slapd/backend.c,v 1.362.2.32 2010/04/14 22:59:08 quanah Exp */
5/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 1998-2010 The OpenLDAP Foundation.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18/* Portions Copyright (c) 1995 Regents of the University of Michigan.
19 * All rights reserved.
20 *
21 * Redistribution and use in source and binary forms are permitted
22 * provided that this notice is preserved and that due credit is given
23 * to the University of Michigan at Ann Arbor. The name of the University
24 * may not be used to endorse or promote products derived from this
25 * software without specific prior written permission. This software
26 * is provided ``as is'' without express or implied warranty.
27 */
28
29
30#include "portable.h"
31
32#include <stdio.h>
33
34#include <ac/string.h>
35#include <ac/socket.h>
36#include <sys/stat.h>
37
38#include "slap.h"
39#include "config.h"
40#include "lutil.h"
41#include "lber_pvt.h"
42
43/*
44 * If a module is configured as dynamic, its header should not
45 * get included into slapd. While this is a general rule and does
46 * not have much of an effect in UNIX, this rule should be adhered
47 * to for Windows, where dynamic object code should not be implicitly
48 * imported into slapd without appropriate __declspec(dllimport) directives.
49 */
50
51int			nBackendInfo = 0;
52slap_bi_head backendInfo = LDAP_STAILQ_HEAD_INITIALIZER(backendInfo);
53
54int			nBackendDB = 0;
55slap_be_head backendDB = LDAP_STAILQ_HEAD_INITIALIZER(backendDB);
56
57static int
58backend_init_controls( BackendInfo *bi )
59{
60	if ( bi->bi_controls ) {
61		int	i;
62
63		for ( i = 0; bi->bi_controls[ i ]; i++ ) {
64			int	cid;
65
66			if ( slap_find_control_id( bi->bi_controls[ i ], &cid )
67					== LDAP_CONTROL_NOT_FOUND )
68			{
69				if ( !( slapMode & SLAP_TOOL_MODE ) ) {
70					assert( 0 );
71				}
72
73				return -1;
74			}
75
76			bi->bi_ctrls[ cid ] = 1;
77		}
78	}
79
80	return 0;
81}
82
83int backend_init(void)
84{
85	int rc = -1;
86	BackendInfo *bi;
87
88	if((nBackendInfo != 0) || !LDAP_STAILQ_EMPTY(&backendInfo)) {
89		/* already initialized */
90		Debug( LDAP_DEBUG_ANY,
91			"backend_init: already initialized\n", 0, 0, 0 );
92		return -1;
93	}
94
95	for( bi=slap_binfo; bi->bi_type != NULL; bi++,nBackendInfo++ ) {
96		assert( bi->bi_init != 0 );
97
98		rc = bi->bi_init( bi );
99
100		if(rc != 0) {
101			Debug( LDAP_DEBUG_ANY,
102				"backend_init: initialized for type \"%s\"\n",
103				bi->bi_type, 0, 0 );
104			/* destroy those we've already inited */
105			for( nBackendInfo--;
106				nBackendInfo >= 0 ;
107				nBackendInfo-- )
108			{
109				if ( slap_binfo[nBackendInfo].bi_destroy ) {
110					slap_binfo[nBackendInfo].bi_destroy(
111						&slap_binfo[nBackendInfo] );
112				}
113			}
114			return rc;
115		}
116
117		LDAP_STAILQ_INSERT_TAIL(&backendInfo, bi, bi_next);
118	}
119
120	if ( nBackendInfo > 0) {
121		return 0;
122	}
123
124#ifdef SLAPD_MODULES
125	return 0;
126#else
127
128	Debug( LDAP_DEBUG_ANY,
129		"backend_init: failed\n",
130		0, 0, 0 );
131
132	return rc;
133#endif /* SLAPD_MODULES */
134}
135
136int backend_add(BackendInfo *aBackendInfo)
137{
138	int rc = 0;
139
140	if ( aBackendInfo->bi_init == NULL ) {
141		Debug( LDAP_DEBUG_ANY, "backend_add: "
142			"backend type \"%s\" does not have the (mandatory)init function\n",
143			aBackendInfo->bi_type, 0, 0 );
144		return -1;
145	}
146
147	rc = aBackendInfo->bi_init(aBackendInfo);
148	if ( rc != 0) {
149		Debug( LDAP_DEBUG_ANY,
150			"backend_add:  initialization for type \"%s\" failed\n",
151			aBackendInfo->bi_type, 0, 0 );
152		return rc;
153	}
154
155	(void)backend_init_controls( aBackendInfo );
156
157	/* now add the backend type to the Backend Info List */
158	LDAP_STAILQ_INSERT_TAIL( &backendInfo, aBackendInfo, bi_next );
159	nBackendInfo++;
160	return 0;
161}
162
163static int
164backend_set_controls( BackendDB *be )
165{
166	BackendInfo	*bi = be->bd_info;
167
168	/* back-relay takes care of itself; so may do other */
169	if ( overlay_is_over( be ) ) {
170		bi = ((slap_overinfo *)be->bd_info->bi_private)->oi_orig;
171	}
172
173	if ( bi->bi_controls ) {
174		if ( be->be_ctrls[ SLAP_MAX_CIDS ] == 0 ) {
175			AC_MEMCPY( be->be_ctrls, bi->bi_ctrls,
176					sizeof( be->be_ctrls ) );
177			be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
178
179		} else {
180			int	i;
181
182			for ( i = 0; i < SLAP_MAX_CIDS; i++ ) {
183				if ( bi->bi_ctrls[ i ] ) {
184					be->be_ctrls[ i ] = bi->bi_ctrls[ i ];
185				}
186			}
187		}
188
189	}
190
191	return 0;
192}
193
194/* startup a specific backend database */
195int backend_startup_one(Backend *be, ConfigReply *cr)
196{
197	int		rc = 0;
198
199	assert( be != NULL );
200
201	be->be_pending_csn_list = (struct be_pcl *)
202		ch_calloc( 1, sizeof( struct be_pcl ) );
203
204	LDAP_TAILQ_INIT( be->be_pending_csn_list );
205
206	Debug( LDAP_DEBUG_TRACE,
207		"backend_startup_one: starting \"%s\"\n",
208		be->be_suffix ? be->be_suffix[0].bv_val : "(unknown)",
209		0, 0 );
210
211	/* set database controls */
212	(void)backend_set_controls( be );
213
214#if 0
215	if ( !BER_BVISEMPTY( &be->be_rootndn )
216		&& select_backend( &be->be_rootndn, 0 ) == be
217		&& BER_BVISNULL( &be->be_rootpw ) )
218	{
219		/* warning: if rootdn entry is created,
220		 * it can take rootdn privileges;
221		 * set empty rootpw to prevent */
222	}
223#endif
224
225	if ( be->bd_info->bi_db_open ) {
226		rc = be->bd_info->bi_db_open( be, cr );
227		if ( rc == 0 ) {
228			(void)backend_set_controls( be );
229
230		} else {
231			char *type = be->bd_info->bi_type;
232			char *suffix = "(null)";
233
234			if ( overlay_is_over( be ) ) {
235				slap_overinfo	*oi = (slap_overinfo *)be->bd_info->bi_private;
236				type = oi->oi_orig->bi_type;
237			}
238
239			if ( be->be_suffix != NULL && !BER_BVISNULL( &be->be_suffix[0] ) ) {
240				suffix = be->be_suffix[0].bv_val;
241			}
242
243			Debug( LDAP_DEBUG_ANY,
244				"backend_startup_one (type=%s, suffix=\"%s\"): "
245				"bi_db_open failed! (%d)\n",
246				type, suffix, rc );
247		}
248	}
249
250	return rc;
251}
252
253int backend_startup(Backend *be)
254{
255	int i;
256	int rc = 0;
257	BackendInfo *bi;
258	ConfigReply cr={0, ""};
259
260	if( ! ( nBackendDB > 0 ) ) {
261		/* no databases */
262		Debug( LDAP_DEBUG_ANY,
263			"backend_startup: %d databases to startup.\n",
264			nBackendDB, 0, 0 );
265		return 1;
266	}
267
268	if(be != NULL) {
269		if ( be->bd_info->bi_open ) {
270			rc = be->bd_info->bi_open( be->bd_info );
271			if ( rc != 0 ) {
272				Debug( LDAP_DEBUG_ANY,
273					"backend_startup: bi_open failed!\n",
274					0, 0, 0 );
275
276				return rc;
277			}
278		}
279
280		return backend_startup_one( be, &cr );
281	}
282
283	/* open frontend, if required */
284	if ( frontendDB->bd_info->bi_db_open ) {
285		rc = frontendDB->bd_info->bi_db_open( frontendDB, &cr );
286		if ( rc != 0 ) {
287			Debug( LDAP_DEBUG_ANY,
288				"backend_startup: bi_db_open(frontend) failed! (%d)\n",
289				rc, 0, 0 );
290			return rc;
291		}
292	}
293
294	/* open each backend type */
295	i = -1;
296	LDAP_STAILQ_FOREACH(bi, &backendInfo, bi_next) {
297		i++;
298		if( bi->bi_nDB == 0) {
299			/* no database of this type, don't open */
300			continue;
301		}
302
303		if( bi->bi_open ) {
304			rc = bi->bi_open( bi );
305			if ( rc != 0 ) {
306				Debug( LDAP_DEBUG_ANY,
307					"backend_startup: bi_open %d (%s) failed!\n",
308					i, bi->bi_type, 0 );
309				return rc;
310			}
311		}
312
313		(void)backend_init_controls( bi );
314	}
315
316	/* open each backend database */
317	i = -1;
318	LDAP_STAILQ_FOREACH(be, &backendDB, be_next) {
319		i++;
320		if ( be->be_suffix == NULL ) {
321			Debug( LDAP_DEBUG_ANY,
322				"backend_startup: warning, database %d (%s) "
323				"has no suffix\n",
324				i, be->bd_info->bi_type, 0 );
325		}
326
327		rc = backend_startup_one( be, &cr );
328
329		if ( rc ) return rc;
330	}
331
332	return rc;
333}
334
335int backend_num( Backend *be )
336{
337	int i = 0;
338	BackendDB *b2;
339
340	if( be == NULL ) return -1;
341
342	LDAP_STAILQ_FOREACH( b2, &backendDB, be_next ) {
343		if( be == b2 ) return i;
344		i++;
345	}
346	return -1;
347}
348
349int backend_shutdown( Backend *be )
350{
351	int rc = 0;
352	BackendInfo *bi;
353
354	if( be != NULL ) {
355		/* shutdown a specific backend database */
356
357		if ( be->bd_info->bi_nDB == 0 ) {
358			/* no database of this type, we never opened it */
359			return 0;
360		}
361
362		if ( be->bd_info->bi_db_close ) {
363			rc = be->bd_info->bi_db_close( be, NULL );
364			if ( rc ) return rc;
365		}
366
367		if( be->bd_info->bi_close ) {
368			rc = be->bd_info->bi_close( be->bd_info );
369			if ( rc ) return rc;
370		}
371
372		return 0;
373	}
374
375	/* close each backend database */
376	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
377		if ( be->bd_info->bi_db_close ) {
378			be->bd_info->bi_db_close( be, NULL );
379		}
380
381		if(rc != 0) {
382			Debug( LDAP_DEBUG_ANY,
383				"backend_close: bi_db_close %s failed!\n",
384				be->be_type, 0, 0 );
385		}
386	}
387
388	/* close each backend type */
389	LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next ) {
390		if( bi->bi_nDB == 0 ) {
391			/* no database of this type */
392			continue;
393		}
394
395		if( bi->bi_close ) {
396			bi->bi_close( bi );
397		}
398	}
399
400	/* close frontend, if required */
401	if ( frontendDB->bd_info->bi_db_close ) {
402		rc = frontendDB->bd_info->bi_db_close ( frontendDB, NULL );
403		if ( rc != 0 ) {
404			Debug( LDAP_DEBUG_ANY,
405				"backend_startup: bi_db_close(frontend) failed! (%d)\n",
406				rc, 0, 0 );
407		}
408	}
409
410	return 0;
411}
412
413/*
414 * This function is supposed to be the exact counterpart
415 * of backend_startup_one(), although this one calls bi_db_destroy()
416 * while backend_startup_one() calls bi_db_open().
417 *
418 * Make sure backend_stopdown_one() destroys resources allocated
419 * by backend_startup_one(); only call backend_destroy_one() when
420 * all stuff in a BackendDB needs to be destroyed
421 */
422void
423backend_stopdown_one( BackendDB *bd )
424{
425	if ( bd->be_pending_csn_list ) {
426		struct slap_csn_entry *csne;
427		csne = LDAP_TAILQ_FIRST( bd->be_pending_csn_list );
428		while ( csne ) {
429			struct slap_csn_entry *tmp_csne = csne;
430
431			LDAP_TAILQ_REMOVE( bd->be_pending_csn_list, csne, ce_csn_link );
432			ch_free( csne->ce_csn.bv_val );
433			csne = LDAP_TAILQ_NEXT( csne, ce_csn_link );
434			ch_free( tmp_csne );
435		}
436		ch_free( bd->be_pending_csn_list );
437	}
438
439	if ( bd->bd_info->bi_db_destroy ) {
440		bd->bd_info->bi_db_destroy( bd, NULL );
441	}
442}
443
444void backend_destroy_one( BackendDB *bd, int dynamic )
445{
446	if ( dynamic ) {
447		LDAP_STAILQ_REMOVE(&backendDB, bd, BackendDB, be_next );
448	}
449
450	if ( bd->be_syncinfo ) {
451		syncinfo_free( bd->be_syncinfo, 1 );
452	}
453
454	backend_stopdown_one( bd );
455
456	ber_bvarray_free( bd->be_suffix );
457	ber_bvarray_free( bd->be_nsuffix );
458	if ( !BER_BVISNULL( &bd->be_rootdn ) ) {
459		free( bd->be_rootdn.bv_val );
460	}
461	if ( !BER_BVISNULL( &bd->be_rootndn ) ) {
462		free( bd->be_rootndn.bv_val );
463	}
464	if ( !BER_BVISNULL( &bd->be_rootpw ) ) {
465		free( bd->be_rootpw.bv_val );
466	}
467	acl_destroy( bd->be_acl );
468	limits_destroy( bd->be_limits );
469	if ( !BER_BVISNULL( &bd->be_update_ndn ) ) {
470		ch_free( bd->be_update_ndn.bv_val );
471	}
472	if ( bd->be_update_refs ) {
473		ber_bvarray_free( bd->be_update_refs );
474	}
475
476	if ( dynamic ) {
477		free( bd );
478	}
479}
480
481int backend_destroy(void)
482{
483	BackendDB *bd;
484	BackendInfo *bi;
485
486	/* destroy each backend database */
487	while (( bd = LDAP_STAILQ_FIRST(&backendDB))) {
488		backend_destroy_one( bd, 1 );
489	}
490
491	/* destroy each backend type */
492	LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next ) {
493		if( bi->bi_destroy ) {
494			bi->bi_destroy( bi );
495		}
496	}
497
498	nBackendInfo = 0;
499	LDAP_STAILQ_INIT(&backendInfo);
500
501	/* destroy frontend database */
502	bd = frontendDB;
503	if ( bd ) {
504		if ( bd->bd_info->bi_db_destroy ) {
505			bd->bd_info->bi_db_destroy( bd, NULL );
506		}
507		ber_bvarray_free( bd->be_suffix );
508		ber_bvarray_free( bd->be_nsuffix );
509		if ( !BER_BVISNULL( &bd->be_rootdn ) ) {
510			free( bd->be_rootdn.bv_val );
511		}
512		if ( !BER_BVISNULL( &bd->be_rootndn ) ) {
513			free( bd->be_rootndn.bv_val );
514		}
515		if ( !BER_BVISNULL( &bd->be_rootpw ) ) {
516			free( bd->be_rootpw.bv_val );
517		}
518		acl_destroy( bd->be_acl );
519		frontendDB = NULL;
520	}
521
522	return 0;
523}
524
525BackendInfo* backend_info(const char *type)
526{
527	BackendInfo *bi;
528
529	/* search for the backend type */
530	LDAP_STAILQ_FOREACH(bi,&backendInfo,bi_next) {
531		if( strcasecmp(bi->bi_type, type) == 0 ) {
532			return bi;
533		}
534	}
535
536	return NULL;
537}
538
539void
540backend_db_insert(
541	BackendDB *be,
542	int idx
543)
544{
545	/* If idx < 0, just add to end of list */
546	if ( idx < 0 ) {
547		LDAP_STAILQ_INSERT_TAIL(&backendDB, be, be_next);
548	} else if ( idx == 0 ) {
549		LDAP_STAILQ_INSERT_HEAD(&backendDB, be, be_next);
550	} else {
551		int i;
552		BackendDB *b2;
553
554		b2 = LDAP_STAILQ_FIRST(&backendDB);
555		idx--;
556		for (i=0; i<idx; i++) {
557			b2 = LDAP_STAILQ_NEXT(b2, be_next);
558		}
559		LDAP_STAILQ_INSERT_AFTER(&backendDB, b2, be, be_next);
560	}
561}
562
563void
564backend_db_move(
565	BackendDB *be,
566	int idx
567)
568{
569	LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
570	backend_db_insert(be, idx);
571}
572
573BackendDB *
574backend_db_init(
575    const char	*type,
576	BackendDB *b0,
577	int idx,
578	ConfigReply *cr)
579{
580	BackendInfo *bi = backend_info(type);
581	BackendDB *be = b0;
582	int	rc = 0;
583
584	if( bi == NULL ) {
585		fprintf( stderr, "Unrecognized database type (%s)\n", type );
586		return NULL;
587	}
588
589	/* If be is provided, treat it as private. Otherwise allocate
590	 * one and add it to the global list.
591	 */
592	if ( !be ) {
593		be = ch_calloc( 1, sizeof(Backend) );
594		/* Just append */
595		if ( idx >= nbackends )
596			idx = -1;
597		nbackends++;
598		backend_db_insert( be, idx );
599	}
600
601	be->bd_info = bi;
602	be->bd_self = be;
603
604	be->be_def_limit = frontendDB->be_def_limit;
605	be->be_dfltaccess = frontendDB->be_dfltaccess;
606
607	be->be_restrictops = frontendDB->be_restrictops;
608	be->be_requires = frontendDB->be_requires;
609	be->be_ssf_set = frontendDB->be_ssf_set;
610
611	ldap_pvt_thread_mutex_init( &be->be_pcl_mutex );
612
613 	/* assign a default depth limit for alias deref */
614	be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;
615
616	if ( bi->bi_db_init ) {
617		rc = bi->bi_db_init( be, cr );
618	}
619
620	if ( rc != 0 ) {
621		fprintf( stderr, "database init failed (%s)\n", type );
622		/* If we created and linked this be, remove it and free it */
623		if ( !b0 ) {
624			LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
625			ch_free( be );
626			be = NULL;
627			nbackends--;
628		}
629	} else {
630		if ( !bi->bi_nDB ) {
631			backend_init_controls( bi );
632		}
633		bi->bi_nDB++;
634	}
635	return( be );
636}
637
638void
639be_db_close( void )
640{
641	BackendDB *be;
642
643	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
644		if ( be->bd_info->bi_db_close ) {
645			be->bd_info->bi_db_close( be, NULL );
646		}
647	}
648
649	if ( frontendDB->bd_info->bi_db_close ) {
650		frontendDB->bd_info->bi_db_close( frontendDB, NULL );
651	}
652
653}
654
655Backend *
656select_backend(
657	struct berval * dn,
658	int noSubs )
659{
660	int		j;
661	ber_len_t	len, dnlen = dn->bv_len;
662	Backend		*be;
663
664	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
665		if ( be->be_nsuffix == NULL || SLAP_DBHIDDEN( be )) {
666			continue;
667		}
668
669		for ( j = 0; !BER_BVISNULL( &be->be_nsuffix[j] ); j++ )
670		{
671			if ( ( SLAP_GLUE_SUBORDINATE( be ) ) && noSubs )
672			{
673			  	continue;
674			}
675
676			len = be->be_nsuffix[j].bv_len;
677
678			if ( len > dnlen ) {
679				/* suffix is longer than DN */
680				continue;
681			}
682
683			/*
684			 * input DN is normalized, so the separator check
685			 * need not look at escaping
686			 */
687			if ( len && len < dnlen &&
688				!DN_SEPARATOR( dn->bv_val[(dnlen-len)-1] ))
689			{
690				continue;
691			}
692
693			if ( strcmp( be->be_nsuffix[j].bv_val,
694				&dn->bv_val[dnlen-len] ) == 0 )
695			{
696				return be;
697			}
698		}
699	}
700
701	return be;
702}
703
704int
705be_issuffix(
706    Backend *be,
707    struct berval *bvsuffix )
708{
709	int	i;
710
711	if ( be->be_nsuffix == NULL ) {
712		return 0;
713	}
714
715	for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) {
716		if ( bvmatch( &be->be_nsuffix[i], bvsuffix ) ) {
717			return 1;
718		}
719	}
720
721	return 0;
722}
723
724int
725be_issubordinate(
726    Backend *be,
727    struct berval *bvsubordinate )
728{
729	int	i;
730
731	if ( be->be_nsuffix == NULL ) {
732		return 0;
733	}
734
735	for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) {
736		if ( dnIsSuffix( bvsubordinate, &be->be_nsuffix[i] ) ) {
737			return 1;
738		}
739	}
740
741	return 0;
742}
743
744int
745be_isroot_dn( Backend *be, struct berval *ndn )
746{
747	if ( BER_BVISEMPTY( ndn ) || BER_BVISEMPTY( &be->be_rootndn ) ) {
748		return 0;
749	}
750
751	return dn_match( &be->be_rootndn, ndn );
752}
753
754int
755be_slurp_update( Operation *op )
756{
757	return ( SLAP_SLURP_SHADOW( op->o_bd ) &&
758		be_isupdate_dn( op->o_bd, &op->o_ndn ) );
759}
760
761int
762be_shadow_update( Operation *op )
763{
764	/* This assumes that all internal ops (connid <= -1000) on a syncrepl
765	 * database are syncrepl operations.
766	 */
767	return ( ( SLAP_SYNC_SHADOW( op->o_bd ) && SLAPD_SYNC_IS_SYNCCONN( op->o_connid ) ) ||
768		( SLAP_SHADOW( op->o_bd ) && be_isupdate_dn( op->o_bd, &op->o_ndn ) ) );
769}
770
771int
772be_isupdate_dn( Backend *be, struct berval *ndn )
773{
774	if ( BER_BVISEMPTY( ndn ) || BER_BVISEMPTY( &be->be_update_ndn ) ) {
775		return 0;
776	}
777
778	return dn_match( &be->be_update_ndn, ndn );
779}
780
781struct berval *
782be_root_dn( Backend *be )
783{
784	return &be->be_rootdn;
785}
786
787int
788be_isroot( Operation *op )
789{
790	return be_isroot_dn( op->o_bd, &op->o_ndn );
791}
792
793int
794be_isroot_pw( Operation *op )
795{
796	return be_rootdn_bind( op, NULL ) == LDAP_SUCCESS;
797}
798
799/*
800 * checks if binding as rootdn
801 *
802 * return value:
803 *	SLAP_CB_CONTINUE		if not the rootdn, or if rootpw is null
804 *	LDAP_SUCCESS			if rootdn & rootpw
805 *	LDAP_INVALID_CREDENTIALS	if rootdn & !rootpw
806 *
807 * if rs != NULL
808 *	if LDAP_SUCCESS, op->orb_edn is set
809 *	if LDAP_INVALID_CREDENTIALS, response is sent to client
810 */
811int
812be_rootdn_bind( Operation *op, SlapReply *rs )
813{
814	int		rc;
815#ifdef SLAPD_SPASSWD
816	void	*old_authctx = NULL;
817#endif
818
819	assert( op->o_tag == LDAP_REQ_BIND );
820	assert( op->orb_method == LDAP_AUTH_SIMPLE );
821
822	if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
823		return SLAP_CB_CONTINUE;
824	}
825
826	if ( BER_BVISNULL( &op->o_bd->be_rootpw ) ) {
827		/* give the database a chance */
828		return SLAP_CB_CONTINUE;
829	}
830
831	if ( BER_BVISEMPTY( &op->o_bd->be_rootpw ) ) {
832		/* rootdn bind explicitly disallowed */
833		rc = LDAP_INVALID_CREDENTIALS;
834		if ( rs ) {
835			goto send_result;
836		}
837
838		return rc;
839	}
840
841#ifdef SLAPD_SPASSWD
842	ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind,
843		op->o_conn->c_sasl_authctx, 0, &old_authctx, NULL );
844#endif
845
846	rc = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL );
847
848#ifdef SLAPD_SPASSWD
849	ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind,
850		old_authctx, 0, NULL, NULL );
851#endif
852
853	rc = ( rc == 0 ? LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS );
854	if ( rs ) {
855send_result:;
856		rs->sr_err = rc;
857
858		Debug( LDAP_DEBUG_TRACE, "%s: rootdn=\"%s\" bind%s\n",
859			op->o_log_prefix, op->o_bd->be_rootdn.bv_val,
860			rc == LDAP_SUCCESS ? " succeeded" : " failed" );
861
862		if ( rc == LDAP_SUCCESS ) {
863			/* Set to the pretty rootdn */
864     			ber_dupbv( &op->orb_edn, &op->o_bd->be_rootdn );
865
866		} else {
867			send_ldap_result( op, rs );
868		}
869	}
870
871	return rc;
872}
873
874int
875be_entry_release_rw(
876	Operation *op,
877	Entry *e,
878	int rw )
879{
880	if ( op->o_bd->be_release ) {
881		/* free and release entry from backend */
882		return op->o_bd->be_release( op, e, rw );
883	} else {
884		/* free entry */
885		entry_free( e );
886		return 0;
887	}
888}
889
890int
891backend_unbind( Operation *op, SlapReply *rs )
892{
893	BackendDB *be;
894
895	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
896		if ( be->be_unbind ) {
897			op->o_bd = be;
898			be->be_unbind( op, rs );
899		}
900	}
901
902	return 0;
903}
904
905int
906backend_connection_init(
907	Connection   *conn )
908{
909	BackendDB *be;
910
911	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
912		if ( be->be_connection_init ) {
913			be->be_connection_init( be, conn );
914		}
915	}
916
917	return 0;
918}
919
920int
921backend_connection_destroy(
922	Connection   *conn )
923{
924	BackendDB *be;
925
926	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
927		if ( be->be_connection_destroy ) {
928			be->be_connection_destroy( be, conn);
929		}
930	}
931
932	return 0;
933}
934
935int
936backend_check_controls(
937	Operation *op,
938	SlapReply *rs )
939{
940	LDAPControl **ctrls = op->o_ctrls;
941	rs->sr_err = LDAP_SUCCESS;
942
943	if( ctrls ) {
944		for( ; *ctrls != NULL ; ctrls++ ) {
945			int cid;
946
947			switch ( slap_global_control( op, (*ctrls)->ldctl_oid, &cid ) ) {
948			case LDAP_CONTROL_NOT_FOUND:
949				/* unrecognized control */
950				if ( (*ctrls)->ldctl_iscritical ) {
951					/* should not be reachable */
952					Debug( LDAP_DEBUG_ANY, "backend_check_controls: "
953						"unrecognized critical control: %s\n",
954						(*ctrls)->ldctl_oid, 0, 0 );
955					assert( 0 );
956				} else {
957					Debug( LDAP_DEBUG_TRACE, "backend_check_controls: "
958						"unrecognized non-critical control: %s\n",
959						(*ctrls)->ldctl_oid, 0, 0 );
960				}
961				break;
962
963			case LDAP_COMPARE_FALSE:
964				if ( !op->o_bd->be_ctrls[cid] && (*ctrls)->ldctl_iscritical ) {
965#ifdef SLAP_CONTROL_X_WHATFAILED
966					if ( get_whatFailed( op ) ) {
967						char *oids[ 2 ];
968						oids[ 0 ] = (*ctrls)->ldctl_oid;
969						oids[ 1 ] = NULL;
970						slap_ctrl_whatFailed_add( op, rs, oids );
971					}
972#endif
973					/* RFC 4511 allows unavailableCriticalExtension to be
974					 * returned when the server is unwilling to perform
975					 * an operation extended by a recognized critical
976					 * control.
977					 */
978					rs->sr_text = "critical control unavailable in context";
979					rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
980					goto done;
981				}
982				break;
983
984			case LDAP_COMPARE_TRUE:
985				break;
986
987			default:
988				/* unreachable */
989				Debug( LDAP_DEBUG_ANY,
990					"backend_check_controls: unable to check control: %s\n",
991					(*ctrls)->ldctl_oid, 0, 0 );
992				assert( 0 );
993
994				rs->sr_text = "unable to check control";
995				rs->sr_err = LDAP_OTHER;
996				goto done;
997			}
998		}
999	}
1000
1001#if 0 /* temporarily removed */
1002	/* check should be generalized */
1003	if( get_relax(op) && !be_isroot(op)) {
1004		rs->sr_text = "requires manager authorization";
1005		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1006	}
1007#endif
1008
1009done:;
1010	return rs->sr_err;
1011}
1012
1013int
1014backend_check_restrictions(
1015	Operation *op,
1016	SlapReply *rs,
1017	struct berval *opdata )
1018{
1019	slap_mask_t restrictops;
1020	slap_mask_t requires;
1021	slap_mask_t opflag;
1022	slap_mask_t exopflag = 0;
1023	slap_ssf_set_t ssfs, *ssf;
1024	int updateop = 0;
1025	int starttls = 0;
1026	int session = 0;
1027
1028	restrictops = frontendDB->be_restrictops;
1029	requires = frontendDB->be_requires;
1030	ssfs = frontendDB->be_ssf_set;
1031	ssf = &ssfs;
1032
1033	if ( op->o_bd ) {
1034		slap_ssf_t *fssf, *bssf;
1035		int	rc = SLAP_CB_CONTINUE, i;
1036
1037		if ( op->o_bd->be_chk_controls ) {
1038			rc = ( *op->o_bd->be_chk_controls )( op, rs );
1039		}
1040
1041		if ( rc == SLAP_CB_CONTINUE ) {
1042			rc = backend_check_controls( op, rs );
1043		}
1044
1045		if ( rc != LDAP_SUCCESS ) {
1046			return rs->sr_err;
1047		}
1048
1049		restrictops |= op->o_bd->be_restrictops;
1050		requires |= op->o_bd->be_requires;
1051		bssf = &op->o_bd->be_ssf_set.sss_ssf;
1052		fssf = &ssfs.sss_ssf;
1053		for ( i=0; i<sizeof(ssfs)/sizeof(slap_ssf_t); i++ ) {
1054			if ( bssf[i] ) fssf[i] = bssf[i];
1055		}
1056	}
1057
1058	switch( op->o_tag ) {
1059	case LDAP_REQ_ADD:
1060		opflag = SLAP_RESTRICT_OP_ADD;
1061		updateop++;
1062		break;
1063	case LDAP_REQ_BIND:
1064		opflag = SLAP_RESTRICT_OP_BIND;
1065		session++;
1066		break;
1067	case LDAP_REQ_COMPARE:
1068		opflag = SLAP_RESTRICT_OP_COMPARE;
1069		break;
1070	case LDAP_REQ_DELETE:
1071		updateop++;
1072		opflag = SLAP_RESTRICT_OP_DELETE;
1073		break;
1074	case LDAP_REQ_EXTENDED:
1075		opflag = SLAP_RESTRICT_OP_EXTENDED;
1076
1077		if( !opdata ) {
1078			/* treat unspecified as a modify */
1079			opflag = SLAP_RESTRICT_OP_MODIFY;
1080			updateop++;
1081			break;
1082		}
1083
1084		if( bvmatch( opdata, &slap_EXOP_START_TLS ) ) {
1085			session++;
1086			starttls++;
1087			exopflag = SLAP_RESTRICT_EXOP_START_TLS;
1088			break;
1089		}
1090
1091		if( bvmatch( opdata, &slap_EXOP_WHOAMI ) ) {
1092			exopflag = SLAP_RESTRICT_EXOP_WHOAMI;
1093			break;
1094		}
1095
1096		if ( bvmatch( opdata, &slap_EXOP_CANCEL ) ) {
1097			exopflag = SLAP_RESTRICT_EXOP_CANCEL;
1098			break;
1099		}
1100
1101		if ( bvmatch( opdata, &slap_EXOP_MODIFY_PASSWD ) ) {
1102			exopflag = SLAP_RESTRICT_EXOP_MODIFY_PASSWD;
1103			updateop++;
1104			break;
1105		}
1106
1107		/* treat everything else as a modify */
1108		opflag = SLAP_RESTRICT_OP_MODIFY;
1109		updateop++;
1110		break;
1111
1112	case LDAP_REQ_MODIFY:
1113		updateop++;
1114		opflag = SLAP_RESTRICT_OP_MODIFY;
1115		break;
1116	case LDAP_REQ_RENAME:
1117		updateop++;
1118		opflag = SLAP_RESTRICT_OP_RENAME;
1119		break;
1120	case LDAP_REQ_SEARCH:
1121		opflag = SLAP_RESTRICT_OP_SEARCH;
1122		break;
1123	case LDAP_REQ_UNBIND:
1124		session++;
1125		opflag = 0;
1126		break;
1127	default:
1128		rs->sr_text = "restrict operations internal error";
1129		rs->sr_err = LDAP_OTHER;
1130		return rs->sr_err;
1131	}
1132
1133	if ( !starttls ) {
1134		/* these checks don't apply to StartTLS */
1135
1136		rs->sr_err = LDAP_CONFIDENTIALITY_REQUIRED;
1137		if( op->o_transport_ssf < ssf->sss_transport ) {
1138			rs->sr_text = op->o_transport_ssf
1139				? "stronger transport confidentiality required"
1140				: "transport confidentiality required";
1141			return rs->sr_err;
1142		}
1143
1144		if( op->o_tls_ssf < ssf->sss_tls ) {
1145			rs->sr_text = op->o_tls_ssf
1146				? "stronger TLS confidentiality required"
1147				: "TLS confidentiality required";
1148			return rs->sr_err;
1149		}
1150
1151
1152		if( op->o_tag == LDAP_REQ_BIND && opdata == NULL ) {
1153			/* simple bind specific check */
1154			if( op->o_ssf < ssf->sss_simple_bind ) {
1155				rs->sr_text = op->o_ssf
1156					? "stronger confidentiality required"
1157					: "confidentiality required";
1158				return rs->sr_err;
1159			}
1160		}
1161
1162		if( op->o_tag != LDAP_REQ_BIND || opdata == NULL ) {
1163			/* these checks don't apply to SASL bind */
1164
1165			if( op->o_sasl_ssf < ssf->sss_sasl ) {
1166				rs->sr_text = op->o_sasl_ssf
1167					? "stronger SASL confidentiality required"
1168					: "SASL confidentiality required";
1169				return rs->sr_err;
1170			}
1171
1172			if( op->o_ssf < ssf->sss_ssf ) {
1173				rs->sr_text = op->o_ssf
1174					? "stronger confidentiality required"
1175					: "confidentiality required";
1176				return rs->sr_err;
1177			}
1178		}
1179
1180		if( updateop ) {
1181			if( op->o_transport_ssf < ssf->sss_update_transport ) {
1182				rs->sr_text = op->o_transport_ssf
1183					? "stronger transport confidentiality required for update"
1184					: "transport confidentiality required for update";
1185				return rs->sr_err;
1186			}
1187
1188			if( op->o_tls_ssf < ssf->sss_update_tls ) {
1189				rs->sr_text = op->o_tls_ssf
1190					? "stronger TLS confidentiality required for update"
1191					: "TLS confidentiality required for update";
1192				return rs->sr_err;
1193			}
1194
1195			if( op->o_sasl_ssf < ssf->sss_update_sasl ) {
1196				rs->sr_text = op->o_sasl_ssf
1197					? "stronger SASL confidentiality required for update"
1198					: "SASL confidentiality required for update";
1199				return rs->sr_err;
1200			}
1201
1202			if( op->o_ssf < ssf->sss_update_ssf ) {
1203				rs->sr_text = op->o_ssf
1204					? "stronger confidentiality required for update"
1205					: "confidentiality required for update";
1206				return rs->sr_err;
1207			}
1208
1209			if( !( global_allows & SLAP_ALLOW_UPDATE_ANON ) &&
1210				BER_BVISEMPTY( &op->o_ndn ) )
1211			{
1212				rs->sr_text = "modifications require authentication";
1213				rs->sr_err = LDAP_STRONG_AUTH_REQUIRED;
1214				return rs->sr_err;
1215			}
1216
1217#ifdef SLAP_X_LISTENER_MOD
1218			if ( op->o_conn->c_listener &&
1219				! ( op->o_conn->c_listener->sl_perms & ( !BER_BVISEMPTY( &op->o_ndn )
1220					? (S_IWUSR|S_IWOTH) : S_IWOTH ) ) )
1221			{
1222				/* no "w" mode means readonly */
1223				rs->sr_text = "modifications not allowed on this listener";
1224				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1225				return rs->sr_err;
1226			}
1227#endif /* SLAP_X_LISTENER_MOD */
1228		}
1229	}
1230
1231	if ( !session ) {
1232		/* these checks don't apply to Bind, StartTLS, or Unbind */
1233
1234		if( requires & SLAP_REQUIRE_STRONG ) {
1235			/* should check mechanism */
1236			if( ( op->o_transport_ssf < ssf->sss_transport
1237				&& op->o_authtype == LDAP_AUTH_SIMPLE )
1238				|| BER_BVISEMPTY( &op->o_dn ) )
1239			{
1240				rs->sr_text = "strong(er) authentication required";
1241				rs->sr_err = LDAP_STRONG_AUTH_REQUIRED;
1242				return rs->sr_err;
1243			}
1244		}
1245
1246		if( requires & SLAP_REQUIRE_SASL ) {
1247			if( op->o_authtype != LDAP_AUTH_SASL || BER_BVISEMPTY( &op->o_dn ) ) {
1248				rs->sr_text = "SASL authentication required";
1249				rs->sr_err = LDAP_STRONG_AUTH_REQUIRED;
1250				return rs->sr_err;
1251			}
1252		}
1253
1254		if( requires & SLAP_REQUIRE_AUTHC ) {
1255			if( BER_BVISEMPTY( &op->o_dn ) ) {
1256				rs->sr_text = "authentication required";
1257				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1258				return rs->sr_err;
1259			}
1260		}
1261
1262		if( requires & SLAP_REQUIRE_BIND ) {
1263			int version;
1264			ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
1265			version = op->o_conn->c_protocol;
1266			ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
1267
1268			if( !version ) {
1269				/* no bind has occurred */
1270				rs->sr_text = "BIND required";
1271				rs->sr_err = LDAP_OPERATIONS_ERROR;
1272				return rs->sr_err;
1273			}
1274		}
1275
1276		if( requires & SLAP_REQUIRE_LDAP_V3 ) {
1277			if( op->o_protocol < LDAP_VERSION3 ) {
1278				/* no bind has occurred */
1279				rs->sr_text = "operation restricted to LDAPv3 clients";
1280				rs->sr_err = LDAP_OPERATIONS_ERROR;
1281				return rs->sr_err;
1282			}
1283		}
1284
1285#ifdef SLAP_X_LISTENER_MOD
1286		if ( !starttls && BER_BVISEMPTY( &op->o_dn ) ) {
1287			if ( op->o_conn->c_listener &&
1288				!( op->o_conn->c_listener->sl_perms & S_IXOTH ))
1289		{
1290				/* no "x" mode means bind required */
1291				rs->sr_text = "bind required on this listener";
1292				rs->sr_err = LDAP_STRONG_AUTH_REQUIRED;
1293				return rs->sr_err;
1294			}
1295		}
1296
1297		if ( !starttls && !updateop ) {
1298			if ( op->o_conn->c_listener &&
1299				!( op->o_conn->c_listener->sl_perms &
1300					( !BER_BVISEMPTY( &op->o_dn )
1301						? (S_IRUSR|S_IROTH) : S_IROTH )))
1302			{
1303				/* no "r" mode means no read */
1304				rs->sr_text = "read not allowed on this listener";
1305				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1306				return rs->sr_err;
1307			}
1308		}
1309#endif /* SLAP_X_LISTENER_MOD */
1310
1311	}
1312
1313	if( ( restrictops & opflag )
1314			|| ( exopflag && ( restrictops & exopflag ) )
1315			|| (( restrictops & SLAP_RESTRICT_READONLY ) && updateop )) {
1316		if( ( restrictops & SLAP_RESTRICT_OP_MASK) == SLAP_RESTRICT_OP_READS ) {
1317			rs->sr_text = "read operations restricted";
1318		} else if ( restrictops & exopflag ) {
1319			rs->sr_text = "extended operation restricted";
1320		} else {
1321			rs->sr_text = "operation restricted";
1322		}
1323		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1324		return rs->sr_err;
1325 	}
1326
1327	rs->sr_err = LDAP_SUCCESS;
1328	return rs->sr_err;
1329}
1330
1331int backend_check_referrals( Operation *op, SlapReply *rs )
1332{
1333	rs->sr_err = LDAP_SUCCESS;
1334
1335	if( op->o_bd->be_chk_referrals ) {
1336		rs->sr_err = op->o_bd->be_chk_referrals( op, rs );
1337
1338		if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_REFERRAL ) {
1339			send_ldap_result( op, rs );
1340		}
1341	}
1342
1343	return rs->sr_err;
1344}
1345
1346int
1347be_entry_get_rw(
1348	Operation *op,
1349	struct berval *ndn,
1350	ObjectClass *oc,
1351	AttributeDescription *at,
1352	int rw,
1353	Entry **e )
1354{
1355	*e = NULL;
1356
1357	if ( op->o_bd == NULL ) {
1358		return LDAP_NO_SUCH_OBJECT;
1359	}
1360
1361	if ( op->o_bd->be_fetch ) {
1362		return op->o_bd->be_fetch( op, ndn, oc, at, rw, e );
1363	}
1364
1365	return LDAP_UNWILLING_TO_PERFORM;
1366}
1367
1368int
1369fe_acl_group(
1370	Operation *op,
1371	Entry	*target,
1372	struct berval *gr_ndn,
1373	struct berval *op_ndn,
1374	ObjectClass *group_oc,
1375	AttributeDescription *group_at )
1376{
1377	Entry *e;
1378	void *o_priv = op->o_private, *e_priv = NULL;
1379	Attribute *a;
1380	int rc;
1381	GroupAssertion *g;
1382	Backend *be = op->o_bd;
1383	OpExtra		*oex;
1384
1385	LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) {
1386		if ( oex->oe_key == (void *)backend_group )
1387			break;
1388	}
1389
1390	if ( oex && ((OpExtraDB *)oex)->oe_db )
1391		op->o_bd = ((OpExtraDB *)oex)->oe_db;
1392
1393	if ( !op->o_bd || !SLAP_DBHIDDEN( op->o_bd ))
1394		op->o_bd = select_backend( gr_ndn, 0 );
1395
1396	for ( g = op->o_groups; g; g = g->ga_next ) {
1397		if ( g->ga_be != op->o_bd || g->ga_oc != group_oc ||
1398			g->ga_at != group_at || g->ga_len != gr_ndn->bv_len )
1399		{
1400			continue;
1401		}
1402		if ( strcmp( g->ga_ndn, gr_ndn->bv_val ) == 0 ) {
1403			break;
1404		}
1405	}
1406
1407	if ( g ) {
1408		rc = g->ga_res;
1409		goto done;
1410	}
1411
1412	if ( target && dn_match( &target->e_nname, gr_ndn ) ) {
1413		e = target;
1414		rc = 0;
1415
1416	} else {
1417		op->o_private = NULL;
1418		rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e );
1419		e_priv = op->o_private;
1420		op->o_private = o_priv;
1421	}
1422
1423	if ( e ) {
1424		a = attr_find( e->e_attrs, group_at );
1425		if ( a ) {
1426			/* If the attribute is a subtype of labeledURI,
1427			 * treat this as a dynamic group ala groupOfURLs
1428			 */
1429			if ( is_at_subtype( group_at->ad_type,
1430				slap_schema.si_ad_labeledURI->ad_type ) )
1431			{
1432				int i;
1433				LDAPURLDesc *ludp;
1434				struct berval bv, nbase;
1435				Filter *filter;
1436				Entry *user = NULL;
1437				void *user_priv = NULL;
1438				Backend *b2 = op->o_bd;
1439
1440				if ( target && dn_match( &target->e_nname, op_ndn ) ) {
1441					user = target;
1442				}
1443
1444				rc = LDAP_COMPARE_FALSE;
1445				for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
1446					if ( ldap_url_parse( a->a_vals[i].bv_val, &ludp ) !=
1447						LDAP_URL_SUCCESS )
1448					{
1449						continue;
1450					}
1451
1452					BER_BVZERO( &nbase );
1453
1454					/* host, attrs and extensions parts must be empty */
1455					if ( ( ludp->lud_host && *ludp->lud_host )
1456						|| ludp->lud_attrs
1457						|| ludp->lud_exts )
1458					{
1459						goto loopit;
1460					}
1461
1462					ber_str2bv( ludp->lud_dn, 0, 0, &bv );
1463					if ( dnNormalize( 0, NULL, NULL, &bv, &nbase,
1464						op->o_tmpmemctx ) != LDAP_SUCCESS )
1465					{
1466						goto loopit;
1467					}
1468
1469					switch ( ludp->lud_scope ) {
1470					case LDAP_SCOPE_BASE:
1471						if ( !dn_match( &nbase, op_ndn ) ) {
1472							goto loopit;
1473						}
1474						break;
1475					case LDAP_SCOPE_ONELEVEL:
1476						dnParent( op_ndn, &bv );
1477						if ( !dn_match( &nbase, &bv ) ) {
1478							goto loopit;
1479						}
1480						break;
1481					case LDAP_SCOPE_SUBTREE:
1482						if ( !dnIsSuffix( op_ndn, &nbase ) ) {
1483							goto loopit;
1484						}
1485						break;
1486					case LDAP_SCOPE_SUBORDINATE:
1487						if ( dn_match( &nbase, op_ndn ) ||
1488							!dnIsSuffix( op_ndn, &nbase ) )
1489						{
1490							goto loopit;
1491						}
1492					}
1493
1494					/* NOTE: this could be NULL
1495					 * if no filter is provided,
1496					 * or if filter parsing fails.
1497					 * In the latter case,
1498					 * we should give up. */
1499					if ( ludp->lud_filter != NULL && ludp->lud_filter != '\0') {
1500						filter = str2filter_x( op, ludp->lud_filter );
1501						if ( filter == NULL ) {
1502							/* give up... */
1503							rc = LDAP_OTHER;
1504							goto loopit;
1505						}
1506
1507						/* only get user if required
1508						 * and not available yet */
1509						if ( user == NULL ) {
1510							int rc2;
1511
1512							op->o_bd = select_backend( op_ndn, 0 );
1513							op->o_private = NULL;
1514							rc2 = be_entry_get_rw( op, op_ndn, NULL, NULL, 0, &user );
1515							user_priv = op->o_private;
1516							op->o_private = o_priv;
1517							if ( rc2 != 0 ) {
1518								/* give up... */
1519								rc = LDAP_OTHER;
1520								goto loopit;
1521							}
1522						}
1523
1524						if ( test_filter( NULL, user, filter ) ==
1525							LDAP_COMPARE_TRUE )
1526						{
1527							rc = 0;
1528						}
1529						filter_free_x( op, filter, 1 );
1530					}
1531loopit:
1532					ldap_free_urldesc( ludp );
1533					if ( !BER_BVISNULL( &nbase ) ) {
1534						op->o_tmpfree( nbase.bv_val, op->o_tmpmemctx );
1535					}
1536					if ( rc != LDAP_COMPARE_FALSE ) {
1537						break;
1538					}
1539				}
1540
1541				if ( user != NULL && user != target ) {
1542					op->o_private = user_priv;
1543					be_entry_release_r( op, user );
1544					op->o_private = o_priv;
1545				}
1546				op->o_bd = b2;
1547
1548			} else {
1549				rc = attr_valfind( a,
1550					SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
1551					SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
1552					op_ndn, NULL, op->o_tmpmemctx );
1553				if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) {
1554					rc = LDAP_COMPARE_FALSE;
1555				}
1556			}
1557
1558		} else {
1559			rc = LDAP_NO_SUCH_ATTRIBUTE;
1560		}
1561
1562		if ( e != target ) {
1563			op->o_private = e_priv;
1564			be_entry_release_r( op, e );
1565			op->o_private = o_priv;
1566		}
1567
1568	} else {
1569		rc = LDAP_NO_SUCH_OBJECT;
1570	}
1571
1572	if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache ) {
1573		g = op->o_tmpalloc( sizeof( GroupAssertion ) + gr_ndn->bv_len,
1574			op->o_tmpmemctx );
1575		g->ga_be = op->o_bd;
1576		g->ga_oc = group_oc;
1577		g->ga_at = group_at;
1578		g->ga_res = rc;
1579		g->ga_len = gr_ndn->bv_len;
1580		strcpy( g->ga_ndn, gr_ndn->bv_val );
1581		g->ga_next = op->o_groups;
1582		op->o_groups = g;
1583	}
1584
1585done:
1586	op->o_bd = be;
1587	return rc;
1588}
1589
1590int
1591backend_group(
1592	Operation *op,
1593	Entry	*target,
1594	struct berval *gr_ndn,
1595	struct berval *op_ndn,
1596	ObjectClass *group_oc,
1597	AttributeDescription *group_at )
1598{
1599	int			rc;
1600	BackendDB *be_orig;
1601	OpExtraDB	oex;
1602
1603	if ( op->o_abandon ) {
1604		return SLAPD_ABANDON;
1605	}
1606
1607	oex.oe_db = op->o_bd;
1608	oex.oe.oe_key = (void *)backend_group;
1609	LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oex.oe, oe_next);
1610
1611	be_orig = op->o_bd;
1612	op->o_bd = frontendDB;
1613	rc = frontendDB->be_group( op, target, gr_ndn,
1614		op_ndn, group_oc, group_at );
1615	op->o_bd = be_orig;
1616	LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next);
1617
1618	return rc;
1619}
1620
1621int
1622fe_acl_attribute(
1623	Operation *op,
1624	Entry	*target,
1625	struct berval	*edn,
1626	AttributeDescription *entry_at,
1627	BerVarray *vals,
1628	slap_access_t access )
1629{
1630	Entry			*e = NULL;
1631	void			*o_priv = op->o_private, *e_priv = NULL;
1632	Attribute		*a = NULL;
1633	int			freeattr = 0, i, j, rc = LDAP_SUCCESS;
1634	AccessControlState	acl_state = ACL_STATE_INIT;
1635	Backend			*be = op->o_bd;
1636	OpExtra		*oex;
1637
1638	LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) {
1639		if ( oex->oe_key == (void *)backend_attribute )
1640			break;
1641	}
1642
1643	if ( oex && ((OpExtraDB *)oex)->oe_db )
1644		op->o_bd = ((OpExtraDB *)oex)->oe_db;
1645
1646	if ( !op->o_bd || !SLAP_DBHIDDEN( op->o_bd ))
1647		op->o_bd = select_backend( edn, 0 );
1648
1649	if ( target && dn_match( &target->e_nname, edn ) ) {
1650		e = target;
1651
1652	} else {
1653		op->o_private = NULL;
1654		rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e );
1655		e_priv = op->o_private;
1656		op->o_private = o_priv;
1657	}
1658
1659	if ( e ) {
1660		if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children ) {
1661			assert( vals == NULL );
1662
1663			rc = LDAP_SUCCESS;
1664			if ( op->o_conn && access > ACL_NONE &&
1665				access_allowed( op, e, entry_at, NULL,
1666						access, &acl_state ) == 0 )
1667			{
1668				rc = LDAP_INSUFFICIENT_ACCESS;
1669			}
1670			goto freeit;
1671		}
1672
1673		a = attr_find( e->e_attrs, entry_at );
1674		if ( a == NULL ) {
1675			SlapReply	rs = { 0 };
1676			AttributeName	anlist[ 2 ];
1677
1678			anlist[ 0 ].an_name = entry_at->ad_cname;
1679			anlist[ 0 ].an_desc = entry_at;
1680			BER_BVZERO( &anlist[ 1 ].an_name );
1681			rs.sr_attrs = anlist;
1682
1683 			/* NOTE: backend_operational() is also called
1684 			 * when returning results, so it's supposed
1685 			 * to do no harm to entries */
1686 			rs.sr_entry = e;
1687  			rc = backend_operational( op, &rs );
1688 			rs.sr_entry = NULL;
1689
1690			if ( rc == LDAP_SUCCESS ) {
1691				if ( rs.sr_operational_attrs ) {
1692					freeattr = 1;
1693					a = rs.sr_operational_attrs;
1694
1695				} else {
1696					rc = LDAP_NO_SUCH_ATTRIBUTE;
1697				}
1698			}
1699		}
1700
1701		if ( a ) {
1702			BerVarray v;
1703
1704			if ( op->o_conn && access > ACL_NONE &&
1705				access_allowed( op, e, entry_at, NULL,
1706						access, &acl_state ) == 0 )
1707			{
1708				rc = LDAP_INSUFFICIENT_ACCESS;
1709				goto freeit;
1710			}
1711
1712			i = a->a_numvals;
1713			v = op->o_tmpalloc( sizeof(struct berval) * ( i + 1 ),
1714				op->o_tmpmemctx );
1715			for ( i = 0, j = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ )
1716			{
1717				if ( op->o_conn && access > ACL_NONE &&
1718					access_allowed( op, e, entry_at,
1719							&a->a_nvals[i],
1720							access,
1721							&acl_state ) == 0 )
1722				{
1723					continue;
1724				}
1725				ber_dupbv_x( &v[j], &a->a_nvals[i],
1726						op->o_tmpmemctx );
1727				if ( !BER_BVISNULL( &v[j] ) ) {
1728					j++;
1729				}
1730			}
1731			if ( j == 0 ) {
1732				op->o_tmpfree( v, op->o_tmpmemctx );
1733				*vals = NULL;
1734				rc = LDAP_INSUFFICIENT_ACCESS;
1735
1736			} else {
1737				BER_BVZERO( &v[j] );
1738				*vals = v;
1739				rc = LDAP_SUCCESS;
1740			}
1741		}
1742freeit:		if ( e != target ) {
1743			op->o_private = e_priv;
1744			be_entry_release_r( op, e );
1745			op->o_private = o_priv;
1746		}
1747		if ( freeattr ) {
1748			attr_free( a );
1749		}
1750	}
1751
1752	op->o_bd = be;
1753	return rc;
1754}
1755
1756int
1757backend_attribute(
1758	Operation *op,
1759	Entry	*target,
1760	struct berval	*edn,
1761	AttributeDescription *entry_at,
1762	BerVarray *vals,
1763	slap_access_t access )
1764{
1765	int			rc;
1766	BackendDB *be_orig;
1767	OpExtraDB	oex;
1768
1769	oex.oe_db = op->o_bd;
1770	oex.oe.oe_key = (void *)backend_attribute;
1771	LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oex.oe, oe_next);
1772
1773	be_orig = op->o_bd;
1774	op->o_bd = frontendDB;
1775	rc = frontendDB->be_attribute( op, target, edn,
1776		entry_at, vals, access );
1777	op->o_bd = be_orig;
1778	LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next);
1779
1780	return rc;
1781}
1782
1783int
1784backend_access(
1785	Operation		*op,
1786	Entry			*target,
1787	struct berval		*edn,
1788	AttributeDescription	*entry_at,
1789	struct berval		*nval,
1790	slap_access_t		access,
1791	slap_mask_t		*mask )
1792{
1793	Entry		*e = NULL;
1794	void		*o_priv = op->o_private, *e_priv = NULL;
1795	int		rc = LDAP_INSUFFICIENT_ACCESS;
1796	Backend		*be = op->o_bd;
1797
1798	/* pedantic */
1799	assert( op != NULL );
1800	assert( op->o_conn != NULL );
1801	assert( edn != NULL );
1802	assert( access > ACL_NONE );
1803
1804	if ( !op->o_bd ) {
1805		op->o_bd = select_backend( edn, 0 );
1806	}
1807
1808	if ( target && dn_match( &target->e_nname, edn ) ) {
1809		e = target;
1810
1811	} else {
1812		op->o_private = NULL;
1813		rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e );
1814		e_priv = op->o_private;
1815		op->o_private = o_priv;
1816	}
1817
1818	if ( e ) {
1819		Attribute	*a = NULL;
1820		int		freeattr = 0;
1821
1822		if ( entry_at == NULL ) {
1823			entry_at = slap_schema.si_ad_entry;
1824		}
1825
1826		if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children )
1827		{
1828			if ( access_allowed_mask( op, e, entry_at,
1829					NULL, access, NULL, mask ) == 0 )
1830			{
1831				rc = LDAP_INSUFFICIENT_ACCESS;
1832
1833			} else {
1834				rc = LDAP_SUCCESS;
1835			}
1836
1837		} else {
1838			a = attr_find( e->e_attrs, entry_at );
1839			if ( a == NULL ) {
1840				SlapReply	rs = { 0 };
1841				AttributeName	anlist[ 2 ];
1842
1843				anlist[ 0 ].an_name = entry_at->ad_cname;
1844				anlist[ 0 ].an_desc = entry_at;
1845				BER_BVZERO( &anlist[ 1 ].an_name );
1846				rs.sr_attrs = anlist;
1847
1848				rs.sr_attr_flags = slap_attr_flags( rs.sr_attrs );
1849
1850				/* NOTE: backend_operational() is also called
1851				 * when returning results, so it's supposed
1852				 * to do no harm to entries */
1853				rs.sr_entry = e;
1854				rc = backend_operational( op, &rs );
1855				rs.sr_entry = NULL;
1856
1857				if ( rc == LDAP_SUCCESS ) {
1858					if ( rs.sr_operational_attrs ) {
1859						freeattr = 1;
1860						a = rs.sr_operational_attrs;
1861
1862					} else {
1863						rc = LDAP_NO_SUCH_OBJECT;
1864					}
1865				}
1866			}
1867
1868			if ( a ) {
1869				if ( access_allowed_mask( op, e, entry_at,
1870						nval, access, NULL, mask ) == 0 )
1871				{
1872					rc = LDAP_INSUFFICIENT_ACCESS;
1873					goto freeit;
1874				}
1875				rc = LDAP_SUCCESS;
1876			}
1877		}
1878freeit:		if ( e != target ) {
1879			op->o_private = e_priv;
1880			be_entry_release_r( op, e );
1881			op->o_private = o_priv;
1882		}
1883		if ( freeattr ) {
1884			attr_free( a );
1885		}
1886	}
1887
1888	op->o_bd = be;
1889	return rc;
1890}
1891
1892int
1893fe_aux_operational(
1894	Operation *op,
1895	SlapReply *rs )
1896{
1897	Attribute		**ap;
1898	int			rc = LDAP_SUCCESS;
1899	BackendDB		*be_orig = op->o_bd;
1900	OpExtra		*oex;
1901
1902	LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) {
1903		if ( oex->oe_key == (void *)backend_operational )
1904			break;
1905	}
1906
1907	for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
1908		/* just count them */ ;
1909
1910	/*
1911	 * If operational attributes (allegedly) are required,
1912	 * and the backend supports specific operational attributes,
1913	 * add them to the attribute list
1914	 */
1915	if ( !( rs->sr_flags & REP_NO_ENTRYDN )
1916		&& ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
1917		ad_inlist( slap_schema.si_ad_entryDN, rs->sr_attrs ) ) ) )
1918	{
1919		*ap = slap_operational_entryDN( rs->sr_entry );
1920		ap = &(*ap)->a_next;
1921	}
1922
1923	if ( !( rs->sr_flags & REP_NO_SUBSCHEMA)
1924		&& ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
1925		ad_inlist( slap_schema.si_ad_subschemaSubentry, rs->sr_attrs ) ) ) )
1926	{
1927		*ap = slap_operational_subschemaSubentry( op->o_bd );
1928		ap = &(*ap)->a_next;
1929	}
1930
1931	/* Let the overlays have a chance at this */
1932	if ( oex && ((OpExtraDB *)oex)->oe_db )
1933		op->o_bd = ((OpExtraDB *)oex)->oe_db;
1934
1935	if ( !op->o_bd || !SLAP_DBHIDDEN( op->o_bd ))
1936		op->o_bd = select_backend( &op->o_req_ndn, 0 );
1937
1938	if ( op->o_bd != NULL && !be_match( op->o_bd, frontendDB ) &&
1939		( SLAP_OPATTRS( rs->sr_attr_flags ) || rs->sr_attrs ) &&
1940		op->o_bd->be_operational != NULL )
1941	{
1942		rc = op->o_bd->be_operational( op, rs );
1943	}
1944	op->o_bd = be_orig;
1945
1946	return rc;
1947}
1948
1949int backend_operational( Operation *op, SlapReply *rs )
1950{
1951	int rc;
1952	BackendDB *be_orig;
1953	OpExtraDB	oex;
1954
1955	oex.oe_db = op->o_bd;
1956	oex.oe.oe_key = (void *)backend_operational;
1957	LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oex.oe, oe_next);
1958
1959	/* Moved this into the frontend so global overlays are called */
1960
1961	be_orig = op->o_bd;
1962	op->o_bd = frontendDB;
1963	rc = frontendDB->be_operational( op, rs );
1964	op->o_bd = be_orig;
1965	LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next);
1966
1967	return rc;
1968}
1969
1970/* helper that calls the bi_tool_entry_first_x() variant with default args;
1971 * use to initialize a backend's bi_tool_entry_first() when appropriate
1972 */
1973ID
1974backend_tool_entry_first( BackendDB *be )
1975{
1976	return be->bd_info->bi_tool_entry_first_x( be,
1977		NULL, LDAP_SCOPE_DEFAULT, NULL );
1978}
1979