1/* $NetBSD: bind.c,v 1.1.1.3 2010/12/12 15:22:53 adam Exp $ */ 2 3/* bind.c - bdb backend bind routine */ 4/* OpenLDAP: pkg/ldap/servers/slapd/back-bdb/bind.c,v 1.45.2.7 2010/04/13 20:23:23 kurt Exp */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2000-2010 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 19#include "portable.h" 20 21#include <stdio.h> 22#include <ac/string.h> 23#include <ac/unistd.h> 24 25#include "back-bdb.h" 26 27int 28bdb_bind( Operation *op, SlapReply *rs ) 29{ 30 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; 31 Entry *e; 32 Attribute *a; 33 EntryInfo *ei; 34 35 AttributeDescription *password = slap_schema.si_ad_userPassword; 36 37 DB_TXN *rtxn; 38 DB_LOCK lock; 39 40 Debug( LDAP_DEBUG_ARGS, 41 "==> " LDAP_XSTRING(bdb_bind) ": dn: %s\n", 42 op->o_req_dn.bv_val, 0, 0); 43 44 /* allow noauth binds */ 45 switch ( be_rootdn_bind( op, NULL ) ) { 46 case LDAP_SUCCESS: 47 /* frontend will send result */ 48 return rs->sr_err; 49 50 default: 51 /* give the database a chanche */ 52 /* NOTE: this behavior departs from that of other backends, 53 * since the others, in case of password checking failure 54 * do not give the database a chance. If an entry with 55 * rootdn's name does not exist in the database the result 56 * will be the same. See ITS#4962 for discussion. */ 57 break; 58 } 59 60 rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn); 61 switch(rs->sr_err) { 62 case 0: 63 break; 64 default: 65 rs->sr_text = "internal error"; 66 send_ldap_result( op, rs ); 67 return rs->sr_err; 68 } 69 70dn2entry_retry: 71 /* get entry with reader lock */ 72 rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1, 73 &lock ); 74 75 switch(rs->sr_err) { 76 case DB_NOTFOUND: 77 case 0: 78 break; 79 case LDAP_BUSY: 80 send_ldap_error( op, rs, LDAP_BUSY, "ldap_server_busy" ); 81 return LDAP_BUSY; 82 case DB_LOCK_DEADLOCK: 83 case DB_LOCK_NOTGRANTED: 84 goto dn2entry_retry; 85 default: 86 send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); 87 return rs->sr_err; 88 } 89 90 e = ei->bei_e; 91 if ( rs->sr_err == DB_NOTFOUND ) { 92 if( e != NULL ) { 93 bdb_cache_return_entry_r( bdb, e, &lock ); 94 e = NULL; 95 } 96 97 rs->sr_err = LDAP_INVALID_CREDENTIALS; 98 send_ldap_result( op, rs ); 99 100 return rs->sr_err; 101 } 102 103 ber_dupbv( &op->oq_bind.rb_edn, &e->e_name ); 104 105 /* check for deleted */ 106 if ( is_entry_subentry( e ) ) { 107 /* entry is an subentry, don't allow bind */ 108 Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0, 109 0, 0 ); 110 rs->sr_err = LDAP_INVALID_CREDENTIALS; 111 goto done; 112 } 113 114 if ( is_entry_alias( e ) ) { 115 /* entry is an alias, don't allow bind */ 116 Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); 117 rs->sr_err = LDAP_INVALID_CREDENTIALS; 118 goto done; 119 } 120 121 if ( is_entry_referral( e ) ) { 122 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 123 0, 0 ); 124 rs->sr_err = LDAP_INVALID_CREDENTIALS; 125 goto done; 126 } 127 128 switch ( op->oq_bind.rb_method ) { 129 case LDAP_AUTH_SIMPLE: 130 a = attr_find( e->e_attrs, password ); 131 if ( a == NULL ) { 132 rs->sr_err = LDAP_INVALID_CREDENTIALS; 133 goto done; 134 } 135 136 if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred, 137 &rs->sr_text ) != 0 ) 138 { 139 /* failure; stop front end from sending result */ 140 rs->sr_err = LDAP_INVALID_CREDENTIALS; 141 goto done; 142 } 143 144 rs->sr_err = 0; 145 break; 146 147 default: 148 assert( 0 ); /* should not be reachable */ 149 rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED; 150 rs->sr_text = "authentication method not supported"; 151 } 152 153done: 154 /* free entry and reader lock */ 155 if( e != NULL ) { 156 bdb_cache_return_entry_r( bdb, e, &lock ); 157 } 158 159 if ( rs->sr_err ) { 160 send_ldap_result( op, rs ); 161 if ( rs->sr_ref ) { 162 ber_bvarray_free( rs->sr_ref ); 163 rs->sr_ref = NULL; 164 } 165 } 166 /* front end will send result on success (rs->sr_err==0) */ 167 return rs->sr_err; 168} 169