3 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6 /* backend.c - routines for dealing with back-end databases */
10 #include "slapi_common.h"
14 #include <ac/string.h>
15 #include <ac/socket.h>
25 * If a module is configured as dynamic, its header should not
26 * get included into slapd. While this is a general rule and does
27 * not have much of an effect in UNIX, this rule should be adhered
28 * to for Windows, where dynamic object code should not be implicitly
29 * imported into slapd without appropriate __declspec(dllimport) directives.
32 #if defined(SLAPD_BDB) && !defined(SLAPD_BDB_DYNAMIC)
33 #include "back-bdb/external.h"
35 #if defined(SLAPD_DNSSRV) && !defined(SLAPD_DNSSRV_DYNAMIC)
36 #include "back-dnssrv/external.h"
38 #if defined(SLAPD_LDAP) && !defined(SLAPD_LDAP_DYNAMIC)
39 #include "back-ldap/external.h"
41 #if defined(SLAPD_LDBM) && !defined(SLAPD_LDBM_DYNAMIC)
42 #include "back-ldbm/external.h"
44 #if defined(SLAPD_META) && !defined(SLAPD_META_DYNAMIC)
45 #include "back-meta/external.h"
47 #if defined(SLAPD_MONITOR) && !defined(SLAPD_MONITOR_DYNAMIC)
48 #include "back-monitor/external.h"
50 #if defined(SLAPD_NULL) && !defined(SLAPD_NULL_DYNAMIC)
51 #include "back-null/external.h"
53 #if defined(SLAPD_PASSWD) && !defined(SLAPD_PASSWD_DYNAMIC)
54 #include "back-passwd/external.h"
56 #if defined(SLAPD_PERL) && !defined(SLAPD_PERL_DYNAMIC)
57 #include "back-perl/external.h"
59 #if defined(SLAPD_SHELL) && !defined(SLAPD_SHELL_DYNAMIC)
60 #include "back-shell/external.h"
62 #if defined(SLAPD_TCL) && !defined(SLAPD_TCL_DYNAMIC)
63 #include "back-tcl/external.h"
65 #if defined(SLAPD_SQL) && !defined(SLAPD_SQL_DYNAMIC)
66 #include "back-sql/external.h"
68 #if defined(SLAPD_PRIVATE) && !defined(SLAPD_PRIVATE_DYNAMIC)
69 #include "private/external.h"
72 static BackendInfo binfo[] = {
73 #if defined(SLAPD_BDB) && !defined(SLAPD_BDB_DYNAMIC)
74 {"bdb", bdb_initialize},
76 #if defined(SLAPD_DNSSRV) && !defined(SLAPD_DNSSRV_DYNAMIC)
77 {"dnssrv", dnssrv_back_initialize},
79 #if defined(SLAPD_LDAP) && !defined(SLAPD_LDAP_DYNAMIC)
80 {"ldap", ldap_back_initialize},
82 #if defined(SLAPD_LDBM) && !defined(SLAPD_LDBM_DYNAMIC)
83 {"ldbm", ldbm_back_initialize},
85 #if defined(SLAPD_META) && !defined(SLAPD_META_DYNAMIC)
86 {"meta", meta_back_initialize},
88 #if defined(SLAPD_MONITOR) && !defined(SLAPD_MONITOR_DYNAMIC)
89 {"monitor", monitor_back_initialize},
91 #if defined(SLAPD_NULL) && !defined(SLAPD_NULL_DYNAMIC)
92 {"null", null_back_initialize},
94 #if defined(SLAPD_PASSWD) && !defined(SLAPD_PASSWD_DYNAMIC)
95 {"passwd", passwd_back_initialize},
97 #if defined(SLAPD_PERL) && !defined(SLAPD_PERL_DYNAMIC)
98 {"perl", perl_back_initialize},
100 #if defined(SLAPD_SHELL) && !defined(SLAPD_SHELL_DYNAMIC)
101 {"shell", shell_back_initialize},
103 #if defined(SLAPD_TCL) && !defined(SLAPD_TCL_DYNAMIC)
104 {"tcl", tcl_back_initialize},
106 #if defined(SLAPD_SQL) && !defined(SLAPD_SQL_DYNAMIC)
107 {"sql", sql_back_initialize},
109 /* for any private backend */
110 #if defined(SLAPD_PRIVATE) && !defined(SLAPD_PRIVATE_DYNAMIC)
111 {"private", private_back_initialize},
116 int nBackendInfo = 0;
117 BackendInfo *backendInfo = NULL;
120 BackendDB *backendDB = NULL;
122 int backend_init(void)
126 if((nBackendInfo != 0) || (backendInfo != NULL)) {
127 /* already initialized */
129 LDAP_LOG( BACKEND, ERR,
130 "backend_init: backend already initialized\n", 0, 0, 0 );
132 Debug( LDAP_DEBUG_ANY,
133 "backend_init: already initialized.\n", 0, 0, 0 );
139 binfo[nBackendInfo].bi_type != NULL;
142 rc = binfo[nBackendInfo].bi_init( &binfo[nBackendInfo] );
146 LDAP_LOG( BACKEND, INFO,
147 "backend_init: initialized for type \"%s\"\n",
148 binfo[nBackendInfo].bi_type, 0, 0 );
150 Debug( LDAP_DEBUG_ANY,
151 "backend_init: initialized for type \"%s\"\n",
152 binfo[nBackendInfo].bi_type, 0, 0 );
154 /* destroy those we've already inited */
159 if ( binfo[nBackendInfo].bi_destroy ) {
160 binfo[nBackendInfo].bi_destroy(
161 &binfo[nBackendInfo] );
168 if ( nBackendInfo > 0) {
178 LDAP_LOG( BACKEND, ERR, "backend_init: failed\n", 0, 0, 0 );
180 Debug( LDAP_DEBUG_ANY,
181 "backend_init: failed\n",
186 #endif /* SLAPD_MODULES */
189 int backend_add(BackendInfo *aBackendInfo)
193 if ((rc = aBackendInfo->bi_init(aBackendInfo)) != 0) {
195 LDAP_LOG( BACKEND, ERR,
196 "backend_add: initialization for type \"%s\" failed\n",
197 aBackendInfo->bi_type, 0, 0 );
199 Debug( LDAP_DEBUG_ANY,
200 "backend_add: initialization for type \"%s\" failed\n",
201 aBackendInfo->bi_type, 0, 0 );
206 /* now add the backend type to the Backend Info List */
208 BackendInfo *newBackendInfo = 0;
210 /* if backendInfo == binfo no deallocation of old backendInfo */
211 if (backendInfo == binfo) {
212 newBackendInfo = ch_calloc(nBackendInfo + 1, sizeof(BackendInfo));
213 AC_MEMCPY(newBackendInfo, backendInfo, sizeof(BackendInfo) *
216 newBackendInfo = ch_realloc(backendInfo, sizeof(BackendInfo) *
219 AC_MEMCPY(&newBackendInfo[nBackendInfo], aBackendInfo,
220 sizeof(BackendInfo));
221 backendInfo = newBackendInfo;
228 int backend_startup(Backend *be)
233 if( ! ( nBackendDB > 0 ) ) {
236 LDAP_LOG( BACKEND, INFO,
237 "backend_startup: %d databases to startup. \n", nBackendDB, 0, 0 );
239 Debug( LDAP_DEBUG_ANY,
240 "backend_startup: %d databases to startup.\n",
247 /* startup a specific backend database */
249 LDAP_LOG( BACKEND, DETAIL1, "backend_startup: starting \"%s\"\n",
250 be->be_suffix[0].bv_val, 0, 0 );
252 Debug( LDAP_DEBUG_TRACE,
253 "backend_startup: starting \"%s\"\n",
254 be->be_suffix[0].bv_val, 0, 0 );
257 if ( be->bd_info->bi_open ) {
258 rc = be->bd_info->bi_open( be->bd_info );
261 LDAP_LOG( BACKEND, CRIT, "backend_startup: bi_open failed!\n", 0, 0, 0 );
263 Debug( LDAP_DEBUG_ANY,
264 "backend_startup: bi_open failed!\n",
272 if ( be->bd_info->bi_db_open ) {
273 rc = be->bd_info->bi_db_open( be );
276 LDAP_LOG( BACKEND, CRIT,
277 "backend_startup: bi_db_open failed! (%d)\n", rc, 0, 0 );
279 Debug( LDAP_DEBUG_ANY,
280 "backend_startup: bi_db_open failed! (%d)\n",
290 /* open each backend type */
291 for( i = 0; i < nBackendInfo; i++ ) {
292 if( backendInfo[i].bi_nDB == 0) {
293 /* no database of this type, don't open */
297 if( backendInfo[i].bi_open ) {
298 rc = backendInfo[i].bi_open(
302 LDAP_LOG( BACKEND, CRIT,
303 "backend_startup: bi_open %d failed!\n", i, 0, 0 );
305 Debug( LDAP_DEBUG_ANY,
306 "backend_startup: bi_open %d failed!\n",
314 /* open each backend database */
315 for( i = 0; i < nBackendDB; i++ ) {
316 /* append global access controls */
317 acl_append( &backendDB[i].be_acl, global_acl );
319 if ( backendDB[i].bd_info->bi_db_open ) {
320 rc = backendDB[i].bd_info->bi_db_open(
324 LDAP_LOG( BACKEND, CRIT,
325 "backend_startup: bi_db_open(%d) failed! (%d)\n", i, rc, 0 );
327 Debug( LDAP_DEBUG_ANY,
328 "backend_startup: bi_db_open(%d) failed! (%d)\n",
339 int backend_num( Backend *be )
343 if( be == NULL ) return -1;
345 for( i = 0; i < nBackendDB; i++ ) {
346 if( be == &backendDB[i] ) return i;
351 int backend_shutdown( Backend *be )
357 /* shutdown a specific backend database */
359 if ( be->bd_info->bi_nDB == 0 ) {
360 /* no database of this type, we never opened it */
364 if ( be->bd_info->bi_db_close ) {
365 be->bd_info->bi_db_close( be );
368 if( be->bd_info->bi_close ) {
369 be->bd_info->bi_close( be->bd_info );
375 /* close each backend database */
376 for( i = 0; i < nBackendDB; i++ ) {
377 if ( backendDB[i].bd_info->bi_db_close ) {
378 backendDB[i].bd_info->bi_db_close(
384 LDAP_LOG( BACKEND, NOTICE,
385 "backend_shutdown: bi_close %s failed!\n",
386 backendDB[i].be_type, 0, 0 );
388 Debug( LDAP_DEBUG_ANY,
389 "backend_close: bi_close %s failed!\n",
390 backendDB[i].be_type, 0, 0 );
395 /* close each backend type */
396 for( i = 0; i < nBackendInfo; i++ ) {
397 if( backendInfo[i].bi_nDB == 0 ) {
398 /* no database of this type */
402 if( backendInfo[i].bi_close ) {
403 backendInfo[i].bi_close(
411 int backend_destroy(void)
416 /* destroy each backend database */
417 for( i = 0, bd = backendDB; i < nBackendDB; i++, bd++ ) {
418 if ( bd->bd_info->bi_db_destroy ) {
419 bd->bd_info->bi_db_destroy( bd );
421 ber_bvarray_free( bd->be_suffix );
422 ber_bvarray_free( bd->be_nsuffix );
423 if ( bd->be_rootdn.bv_val ) free( bd->be_rootdn.bv_val );
424 if ( bd->be_rootndn.bv_val ) free( bd->be_rootndn.bv_val );
425 if ( bd->be_rootpw.bv_val ) free( bd->be_rootpw.bv_val );
426 acl_destroy( bd->be_acl, global_acl );
430 /* destroy each backend type */
431 for( i = 0; i < nBackendInfo; i++ ) {
432 if( backendInfo[i].bi_destroy ) {
433 backendInfo[i].bi_destroy(
439 if (backendInfo != binfo) {
442 #endif /* SLAPD_MODULES */
450 BackendInfo* backend_info(const char *type)
454 /* search for the backend type */
455 for( i = 0; i < nBackendInfo; i++ ) {
456 if( strcasecmp(backendInfo[i].bi_type, type) == 0 ) {
457 return &backendInfo[i];
471 BackendInfo *bi = backend_info(type);
475 fprintf( stderr, "Unrecognized database type (%s)\n", type );
479 backendDB = (BackendDB *) ch_realloc(
481 (nBackendDB + 1) * sizeof(Backend) );
483 memset( &backendDB[nbackends], '\0', sizeof(Backend) );
485 be = &backends[nbackends++];
488 be->be_def_limit = deflimit;
489 be->be_dfltaccess = global_default_access;
491 be->be_restrictops = global_restrictops;
492 be->be_requires = global_requires;
493 be->be_ssf_set = global_ssf_set;
495 /* assign a default depth limit for alias deref */
496 be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;
499 rc = bi->bi_db_init( be );
503 fprintf( stderr, "database init failed (%s)\n", type );
517 for ( i = 0; i < nbackends; i++ ) {
518 if ( backends[i].bd_info->bi_db_close ) {
519 (*backends[i].bd_info->bi_db_close)( &backends[i] );
531 ber_len_t len, dnlen = dn->bv_len;
534 for ( i = 0; i < nbackends; i++ ) {
535 for ( j = 0; backends[i].be_nsuffix != NULL &&
536 backends[i].be_nsuffix[j].bv_val != NULL; j++ )
538 if (( backends[i].be_flags & SLAP_BFLAG_GLUE_SUBORDINATE )
544 len = backends[i].be_nsuffix[j].bv_len;
547 /* suffix is longer than DN */
552 * input DN is normalized, so the separator check
553 * need not look at escaping
555 if ( len && len < dnlen &&
556 !DN_SEPARATOR( dn->bv_val[(dnlen-len)-1] ))
561 if ( strcmp( backends[i].be_nsuffix[j].bv_val,
562 &dn->bv_val[dnlen-len] ) == 0 )
567 if( manageDSAit && len == dnlen ) {
584 struct berval *bvsuffix
589 for ( i = 0; be->be_nsuffix != NULL && be->be_nsuffix[i].bv_val != NULL; i++ ) {
590 if ( bvmatch( &be->be_nsuffix[i], bvsuffix ) ) {
599 be_isroot( Backend *be, struct berval *ndn )
601 if ( !ndn->bv_len ) {
605 if ( !be->be_rootndn.bv_len ) {
609 return dn_match( &be->be_rootndn, ndn );
613 be_isupdate( Backend *be, struct berval *ndn )
615 if ( !ndn->bv_len ) {
619 if ( !be->be_update_ndn.bv_len ) {
623 return dn_match( &be->be_update_ndn, ndn );
627 be_root_dn( Backend *be )
629 return &be->be_rootdn;
633 be_isroot_pw( Backend *be,
636 struct berval *cred )
640 if ( ! be_isroot( be, ndn ) ) {
644 if( be->be_rootpw.bv_len == 0 ) {
648 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
649 ldap_pvt_thread_mutex_lock( &passwd_mutex );
651 lutil_passwd_sasl_conn = conn->c_sasl_context;
655 result = lutil_passwd( &be->be_rootpw, cred, NULL );
657 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
659 lutil_passwd_sasl_conn = NULL;
661 ldap_pvt_thread_mutex_unlock( &passwd_mutex );
675 if ( be->be_release ) {
676 /* free and release entry from backend */
677 return be->be_release( be, conn, op, e, rw );
693 Slapi_PBlock *pb = op->o_pb;
695 #if defined( LDAP_SLAPI )
696 slapi_pblock_set( pb, SLAPI_CONNECTION, (void *)conn );
697 slapi_pblock_set( pb, SLAPI_OPERATION, (void *)op );
698 #endif /* defined( LDAP_SLAPI ) */
700 for ( i = 0; i < nbackends; i++ ) {
701 #if defined( LDAP_SLAPI )
702 slapi_pblock_set( pb, SLAPI_BACKEND, (void *)&backends[i] );
703 rc = doPluginFNs( &backends[i], SLAPI_PLUGIN_PRE_UNBIND_FN,
704 (Slapi_PBlock *)pb );
705 if ( rc != 0 && rc != LDAP_OTHER ) {
707 * either there is no preOp (unbind) plugins
708 * or a plugin failed. Just log it.
710 * FIXME: is this correct?
713 LDAP_LOG( OPERATION, INFO, "do_bind: Unbind preOps "
714 "failed\n", 0, 0, 0);
716 Debug(LDAP_DEBUG_TRACE, "do_bind: Unbind preOps "
717 "failed.\n", 0, 0, 0);
720 #endif /* defined( LDAP_SLAPI ) */
722 if ( backends[i].be_unbind ) {
723 (*backends[i].be_unbind)( &backends[i], conn, op );
726 #if defined( LDAP_SLAPI )
727 rc = doPluginFNs( &backends[i], SLAPI_PLUGIN_POST_UNBIND_FN,
728 (Slapi_PBlock *)pb );
729 if ( rc != 0 && rc != LDAP_OTHER ) {
731 * either there is no postOp (unbind) plugins
732 * or a plugin failed. Just log it.
734 * FIXME: is this correct?
737 LDAP_LOG( OPERATION, INFO, "do_unbind: Unbind postOps "
738 "failed\n", 0, 0, 0);
740 Debug(LDAP_DEBUG_TRACE, "do_unbind: Unbind postOps "
741 "failed.\n", 0, 0, 0);
744 #endif /* defined( LDAP_SLAPI ) */
751 backend_connection_init(
757 for ( i = 0; i < nbackends; i++ ) {
758 if ( backends[i].be_connection_init ) {
759 (*backends[i].be_connection_init)( &backends[i], conn);
767 backend_connection_destroy(
773 for ( i = 0; i < nbackends; i++ ) {
774 if ( backends[i].be_connection_destroy ) {
775 (*backends[i].be_connection_destroy)( &backends[i], conn);
783 backend_check_controls(
789 LDAPControl **ctrls = op->o_ctrls;
791 if( ctrls == NULL ) return LDAP_SUCCESS;
793 for( ; *ctrls != NULL ; ctrls++ ) {
794 if( (*ctrls)->ldctl_iscritical &&
795 !ldap_charray_inlist( be->be_controls, (*ctrls)->ldctl_oid ) )
797 *text = "control unavailable in context";
798 return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
806 backend_check_restrictions(
810 struct berval *opdata,
814 slap_mask_t restrictops;
815 slap_mask_t requires;
823 rc = backend_check_controls( be, conn, op, text );
825 if( rc != LDAP_SUCCESS ) {
829 restrictops = be->be_restrictops;
830 requires = be->be_requires;
831 ssf = &be->be_ssf_set;
834 restrictops = global_restrictops;
835 requires = global_requires;
836 ssf = &global_ssf_set;
839 switch( op->o_tag ) {
841 opflag = SLAP_RESTRICT_OP_ADD;
845 opflag = SLAP_RESTRICT_OP_BIND;
848 case LDAP_REQ_COMPARE:
849 opflag = SLAP_RESTRICT_OP_COMPARE;
851 case LDAP_REQ_DELETE:
853 opflag = SLAP_RESTRICT_OP_DELETE;
855 case LDAP_REQ_EXTENDED:
856 opflag = SLAP_RESTRICT_OP_EXTENDED;
859 /* treat unspecified as a modify */
860 opflag = SLAP_RESTRICT_OP_MODIFY;
866 struct berval bv = BER_BVC( LDAP_EXOP_START_TLS );
867 if( bvmatch( opdata, &bv ) ) {
875 struct berval bv = BER_BVC( LDAP_EXOP_X_WHO_AM_I );
876 if( bvmatch( opdata, &bv ) ) {
881 /* treat everything else as a modify */
882 opflag = SLAP_RESTRICT_OP_MODIFY;
886 case LDAP_REQ_MODIFY:
888 opflag = SLAP_RESTRICT_OP_MODIFY;
890 case LDAP_REQ_RENAME:
892 opflag = SLAP_RESTRICT_OP_RENAME;
894 case LDAP_REQ_SEARCH:
895 opflag = SLAP_RESTRICT_OP_SEARCH;
897 case LDAP_REQ_UNBIND:
902 *text = "restrict operations internal error";
907 /* these checks don't apply to StartTLS */
909 if( op->o_transport_ssf < ssf->sss_transport ) {
910 *text = "transport confidentiality required";
911 return LDAP_CONFIDENTIALITY_REQUIRED;
914 if( op->o_tls_ssf < ssf->sss_tls ) {
915 *text = "TLS confidentiality required";
916 return LDAP_CONFIDENTIALITY_REQUIRED;
920 if( op->o_tag == LDAP_REQ_BIND && opdata == NULL ) {
921 /* simple bind specific check */
922 if( op->o_ssf < ssf->sss_simple_bind ) {
923 *text = "confidentiality required";
924 return LDAP_CONFIDENTIALITY_REQUIRED;
928 if( op->o_tag != LDAP_REQ_BIND || opdata == NULL ) {
929 /* these checks don't apply to SASL bind */
931 if( op->o_sasl_ssf < ssf->sss_sasl ) {
932 *text = "SASL confidentiality required";
933 return LDAP_CONFIDENTIALITY_REQUIRED;
936 if( op->o_ssf < ssf->sss_ssf ) {
937 *text = "confidentiality required";
938 return LDAP_CONFIDENTIALITY_REQUIRED;
943 if( op->o_transport_ssf < ssf->sss_update_transport ) {
944 *text = "transport update confidentiality required";
945 return LDAP_CONFIDENTIALITY_REQUIRED;
948 if( op->o_tls_ssf < ssf->sss_update_tls ) {
949 *text = "TLS update confidentiality required";
950 return LDAP_CONFIDENTIALITY_REQUIRED;
953 if( op->o_sasl_ssf < ssf->sss_update_sasl ) {
954 *text = "SASL update confidentiality required";
955 return LDAP_CONFIDENTIALITY_REQUIRED;
958 if( op->o_ssf < ssf->sss_update_ssf ) {
959 *text = "update confidentiality required";
960 return LDAP_CONFIDENTIALITY_REQUIRED;
963 if( !( global_allows & SLAP_ALLOW_UPDATE_ANON ) &&
964 op->o_ndn.bv_len == 0 )
966 *text = "modifications require authentication";
967 return LDAP_STRONG_AUTH_REQUIRED;
970 #ifdef SLAP_X_LISTENER_MOD
971 if ( ! ( conn->c_listener->sl_perms & S_IWUSR ) ) {
972 /* no "w" mode means readonly */
973 *text = "modifications not allowed on this listener";
974 return LDAP_UNWILLING_TO_PERFORM;
976 #endif /* SLAP_X_LISTENER_MOD */
981 /* these checks don't apply to Bind, StartTLS, or Unbind */
983 if( requires & SLAP_REQUIRE_STRONG ) {
984 /* should check mechanism */
985 if( ( op->o_transport_ssf < ssf->sss_transport
986 && op->o_authmech.bv_len == 0 ) || op->o_dn.bv_len == 0 )
988 *text = "strong authentication required";
989 return LDAP_STRONG_AUTH_REQUIRED;
993 if( requires & SLAP_REQUIRE_SASL ) {
994 if( op->o_authmech.bv_len == 0 || op->o_dn.bv_len == 0 ) {
995 *text = "SASL authentication required";
996 return LDAP_STRONG_AUTH_REQUIRED;
1000 if( requires & SLAP_REQUIRE_AUTHC ) {
1001 if( op->o_dn.bv_len == 0 ) {
1002 *text = "authentication required";
1003 return LDAP_UNWILLING_TO_PERFORM;
1007 if( requires & SLAP_REQUIRE_BIND ) {
1009 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
1010 version = conn->c_protocol;
1011 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
1014 /* no bind has occurred */
1015 *text = "BIND required";
1016 return LDAP_OPERATIONS_ERROR;
1020 if( requires & SLAP_REQUIRE_LDAP_V3 ) {
1021 if( op->o_protocol < LDAP_VERSION3 ) {
1022 /* no bind has occurred */
1023 *text = "operation restricted to LDAPv3 clients";
1024 return LDAP_OPERATIONS_ERROR;
1028 #ifdef SLAP_X_LISTENER_MOD
1029 if ( !starttls && op->o_dn.bv_len == 0 ) {
1030 if ( ! ( conn->c_listener->sl_perms & S_IXUSR ) ) {
1031 /* no "x" mode means bind required */
1032 *text = "bind required on this listener";
1033 return LDAP_STRONG_AUTH_REQUIRED;
1037 if ( !starttls && !updateop ) {
1038 if ( ! ( conn->c_listener->sl_perms & S_IRUSR ) ) {
1039 /* no "r" mode means no read */
1040 *text = "read not allowed on this listener";
1041 return LDAP_UNWILLING_TO_PERFORM;
1044 #endif /* SLAP_X_LISTENER_MOD */
1048 if( restrictops & opflag ) {
1049 if( restrictops == SLAP_RESTRICT_OP_READS ) {
1050 *text = "read operations restricted";
1052 *text = "operation restricted";
1054 return LDAP_UNWILLING_TO_PERFORM;
1057 return LDAP_SUCCESS;
1060 int backend_check_referrals(
1065 struct berval *ndn )
1067 int rc = LDAP_SUCCESS;
1069 if( be->be_chk_referrals ) {
1072 rc = be->be_chk_referrals( be,
1073 conn, op, dn, ndn, &text );
1075 if( rc != LDAP_SUCCESS && rc != LDAP_REFERRAL ) {
1076 send_ldap_result( conn, op, rc,
1077 NULL, text, NULL, NULL );
1090 struct berval *gr_ndn,
1091 struct berval *op_ndn,
1092 ObjectClass *group_oc,
1093 AttributeDescription *group_at
1098 if ( op->o_abandon ) return SLAPD_ABANDON;
1100 if ( !dn_match( &target->e_nname, gr_ndn ) ) {
1101 /* we won't attempt to send it to a different backend */
1103 be = select_backend( gr_ndn, 0, 0 );
1106 return LDAP_NO_SUCH_OBJECT;
1110 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
1112 for (g = conn->c_groups; g; g=g->ga_next) {
1113 if (g->ga_be != be || g->ga_oc != group_oc ||
1114 g->ga_at != group_at || g->ga_len != gr_ndn->bv_len)
1116 if (strcmp( g->ga_ndn, gr_ndn->bv_val ) == 0)
1120 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
1126 if( be->be_group ) {
1127 int res = be->be_group( be, conn, op,
1128 target, gr_ndn, op_ndn,
1129 group_oc, group_at );
1131 if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache ) {
1132 g = ch_malloc(sizeof(GroupAssertion) + gr_ndn->bv_len);
1134 g->ga_oc = group_oc;
1135 g->ga_at = group_at;
1137 g->ga_len = gr_ndn->bv_len;
1138 strcpy(g->ga_ndn, gr_ndn->bv_val);
1139 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
1140 g->ga_next = conn->c_groups;
1142 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
1148 return LDAP_UNWILLING_TO_PERFORM;
1158 AttributeDescription *entry_at,
1162 if ( target == NULL || !dn_match( &target->e_nname, edn ) ) {
1163 /* we won't attempt to send it to a different backend */
1165 be = select_backend( edn, 0, 0 );
1168 return LDAP_NO_SUCH_OBJECT;
1172 if( be->be_attribute ) {
1173 return be->be_attribute( be, conn, op, target, edn,
1177 return LDAP_UNWILLING_TO_PERFORM;
1180 Attribute *backend_operational(
1185 AttributeName *attrs,
1188 Attribute *a = NULL, **ap = &a;
1191 * If operational attributes (allegedly) are required,
1192 * and the backend supports specific operational attributes,
1193 * add them to the attribute list
1195 if ( opattrs || ( attrs &&
1196 ad_inlist( slap_schema.si_ad_subschemaSubentry, attrs )) ) {
1197 *ap = slap_operational_subschemaSubentry( be );
1198 ap = &(*ap)->a_next;
1201 if ( ( opattrs || attrs ) && be && be->be_operational != NULL ) {
1202 ( void )be->be_operational( be, conn, op, e, attrs, opattrs, ap );