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