]> git.sur5r.net Git - openldap/commitdiff
add support for don't use copy in SASL auxprops lookup/store (ITS#6475; TODO: documen...
authorPierangelo Masarati <ando@openldap.org>
Thu, 15 Apr 2010 18:13:53 +0000 (18:13 +0000)
committerPierangelo Masarati <ando@openldap.org>
Thu, 15 Apr 2010 18:13:53 +0000 (18:13 +0000)
servers/slapd/back-ldap/chain.c
servers/slapd/bconfig.c
servers/slapd/proto-slap.h
servers/slapd/sasl.c
servers/slapd/slap.h

index c517f15a10d47ef49dd138c5dba046a2479aeaef..6b7036a8334ba53b2c20ad116c6ec608c97d8fb3 100644 (file)
@@ -854,6 +854,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 
        /* we need this to know if back-ldap returned any result */
        lb.lb_lc = lc;
+       sc2.sc_next = sc->sc_next;
        sc2.sc_private = &lb;
        sc2.sc_response = ldap_chain_cb_response;
        op->o_callback = &sc2;
@@ -947,6 +948,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 
        case LDAP_SUCCESS:
        case LDAP_REFERRAL:
+               sr_err = rs->sr_err;
                /* slapd-ldap sent response */
                if ( !op->o_abandon && lb.lb_status != LDAP_CH_RES ) {
                        /* FIXME: should we send response? */
@@ -974,7 +976,7 @@ cannot_chain:;
                default:
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
                        if ( LDAP_CHAIN_RETURN_ERR( lc ) ) {
-                               rs->sr_err = rc;
+                               sr_err = rs->sr_err = rc;
                                rs->sr_type = sr_type;
 
                        } else {
@@ -992,7 +994,8 @@ cannot_chain:;
        }
 
        if ( lb.lb_status == LDAP_CH_NONE && rc != SLAPD_ABANDON ) {
-               op->o_callback = NULL;
+               /* give the remaining callbacks a chance */
+               op->o_callback = sc->sc_next;
                rc = rs->sr_err = slap_map_api2result( rs );
                send_ldap_result( op, rs );
        }
index 2987bf6d9ac98bd6ced629102d533c38d79be296..1db63ea574cb492ead09168e68778ec1fa0f8ed5 100644 (file)
@@ -179,6 +179,8 @@ enum {
        CFG_LASTMOD,
        CFG_AZPOLICY,
        CFG_AZREGEXP,
+       CFG_AZDUC,
+       CFG_AZDUC_IGNORE,
        CFG_SASLSECP,
        CFG_SSTR_IF_MAX,
        CFG_SSTR_IF_MIN,
@@ -549,6 +551,24 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:89 NAME 'olcSaslAuxprops' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+       { "sasl-auxprops-dontusecopy", NULL, 2, 0, 0,
+#if defined(HAVE_CYRUS_SASL) && defined(SLAP_AUXPROP_DONTUSECOPY)
+               ARG_MAGIC|CFG_AZDUC, &config_generic,
+#else
+               ARG_IGNORED, NULL,
+#endif
+               "( OLcfgGlAt:91 NAME 'olcSaslAuxpropsDontUseCopy' "
+                       "EQUALITY caseIgnoreMatch "
+                       "SYNTAX OMsDirectoryString )", NULL, NULL },
+       { "sasl-auxprops-dontusecopy-ignore", "true|FALSE", 2, 0, 0,
+#if defined(HAVE_CYRUS_SASL) && defined(SLAP_AUXPROP_DONTUSECOPY)
+               ARG_ON_OFF|CFG_AZDUC_IGNORE, &slap_dontUseCopy_ignore,
+#else
+               ARG_IGNORED, NULL,
+#endif
+               "( OLcfgGlAt:92 NAME 'olcSaslAuxpropsDontUseCopyIgnore' "
+                       "EQUALITY booleanMatch "
+                       "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
        { "sasl-host", "host", 2, 2, 0,
 #ifdef HAVE_CYRUS_SASL
                ARG_STRING|ARG_UNIQUE, &sasl_host,
@@ -792,7 +812,8 @@ static ConfigOCs cf_ocs[] = {
                 "olcPluginLogFile $ olcReadOnly $ olcReferral $ "
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
                 "olcRootDSE $ "
-                "olcSaslAuxprops $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
+                "olcSaslAuxprops $ olcSaslAuxpropsDontUseCopy $ olcSaslAuxpropsDontUseCopyIgnore $ "
+                "olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
                 "olcSecurity $ olcServerID $ olcSizeLimit $ "
                 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ "
                 "olcTCPBuffer $ "
@@ -939,6 +960,47 @@ config_generic(ConfigArgs *c) {
                        if ( !c->rvalue_vals ) rc = 1;
                        break;
 #ifdef HAVE_CYRUS_SASL
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+               case CFG_AZDUC: {
+                       static int duc_done = 0;
+
+                       /* take the opportunity to initialize with known values */
+                       if ( !duc_done ) {
+                               struct berval duc[] = { BER_BVC("cmusaslsecretOTP"), BER_BVNULL };
+                               int i;
+                               
+                               for ( i = 0; !BER_BVISNULL( &duc[ i ] ); i++ ) {
+                                       const char *text = NULL;
+                                       AttributeDescription *ad = NULL;
+
+                                       if ( slap_bv2ad( &duc[ i ], &ad, &text ) == LDAP_SUCCESS ) {
+                                               int gotit = 0;
+                                               if ( slap_dontUseCopy_propnames ) {
+                                                       int j;
+
+                                                       for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ] ); j++ ) {
+                                                               if ( bvmatch( &slap_dontUseCopy_propnames[ j ], &ad->ad_cname ) ) {
+                                                                       gotit = 1;
+                                                               }
+                                                       }
+                                               }
+
+                                               if ( !gotit ) {
+                                                       value_add_one( &slap_dontUseCopy_propnames, &ad->ad_cname );
+                                               }
+                                       }
+                               }
+
+                               duc_done = 1;
+                       }
+
+                       if ( slap_dontUseCopy_propnames != NULL ) {
+                               ber_bvarray_dup_x( &c->rvalue_vals, slap_dontUseCopy_propnames, NULL );
+                       } else {
+                               rc = 1;
+                       }
+                       } break;
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
                case CFG_SASLSECP: {
                        struct berval bv = BER_BVNULL;
                        slap_sasl_secprops_unparse( &bv );
@@ -1221,6 +1283,35 @@ config_generic(ConfigArgs *c) {
                        snprintf(c->log, sizeof( c->log ), "change requires slapd restart");
                        break;
 
+#if defined(HAVE_CYRUS_SASL) && defined(SLAP_AUXPROP_DONTUSECOPY)
+               case CFG_AZDUC:
+                       if ( c->valx < 0 ) {
+                               if ( slap_dontUseCopy_propnames != NULL ) {
+                                       ber_bvarray_free( slap_dontUseCopy_propnames );
+                                       slap_dontUseCopy_propnames = NULL;
+                               }
+       
+                       } else {
+                               int i;
+
+                               if ( slap_dontUseCopy_propnames == NULL ) {
+                                       rc = 1;
+                                       break;
+                               }
+
+                               for ( i = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ i ] ) && i < c->valx; i++ );
+                               if ( i < c->valx ) {
+                                       rc = 1;
+                                       break;
+                               }
+                               ber_memfree( slap_dontUseCopy_propnames[ i ].bv_val );
+                               for ( ; !BER_BVISNULL( &slap_dontUseCopy_propnames[ i + 1 ] ); i++ ) {
+                                       slap_dontUseCopy_propnames[ i ] = slap_dontUseCopy_propnames[ i + 1 ];
+                               }
+                               BER_BVZERO( &slap_dontUseCopy_propnames[ i ] );
+                       }
+                       break;
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
                case CFG_SALT:
                        ch_free( passwd_salt );
                        passwd_salt = NULL;
@@ -1556,6 +1647,47 @@ config_generic(ConfigArgs *c) {
                        break;
                                
 #ifdef HAVE_CYRUS_SASL
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+               case CFG_AZDUC: {
+                       int arg, cnt;
+
+                       for ( arg = 1; arg < c->argc; arg++ ) {
+                               int duplicate = 0, err;
+                               AttributeDescription *ad = NULL;
+                               const char *text = NULL;
+
+                               err = slap_str2ad( c->argv[ arg ], &ad, &text );
+                               if ( err != LDAP_SUCCESS ) {
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s>: attr #%d (\"%s\") unknown (err=%d \"%s\"; ignored)",
+                                               c->argv[0], arg, c->argv[ arg ], err, text );
+                                       Debug(LDAP_DEBUG_ANY, "%s: %s\n",
+                                               c->log, c->cr_msg, 0 );
+
+                               } else {
+                                       if ( slap_dontUseCopy_propnames != NULL ) {
+                                               for ( cnt = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ cnt ] ); cnt++ ) {
+                                                       if ( bvmatch( &slap_dontUseCopy_propnames[ cnt ], &ad->ad_cname ) ) {
+                                                               duplicate = 1;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+
+                                       if ( duplicate ) {
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s>: attr #%d (\"%s\") already defined (ignored)",
+                                                       c->argv[0], arg, ad->ad_cname.bv_val);
+                                               Debug(LDAP_DEBUG_ANY, "%s: %s\n",
+                                                       c->log, c->cr_msg, 0 );
+                                               continue;
+                                       }
+
+                                       value_add_one( &slap_dontUseCopy_propnames, &ad->ad_cname );
+                               }
+                       }
+                       
+                       } break;
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
+
                case CFG_SASLSECP:
                        {
                        char *txt = slap_sasl_secprops( c->argv[1] );
index fa225d9e7ed485393e20967bf3984fd9fcac6d6f..7fdf090fac2801336d652447027cb49263e24622 100644 (file)
@@ -1965,6 +1965,10 @@ LDAP_SLAPD_V (struct berval)     global_host_bv;
 LDAP_SLAPD_V (char *)  global_realm;
 LDAP_SLAPD_V (char *)  sasl_host;
 LDAP_SLAPD_V (char *)  slap_sasl_auxprops;
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+LDAP_SLAPD_V (int)             slap_dontUseCopy_ignore;
+LDAP_SLAPD_V (BerVarray)       slap_dontUseCopy_propnames;
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
 LDAP_SLAPD_V (char **) default_passwd_hash;
 LDAP_SLAPD_V (int)             lber_debug;
 LDAP_SLAPD_V (int)             ldap_syslog;
index fd25cf363fada1b5aa517740b530a46013a2e937..ca6e7c9ce8069a7a6e67c8fff23cec86415fa050 100644 (file)
@@ -149,6 +149,11 @@ static const char *slap_propnames[] = {
        "*slapConn", "*slapAuthcDNlen", "*slapAuthcDN",
        "*slapAuthzDNlen", "*slapAuthzDN", NULL };
 
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+int slap_dontUseCopy_ignore;
+BerVarray slap_dontUseCopy_propnames;
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
+
 static Filter generic_filter = { LDAP_FILTER_PRESENT, { 0 }, NULL };
 static struct berval generic_filterstr = BER_BVC("(objectclass=*)");
 
@@ -179,7 +184,10 @@ sasl_ap_lookup( Operation *op, SlapReply *rs )
        int rc, i;
        lookup_info *sl = (lookup_info *)op->o_callback->sc_private;
 
-       if (rs->sr_type != REP_SEARCH) return 0;
+       /* return the actual error code,
+        * to allow caller to handle specific errors
+        */
+       if (rs->sr_type != REP_SEARCH) return rs->sr_err;
 
        for( i = 0; sl->list[i].name; i++ ) {
                const char *name = sl->list[i].name;
@@ -276,6 +284,10 @@ slap_auxprop_lookup(
        Connection *conn = NULL;
        lookup_info sl;
        int rc = LDAP_SUCCESS;
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+       int dontUseCopy = 0;
+       BackendDB *dontUseCopy_bd = NULL;
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
 
        sl.list = sparams->utils->prop_get( sparams->propctx );
        sl.sparams = sparams;
@@ -312,6 +324,19 @@ slap_auxprop_lookup(
                                                break;
                                }
                        }
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+                       if ( slap_dontUseCopy_propnames != NULL ) {
+                               int j;
+                               struct berval bv;
+                               ber_str2bv( &sl.list[i].name[1], 0, 1, &bv );
+                               for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ]); j++ ) {
+                                       if ( bvmatch( &bv, &slap_dontUseCopy_propnames[ j ] ) ) {
+                                               dontUseCopy = 1;
+                                               break;
+                                       }
+                               }
+                       }
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
                }
        }
 
@@ -386,8 +411,22 @@ slap_auxprop_lookup(
                                }
                        }
 
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+                       if ( SLAP_SHADOW( op->o_bd ) && dontUseCopy ) {
+                               dontUseCopy_bd = op->o_bd;
+                               op->o_bd = frontendDB;
+                       }
+
+retry_dontUseCopy:;
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
+
                        if ( op->o_bd->be_search ) {
                                SlapReply rs = {REP_RESULT};
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+                               LDAPControl **save_ctrls = NULL, c;
+                               int save_dontUseCopy;
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
+
                                op->o_hdr = conn->c_sasl_bindop->o_hdr;
                                op->o_controls = opbuf.ob_controls;
                                op->o_tag = LDAP_REQ_SEARCH;
@@ -408,7 +447,49 @@ slap_auxprop_lookup(
                                /* FIXME: we want all attributes, right? */
                                op->ors_attrs = NULL;
 
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+                               if ( dontUseCopy ) {
+                                       save_dontUseCopy = op->o_dontUseCopy;
+                                       if ( !op->o_dontUseCopy ) {
+                                               int cnt = 0;
+                                               save_ctrls = op->o_ctrls;
+                                               if ( op->o_ctrls ) {
+                                                       for ( ; op->o_ctrls[ cnt ]; cnt++ )
+                                                               ;
+                                               }
+                                               op->o_ctrls = op->o_tmpcalloc( sizeof(LDAPControl *), cnt + 2, op->o_tmpmemctx );
+                                               if ( cnt ) {
+                                                       for ( cnt = 0; save_ctrls[ cnt ]; cnt++ ) {
+                                                               op->o_ctrls[ cnt ] = save_ctrls[ cnt ];
+                                                       }
+                                               }
+                                               c.ldctl_oid = LDAP_CONTROL_DONTUSECOPY;
+                                               c.ldctl_iscritical = 1;
+                                               BER_BVZERO( &c.ldctl_value );
+                                               op->o_ctrls[ cnt ] = &c;
+                                       }
+                                       op->o_dontUseCopy = SLAP_CONTROL_CRITICAL;
+                               }
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
+
                                rc = op->o_bd->be_search( op, &rs );
+
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+                               if ( dontUseCopy ) {
+                                       if ( save_ctrls != op->o_ctrls ) {
+                                               op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
+                                               op->o_ctrls = save_ctrls;
+                                               op->o_dontUseCopy = save_dontUseCopy;
+                                       }
+
+                                       if ( rs.sr_err == LDAP_UNAVAILABLE && slap_dontUseCopy_ignore )
+                                       {
+                                               op->o_bd = dontUseCopy_bd;
+                                               dontUseCopy = 0;
+                                               goto retry_dontUseCopy;
+                                       }
+                               }
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
                        }
                }
        }
@@ -438,6 +519,10 @@ slap_auxprop_store(
        char textbuf[SLAP_TEXT_BUFLEN];
        const char *text;
        size_t textlen = sizeof(textbuf);
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+       int dontUseCopy = 0;
+       BackendDB *dontUseCopy_bd = NULL;
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
 
        /* just checking if we are enabled */
        if (!prctx) return SASL_OK;
@@ -462,6 +547,18 @@ slap_auxprop_store(
                                if ( pr[i].values )
                                        op.o_req_ndn.bv_val = (char *)pr[i].values[0];
                        }
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+                       {
+                               struct berval bv;
+                               ber_str2bv( &pr[i].name[1], 0, 1, &bv );
+                               for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ] ); j++ ) {
+                                       if ( bvmatch( &bv, &slap_dontUseCopy_propnames[ j ] ) ) {
+                                               dontUseCopy = 1;
+                                               break;
+                                       }
+                               }
+                       }
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
                }
        }
        if (!conn || !op.o_req_ndn.bv_val) return SASL_BADPARAM;
@@ -469,7 +566,15 @@ slap_auxprop_store(
        op.o_bd = select_backend( &op.o_req_ndn, 1 );
 
        if ( !op.o_bd || !op.o_bd->be_modify ) return SASL_FAIL;
-               
+
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+       if ( SLAP_SHADOW( op.o_bd ) && dontUseCopy ) {
+               dontUseCopy_bd = op.o_bd;
+               op.o_bd = frontendDB;
+               op.o_dontUseCopy = SLAP_CONTROL_CRITICAL;
+       }
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
+
        pr = sparams->utils->prop_get( prctx );
        if (!pr) return SASL_BADPARAM;
 
@@ -518,7 +623,20 @@ slap_auxprop_store(
                        op.o_req_dn = op.o_req_ndn;
                        op.orm_modlist = modlist;
 
+retry_dontUseCopy:;
                        rc = op.o_bd->be_modify( &op, &rs );
+
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+                       if ( dontUseCopy &&
+                               rs.sr_err == LDAP_UNAVAILABLE &&
+                               slap_dontUseCopy_ignore )
+                       {
+                               op.o_bd = dontUseCopy_bd;
+                               op.o_dontUseCopy = SLAP_CONTROL_NONE;
+                               dontUseCopy = 0;
+                               goto retry_dontUseCopy;
+                       }
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
                }
        }
        slap_mods_free( modlist, 1 );
@@ -1188,6 +1306,13 @@ int slap_sasl_destroy( void )
 {
 #ifdef HAVE_CYRUS_SASL
        sasl_done();
+
+#ifdef SLAP_AUXPROP_DONTUSECOPY
+       if ( slap_dontUseCopy_propnames ) {
+               ber_bvarray_free( slap_dontUseCopy_propnames );
+               slap_dontUseCopy_propnames = NULL;
+       }
+#endif /* SLAP_AUXPROP_DONTUSECOPY */
 #endif
        free( sasl_host );
        sasl_host = NULL;
index 829b6973d159f3dfcece95dce48b5fb334f1f169..2e7d0b28e43594ec313a3605193c8a77a360301b 100644 (file)
@@ -65,6 +65,7 @@ LDAP_BEGIN_DECL
 #define SLAP_CONTROL_X_SESSION_TRACKING
 #define SLAP_CONTROL_X_WHATFAILED
 #define SLAP_CONFIG_DELETE
+#define SLAP_AUXPROP_DONTUSECOPY
 #ifndef SLAP_SCHEMA_EXPOSE
 #define SLAP_SCHEMA_EXPOSE
 #endif