int backsql_bind( Operation *op, SlapReply *rs ) { SQLHDBC dbh = SQL_NULL_HDBC; Entry e = { 0 }; Attribute *a; backsql_srch_info bsi = { 0 }; AttributeName anlist[2]; int rc; Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n", 0, 0, 0 ); switch ( be_rootdn_bind( op, rs ) ) { case SLAP_CB_CONTINUE: break; default: /* in case of success, front end will send result; * otherwise, be_rootdn_bind() did */ Debug( LDAP_DEBUG_TRACE, "<==backsql_bind(%d)\n", rs->sr_err, 0, 0 ); return rs->sr_err; } rs->sr_err = backsql_get_db_conn( op, &dbh ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_bind(): " "could not get connection handle - exiting\n", 0, 0, 0 ); rs->sr_text = ( rs->sr_err == LDAP_OTHER ) ? "SQL-backend error" : NULL; goto error_return; } anlist[0].an_name = slap_schema.si_ad_userPassword->ad_cname; anlist[0].an_desc = slap_schema.si_ad_userPassword; anlist[1].an_name.bv_val = NULL; bsi.bsi_e = &e; rc = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, anlist, BACKSQL_ISF_GET_ENTRY ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_bind(): " "could not retrieve bindDN ID - no such entry\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto error_return; } a = attr_find( e.e_attrs, slap_schema.si_ad_userPassword ); if ( a == NULL ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto error_return; } if ( slap_passwd_check( op, &e, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto error_return; } error_return:; if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &e.e_nname ) ) { backsql_entry_clean( op, &e ); } if ( bsi.bsi_attrs != NULL ) { op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); } if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); } Debug( LDAP_DEBUG_TRACE,"<==backsql_bind()\n", 0, 0, 0 ); return rs->sr_err; }
int bdb_bind( Operation *op, SlapReply *rs ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; Entry *e; Attribute *a; EntryInfo *ei; AttributeDescription *password = slap_schema.si_ad_userPassword; DB_TXN *rtxn; DB_LOCK lock; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n", op->o_req_dn.bv_val, 0, 0); /* allow noauth binds */ switch ( be_rootdn_bind( op, NULL ) ) { case LDAP_SUCCESS: /* frontend will send result */ return rs->sr_err = LDAP_SUCCESS; default: /* give the database a chance */ /* NOTE: this behavior departs from that of other backends, * since the others, in case of password checking failure * do not give the database a chance. If an entry with * rootdn's name does not exist in the database the result * will be the same. See ITS#4962 for discussion. */ break; } rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn); switch(rs->sr_err) { case 0: break; default: rs->sr_text = "internal error"; send_ldap_result( op, rs ); return rs->sr_err; } dn2entry_retry: /* get entry with reader lock */ rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1, &lock ); switch(rs->sr_err) { case DB_NOTFOUND: case 0: break; case LDAP_BUSY: send_ldap_error( op, rs, LDAP_BUSY, "ldap_server_busy" ); return LDAP_BUSY; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto dn2entry_retry; default: send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); return rs->sr_err; } e = ei->bei_e; if ( rs->sr_err == DB_NOTFOUND ) { if( e != NULL ) { bdb_cache_return_entry_r( bdb, e, &lock ); e = NULL; } rs->sr_err = LDAP_INVALID_CREDENTIALS; send_ldap_result( op, rs ); return rs->sr_err; } ber_dupbv( &op->oq_bind.rb_edn, &e->e_name ); /* check for deleted */ if ( is_entry_subentry( e ) ) { /* entry is an subentry, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_alias( e ) ) { /* entry is an alias, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_referral( e ) ) { Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } switch ( op->oq_bind.rb_method ) { case LDAP_AUTH_SIMPLE: a = attr_find( e->e_attrs, password ); if ( a == NULL ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) { /* failure; stop front end from sending result */ rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } rs->sr_err = 0; break; default: assert( 0 ); /* should not be reachable */ rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED; rs->sr_text = "authentication method not supported"; } done: /* free entry and reader lock */ if( e != NULL ) { bdb_cache_return_entry_r( bdb, e, &lock ); } if ( rs->sr_err ) { send_ldap_result( op, rs ); if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } /* front end will send result on success (rs->sr_err==0) */ 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; int rc; BackendDB *op_be; int freenewpw = 0; struct berval dn = BER_BVNULL, ndn = BER_BVNULL; 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, 0, 0, 0, 0 ); 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" : "", 0 ); } 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" : "", 0, 0 ); } 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 ); } 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( op->o_bd->be_update_refs, NULL, NULL, LDAP_SCOPE_DEFAULT ); if(rs->sr_ref) { rs->sr_flags |= REP_REF_MUSTBEFREED; } else { rs->sr_ref = defref; } 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->be_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->be_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:; 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; }
extern "C" int ndb_back_bind( Operation *op, SlapReply *rs ) { struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; Entry e = {0}; Attribute *a; AttributeDescription *password = slap_schema.si_ad_userPassword; NdbArgs NA; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(ndb_back_bind) ": dn: %s\n", op->o_req_dn.bv_val, 0, 0); /* allow noauth binds */ switch ( be_rootdn_bind( op, NULL ) ) { case LDAP_SUCCESS: /* frontend will send result */ return rs->sr_err = LDAP_SUCCESS; default: /* give the database a chance */ break; } /* Get our NDB handle */ rs->sr_err = ndb_thread_handle( op, &NA.ndb ); e.e_name = op->o_req_dn; e.e_nname = op->o_req_ndn; NA.e = &e; dn2entry_retry: NA.txn = NA.ndb->startTransaction(); rs->sr_text = NULL; if( !NA.txn ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_bind) ": startTransaction failed: %s (%d)\n", NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto done; } /* get entry */ { NdbRdns rdns; rdns.nr_num = 0; NA.rdns = &rdns; NA.ocs = NULL; rs->sr_err = ndb_entry_get_info( op, &NA, 0, NULL ); } switch(rs->sr_err) { case 0: break; case LDAP_NO_SUCH_OBJECT: rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; case LDAP_BUSY: rs->sr_text = "ldap_server_busy"; goto done; #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto dn2entry_retry; #endif default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto done; } rs->sr_err = ndb_entry_get_data( op, &NA, 0 ); ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); ber_dupbv( &op->oq_bind.rb_edn, &e.e_name ); /* check for deleted */ if ( is_entry_subentry( &e ) ) { /* entry is an subentry, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_alias( &e ) ) { /* entry is an alias, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_referral( &e ) ) { Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } switch ( op->oq_bind.rb_method ) { case LDAP_AUTH_SIMPLE: a = attr_find( e.e_attrs, password ); if ( a == NULL ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( slap_passwd_check( op, &e, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) { /* failure; stop front end from sending result */ rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } rs->sr_err = 0; break; default: assert( 0 ); /* should not be reachable */ rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED; rs->sr_text = "authentication method not supported"; } done: NA.txn->close(); if ( e.e_attrs ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } if ( rs->sr_err ) { send_ldap_result( op, rs ); } /* front end will send result on success (rs->sr_err==0) */ return rs->sr_err; }
int mdb_bind( Operation *op, SlapReply *rs ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; Entry *e; Attribute *a; AttributeDescription *password = slap_schema.si_ad_userPassword; MDB_txn *rtxn; mdb_op_info opinfo = {{{0}}}, *moi = &opinfo; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(mdb_bind) ": dn: %s\n", op->o_req_dn.bv_val, 0, 0); /* allow noauth binds */ switch ( be_rootdn_bind( op, NULL ) ) { case LDAP_SUCCESS: /* frontend will send result */ return rs->sr_err = LDAP_SUCCESS; default: /* give the database a chance */ /* NOTE: this behavior departs from that of other backends, * since the others, in case of password checking failure * do not give the database a chance. If an entry with * rootdn's name does not exist in the database the result * will be the same. See ITS#4962 for discussion. */ break; } rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi); switch(rs->sr_err) { case 0: break; default: rs->sr_text = "internal error"; send_ldap_result( op, rs ); return rs->sr_err; } rtxn = moi->moi_txn; /* get entry with reader lock */ rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, NULL, 0 ); switch(rs->sr_err) { case MDB_NOTFOUND: rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; case 0: break; case LDAP_BUSY: rs->sr_text = "ldap_server_busy"; goto done; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto done; } ber_dupbv( &op->oq_bind.rb_edn, &e->e_name ); /* check for deleted */ if ( is_entry_subentry( e ) ) { /* entry is an subentry, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_alias( e ) ) { /* entry is an alias, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_referral( e ) ) { Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } switch ( op->oq_bind.rb_method ) { case LDAP_AUTH_SIMPLE: a = attr_find( e->e_attrs, password ); if ( a == NULL ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) { /* failure; stop front end from sending result */ rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } rs->sr_err = 0; break; default: assert( 0 ); /* should not be reachable */ rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED; rs->sr_text = "authentication method not supported"; } done: if ( moi == &opinfo ) { mdb_txn_reset( moi->moi_txn ); LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); } else { moi->moi_ref--; } /* free entry and reader lock */ if( e != NULL ) { mdb_entry_return( op, e ); } if ( rs->sr_err ) { send_ldap_result( op, rs ); if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } /* front end will send result on success (rs->sr_err==0) */ return rs->sr_err; }
int wt_bind( Operation *op, SlapReply *rs ) { struct wt_info *wi = (struct wt_info *) op->o_bd->be_private; WT_SESSION *session; wt_ctx *wc; int rc; Entry *e = NULL; Attribute *a; AttributeDescription *password = slap_schema.si_ad_userPassword; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(wt_bind) ": dn: %s\n", op->o_req_dn.bv_val, 0, 0); /* allow noauth binds */ switch ( be_rootdn_bind( op, NULL ) ) { case LDAP_SUCCESS: /* frontend will send result */ return rs->sr_err = LDAP_SUCCESS; default: /* give the database a chance */ /* NOTE: this behavior departs from that of other backends, * since the others, in case of password checking failure * do not give the database a chance. If an entry with * rootdn's name does not exist in the database the result * will be the same. See ITS#4962 for discussion. */ break; } wc = wt_ctx_get(op, wi); if( !wc ){ Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(wt_bind) ": wt_ctx_get failed\n", 0, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; send_ldap_result( op, rs ); return rs->sr_err; } /* get entry */ rc = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e); switch( rc ) { case 0: break; case WT_NOTFOUND: rs->sr_err = LDAP_INVALID_CREDENTIALS; send_ldap_result( op, rs ); return rs->sr_err; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; send_ldap_result( op, rs ); return rs->sr_err; } ber_dupbv( &op->oq_bind.rb_edn, &e->e_name ); /* check for deleted */ if ( is_entry_subentry( e ) ) { /* entry is an subentry, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_alias( e ) ) { /* entry is an alias, don't allow bind */ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( is_entry_referral( e ) ) { Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } switch ( op->oq_bind.rb_method ) { case LDAP_AUTH_SIMPLE: a = attr_find( e->e_attrs, password ); if ( a == NULL ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) { /* failure; stop front end from sending result */ rs->sr_err = LDAP_INVALID_CREDENTIALS; goto done; } rs->sr_err = 0; break; default: rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED; rs->sr_text = "authentication method not supported"; } done: /* free entry */ if (e) { wt_entry_return(e); } if (rs->sr_err) { send_ldap_result( op, rs ); if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } return rs->sr_err; }
int ldbm_back_bind( Backend *be, Connection *conn, Operation *op, struct berval *dn, struct berval *ndn, int method, struct berval *cred, struct berval *edn ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; Entry *e; Attribute *a; int rc; Entry *matched; #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND char krbname[MAX_K_NAME_SZ + 1]; AttributeDescription *krbattr = slap_schema.si_ad_krbName; AUTH_DAT ad; #endif AttributeDescription *password = slap_schema.si_ad_userPassword; #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_back_bind: dn: %s.\n", dn->bv_val, 0, 0 ); #else Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_bind: dn: %s\n", dn->bv_val, 0, 0); #endif dn = ndn; /* grab giant lock for reading */ ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock); /* get entry with reader lock */ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) { char *matched_dn = NULL; BerVarray refs = NULL; if( matched != NULL ) { matched_dn = ch_strdup( matched->e_dn ); refs = is_entry_referral( matched ) ? get_entry_referrals( be, conn, op, matched ) : NULL; cache_return_entry_r( &li->li_cache, matched ); } else { refs = referral_rewrite( default_referral, NULL, dn, LDAP_SCOPE_DEFAULT ); } ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); /* allow noauth binds */ rc = 1; if ( method == LDAP_AUTH_SIMPLE ) { if ( be_isroot_pw( be, conn, dn, cred ) ) { ber_dupbv( edn, be_root_dn( be ) ); rc = 0; /* front end will send result */ } else if ( refs != NULL ) { send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); } else { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); } } else if ( refs != NULL ) { send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); } else { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); } if ( refs ) ber_bvarray_free( refs ); if ( matched_dn ) free( matched_dn ); return( rc ); } ber_dupbv( edn, &e->e_name ); /* check for deleted */ if ( is_entry_alias( e ) ) { /* entry is an alias, don't allow bind */ #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, INFO, "ldbm_back_bind: entry (%s) is an alias.\n", e->e_dn, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); #endif send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, NULL, "entry is alias", NULL, NULL ); rc = 1; goto return_results; } if ( is_entry_referral( e ) ) { /* entry is a referral, don't allow bind */ BerVarray refs = get_entry_referrals( be, conn, op, e ); #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, INFO, "ldbm_back_bind: entry(%s) is a referral.\n", e->e_dn, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); #endif if( refs != NULL ) { send_ldap_result( conn, op, LDAP_REFERRAL, e->e_dn, NULL, refs, NULL ); } else { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); } ber_bvarray_free( refs ); rc = 1; goto return_results; } switch ( method ) { case LDAP_AUTH_SIMPLE: /* check for root dn/passwd */ if ( be_isroot_pw( be, conn, dn, cred ) ) { /* front end will send result */ if(edn->bv_val != NULL) free( edn->bv_val ); ber_dupbv( edn, be_root_dn( be ) ); rc = 0; goto return_results; } if ( ! access_allowed( be, conn, op, e, password, NULL, ACL_AUTH, NULL ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } if ( (a = attr_find( e->e_attrs, password )) == NULL ) { send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, NULL, NULL ); /* stop front end from sending result */ rc = 1; goto return_results; } if ( slap_passwd_check( conn, a, cred ) != 0 ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); /* stop front end from sending result */ rc = 1; goto return_results; } rc = 0; break; #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND case LDAP_AUTH_KRBV41: if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } if ( ! access_allowed( be, conn, op, e, krbattr, NULL, ACL_AUTH, NULL ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "." : "", ad.pinst, ad.prealm ); if ( (a = attr_find( e->e_attrs, krbattr )) == NULL ) { /* * no krbname values present: check against DN */ if ( strcasecmp( dn->bv_val, krbname ) == 0 ) { rc = 0; break; } send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } else { /* look for krbname match */ struct berval krbval; krbval.bv_val = krbname; krbval.bv_len = strlen( krbname ); if ( value_find( a->a_desc, a->a_vals, &krbval ) != 0 ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } } rc = 0; break; case LDAP_AUTH_KRBV42: send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL, "Kerberos bind step 2 not supported", NULL, NULL ); /* stop front end from sending result */ rc = LDAP_UNWILLING_TO_PERFORM; goto return_results; #endif default: send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED, NULL, "authentication method not supported", NULL, NULL ); rc = 1; goto return_results; } return_results:; /* free entry and reader lock */ cache_return_entry_r( &li->li_cache, e ); ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); /* front end will send result on success (rc==0) */ return( rc ); }