Back to index

openldap  2.4.31
bind.c
Go to the documentation of this file.
00001 /* bind.c - bdb backend bind routine */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2000-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include "portable.h"
00018 
00019 #include <stdio.h>
00020 #include <ac/string.h>
00021 #include <ac/unistd.h>
00022 
00023 #include "back-bdb.h"
00024 
00025 int
00026 bdb_bind( Operation *op, SlapReply *rs )
00027 {
00028        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
00029        Entry         *e;
00030        Attribute     *a;
00031        EntryInfo     *ei;
00032 
00033        AttributeDescription *password = slap_schema.si_ad_userPassword;
00034 
00035        DB_TXN        *rtxn;
00036        DB_LOCK              lock;
00037 
00038        Debug( LDAP_DEBUG_ARGS,
00039               "==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n",
00040               op->o_req_dn.bv_val, 0, 0);
00041 
00042        /* allow noauth binds */
00043        switch ( be_rootdn_bind( op, NULL ) ) {
00044        case LDAP_SUCCESS:
00045               /* frontend will send result */
00046               return rs->sr_err = LDAP_SUCCESS;
00047 
00048        default:
00049               /* give the database a chance */
00050               /* NOTE: this behavior departs from that of other backends,
00051                * since the others, in case of password checking failure
00052                * do not give the database a chance.  If an entry with
00053                * rootdn's name does not exist in the database the result
00054                * will be the same.  See ITS#4962 for discussion. */
00055               break;
00056        }
00057 
00058        rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
00059        switch(rs->sr_err) {
00060        case 0:
00061               break;
00062        default:
00063               rs->sr_text = "internal error";
00064               send_ldap_result( op, rs );
00065               return rs->sr_err;
00066        }
00067 
00068 dn2entry_retry:
00069        /* get entry with reader lock */
00070        rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
00071               &lock );
00072 
00073        switch(rs->sr_err) {
00074        case DB_NOTFOUND:
00075        case 0:
00076               break;
00077        case LDAP_BUSY:
00078               send_ldap_error( op, rs, LDAP_BUSY, "ldap_server_busy" );
00079               return LDAP_BUSY;
00080        case DB_LOCK_DEADLOCK:
00081        case DB_LOCK_NOTGRANTED:
00082               goto dn2entry_retry;
00083        default:
00084               send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
00085               return rs->sr_err;
00086        }
00087 
00088        e = ei->bei_e;
00089        if ( rs->sr_err == DB_NOTFOUND ) {
00090               if( e != NULL ) {
00091                      bdb_cache_return_entry_r( bdb, e, &lock );
00092                      e = NULL;
00093               }
00094 
00095               rs->sr_err = LDAP_INVALID_CREDENTIALS;
00096               send_ldap_result( op, rs );
00097 
00098               return rs->sr_err;
00099        }
00100 
00101        ber_dupbv( &op->oq_bind.rb_edn, &e->e_name );
00102 
00103        /* check for deleted */
00104        if ( is_entry_subentry( e ) ) {
00105               /* entry is an subentry, don't allow bind */
00106               Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0,
00107                      0, 0 );
00108               rs->sr_err = LDAP_INVALID_CREDENTIALS;
00109               goto done;
00110        }
00111 
00112        if ( is_entry_alias( e ) ) {
00113               /* entry is an alias, don't allow bind */
00114               Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 );
00115               rs->sr_err = LDAP_INVALID_CREDENTIALS;
00116               goto done;
00117        }
00118 
00119        if ( is_entry_referral( e ) ) {
00120               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
00121                      0, 0 );
00122               rs->sr_err = LDAP_INVALID_CREDENTIALS;
00123               goto done;
00124        }
00125 
00126        switch ( op->oq_bind.rb_method ) {
00127        case LDAP_AUTH_SIMPLE:
00128               a = attr_find( e->e_attrs, password );
00129               if ( a == NULL ) {
00130                      rs->sr_err = LDAP_INVALID_CREDENTIALS;
00131                      goto done;
00132               }
00133 
00134               if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred,
00135                                    &rs->sr_text ) != 0 )
00136               {
00137                      /* failure; stop front end from sending result */
00138                      rs->sr_err = LDAP_INVALID_CREDENTIALS;
00139                      goto done;
00140               }
00141                      
00142               rs->sr_err = 0;
00143               break;
00144 
00145        default:
00146               assert( 0 ); /* should not be reachable */
00147               rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED;
00148               rs->sr_text = "authentication method not supported";
00149        }
00150 
00151 done:
00152        /* free entry and reader lock */
00153        if( e != NULL ) {
00154               bdb_cache_return_entry_r( bdb, e, &lock );
00155        }
00156 
00157        if ( rs->sr_err ) {
00158               send_ldap_result( op, rs );
00159               if ( rs->sr_ref ) {
00160                      ber_bvarray_free( rs->sr_ref );
00161                      rs->sr_ref = NULL;
00162               }
00163        }
00164        /* front end will send result on success (rs->sr_err==0) */
00165        return rs->sr_err;
00166 }