+ qpw->rs_old.bv_val = NULL;
+ qpw->rs_new.bv_val = NULL;
+ qpw->rs_mods = NULL;
+ qpw->rs_modtail = NULL;
+
+ rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id, &qpw->rs_old,
+ &qpw->rs_new, &rs->sr_text );
+
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ return rs->sr_err;
+ }
+
+ if ( id.bv_len ) {
+ ber_dupbv_x( &op->o_req_dn, &id, op->o_tmpmemctx );
+ /* ndn is in tmpmem, so we don't need to free it */
+ rs->sr_err = dnNormalize( 0, NULL, NULL, &id, &op->o_req_ndn, op->o_tmpmemctx );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ rs->sr_text = "Invalid DN";
+ rc = rs->sr_err;
+ goto error_return;
+ }
+ op->o_bd = select_backend( &op->o_req_ndn, 0, 1 );
+
+ } else {
+ ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
+ ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
+ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
+ op->o_bd = op->o_conn->c_authz_backend;
+ ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
+ }
+
+ if( op->o_bd == NULL ) {
+#ifdef HAVE_CYRUS_SASL
+ rc = slap_sasl_setpass( op, rs );
+#else
+ rs->sr_text = "no authz backend";
+ rc = LDAP_OTHER;
+#endif
+ goto error_return;
+ }
+
+ if ( op->o_req_ndn.bv_len == 0 ) {
+ rs->sr_text = "no password is associated with the Root DSE";
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ goto error_return;
+ }
+
+ /* If we've got a glued backend, check the real backend */
+ op_be = op->o_bd;
+ if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
+ op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+ }
+
+ if (backend_check_restrictions( op, rs,
+ (struct berval *)&slap_EXOP_MODIFY_PASSWD ) != LDAP_SUCCESS) {
+ rc = rs->sr_err;
+ goto error_return;
+ }
+
+ /* check for referrals */
+ if ( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
+ rc = rs->sr_err;
+ goto error_return;
+ }
+
+#ifndef SLAPD_MULTIMASTER
+ /* This does not apply to multi-master case */
+ if(!( !SLAP_SHADOW( op->o_bd ) || be_isupdate( op ))) {
+ /* we SHOULD return a referral in this case */
+ BerVarray defref = op->o_bd->be_update_refs
+ ? op->o_bd->be_update_refs : default_referral;