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