static int dds_expire( void *ctx, dds_info_t *di ) { Connection conn = { 0 }; OperationBuffer opbuf; Operation *op; slap_callback sc = { 0 }; dds_cb_t dc = { 0 }; dds_expire_t *de = NULL, **dep; SlapReply rs = { REP_RESULT }; time_t expire; char tsbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; struct berval ts; int ndeletes, ntotdeletes; int rc; char *extra = ""; connection_fake_init2( &conn, &opbuf, ctx, 0 ); op = &opbuf.ob_op; op->o_tag = LDAP_REQ_SEARCH; memset( &op->oq_search, 0, sizeof( op->oq_search ) ); op->o_bd = select_backend( &di->di_nsuffix[ 0 ], 0 ); op->o_req_dn = op->o_bd->be_suffix[ 0 ]; op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ]; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->ors_scope = LDAP_SCOPE_SUBTREE; op->ors_tlimit = DDS_INTERVAL( di )/2 + 1; op->ors_slimit = SLAP_NO_LIMIT; op->ors_attrs = slap_anlist_no_attrs; expire = slap_get_time() - di->di_tolerance; ts.bv_val = tsbuf; ts.bv_len = sizeof( tsbuf ); slap_timestamp( &expire, &ts ); op->ors_filterstr.bv_len = STRLENOF( "(&(objectClass=" ")(" "<=" "))" ) + slap_schema.si_oc_dynamicObject->soc_cname.bv_len + ad_entryExpireTimestamp->ad_cname.bv_len + ts.bv_len; op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1, "(&(objectClass=%s)(%s<=%s))", slap_schema.si_oc_dynamicObject->soc_cname.bv_val, ad_entryExpireTimestamp->ad_cname.bv_val, ts.bv_val ); op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val ); if ( op->ors_filter == NULL ) { rs.sr_err = LDAP_OTHER; goto done_search; } op->o_callback = ≻ sc.sc_response = dds_expire_cb; sc.sc_private = &dc; (void)op->o_bd->bd_info->bi_op_search( op, &rs ); done_search:; op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); filter_free_x( op, op->ors_filter, 1 ); rc = rs.sr_err; switch ( rs.sr_err ) { case LDAP_SUCCESS: break; case LDAP_NO_SUCH_OBJECT: /* (ITS#5267) database not created yet? */ rs.sr_err = LDAP_SUCCESS; extra = " (ignored)"; /* fallthru */ default: Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR, "DDS expired objects lookup failed err=%d%s\n", rc, extra ); goto done; } op->o_tag = LDAP_REQ_DELETE; op->o_callback = ≻ sc.sc_response = slap_null_cb; sc.sc_private = NULL; slap_biglock_acquire(op->o_bd); for ( ntotdeletes = 0, ndeletes = 1; dc.dc_ndnlist != NULL && ndeletes > 0; ) { ndeletes = 0; for ( dep = &dc.dc_ndnlist; *dep != NULL; ) { de = *dep; op->o_req_dn = de->de_ndn; op->o_req_ndn = de->de_ndn; (void)op->o_bd->bd_info->bi_op_delete( op, &rs ); switch ( rs.sr_err ) { case LDAP_SUCCESS: Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO, "DDS dn=\"%s\" expired.\n", de->de_ndn.bv_val ); ndeletes++; break; case LDAP_NOT_ALLOWED_ON_NONLEAF: Log1( LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE, "DDS dn=\"%s\" is non-leaf; " "deferring.\n", de->de_ndn.bv_val ); dep = &de->de_next; de = NULL; break; default: Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE, "DDS dn=\"%s\" err=%d; " "deferring.\n", de->de_ndn.bv_val, rs.sr_err ); break; } if ( de != NULL ) { *dep = de->de_next; op->o_tmpfree( de, op->o_tmpmemctx ); } } ntotdeletes += ndeletes; } slap_biglock_release(op->o_bd); rs.sr_err = LDAP_SUCCESS; Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO, "DDS expired=%d\n", ntotdeletes ); done:; return rs.sr_err; }
int passwd_extop( Operation *op, SlapReply *rs ) { struct berval id = {0, NULL}, hash, *rsp = NULL; req_pwdexop_s *qpw = &op->oq_pwdexop; req_extended_s qext = op->oq_extended; Modifications *ml; slap_callback cb = { NULL, slap_null_cb, NULL, NULL }; int i, nhash; char **hashes, idNul = 0; int rc; BackendDB *op_be; int freenewpw = 0; struct berval dn = BER_BVNULL, ndn = BER_BVNULL; slap_biglock_t *bl = NULL; assert( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) == 0 ); if( op->o_dn.bv_len == 0 ) { Statslog( LDAP_DEBUG_STATS, "%s PASSMOD\n", op->o_log_prefix ); rs->sr_text = "only authenticated users may change passwords"; return LDAP_STRONG_AUTH_REQUIRED; } qpw->rs_old.bv_len = 0; qpw->rs_old.bv_val = NULL; qpw->rs_new.bv_len = 0; 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 ( !BER_BVISNULL( &id )) { idNul = id.bv_val[id.bv_len]; id.bv_val[id.bv_len] = '\0'; } if ( rs->sr_err == LDAP_SUCCESS && !BER_BVISEMPTY( &id ) ) { Statslog( LDAP_DEBUG_STATS, "%s PASSMOD id=\"%s\"%s%s\n", op->o_log_prefix, id.bv_val, qpw->rs_old.bv_val ? " old" : "", qpw->rs_new.bv_val ? " new" : "" ); } else { Statslog( LDAP_DEBUG_STATS, "%s PASSMOD%s%s\n", op->o_log_prefix, qpw->rs_old.bv_val ? " old" : "", qpw->rs_new.bv_val ? " new" : "" ); } if ( rs->sr_err != LDAP_SUCCESS ) { if ( !BER_BVISNULL( &id )) id.bv_val[id.bv_len] = idNul; return rs->sr_err; } if ( !BER_BVISEMPTY( &id ) ) { rs->sr_err = dnPrettyNormal( NULL, &id, &dn, &ndn, op->o_tmpmemctx ); id.bv_val[id.bv_len] = idNul; if ( rs->sr_err != LDAP_SUCCESS ) { rs->sr_text = "Invalid DN"; rc = rs->sr_err; goto error_return; } op->o_req_dn = dn; op->o_req_ndn = ndn; op->o_bd = select_backend( &op->o_req_ndn, 1 ); } else { ber_dupbv_x( &dn, &op->o_dn, op->o_tmpmemctx ); ber_dupbv_x( &ndn, &op->o_ndn, op->o_tmpmemctx ); op->o_req_dn = dn; op->o_req_ndn = ndn; 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 ) { if ( qpw->rs_old.bv_val != NULL ) { rs->sr_text = "unwilling to verify old password"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } #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 ); } bl = slap_biglock_get(op->o_bd); slap_biglock_acquire(bl); 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; } /* This does not apply to multi-master case */ if(!( !SLAP_SINGLE_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; if( defref != NULL ) { rs->sr_ref = referral_rewrite( defref, NULL, NULL, LDAP_SCOPE_DEFAULT ); if ( ! rs->sr_ref ) ber_bvarray_dup_x( &rs->sr_ref, defref, NULL ); rs->sr_flags |= REP_REF_MUSTBEFREED; rc = LDAP_REFERRAL; goto error_return; } rs->sr_text = "shadow context; no update referral"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } /* generate a new password if none was provided */ if ( qpw->rs_new.bv_len == 0 ) { slap_passwd_generate( &qpw->rs_new ); if ( qpw->rs_new.bv_len ) { rsp = slap_passwd_return( &qpw->rs_new ); freenewpw = 1; } } if ( qpw->rs_new.bv_len == 0 ) { rs->sr_text = "password generation failed"; rc = LDAP_OTHER; goto error_return; } op->o_bd = op_be; /* Give the backend a chance to handle this itself */ if ( op->o_bd->be_extended ) { rs->sr_err = op->o_bd->be_extended( op, rs ); if ( rs->sr_err != LDAP_UNWILLING_TO_PERFORM && rs->sr_err != SLAP_CB_CONTINUE ) { rc = rs->sr_err; if ( rsp ) { rs->sr_rspdata = rsp; rsp = NULL; } goto error_return; } } /* The backend didn't handle it, so try it here */ if( op->o_bd && !op->o_bd->bd_info->bi_op_modify ) { rs->sr_text = "operation not supported for current user"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } if ( qpw->rs_old.bv_val != NULL ) { Entry *e = NULL; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, slap_schema.si_ad_userPassword, 0, &e ); if ( rc == LDAP_SUCCESS && e ) { Attribute *a = attr_find( e->e_attrs, slap_schema.si_ad_userPassword ); if ( a ) rc = slap_passwd_check( op, e, a, &qpw->rs_old, &rs->sr_text ); else rc = 1; be_entry_release_r( op, e ); if ( rc == LDAP_SUCCESS ) goto old_good; } rs->sr_text = "unwilling to verify old password"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } old_good: ml = ch_malloc( sizeof(Modifications) ); if ( !qpw->rs_modtail ) qpw->rs_modtail = &ml->sml_next; if ( default_passwd_hash ) { for ( nhash = 0; default_passwd_hash[nhash]; nhash++ ); hashes = default_passwd_hash; } else { nhash = 1; hashes = (char **)defhash; } ml->sml_numvals = nhash; ml->sml_values = ch_malloc( (nhash+1)*sizeof(struct berval) ); for ( i=0; hashes[i]; i++ ) { slap_passwd_hash_type( &qpw->rs_new, &hash, hashes[i], &rs->sr_text ); if ( hash.bv_len == 0 ) { if ( !rs->sr_text ) { rs->sr_text = "password hash failed"; } break; } ml->sml_values[i] = hash; } ml->sml_values[i].bv_val = NULL; ml->sml_nvalues = NULL; ml->sml_desc = slap_schema.si_ad_userPassword; ml->sml_type = ml->sml_desc->ad_cname; ml->sml_op = LDAP_MOD_REPLACE; ml->sml_flags = 0; ml->sml_next = qpw->rs_mods; qpw->rs_mods = ml; if ( hashes[i] ) { rs->sr_err = LDAP_OTHER; } else { slap_callback *sc = op->o_callback; op->o_tag = LDAP_REQ_MODIFY; op->o_callback = &cb; op->orm_modlist = qpw->rs_mods; op->orm_no_opattrs = 0; cb.sc_private = qpw; /* let Modify know this was pwdMod, * if it cares... */ rs->sr_err = op->o_bd->bd_info->bi_op_modify( op, rs ); /* be_modify() might have shuffled modifications */ qpw->rs_mods = op->orm_modlist; if ( rs->sr_err == LDAP_SUCCESS ) { rs->sr_rspdata = rsp; } else if ( rsp ) { ber_bvfree( rsp ); rsp = NULL; } op->o_tag = LDAP_REQ_EXTENDED; op->o_callback = sc; } rc = rs->sr_err; op->oq_extended = qext; error_return:; slap_biglock_release(bl); if ( qpw->rs_mods ) { slap_mods_free( qpw->rs_mods, 1 ); } if ( freenewpw ) { free( qpw->rs_new.bv_val ); } if ( !BER_BVISNULL( &dn ) ) { op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_dn ); } if ( !BER_BVISNULL( &ndn ) ) { op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_ndn ); } return rc; }