+int
+backend_check_restrictions(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ const void *opdata,
+ const char **text )
+{
+ int rc;
+ slap_mask_t restrictops;
+ slap_mask_t requires;
+ slap_mask_t opflag;
+ slap_ssf_set_t *ssf;
+ int updateop = 0;
+
+ if( be ) {
+ rc = backend_check_controls( be, conn, op, text );
+
+ if( rc != LDAP_SUCCESS ) {
+ return rc;
+ }
+
+ restrictops = be->be_restrictops;
+ requires = be->be_requires;
+ ssf = &be->be_ssf_set;
+
+ } else {
+ restrictops = global_restrictops;
+ requires = global_requires;
+ ssf = &global_ssf_set;
+ }
+
+ switch( op->o_tag ) {
+ case LDAP_REQ_ADD:
+ opflag = SLAP_RESTRICT_OP_ADD;
+ updateop++;
+ break;
+ case LDAP_REQ_BIND:
+ opflag = SLAP_RESTRICT_OP_BIND;
+ break;
+ case LDAP_REQ_COMPARE:
+ opflag = SLAP_RESTRICT_OP_COMPARE;
+ break;
+ case LDAP_REQ_DELETE:
+ updateop++;
+ opflag = SLAP_RESTRICT_OP_DELETE;
+ break;
+ case LDAP_REQ_EXTENDED:
+ opflag = SLAP_RESTRICT_OP_EXTENDED;
+ break;
+ case LDAP_REQ_MODIFY:
+ updateop++;
+ opflag = SLAP_RESTRICT_OP_MODIFY;
+ break;
+ case LDAP_REQ_RENAME:
+ updateop++;
+ opflag = SLAP_RESTRICT_OP_RENAME;
+ break;
+ case LDAP_REQ_SEARCH:
+ opflag = SLAP_RESTRICT_OP_SEARCH;
+ break;
+ case LDAP_REQ_UNBIND:
+ opflag = 0;
+ break;
+ default:
+ *text = "restrict operations internal error";
+ return LDAP_OTHER;
+ }
+
+ if ( op->o_tag != LDAP_REQ_EXTENDED
+ || strcmp( (const char *) opdata, LDAP_EXOP_START_TLS ) )
+ {
+ /* these checks don't apply to StartTLS */
+
+ if( op->o_tag == LDAP_REQ_EXTENDED ) {
+ /* threat other extended operations as update ops */
+ updateop++;
+ }
+
+ if( op->o_transport_ssf < ssf->sss_transport ) {
+ *text = "transport confidentiality required";
+ return LDAP_CONFIDENTIALITY_REQUIRED;
+ }
+
+ if( op->o_tls_ssf < ssf->sss_tls ) {
+ *text = "TLS confidentiality required";
+ return LDAP_CONFIDENTIALITY_REQUIRED;
+ }
+
+ if( op->o_tag != LDAP_REQ_BIND || opdata == NULL ) {
+ /* these checks don't apply to SASL bind */
+
+ if( op->o_sasl_ssf < ssf->sss_sasl ) {
+ *text = "SASL confidentiality required";
+ return LDAP_CONFIDENTIALITY_REQUIRED;
+ }
+
+ if( op->o_ssf < ssf->sss_ssf ) {
+ *text = "confidentiality required";
+ return LDAP_CONFIDENTIALITY_REQUIRED;
+ }
+ }
+
+ if( updateop ) {
+ if( op->o_transport_ssf < ssf->sss_update_transport ) {
+ *text = "transport update confidentiality required";
+ return LDAP_CONFIDENTIALITY_REQUIRED;
+ }
+
+ if( op->o_tls_ssf < ssf->sss_update_tls ) {
+ *text = "TLS update confidentiality required";
+ return LDAP_CONFIDENTIALITY_REQUIRED;
+ }
+
+ if( op->o_sasl_ssf < ssf->sss_update_sasl ) {
+ *text = "SASL update confidentiality required";
+ return LDAP_CONFIDENTIALITY_REQUIRED;
+ }
+
+ if( op->o_ssf < ssf->sss_update_ssf ) {
+ *text = "update confidentiality required";
+ return LDAP_CONFIDENTIALITY_REQUIRED;
+ }
+
+ if( op->o_ndn.bv_len == 0 ) {
+ *text = "modifications require authentication";
+ return LDAP_OPERATIONS_ERROR;
+ }
+ }
+ }
+
+ if ( op->o_tag != LDAP_REQ_BIND && ( op->o_tag != LDAP_REQ_EXTENDED ||
+ strcmp( (const char *) opdata, LDAP_EXOP_START_TLS ) ) )
+ {
+ /* these checks don't apply to Bind or StartTLS */
+
+ if( requires & SLAP_REQUIRE_STRONG ) {
+ /* should check mechanism */
+ if( op->o_authmech.bv_len == 0 || op->o_dn.bv_len == 0 )
+ {
+ *text = "strong authentication required";
+ return LDAP_STRONG_AUTH_REQUIRED;
+ }
+ }
+
+ if( requires & SLAP_REQUIRE_SASL ) {
+ if( op->o_authmech.bv_len == 0 || op->o_dn.bv_len == 0 )
+ {
+ *text = "SASL authentication required";
+ return LDAP_STRONG_AUTH_REQUIRED;
+ }
+ }
+
+ if( requires & SLAP_REQUIRE_AUTHC ) {
+ if( op->o_dn.bv_len == 0 ) {
+ *text = "authentication required";
+ return LDAP_UNWILLING_TO_PERFORM;
+ }
+ }
+
+ if( requires & SLAP_REQUIRE_BIND ) {
+ int version;
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+ version = conn->c_protocol;
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+ if( !version ) {
+ /* no bind has occurred */
+ *text = "BIND required";
+ return LDAP_OPERATIONS_ERROR;
+ }
+ }
+
+ if( requires & SLAP_REQUIRE_LDAP_V3 ) {
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ /* no bind has occurred */
+ *text = "operation restricted to LDAPv3 clients";
+ return LDAP_OPERATIONS_ERROR;
+ }
+ }
+ }
+
+ if( restrictops & opflag ) {
+ if( restrictops == SLAP_RESTRICT_OP_READS ) {
+ *text = "read operations restricted";
+ } else {
+ *text = "operation restricted";
+ }
+ return LDAP_UNWILLING_TO_PERFORM;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int backend_check_referrals(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ struct berval *dn,
+ struct berval *ndn )
+{
+ int rc = LDAP_SUCCESS;
+
+ if( be->be_chk_referrals ) {
+ const char *text;
+
+ rc = be->be_chk_referrals( be,
+ conn, op, dn, ndn, &text );
+
+ if( rc != LDAP_SUCCESS && rc != LDAP_REFERRAL ) {
+ send_ldap_result( conn, op, rc,
+ NULL, text, NULL, NULL );
+ }
+ }
+
+ return rc;
+}
+