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