diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 1fbeecde21..655c2fdc46 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -17,6 +17,7 @@ #include "slap.h" #include "lutil.h" +#include "lber_pvt.h" /* * If a module is configured as dynamic, its header should not @@ -767,7 +768,7 @@ backend_check_restrictions( Backend *be, Connection *conn, Operation *op, - const void *opdata, + struct berval *opdata, const char **text ) { int rc; @@ -776,6 +777,8 @@ backend_check_restrictions( slap_mask_t opflag; slap_ssf_set_t *ssf; int updateop = 0; + int starttls = 0; + int session = 0; if( be ) { rc = backend_check_controls( be, conn, op, text ); @@ -801,6 +804,7 @@ backend_check_restrictions( break; case LDAP_REQ_BIND: opflag = SLAP_RESTRICT_OP_BIND; + session++; break; case LDAP_REQ_COMPARE: opflag = SLAP_RESTRICT_OP_COMPARE; @@ -811,7 +815,35 @@ backend_check_restrictions( break; case LDAP_REQ_EXTENDED: opflag = SLAP_RESTRICT_OP_EXTENDED; + + if( !opdata ) { + /* treat unspecified as a modify */ + opflag = SLAP_RESTRICT_OP_MODIFY; + updateop++; + break; + } + + { + struct berval bv = BER_BVC( LDAP_EXOP_START_TLS ); + if( ber_bvcmp( opdata, &bv ) == 0 ) { + session++; + starttls++; + break; + } + } + + { + struct berval bv = BER_BVC( LDAP_EXOP_X_WHO_AM_I ); + if( ber_bvcmp( opdata, &bv ) == 0 ) { + break; + } + } + + /* treat everything else as a modify */ + opflag = SLAP_RESTRICT_OP_MODIFY; + updateop++; break; + case LDAP_REQ_MODIFY: updateop++; opflag = SLAP_RESTRICT_OP_MODIFY; @@ -824,6 +856,7 @@ backend_check_restrictions( opflag = SLAP_RESTRICT_OP_SEARCH; break; case LDAP_REQ_UNBIND: + session++; opflag = 0; break; default: @@ -831,16 +864,9 @@ backend_check_restrictions( return LDAP_OTHER; } - if ( op->o_tag != LDAP_REQ_EXTENDED - || strcmp( (const char *) opdata, LDAP_EXOP_START_TLS ) ) - { + if ( !starttls ) { /* 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; @@ -893,10 +919,8 @@ backend_check_restrictions( } } - 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 ( !session ) { + /* these checks don't apply to Bind, StartTLS, or Unbind */ if( requires & SLAP_REQUIRE_STRONG ) { /* should check mechanism */ diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index b2b4d32b4a..cbbb1383f6 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -265,7 +265,7 @@ do_bind( } /* check restrictions */ - rc = backend_check_restrictions( NULL, conn, op, mech.bv_val, &text ); + rc = backend_check_restrictions( NULL, conn, op, &mech, &text ); if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); @@ -367,7 +367,8 @@ do_bind( text = "anonymous bind disallowed"; } else { - rc = backend_check_restrictions( NULL, conn, op, mech.bv_val, &text ); + rc = backend_check_restrictions( NULL, conn, op, + &mech, &text ); } /* diff --git a/servers/slapd/extended.c b/servers/slapd/extended.c index 64e8cc2df4..ace5cb55f1 100644 --- a/servers/slapd/extended.c +++ b/servers/slapd/extended.c @@ -32,6 +32,7 @@ #include #include "slap.h" +#include "lber_pvt.h" static struct extop_list { struct extop_list *next; @@ -307,6 +308,7 @@ whoami_extop ( const char ** text, BerVarray * refs ) { + int rc; struct berval *bv; if ( reqdata != NULL ) { @@ -315,6 +317,16 @@ whoami_extop ( return LDAP_PROTOCOL_ERROR; } + { + int rc; + struct berval whoami = BER_BVC( LDAP_EXOP_X_WHO_AM_I ); + + rc = backend_check_restrictions( conn->c_authz_backend, + conn, op, &whoami, text ); + + if( rc != LDAP_SUCCESS ) return rc; + } + bv = (struct berval *) ch_malloc( sizeof(struct berval) ); if( op->o_dn.bv_len ) { bv->bv_len = op->o_dn.bv_len + sizeof("dn:")-1; diff --git a/servers/slapd/passwd.c b/servers/slapd/passwd.c index 8382f284ae..3a8ddd9c1d 100644 --- a/servers/slapd/passwd.c +++ b/servers/slapd/passwd.c @@ -16,6 +16,7 @@ #include "slap.h" +#include #include int passwd_extop( @@ -38,28 +39,34 @@ int passwd_extop( return LDAP_STRONG_AUTH_REQUIRED; } - if( conn->c_authz_backend != NULL && conn->c_authz_backend->be_extended ) { - if( conn->c_authz_backend->be_restrictops & SLAP_RESTRICT_OP_MODIFY ) { - *text = "authorization database is read only"; - rc = LDAP_UNWILLING_TO_PERFORM; + if( conn->c_authz_backend == NULL || !conn->c_authz_backend->be_extended ) { + *text = "operation not supported for current user"; + return LDAP_UNWILLING_TO_PERFORM; + } - } else if( conn->c_authz_backend->be_update_ndn.bv_len ) { - /* we SHOULD return a referral in this case */ - *refs = referral_rewrite( conn->c_authz_backend->be_update_refs, - NULL, NULL, LDAP_SCOPE_DEFAULT ); + { + struct berval passwd = BER_BVC( LDAP_EXOP_MODIFY_PASSWD ); + + rc = backend_check_restrictions( conn->c_authz_backend, + conn, op, &passwd, text ); + } + + if( rc != LDAP_SUCCESS ) { + return rc; + } + + if( conn->c_authz_backend->be_update_ndn.bv_len ) { + /* we SHOULD return a referral in this case */ + *refs = referral_rewrite( conn->c_authz_backend->be_update_refs, + NULL, NULL, LDAP_SCOPE_DEFAULT ); rc = LDAP_REFERRAL; - } else { - rc = conn->c_authz_backend->be_extended( - conn->c_authz_backend, conn, op, - reqoid, reqdata, - rspoid, rspdata, rspctrls, - text, refs ); - } - } else { - *text = "operation not supported for current user"; - rc = LDAP_UNWILLING_TO_PERFORM; + rc = conn->c_authz_backend->be_extended( + conn->c_authz_backend, conn, op, + reqoid, reqdata, + rspoid, rspdata, rspctrls, + text, refs ); } return rc; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 7eaea28368..c3e04319f5 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -184,7 +184,7 @@ LDAP_SLAPD_F( int ) backend_check_restrictions LDAP_P(( BackendDB *be, Connection *conn, Operation *op, - const void *opdata, + struct berval *opdata, const char **text )); LDAP_SLAPD_F( int ) backend_check_referrals LDAP_P((