]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/saslauthz.c
Don't bother setting up threads if there are no indexed attrs
[openldap] / servers / slapd / saslauthz.c
index d2d2facdad463f010490fff1a4da1d61ddec357a..dcf0c0c9ef1f4bd7d0f8b923600ab35fc5ff6d9b 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2005 The OpenLDAP Foundation.
+ * Copyright 1998-2006 The OpenLDAP Foundation.
  * Portions Copyright 2000 Mark Adamson, Carnegie Mellon.
  * All rights reserved.
  *
@@ -148,7 +148,7 @@ int slap_parse_user( struct berval *id, struct berval *user,
         *              u[.mech[/realm]]:user
         */
        
-       user->bv_val = strchr( id->bv_val, ':' );
+       user->bv_val = ber_bvchr( id, ':' );
        if ( BER_BVISNULL( user ) ) {
                return LDAP_PROTOCOL_ERROR;
        }
@@ -156,20 +156,19 @@ int slap_parse_user( struct berval *id, struct berval *user,
        user->bv_val++;
        user->bv_len = id->bv_len - ( user->bv_val - id->bv_val );
 
-       mech->bv_val = strchr( id->bv_val, '.' );
+       mech->bv_val = ber_bvchr( id, '.' );
        if ( !BER_BVISNULL( mech ) ) {
                mech->bv_val[ 0 ] = '\0';
                mech->bv_val++;
+               mech->bv_len = user->bv_val - mech->bv_val - 1;
 
-               realm->bv_val = strchr( mech->bv_val, '/' );
+               realm->bv_val = ber_bvchr( mech, '/' );
 
                if ( !BER_BVISNULL( realm ) ) {
                        realm->bv_val[ 0 ] = '\0';
                        realm->bv_val++;
                        mech->bv_len = realm->bv_val - mech->bv_val - 1;
                        realm->bv_len = user->bv_val - realm->bv_val - 1;
-               } else {
-                       mech->bv_len = user->bv_val - mech->bv_val - 1;
                }
 
        } else {
@@ -341,7 +340,8 @@ is_dn:              bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
                                member_at = BER_BVNULL;
 
                bv.bv_val = in->bv_val + STRLENOF( "group" );
-               group_dn.bv_val = strchr( bv.bv_val, ':' );
+               bv.bv_len = in->bv_len - STRLENOF( "group" );
+               group_dn.bv_val = ber_bvchr( &bv, ':' );
                if ( group_dn.bv_val == NULL ) {
                        /* last chance: assume it's a(n exact) DN ... */
                        bv.bv_val = in->bv_val;
@@ -355,8 +355,9 @@ is_dn:              bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
                 */
                if ( bv.bv_val[ 0 ] == '/' ) {
                        group_oc.bv_val = &bv.bv_val[ 1 ];
+                       group_oc.bv_len = group_dn.bv_val - group_oc.bv_val;
 
-                       member_at.bv_val = strchr( group_oc.bv_val, '/' );
+                       member_at.bv_val = ber_bvchr( &group_oc, '/' );
                        if ( member_at.bv_val ) {
                                AttributeDescription    *ad = NULL;
                                const char              *text = NULL;
@@ -368,13 +369,10 @@ is_dn:            bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
                                if ( rc != LDAP_SUCCESS ) {
                                        return rc;
                                }
+                       }
 
-                       } else {
-                               group_oc.bv_len = group_dn.bv_val - group_oc.bv_val;
-
-                               if ( oc_bvfind( &group_oc ) == NULL ) {
-                                       return LDAP_INVALID_SYNTAX;
-                               }
+                       if ( oc_bvfind( &group_oc ) == NULL ) {
+                               return LDAP_INVALID_SYNTAX;
                        }
                }
 
@@ -668,7 +666,8 @@ is_dn:              bv.bv_len = val->bv_len - ( bv.bv_val - val->bv_val );
                char            *ptr;
 
                bv.bv_val = val->bv_val + STRLENOF( "group" );
-               group_dn.bv_val = strchr( bv.bv_val, ':' );
+               bv.bv_len = val->bv_len - STRLENOF( "group" );
+               group_dn.bv_val = ber_bvchr( &bv, ':' );
                if ( group_dn.bv_val == NULL ) {
                        /* last chance: assume it's a(n exact) DN ... */
                        bv.bv_val = val->bv_val;
@@ -681,9 +680,12 @@ is_dn:             bv.bv_len = val->bv_len - ( bv.bv_val - val->bv_val );
                 * are present in schema...
                 */
                if ( bv.bv_val[ 0 ] == '/' ) {
+                       ObjectClass             *oc = NULL;
+
                        group_oc.bv_val = &bv.bv_val[ 1 ];
+                       group_oc.bv_len = group_dn.bv_val - group_oc.bv_val;
 
-                       member_at.bv_val = strchr( group_oc.bv_val, '/' );
+                       member_at.bv_val = ber_bvchr( &group_oc, '/' );
                        if ( member_at.bv_val ) {
                                AttributeDescription    *ad = NULL;
                                const char              *text = NULL;
@@ -698,18 +700,14 @@ is_dn:            bv.bv_len = val->bv_len - ( bv.bv_val - val->bv_val );
 
                                member_at = ad->ad_cname;
 
-                       } else {
-                               ObjectClass             *oc = NULL;
-
-                               group_oc.bv_len = group_dn.bv_val - group_oc.bv_val;
-
-                               oc = oc_bvfind( &group_oc );
-                               if ( oc == NULL ) {
-                                       return LDAP_INVALID_SYNTAX;
-                               }
+                       }
 
-                               group_oc = oc->soc_cname;
+                       oc = oc_bvfind( &group_oc );
+                       if ( oc == NULL ) {
+                               return LDAP_INVALID_SYNTAX;
                        }
+
+                       group_oc = oc->soc_cname;
                }
 
                group_dn.bv_val++;
@@ -959,7 +957,7 @@ slap_parseURI(
        if ( idx.bv_val[ 0 ] == '{' ) {
                char    *ptr;
 
-               ptr = strchr( idx.bv_val, '}' ) + 1;
+               ptr = ber_bvchr( &idx, '}' ) + 1;
 
                assert( ptr != (void *)1 );
 
@@ -1113,7 +1111,8 @@ is_dn:            bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val);
                char            *tmp;
 
                bv.bv_val = uri->bv_val + STRLENOF( "group" );
-               group_dn.bv_val = strchr( bv.bv_val, ':' );
+               bv.bv_len = uri->bv_len - STRLENOF( "group" );
+               group_dn.bv_val = ber_bvchr( &bv, ':' );
                if ( group_dn.bv_val == NULL ) {
                        /* last chance: assume it's a(n exact) DN ... */
                        bv.bv_val = uri->bv_val;
@@ -1123,20 +1122,21 @@ is_dn:          bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val);
                
                if ( bv.bv_val[ 0 ] == '/' ) {
                        group_oc.bv_val = &bv.bv_val[ 1 ];
+                       group_oc.bv_len = group_dn.bv_val - group_oc.bv_val;
 
-                       member_at.bv_val = strchr( group_oc.bv_val, '/' );
+                       member_at.bv_val = ber_bvchr( &group_oc, '/' );
                        if ( member_at.bv_val ) {
                                group_oc.bv_len = member_at.bv_val - group_oc.bv_val;
                                member_at.bv_val++;
                                member_at.bv_len = group_dn.bv_val - member_at.bv_val;
 
                        } else {
-                               group_oc.bv_len = group_dn.bv_val - group_oc.bv_val;
                                BER_BVSTR( &member_at, SLAPD_GROUP_ATTR );
                        }
 
                } else {
                        BER_BVSTR( &group_oc, SLAPD_GROUP_CLASS );
+                       BER_BVSTR( &member_at, SLAPD_GROUP_ATTR );
                }
                group_dn.bv_val++;
                group_dn.bv_len = uri->bv_len - ( group_dn.bv_val - uri->bv_val );
@@ -1577,24 +1577,25 @@ static int slap_authz_regexp( struct berval *in, struct berval *out,
 }
 
 /* This callback actually does some work...*/
-static int sasl_sc_sasl2dn( Operation *o, SlapReply *rs )
+static int sasl_sc_sasl2dn( Operation *op, SlapReply *rs )
 {
-       struct berval *ndn = o->o_callback->sc_private;
+       struct berval *ndn = op->o_callback->sc_private;
 
-       if (rs->sr_type != REP_SEARCH) return 0;
+       if ( rs->sr_type != REP_SEARCH ) return LDAP_SUCCESS;
 
        /* We only want to be called once */
        if ( !BER_BVISNULL( ndn ) ) {
-               o->o_tmpfree(ndn->bv_val, o->o_tmpmemctx);
+               op->o_tmpfree( ndn->bv_val, op->o_tmpmemctx );
                BER_BVZERO( ndn );
 
                Debug( LDAP_DEBUG_TRACE,
-                       "slap_sc_sasl2dn: search DN returned more than 1 entry\n", 0, 0, 0 );
-               return -1;
+                       "%s: slap_sc_sasl2dn: search DN returned more than 1 entry\n",
+                       op->o_log_prefix, 0, 0 );
+               return LDAP_UNAVAILABLE; /* short-circuit the search */
        }
 
-       ber_dupbv_x(ndn, &rs->sr_entry->e_nname, o->o_tmpmemctx);
-       return 0;
+       ber_dupbv_x( ndn, &rs->sr_entry->e_nname, op->o_tmpmemctx );
+       return LDAP_SUCCESS;
 }
 
 
@@ -1607,23 +1608,11 @@ static int sasl_sc_smatch( Operation *o, SlapReply *rs )
 {
        smatch_info *sm = o->o_callback->sc_private;
 
-       if ( rs->sr_type != REP_SEARCH ) {
-               if ( rs->sr_err != LDAP_SUCCESS ) {
-                       sm->match = -1;
-               }
-               return 0;
-       }
-
-       if ( sm->match == 1 ) {
-               sm->match = -1;
-               return 0;
-       }
+       if (rs->sr_type != REP_SEARCH) return 0;
 
        if (dn_match(sm->dn, &rs->sr_entry->e_nname)) {
                sm->match = 1;
-
-       } else {
-               sm->match = -1;
+               return LDAP_UNAVAILABLE;        /* short-circuit the search */
        }
 
        return 0;
@@ -1831,7 +1820,7 @@ exact_match:
        op.o_tag = LDAP_REQ_SEARCH;
        op.o_ndn = *authc;
        op.o_callback = &cb;
-       op.o_time = slap_get_time();
+       slap_op_time( &op.o_time, &op.o_tincr );
        op.o_do_not_cache = 1;
        op.o_is_auth_check = 1;
        /* use req_ndn as req_dn instead of non-pretty base of uri */
@@ -1849,7 +1838,7 @@ exact_match:
 
        op.o_bd->be_search( &op, &rs );
 
-       if (sm.match == 1) {
+       if (sm.match) {
                rc = LDAP_SUCCESS;
        } else {
                rc = LDAP_INAPPROPRIATE_AUTH;
@@ -1883,14 +1872,18 @@ slap_sasl_check_authz( Operation *op,
        AttributeDescription *ad,
        struct berval *authc )
 {
-       int rc;
-       BerVarray vals = NULL;
+       int             rc,
+                       do_not_cache = op->o_do_not_cache;
+       BerVarray       vals = NULL;
 
        Debug( LDAP_DEBUG_TRACE,
           "==>slap_sasl_check_authz: does %s match %s rule in %s?\n",
           assertDN->bv_val, ad->ad_cname.bv_val, searchDN->bv_val);
 
+       /* ITS#4760: don't cache group access */
+       op->o_do_not_cache = 1;
        rc = backend_attribute( op, NULL, searchDN, ad, &vals, ACL_AUTH );
+       op->o_do_not_cache = do_not_cache;
        if( rc != LDAP_SUCCESS ) goto COMPLETE;
 
        /* Check if the *assertDN matches any *vals */
@@ -1970,9 +1963,7 @@ slap_sasl2dn(
        case LDAP_SCOPE_BASE:
        case LDAP_SCOPE_ONELEVEL:
        case LDAP_SCOPE_SUBTREE:
-#ifdef LDAP_SCOPE_SUBORDINATE
        case LDAP_SCOPE_SUBORDINATE:
-#endif
                /* do a search */
                break;
 
@@ -1999,7 +1990,7 @@ slap_sasl2dn(
        op.o_tag = LDAP_REQ_SEARCH;
        op.o_ndn = opx->o_conn->c_ndn;
        op.o_callback = &cb;
-       op.o_time = slap_get_time();
+       slap_op_time( &op.o_time, &op.o_tincr );
        op.o_do_not_cache = 1;
        op.o_is_auth_check = 1;
        op.ors_deref = LDAP_DEREF_NEVER;
@@ -2058,7 +2049,8 @@ int slap_sasl_authorized( Operation *op,
 
        Debug( LDAP_DEBUG_TRACE,
           "==>slap_sasl_authorized: can %s become %s?\n",
-               authcDN->bv_val, authzDN->bv_val, 0 );
+               authcDN->bv_len ? authcDN->bv_val : "(null)",
+               authzDN->bv_len ? authzDN->bv_val : "(null)",  0 );
 
        /* If person is authorizing to self, succeed */
        if ( dn_match( authcDN, authzDN ) ) {