1 /* backend.c - routines for dealing with back-end databases */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/backend.c,v 1.362.2.17 2008/04/24 08:13:39 hyc Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17 * All rights reserved.
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.
32 #include <ac/string.h>
33 #include <ac/socket.h>
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.
50 slap_bi_head backendInfo
= LDAP_STAILQ_HEAD_INITIALIZER(backendInfo
);
53 slap_be_head backendDB
= LDAP_STAILQ_HEAD_INITIALIZER(backendDB
);
56 backend_init_controls( BackendInfo
*bi
)
58 if ( bi
->bi_controls
) {
61 for ( i
= 0; bi
->bi_controls
[ i
]; i
++ ) {
64 if ( slap_find_control_id( bi
->bi_controls
[ i
], &cid
)
65 == LDAP_CONTROL_NOT_FOUND
)
67 if ( !( slapMode
& SLAP_TOOL_MODE
) ) {
74 bi
->bi_ctrls
[ cid
] = 1;
81 int backend_init(void)
86 if((nBackendInfo
!= 0) || !LDAP_STAILQ_EMPTY(&backendInfo
)) {
87 /* already initialized */
88 Debug( LDAP_DEBUG_ANY
,
89 "backend_init: already initialized\n", 0, 0, 0 );
93 for( bi
=slap_binfo
; bi
->bi_type
!= NULL
; bi
++,nBackendInfo
++ ) {
94 assert( bi
->bi_init
!= 0 );
96 rc
= bi
->bi_init( bi
);
99 Debug( LDAP_DEBUG_ANY
,
100 "backend_init: initialized for type \"%s\"\n",
102 /* destroy those we've already inited */
107 if ( slap_binfo
[nBackendInfo
].bi_destroy
) {
108 slap_binfo
[nBackendInfo
].bi_destroy(
109 &slap_binfo
[nBackendInfo
] );
115 LDAP_STAILQ_INSERT_TAIL(&backendInfo
, bi
, bi_next
);
118 if ( nBackendInfo
> 0) {
126 Debug( LDAP_DEBUG_ANY
,
127 "backend_init: failed\n",
131 #endif /* SLAPD_MODULES */
134 int backend_add(BackendInfo
*aBackendInfo
)
138 if ( aBackendInfo
->bi_init
== NULL
) {
139 Debug( LDAP_DEBUG_ANY
, "backend_add: "
140 "backend type \"%s\" does not have the (mandatory)init function\n",
141 aBackendInfo
->bi_type
, 0, 0 );
145 rc
= aBackendInfo
->bi_init(aBackendInfo
);
147 Debug( LDAP_DEBUG_ANY
,
148 "backend_add: initialization for type \"%s\" failed\n",
149 aBackendInfo
->bi_type
, 0, 0 );
153 (void)backend_init_controls( aBackendInfo
);
155 /* now add the backend type to the Backend Info List */
156 LDAP_STAILQ_INSERT_TAIL( &backendInfo
, aBackendInfo
, bi_next
);
162 backend_set_controls( BackendDB
*be
)
164 BackendInfo
*bi
= be
->bd_info
;
166 /* back-relay takes care of itself; so may do other */
167 if ( overlay_is_over( be
) ) {
168 bi
= ((slap_overinfo
*)be
->bd_info
->bi_private
)->oi_orig
;
171 if ( bi
->bi_controls
) {
172 if ( be
->be_ctrls
[ SLAP_MAX_CIDS
] == 0 ) {
173 AC_MEMCPY( be
->be_ctrls
, bi
->bi_ctrls
,
174 sizeof( be
->be_ctrls
) );
175 be
->be_ctrls
[ SLAP_MAX_CIDS
] = 1;
180 for ( i
= 0; i
< SLAP_MAX_CIDS
; i
++ ) {
181 if ( bi
->bi_ctrls
[ i
] ) {
182 be
->be_ctrls
[ i
] = bi
->bi_ctrls
[ i
];
192 /* startup a specific backend database */
193 int backend_startup_one(Backend
*be
, ConfigReply
*cr
)
197 assert( be
!= NULL
);
199 be
->be_pending_csn_list
= (struct be_pcl
*)
200 ch_calloc( 1, sizeof( struct be_pcl
) );
202 LDAP_TAILQ_INIT( be
->be_pending_csn_list
);
204 Debug( LDAP_DEBUG_TRACE
,
205 "backend_startup_one: starting \"%s\"\n",
206 be
->be_suffix
? be
->be_suffix
[0].bv_val
: "(unknown)",
209 /* set database controls */
210 (void)backend_set_controls( be
);
213 if ( !BER_BVISEMPTY( &be
->be_rootndn
)
214 && select_backend( &be
->be_rootndn
, 0 ) == be
215 && BER_BVISNULL( &be
->be_rootpw
) )
217 /* warning: if rootdn entry is created,
218 * it can take rootdn privileges;
219 * set empty rootpw to prevent */
223 if ( be
->bd_info
->bi_db_open
) {
224 rc
= be
->bd_info
->bi_db_open( be
, cr
);
226 (void)backend_set_controls( be
);
229 Debug( LDAP_DEBUG_ANY
,
230 "backend_startup_one: bi_db_open failed! (%d)\n",
238 int backend_startup(Backend
*be
)
243 ConfigReply cr
={0, ""};
245 if( ! ( nBackendDB
> 0 ) ) {
247 Debug( LDAP_DEBUG_ANY
,
248 "backend_startup: %d databases to startup.\n",
254 if ( be
->bd_info
->bi_open
) {
255 rc
= be
->bd_info
->bi_open( be
->bd_info
);
257 Debug( LDAP_DEBUG_ANY
,
258 "backend_startup: bi_open failed!\n",
264 /* append global access controls */
265 acl_append( &be
->be_acl
, frontendDB
->be_acl
, -1 );
267 return backend_startup_one( be
, &cr
);
270 /* open frontend, if required */
271 if ( frontendDB
->bd_info
->bi_db_open
) {
272 rc
= frontendDB
->bd_info
->bi_db_open( frontendDB
, &cr
);
274 Debug( LDAP_DEBUG_ANY
,
275 "backend_startup: bi_db_open(frontend) failed! (%d)\n",
281 /* open each backend type */
283 LDAP_STAILQ_FOREACH(bi
, &backendInfo
, bi_next
) {
285 if( bi
->bi_nDB
== 0) {
286 /* no database of this type, don't open */
291 rc
= bi
->bi_open( bi
);
293 Debug( LDAP_DEBUG_ANY
,
294 "backend_startup: bi_open %d (%s) failed!\n",
300 (void)backend_init_controls( bi
);
303 /* open each backend database */
305 LDAP_STAILQ_FOREACH(be
, &backendDB
, be_next
) {
307 if ( be
->be_suffix
== NULL
) {
308 Debug( LDAP_DEBUG_ANY
,
309 "backend_startup: warning, database %d (%s) "
311 i
, be
->bd_info
->bi_type
, 0 );
313 /* append global access controls */
314 acl_append( &be
->be_acl
, frontendDB
->be_acl
, -1 );
316 rc
= backend_startup_one( be
, &cr
);
324 int backend_num( Backend
*be
)
329 if( be
== NULL
) return -1;
331 LDAP_STAILQ_FOREACH( b2
, &backendDB
, be_next
) {
332 if( be
== b2
) return i
;
338 int backend_shutdown( Backend
*be
)
344 /* shutdown a specific backend database */
346 if ( be
->bd_info
->bi_nDB
== 0 ) {
347 /* no database of this type, we never opened it */
351 if ( be
->bd_info
->bi_db_close
) {
352 be
->bd_info
->bi_db_close( be
, NULL
);
355 if( be
->bd_info
->bi_close
) {
356 be
->bd_info
->bi_close( be
->bd_info
);
362 /* close each backend database */
363 LDAP_STAILQ_FOREACH( be
, &backendDB
, be_next
) {
364 if ( be
->bd_info
->bi_db_close
) {
365 be
->bd_info
->bi_db_close( be
, NULL
);
369 Debug( LDAP_DEBUG_ANY
,
370 "backend_close: bi_db_close %s failed!\n",
375 /* close each backend type */
376 LDAP_STAILQ_FOREACH( bi
, &backendInfo
, bi_next
) {
377 if( bi
->bi_nDB
== 0 ) {
378 /* no database of this type */
387 /* close frontend, if required */
388 if ( frontendDB
->bd_info
->bi_db_close
) {
389 rc
= frontendDB
->bd_info
->bi_db_close ( frontendDB
, NULL
);
391 Debug( LDAP_DEBUG_ANY
,
392 "backend_startup: bi_db_close(frontend) failed! (%d)\n",
401 * This function is supposed to be the exact counterpart
402 * of backend_startup_one(), although this one calls bi_db_destroy()
403 * while backend_startup_one() calls bi_db_open().
405 * Make sure backend_stopdown_one() destroys resources allocated
406 * by backend_startup_one(); only call backend_destroy_one() when
407 * all stuff in a BackendDB needs to be destroyed
410 backend_stopdown_one( BackendDB
*bd
)
412 if ( bd
->be_pending_csn_list
) {
413 struct slap_csn_entry
*csne
;
414 csne
= LDAP_TAILQ_FIRST( bd
->be_pending_csn_list
);
416 struct slap_csn_entry
*tmp_csne
= csne
;
418 LDAP_TAILQ_REMOVE( bd
->be_pending_csn_list
, csne
, ce_csn_link
);
419 ch_free( csne
->ce_csn
.bv_val
);
420 csne
= LDAP_TAILQ_NEXT( csne
, ce_csn_link
);
423 ch_free( bd
->be_pending_csn_list
);
426 if ( bd
->bd_info
->bi_db_destroy
) {
427 bd
->bd_info
->bi_db_destroy( bd
, NULL
);
431 void backend_destroy_one( BackendDB
*bd
, int dynamic
)
434 LDAP_STAILQ_REMOVE(&backendDB
, bd
, BackendDB
, be_next
);
437 if ( bd
->be_syncinfo
) {
438 syncinfo_free( bd
->be_syncinfo
, 1 );
441 backend_stopdown_one( bd
);
443 ber_bvarray_free( bd
->be_suffix
);
444 ber_bvarray_free( bd
->be_nsuffix
);
445 if ( !BER_BVISNULL( &bd
->be_rootdn
) ) {
446 free( bd
->be_rootdn
.bv_val
);
448 if ( !BER_BVISNULL( &bd
->be_rootndn
) ) {
449 free( bd
->be_rootndn
.bv_val
);
451 if ( !BER_BVISNULL( &bd
->be_rootpw
) ) {
452 free( bd
->be_rootpw
.bv_val
);
454 acl_destroy( bd
->be_acl
, frontendDB
->be_acl
);
455 limits_destroy( bd
->be_limits
);
456 if ( !BER_BVISNULL( &bd
->be_update_ndn
) ) {
457 ch_free( bd
->be_update_ndn
.bv_val
);
459 if ( bd
->be_update_refs
) {
460 ber_bvarray_free( bd
->be_update_refs
);
468 int backend_destroy(void)
473 /* destroy each backend database */
474 while (( bd
= LDAP_STAILQ_FIRST(&backendDB
))) {
475 backend_destroy_one( bd
, 1 );
478 /* destroy each backend type */
479 LDAP_STAILQ_FOREACH( bi
, &backendInfo
, bi_next
) {
480 if( bi
->bi_destroy
) {
481 bi
->bi_destroy( bi
);
486 LDAP_STAILQ_INIT(&backendInfo
);
488 /* destroy frontend database */
491 if ( bd
->bd_info
->bi_db_destroy
) {
492 bd
->bd_info
->bi_db_destroy( bd
, NULL
);
494 ber_bvarray_free( bd
->be_suffix
);
495 ber_bvarray_free( bd
->be_nsuffix
);
496 if ( !BER_BVISNULL( &bd
->be_rootdn
) ) {
497 free( bd
->be_rootdn
.bv_val
);
499 if ( !BER_BVISNULL( &bd
->be_rootndn
) ) {
500 free( bd
->be_rootndn
.bv_val
);
502 if ( !BER_BVISNULL( &bd
->be_rootpw
) ) {
503 free( bd
->be_rootpw
.bv_val
);
505 acl_destroy( bd
->be_acl
, frontendDB
->be_acl
);
511 BackendInfo
* backend_info(const char *type
)
515 /* search for the backend type */
516 LDAP_STAILQ_FOREACH(bi
,&backendInfo
,bi_next
) {
517 if( strcasecmp(bi
->bi_type
, type
) == 0 ) {
531 /* If idx < 0, just add to end of list */
533 LDAP_STAILQ_INSERT_TAIL(&backendDB
, be
, be_next
);
534 } else if ( idx
== 0 ) {
535 LDAP_STAILQ_INSERT_HEAD(&backendDB
, be
, be_next
);
540 b2
= LDAP_STAILQ_FIRST(&backendDB
);
542 for (i
=0; i
<idx
; i
++) {
543 b2
= LDAP_STAILQ_NEXT(b2
, be_next
);
545 LDAP_STAILQ_INSERT_AFTER(&backendDB
, b2
, be
, be_next
);
555 LDAP_STAILQ_REMOVE(&backendDB
, be
, BackendDB
, be_next
);
556 backend_db_insert(be
, idx
);
566 BackendInfo
*bi
= backend_info(type
);
571 fprintf( stderr
, "Unrecognized database type (%s)\n", type
);
575 /* If be is provided, treat it as private. Otherwise allocate
576 * one and add it to the global list.
579 be
= ch_calloc( 1, sizeof(Backend
) );
581 if ( idx
>= nbackends
)
584 backend_db_insert( be
, idx
);
590 be
->be_def_limit
= frontendDB
->be_def_limit
;
591 be
->be_dfltaccess
= frontendDB
->be_dfltaccess
;
593 be
->be_restrictops
= frontendDB
->be_restrictops
;
594 be
->be_requires
= frontendDB
->be_requires
;
595 be
->be_ssf_set
= frontendDB
->be_ssf_set
;
597 be
->be_pcl_mutexp
= &be
->be_pcl_mutex
;
598 ldap_pvt_thread_mutex_init( be
->be_pcl_mutexp
);
600 /* assign a default depth limit for alias deref */
601 be
->be_max_deref_depth
= SLAPD_DEFAULT_MAXDEREFDEPTH
;
603 if ( bi
->bi_db_init
) {
604 rc
= bi
->bi_db_init( be
, cr
);
608 fprintf( stderr
, "database init failed (%s)\n", type
);
609 /* If we created and linked this be, remove it and free it */
611 LDAP_STAILQ_REMOVE(&backendDB
, be
, BackendDB
, be_next
);
627 LDAP_STAILQ_FOREACH( be
, &backendDB
, be_next
) {
628 if ( be
->bd_info
->bi_db_close
) {
629 be
->bd_info
->bi_db_close( be
, NULL
);
633 if ( frontendDB
->bd_info
->bi_db_close
) {
634 frontendDB
->bd_info
->bi_db_close( frontendDB
, NULL
);
645 ber_len_t len
, dnlen
= dn
->bv_len
;
648 LDAP_STAILQ_FOREACH( be
, &backendDB
, be_next
) {
649 if ( be
->be_nsuffix
== NULL
|| SLAP_DBHIDDEN( be
)) {
653 for ( j
= 0; !BER_BVISNULL( &be
->be_nsuffix
[j
] ); j
++ )
655 if ( ( SLAP_GLUE_SUBORDINATE( be
) ) && noSubs
)
660 len
= be
->be_nsuffix
[j
].bv_len
;
663 /* suffix is longer than DN */
668 * input DN is normalized, so the separator check
669 * need not look at escaping
671 if ( len
&& len
< dnlen
&&
672 !DN_SEPARATOR( dn
->bv_val
[(dnlen
-len
)-1] ))
677 if ( strcmp( be
->be_nsuffix
[j
].bv_val
,
678 &dn
->bv_val
[dnlen
-len
] ) == 0 )
691 struct berval
*bvsuffix
)
695 if ( be
->be_nsuffix
== NULL
) {
699 for ( i
= 0; !BER_BVISNULL( &be
->be_nsuffix
[i
] ); i
++ ) {
700 if ( bvmatch( &be
->be_nsuffix
[i
], bvsuffix
) ) {
711 struct berval
*bvsubordinate
)
715 if ( be
->be_nsuffix
== NULL
) {
719 for ( i
= 0; !BER_BVISNULL( &be
->be_nsuffix
[i
] ); i
++ ) {
720 if ( dnIsSuffix( bvsubordinate
, &be
->be_nsuffix
[i
] ) ) {
729 be_isroot_dn( Backend
*be
, struct berval
*ndn
)
731 if ( BER_BVISEMPTY( ndn
) || BER_BVISEMPTY( &be
->be_rootndn
) ) {
735 return dn_match( &be
->be_rootndn
, ndn
);
739 be_slurp_update( Operation
*op
)
741 return ( SLAP_SLURP_SHADOW( op
->o_bd
) &&
742 be_isupdate_dn( op
->o_bd
, &op
->o_ndn
) );
746 be_shadow_update( Operation
*op
)
748 /* This assumes that all internal ops (connid == -1) on a syncrepl
749 * database are syncrepl operations.
751 return (( SLAP_SYNC_SHADOW( op
->o_bd
) && op
->o_connid
== -1 ) ||
752 ( SLAP_SHADOW( op
->o_bd
) && be_isupdate_dn( op
->o_bd
, &op
->o_ndn
) ) );
756 be_isupdate_dn( Backend
*be
, struct berval
*ndn
)
758 if ( BER_BVISEMPTY( ndn
) || BER_BVISEMPTY( &be
->be_update_ndn
) ) {
762 return dn_match( &be
->be_update_ndn
, ndn
);
766 be_root_dn( Backend
*be
)
768 return &be
->be_rootdn
;
772 be_isroot( Operation
*op
)
774 return be_isroot_dn( op
->o_bd
, &op
->o_ndn
);
778 be_isroot_pw( Operation
*op
)
780 return be_rootdn_bind( op
, NULL
) == LDAP_SUCCESS
;
784 * checks if binding as rootdn
787 * SLAP_CB_CONTINUE if not the rootdn, or if rootpw is null
788 * LDAP_SUCCESS if rootdn & rootpw
789 * LDAP_INVALID_CREDENTIALS if rootdn & !rootpw
792 * if LDAP_SUCCESS, op->orb_edn is set
793 * if LDAP_INVALID_CREDENTIALS, response is sent to client
796 be_rootdn_bind( Operation
*op
, SlapReply
*rs
)
800 void *old_authctx
= NULL
;
803 assert( op
->o_tag
== LDAP_REQ_BIND
);
804 assert( op
->orb_method
== LDAP_AUTH_SIMPLE
);
806 if ( !be_isroot_dn( op
->o_bd
, &op
->o_req_ndn
) ) {
807 return SLAP_CB_CONTINUE
;
810 if ( BER_BVISNULL( &op
->o_bd
->be_rootpw
) ) {
811 /* give the database a chance */
812 return SLAP_CB_CONTINUE
;
815 if ( BER_BVISEMPTY( &op
->o_bd
->be_rootpw
) ) {
816 /* rootdn bind explicitly disallowed */
817 rc
= LDAP_INVALID_CREDENTIALS
;
826 ldap_pvt_thread_pool_setkey( op
->o_threadctx
, (void *)slap_sasl_bind
,
827 op
->o_conn
->c_sasl_authctx
, 0, &old_authctx
, NULL
);
830 rc
= lutil_passwd( &op
->o_bd
->be_rootpw
, &op
->orb_cred
, NULL
, NULL
);
833 ldap_pvt_thread_pool_setkey( op
->o_threadctx
, (void *)slap_sasl_bind
,
834 old_authctx
, 0, NULL
, NULL
);
837 rc
= ( rc
== 0 ? LDAP_SUCCESS
: LDAP_INVALID_CREDENTIALS
);
842 Debug( LDAP_DEBUG_TRACE
, "%s: rootdn=\"%s\" bind%s\n",
843 op
->o_log_prefix
, op
->o_bd
->be_rootdn
.bv_val
,
844 rc
== LDAP_SUCCESS
? " succeeded" : " failed" );
846 if ( rc
== LDAP_SUCCESS
) {
847 /* Set to the pretty rootdn */
848 ber_dupbv( &op
->orb_edn
, &op
->o_bd
->be_rootdn
);
851 send_ldap_result( op
, rs
);
864 if ( op
->o_bd
->be_release
) {
865 /* free and release entry from backend */
866 return op
->o_bd
->be_release( op
, e
, rw
);
875 backend_unbind( Operation
*op
, SlapReply
*rs
)
879 LDAP_STAILQ_FOREACH( be
, &backendDB
, be_next
) {
880 if ( be
->be_unbind
) {
882 be
->be_unbind( op
, rs
);
890 backend_connection_init(
895 LDAP_STAILQ_FOREACH( be
, &backendDB
, be_next
) {
896 if ( be
->be_connection_init
) {
897 be
->be_connection_init( be
, conn
);
905 backend_connection_destroy(
910 LDAP_STAILQ_FOREACH( be
, &backendDB
, be_next
) {
911 if ( be
->be_connection_destroy
) {
912 be
->be_connection_destroy( be
, conn
);
920 backend_check_controls(
924 LDAPControl
**ctrls
= op
->o_ctrls
;
925 rs
->sr_err
= LDAP_SUCCESS
;
928 for( ; *ctrls
!= NULL
; ctrls
++ ) {
931 switch ( slap_global_control( op
, (*ctrls
)->ldctl_oid
, &cid
) ) {
932 case LDAP_CONTROL_NOT_FOUND
:
933 /* unrecognized control */
934 if ( (*ctrls
)->ldctl_iscritical
) {
935 /* should not be reachable */
936 Debug( LDAP_DEBUG_ANY
, "backend_check_controls: "
937 "unrecognized critical control: %s\n",
938 (*ctrls
)->ldctl_oid
, 0, 0 );
941 Debug( LDAP_DEBUG_TRACE
, "backend_check_controls: "
942 "unrecognized non-critical control: %s\n",
943 (*ctrls
)->ldctl_oid
, 0, 0 );
947 case LDAP_COMPARE_FALSE
:
948 if ( !op
->o_bd
->be_ctrls
[cid
] && (*ctrls
)->ldctl_iscritical
) {
949 /* RFC 4511 allows unavailableCriticalExtension to be
950 * returned when the server is unwilling to perform
951 * an operation extended by a recognized critical
954 rs
->sr_text
= "critical control unavailable in context";
955 rs
->sr_err
= LDAP_UNAVAILABLE_CRITICAL_EXTENSION
;
960 case LDAP_COMPARE_TRUE
:
965 Debug( LDAP_DEBUG_ANY
,
966 "backend_check_controls: unable to check control: %s\n",
967 (*ctrls
)->ldctl_oid
, 0, 0 );
970 rs
->sr_text
= "unable to check control";
971 rs
->sr_err
= LDAP_OTHER
;
977 #if 0 /* temporarily removed */
978 /* check should be generalized */
979 if( get_relax(op
) && !be_isroot(op
)) {
980 rs
->sr_text
= "requires manager authorization";
981 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
990 backend_check_restrictions(
993 struct berval
*opdata
)
995 slap_mask_t restrictops
;
996 slap_mask_t requires
;
998 slap_mask_t exopflag
= 0;
1005 int rc
= SLAP_CB_CONTINUE
;
1007 if ( op
->o_bd
->be_chk_controls
) {
1008 rc
= ( *op
->o_bd
->be_chk_controls
)( op
, rs
);
1011 if ( rc
== SLAP_CB_CONTINUE
) {
1012 rc
= backend_check_controls( op
, rs
);
1015 if ( rc
!= LDAP_SUCCESS
) {
1019 restrictops
= op
->o_bd
->be_restrictops
;
1020 requires
= op
->o_bd
->be_requires
;
1021 ssf
= &op
->o_bd
->be_ssf_set
;
1024 restrictops
= frontendDB
->be_restrictops
;
1025 requires
= frontendDB
->be_requires
;
1026 ssf
= &frontendDB
->be_ssf_set
;
1029 switch( op
->o_tag
) {
1031 opflag
= SLAP_RESTRICT_OP_ADD
;
1035 opflag
= SLAP_RESTRICT_OP_BIND
;
1038 case LDAP_REQ_COMPARE
:
1039 opflag
= SLAP_RESTRICT_OP_COMPARE
;
1041 case LDAP_REQ_DELETE
:
1043 opflag
= SLAP_RESTRICT_OP_DELETE
;
1045 case LDAP_REQ_EXTENDED
:
1046 opflag
= SLAP_RESTRICT_OP_EXTENDED
;
1049 /* treat unspecified as a modify */
1050 opflag
= SLAP_RESTRICT_OP_MODIFY
;
1055 if( bvmatch( opdata
, &slap_EXOP_START_TLS
) ) {
1058 exopflag
= SLAP_RESTRICT_EXOP_START_TLS
;
1062 if( bvmatch( opdata
, &slap_EXOP_WHOAMI
) ) {
1063 exopflag
= SLAP_RESTRICT_EXOP_WHOAMI
;
1067 if ( bvmatch( opdata
, &slap_EXOP_CANCEL
) ) {
1068 exopflag
= SLAP_RESTRICT_EXOP_CANCEL
;
1072 if ( bvmatch( opdata
, &slap_EXOP_MODIFY_PASSWD
) ) {
1073 exopflag
= SLAP_RESTRICT_EXOP_MODIFY_PASSWD
;
1078 /* treat everything else as a modify */
1079 opflag
= SLAP_RESTRICT_OP_MODIFY
;
1083 case LDAP_REQ_MODIFY
:
1085 opflag
= SLAP_RESTRICT_OP_MODIFY
;
1087 case LDAP_REQ_RENAME
:
1089 opflag
= SLAP_RESTRICT_OP_RENAME
;
1091 case LDAP_REQ_SEARCH
:
1092 opflag
= SLAP_RESTRICT_OP_SEARCH
;
1094 case LDAP_REQ_UNBIND
:
1099 rs
->sr_text
= "restrict operations internal error";
1100 rs
->sr_err
= LDAP_OTHER
;
1105 /* these checks don't apply to StartTLS */
1107 rs
->sr_err
= LDAP_CONFIDENTIALITY_REQUIRED
;
1108 if( op
->o_transport_ssf
< ssf
->sss_transport
) {
1109 rs
->sr_text
= op
->o_transport_ssf
1110 ? "stronger transport confidentiality required"
1111 : "transport confidentiality required";
1115 if( op
->o_tls_ssf
< ssf
->sss_tls
) {
1116 rs
->sr_text
= op
->o_tls_ssf
1117 ? "stronger TLS confidentiality required"
1118 : "TLS confidentiality required";
1123 if( op
->o_tag
== LDAP_REQ_BIND
&& opdata
== NULL
) {
1124 /* simple bind specific check */
1125 if( op
->o_ssf
< ssf
->sss_simple_bind
) {
1126 rs
->sr_text
= op
->o_ssf
1127 ? "stronger confidentiality required"
1128 : "confidentiality required";
1133 if( op
->o_tag
!= LDAP_REQ_BIND
|| opdata
== NULL
) {
1134 /* these checks don't apply to SASL bind */
1136 if( op
->o_sasl_ssf
< ssf
->sss_sasl
) {
1137 rs
->sr_text
= op
->o_sasl_ssf
1138 ? "stronger SASL confidentiality required"
1139 : "SASL confidentiality required";
1143 if( op
->o_ssf
< ssf
->sss_ssf
) {
1144 rs
->sr_text
= op
->o_ssf
1145 ? "stronger confidentiality required"
1146 : "confidentiality required";
1152 if( op
->o_transport_ssf
< ssf
->sss_update_transport
) {
1153 rs
->sr_text
= op
->o_transport_ssf
1154 ? "stronger transport confidentiality required for update"
1155 : "transport confidentiality required for update";
1159 if( op
->o_tls_ssf
< ssf
->sss_update_tls
) {
1160 rs
->sr_text
= op
->o_tls_ssf
1161 ? "stronger TLS confidentiality required for update"
1162 : "TLS confidentiality required for update";
1166 if( op
->o_sasl_ssf
< ssf
->sss_update_sasl
) {
1167 rs
->sr_text
= op
->o_sasl_ssf
1168 ? "stronger SASL confidentiality required for update"
1169 : "SASL confidentiality required for update";
1173 if( op
->o_ssf
< ssf
->sss_update_ssf
) {
1174 rs
->sr_text
= op
->o_ssf
1175 ? "stronger confidentiality required for update"
1176 : "confidentiality required for update";
1180 if( !( global_allows
& SLAP_ALLOW_UPDATE_ANON
) &&
1181 BER_BVISEMPTY( &op
->o_ndn
) )
1183 rs
->sr_text
= "modifications require authentication";
1184 rs
->sr_err
= LDAP_STRONG_AUTH_REQUIRED
;
1188 #ifdef SLAP_X_LISTENER_MOD
1189 if ( op
->o_conn
->c_listener
&&
1190 ! ( op
->o_conn
->c_listener
->sl_perms
& ( !BER_BVISEMPTY( &op
->o_ndn
)
1191 ? (S_IWUSR
|S_IWOTH
) : S_IWOTH
) ) )
1193 /* no "w" mode means readonly */
1194 rs
->sr_text
= "modifications not allowed on this listener";
1195 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
1198 #endif /* SLAP_X_LISTENER_MOD */
1203 /* these checks don't apply to Bind, StartTLS, or Unbind */
1205 if( requires
& SLAP_REQUIRE_STRONG
) {
1206 /* should check mechanism */
1207 if( ( op
->o_transport_ssf
< ssf
->sss_transport
1208 && op
->o_authtype
== LDAP_AUTH_SIMPLE
)
1209 || BER_BVISEMPTY( &op
->o_dn
) )
1211 rs
->sr_text
= "strong(er) authentication required";
1212 rs
->sr_err
= LDAP_STRONG_AUTH_REQUIRED
;
1217 if( requires
& SLAP_REQUIRE_SASL
) {
1218 if( op
->o_authtype
!= LDAP_AUTH_SASL
|| BER_BVISEMPTY( &op
->o_dn
) ) {
1219 rs
->sr_text
= "SASL authentication required";
1220 rs
->sr_err
= LDAP_STRONG_AUTH_REQUIRED
;
1225 if( requires
& SLAP_REQUIRE_AUTHC
) {
1226 if( BER_BVISEMPTY( &op
->o_dn
) ) {
1227 rs
->sr_text
= "authentication required";
1228 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
1233 if( requires
& SLAP_REQUIRE_BIND
) {
1235 ldap_pvt_thread_mutex_lock( &op
->o_conn
->c_mutex
);
1236 version
= op
->o_conn
->c_protocol
;
1237 ldap_pvt_thread_mutex_unlock( &op
->o_conn
->c_mutex
);
1240 /* no bind has occurred */
1241 rs
->sr_text
= "BIND required";
1242 rs
->sr_err
= LDAP_OPERATIONS_ERROR
;
1247 if( requires
& SLAP_REQUIRE_LDAP_V3
) {
1248 if( op
->o_protocol
< LDAP_VERSION3
) {
1249 /* no bind has occurred */
1250 rs
->sr_text
= "operation restricted to LDAPv3 clients";
1251 rs
->sr_err
= LDAP_OPERATIONS_ERROR
;
1256 #ifdef SLAP_X_LISTENER_MOD
1257 if ( !starttls
&& BER_BVISEMPTY( &op
->o_dn
) ) {
1258 if ( op
->o_conn
->c_listener
&&
1259 !( op
->o_conn
->c_listener
->sl_perms
& S_IXOTH
))
1261 /* no "x" mode means bind required */
1262 rs
->sr_text
= "bind required on this listener";
1263 rs
->sr_err
= LDAP_STRONG_AUTH_REQUIRED
;
1268 if ( !starttls
&& !updateop
) {
1269 if ( op
->o_conn
->c_listener
&&
1270 !( op
->o_conn
->c_listener
->sl_perms
&
1271 ( !BER_BVISEMPTY( &op
->o_dn
)
1272 ? (S_IRUSR
|S_IROTH
) : S_IROTH
)))
1274 /* no "r" mode means no read */
1275 rs
->sr_text
= "read not allowed on this listener";
1276 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
1280 #endif /* SLAP_X_LISTENER_MOD */
1284 if( ( restrictops
& opflag
)
1285 || ( exopflag
&& ( restrictops
& exopflag
) ) ) {
1286 if( ( restrictops
& SLAP_RESTRICT_OP_MASK
) == SLAP_RESTRICT_OP_READS
) {
1287 rs
->sr_text
= "read operations restricted";
1288 } else if ( restrictops
& exopflag
) {
1289 rs
->sr_text
= "extended operation restricted";
1291 rs
->sr_text
= "operation restricted";
1293 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
1297 rs
->sr_err
= LDAP_SUCCESS
;
1301 int backend_check_referrals( Operation
*op
, SlapReply
*rs
)
1303 rs
->sr_err
= LDAP_SUCCESS
;
1305 if( op
->o_bd
->be_chk_referrals
) {
1306 rs
->sr_err
= op
->o_bd
->be_chk_referrals( op
, rs
);
1308 if( rs
->sr_err
!= LDAP_SUCCESS
&& rs
->sr_err
!= LDAP_REFERRAL
) {
1309 send_ldap_result( op
, rs
);
1321 AttributeDescription
*at
,
1327 if ( op
->o_bd
== NULL
) {
1328 return LDAP_NO_SUCH_OBJECT
;
1331 if ( op
->o_bd
->be_fetch
) {
1332 return op
->o_bd
->be_fetch( op
, ndn
, oc
, at
, rw
, e
);
1335 return LDAP_UNWILLING_TO_PERFORM
;
1342 struct berval
*gr_ndn
,
1343 struct berval
*op_ndn
,
1344 ObjectClass
*group_oc
,
1345 AttributeDescription
*group_at
)
1348 void *o_priv
= op
->o_private
, *e_priv
= NULL
;
1352 Backend
*be
= op
->o_bd
;
1355 LDAP_SLIST_FOREACH(oex
, &op
->o_extra
, oe_next
) {
1356 if ( oex
->oe_key
== (void *)backend_group
)
1360 if ( oex
&& ((OpExtraDB
*)oex
)->oe_db
)
1361 op
->o_bd
= ((OpExtraDB
*)oex
)->oe_db
;
1363 if ( !op
->o_bd
|| !SLAP_DBHIDDEN( op
->o_bd
))
1364 op
->o_bd
= select_backend( gr_ndn
, 0 );
1366 for ( g
= op
->o_groups
; g
; g
= g
->ga_next
) {
1367 if ( g
->ga_be
!= op
->o_bd
|| g
->ga_oc
!= group_oc
||
1368 g
->ga_at
!= group_at
|| g
->ga_len
!= gr_ndn
->bv_len
)
1372 if ( strcmp( g
->ga_ndn
, gr_ndn
->bv_val
) == 0 ) {
1382 if ( target
&& dn_match( &target
->e_nname
, gr_ndn
) ) {
1387 op
->o_private
= NULL
;
1388 rc
= be_entry_get_rw( op
, gr_ndn
, group_oc
, group_at
, 0, &e
);
1389 e_priv
= op
->o_private
;
1390 op
->o_private
= o_priv
;
1394 a
= attr_find( e
->e_attrs
, group_at
);
1396 /* If the attribute is a subtype of labeledURI,
1397 * treat this as a dynamic group ala groupOfURLs
1399 if ( is_at_subtype( group_at
->ad_type
,
1400 slap_schema
.si_ad_labeledURI
->ad_type
) )
1404 struct berval bv
, nbase
;
1407 void *user_priv
= NULL
;
1408 Backend
*b2
= op
->o_bd
;
1410 if ( target
&& dn_match( &target
->e_nname
, op_ndn
) ) {
1414 rc
= LDAP_COMPARE_FALSE
;
1415 for ( i
= 0; !BER_BVISNULL( &a
->a_vals
[i
] ); i
++ ) {
1416 if ( ldap_url_parse( a
->a_vals
[i
].bv_val
, &ludp
) !=
1422 BER_BVZERO( &nbase
);
1424 /* host, attrs and extensions parts must be empty */
1425 if ( ( ludp
->lud_host
&& *ludp
->lud_host
)
1432 ber_str2bv( ludp
->lud_dn
, 0, 0, &bv
);
1433 if ( dnNormalize( 0, NULL
, NULL
, &bv
, &nbase
,
1434 op
->o_tmpmemctx
) != LDAP_SUCCESS
)
1439 switch ( ludp
->lud_scope
) {
1440 case LDAP_SCOPE_BASE
:
1441 if ( !dn_match( &nbase
, op_ndn
) ) {
1445 case LDAP_SCOPE_ONELEVEL
:
1446 dnParent( op_ndn
, &bv
);
1447 if ( !dn_match( &nbase
, &bv
) ) {
1451 case LDAP_SCOPE_SUBTREE
:
1452 if ( !dnIsSuffix( op_ndn
, &nbase
) ) {
1456 case LDAP_SCOPE_SUBORDINATE
:
1457 if ( dn_match( &nbase
, op_ndn
) ||
1458 !dnIsSuffix( op_ndn
, &nbase
) )
1464 /* NOTE: this could be NULL
1465 * if no filter is provided,
1466 * or if filter parsing fails.
1467 * In the latter case,
1468 * we should give up. */
1469 if ( ludp
->lud_filter
!= NULL
&& ludp
->lud_filter
!= '\0') {
1470 filter
= str2filter_x( op
, ludp
->lud_filter
);
1471 if ( filter
== NULL
) {
1477 /* only get user if required
1478 * and not available yet */
1479 if ( user
== NULL
) {
1482 op
->o_bd
= select_backend( op_ndn
, 0 );
1483 op
->o_private
= NULL
;
1484 rc2
= be_entry_get_rw( op
, op_ndn
, NULL
, NULL
, 0, &user
);
1485 user_priv
= op
->o_private
;
1486 op
->o_private
= o_priv
;
1494 if ( test_filter( NULL
, user
, filter
) ==
1499 filter_free_x( op
, filter
);
1502 ldap_free_urldesc( ludp
);
1503 if ( !BER_BVISNULL( &nbase
) ) {
1504 op
->o_tmpfree( nbase
.bv_val
, op
->o_tmpmemctx
);
1506 if ( rc
!= LDAP_COMPARE_FALSE
) {
1511 if ( user
!= NULL
&& user
!= target
) {
1512 op
->o_private
= user_priv
;
1513 be_entry_release_r( op
, user
);
1514 op
->o_private
= o_priv
;
1519 rc
= attr_valfind( a
,
1520 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH
|
1521 SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
,
1522 op_ndn
, NULL
, op
->o_tmpmemctx
);
1523 if ( rc
== LDAP_NO_SUCH_ATTRIBUTE
) {
1524 rc
= LDAP_COMPARE_FALSE
;
1529 rc
= LDAP_NO_SUCH_ATTRIBUTE
;
1532 if ( e
!= target
) {
1533 op
->o_private
= e_priv
;
1534 be_entry_release_r( op
, e
);
1535 op
->o_private
= o_priv
;
1539 rc
= LDAP_NO_SUCH_OBJECT
;
1542 if ( op
->o_tag
!= LDAP_REQ_BIND
&& !op
->o_do_not_cache
) {
1543 g
= op
->o_tmpalloc( sizeof( GroupAssertion
) + gr_ndn
->bv_len
,
1545 g
->ga_be
= op
->o_bd
;
1546 g
->ga_oc
= group_oc
;
1547 g
->ga_at
= group_at
;
1549 g
->ga_len
= gr_ndn
->bv_len
;
1550 strcpy( g
->ga_ndn
, gr_ndn
->bv_val
);
1551 g
->ga_next
= op
->o_groups
;
1564 struct berval
*gr_ndn
,
1565 struct berval
*op_ndn
,
1566 ObjectClass
*group_oc
,
1567 AttributeDescription
*group_at
)
1573 if ( op
->o_abandon
) {
1574 return SLAPD_ABANDON
;
1577 oex
.oe_db
= op
->o_bd
;
1578 oex
.oe
.oe_key
= (void *)backend_group
;
1579 LDAP_SLIST_INSERT_HEAD(&op
->o_extra
, &oex
.oe
, oe_next
);
1582 op
->o_bd
= frontendDB
;
1583 rc
= frontendDB
->be_group( op
, target
, gr_ndn
,
1584 op_ndn
, group_oc
, group_at
);
1586 LDAP_SLIST_REMOVE(&op
->o_extra
, &oex
.oe
, OpExtra
, oe_next
);
1596 AttributeDescription
*entry_at
,
1598 slap_access_t access
)
1601 void *o_priv
= op
->o_private
, *e_priv
= NULL
;
1602 Attribute
*a
= NULL
;
1603 int freeattr
= 0, i
, j
, rc
= LDAP_SUCCESS
;
1604 AccessControlState acl_state
= ACL_STATE_INIT
;
1605 Backend
*be
= op
->o_bd
;
1608 LDAP_SLIST_FOREACH(oex
, &op
->o_extra
, oe_next
) {
1609 if ( oex
->oe_key
== (void *)backend_attribute
)
1613 if ( oex
&& ((OpExtraDB
*)oex
)->oe_db
)
1614 op
->o_bd
= ((OpExtraDB
*)oex
)->oe_db
;
1616 if ( !op
->o_bd
|| !SLAP_DBHIDDEN( op
->o_bd
))
1617 op
->o_bd
= select_backend( edn
, 0 );
1619 if ( target
&& dn_match( &target
->e_nname
, edn
) ) {
1623 op
->o_private
= NULL
;
1624 rc
= be_entry_get_rw( op
, edn
, NULL
, entry_at
, 0, &e
);
1625 e_priv
= op
->o_private
;
1626 op
->o_private
= o_priv
;
1630 if ( entry_at
== slap_schema
.si_ad_entry
|| entry_at
== slap_schema
.si_ad_children
) {
1631 assert( vals
== NULL
);
1634 if ( op
->o_conn
&& access
> ACL_NONE
&&
1635 access_allowed( op
, e
, entry_at
, NULL
,
1636 access
, &acl_state
) == 0 )
1638 rc
= LDAP_INSUFFICIENT_ACCESS
;
1643 a
= attr_find( e
->e_attrs
, entry_at
);
1645 SlapReply rs
= { 0 };
1646 AttributeName anlist
[ 2 ];
1648 anlist
[ 0 ].an_name
= entry_at
->ad_cname
;
1649 anlist
[ 0 ].an_desc
= entry_at
;
1650 BER_BVZERO( &anlist
[ 1 ].an_name
);
1651 rs
.sr_attrs
= anlist
;
1653 /* NOTE: backend_operational() is also called
1654 * when returning results, so it's supposed
1655 * to do no harm to entries */
1657 rc
= backend_operational( op
, &rs
);
1660 if ( rc
== LDAP_SUCCESS
) {
1661 if ( rs
.sr_operational_attrs
) {
1663 a
= rs
.sr_operational_attrs
;
1666 rc
= LDAP_NO_SUCH_ATTRIBUTE
;
1674 if ( op
->o_conn
&& access
> ACL_NONE
&&
1675 access_allowed( op
, e
, entry_at
, NULL
,
1676 access
, &acl_state
) == 0 )
1678 rc
= LDAP_INSUFFICIENT_ACCESS
;
1683 v
= op
->o_tmpalloc( sizeof(struct berval
) * ( i
+ 1 ),
1685 for ( i
= 0, j
= 0; !BER_BVISNULL( &a
->a_vals
[i
] ); i
++ )
1687 if ( op
->o_conn
&& access
> ACL_NONE
&&
1688 access_allowed( op
, e
, entry_at
,
1695 ber_dupbv_x( &v
[j
], &a
->a_nvals
[i
],
1697 if ( !BER_BVISNULL( &v
[j
] ) ) {
1702 op
->o_tmpfree( v
, op
->o_tmpmemctx
);
1704 rc
= LDAP_INSUFFICIENT_ACCESS
;
1707 BER_BVZERO( &v
[j
] );
1712 freeit
: if ( e
!= target
) {
1713 op
->o_private
= e_priv
;
1714 be_entry_release_r( op
, e
);
1715 op
->o_private
= o_priv
;
1731 AttributeDescription
*entry_at
,
1733 slap_access_t access
)
1739 oex
.oe_db
= op
->o_bd
;
1740 oex
.oe
.oe_key
= (void *)backend_attribute
;
1741 LDAP_SLIST_INSERT_HEAD(&op
->o_extra
, &oex
.oe
, oe_next
);
1744 op
->o_bd
= frontendDB
;
1745 rc
= frontendDB
->be_attribute( op
, target
, edn
,
1746 entry_at
, vals
, access
);
1748 LDAP_SLIST_REMOVE(&op
->o_extra
, &oex
.oe
, OpExtra
, oe_next
);
1758 AttributeDescription
*entry_at
,
1759 struct berval
*nval
,
1760 slap_access_t access
,
1764 void *o_priv
= op
->o_private
, *e_priv
= NULL
;
1765 int rc
= LDAP_INSUFFICIENT_ACCESS
;
1766 Backend
*be
= op
->o_bd
;
1769 assert( op
!= NULL
);
1770 assert( op
->o_conn
!= NULL
);
1771 assert( edn
!= NULL
);
1772 assert( access
> ACL_NONE
);
1775 op
->o_bd
= select_backend( edn
, 0 );
1778 if ( target
&& dn_match( &target
->e_nname
, edn
) ) {
1782 op
->o_private
= NULL
;
1783 rc
= be_entry_get_rw( op
, edn
, NULL
, entry_at
, 0, &e
);
1784 e_priv
= op
->o_private
;
1785 op
->o_private
= o_priv
;
1789 Attribute
*a
= NULL
;
1792 if ( entry_at
== NULL
) {
1793 entry_at
= slap_schema
.si_ad_entry
;
1796 if ( entry_at
== slap_schema
.si_ad_entry
|| entry_at
== slap_schema
.si_ad_children
)
1798 if ( access_allowed_mask( op
, e
, entry_at
,
1799 NULL
, access
, NULL
, mask
) == 0 )
1801 rc
= LDAP_INSUFFICIENT_ACCESS
;
1808 a
= attr_find( e
->e_attrs
, entry_at
);
1810 SlapReply rs
= { 0 };
1811 AttributeName anlist
[ 2 ];
1813 anlist
[ 0 ].an_name
= entry_at
->ad_cname
;
1814 anlist
[ 0 ].an_desc
= entry_at
;
1815 BER_BVZERO( &anlist
[ 1 ].an_name
);
1816 rs
.sr_attrs
= anlist
;
1818 rs
.sr_attr_flags
= slap_attr_flags( rs
.sr_attrs
);
1820 /* NOTE: backend_operational() is also called
1821 * when returning results, so it's supposed
1822 * to do no harm to entries */
1824 rc
= backend_operational( op
, &rs
);
1827 if ( rc
== LDAP_SUCCESS
) {
1828 if ( rs
.sr_operational_attrs
) {
1830 a
= rs
.sr_operational_attrs
;
1833 rc
= LDAP_NO_SUCH_OBJECT
;
1839 if ( access_allowed_mask( op
, e
, entry_at
,
1840 nval
, access
, NULL
, mask
) == 0 )
1842 rc
= LDAP_INSUFFICIENT_ACCESS
;
1848 freeit
: if ( e
!= target
) {
1849 op
->o_private
= e_priv
;
1850 be_entry_release_r( op
, e
);
1851 op
->o_private
= o_priv
;
1868 int rc
= LDAP_SUCCESS
;
1869 BackendDB
*be_orig
= op
->o_bd
;
1872 LDAP_SLIST_FOREACH(oex
, &op
->o_extra
, oe_next
) {
1873 if ( oex
->oe_key
== (void *)backend_operational
)
1877 for ( ap
= &rs
->sr_operational_attrs
; *ap
; ap
= &(*ap
)->a_next
)
1878 /* just count them */ ;
1881 * If operational attributes (allegedly) are required,
1882 * and the backend supports specific operational attributes,
1883 * add them to the attribute list
1885 if ( !( rs
->sr_flags
& REP_NO_ENTRYDN
)
1886 && ( SLAP_OPATTRS( rs
->sr_attr_flags
) || ( rs
->sr_attrs
&&
1887 ad_inlist( slap_schema
.si_ad_entryDN
, rs
->sr_attrs
) ) ) )
1889 *ap
= slap_operational_entryDN( rs
->sr_entry
);
1890 ap
= &(*ap
)->a_next
;
1893 if ( !( rs
->sr_flags
& REP_NO_SUBSCHEMA
)
1894 && ( SLAP_OPATTRS( rs
->sr_attr_flags
) || ( rs
->sr_attrs
&&
1895 ad_inlist( slap_schema
.si_ad_subschemaSubentry
, rs
->sr_attrs
) ) ) )
1897 *ap
= slap_operational_subschemaSubentry( op
->o_bd
);
1898 ap
= &(*ap
)->a_next
;
1901 /* Let the overlays have a chance at this */
1902 if ( oex
&& ((OpExtraDB
*)oex
)->oe_db
)
1903 op
->o_bd
= ((OpExtraDB
*)oex
)->oe_db
;
1905 if ( !op
->o_bd
|| !SLAP_DBHIDDEN( op
->o_bd
))
1906 op
->o_bd
= select_backend( &op
->o_req_ndn
, 0 );
1908 if ( op
->o_bd
!= NULL
&& !be_match( op
->o_bd
, frontendDB
) &&
1909 ( SLAP_OPATTRS( rs
->sr_attr_flags
) || rs
->sr_attrs
) &&
1910 op
->o_bd
->be_operational
!= NULL
)
1912 rc
= op
->o_bd
->be_operational( op
, rs
);
1919 int backend_operational( Operation
*op
, SlapReply
*rs
)
1925 oex
.oe_db
= op
->o_bd
;
1926 oex
.oe
.oe_key
= (void *)backend_operational
;
1927 LDAP_SLIST_INSERT_HEAD(&op
->o_extra
, &oex
.oe
, oe_next
);
1929 /* Moved this into the frontend so global overlays are called */
1932 op
->o_bd
= frontendDB
;
1933 rc
= frontendDB
->be_operational( op
, rs
);
1935 LDAP_SLIST_REMOVE(&op
->o_extra
, &oex
.oe
, OpExtra
, oe_next
);