1 /* bind.cpp - ndb backend bind routine */ 2 /* $OpenLDAP$ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 2008-2016 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16 /* ACKNOWLEDGEMENTS: 17 * This work was initially developed by Howard Chu for inclusion 18 * in OpenLDAP Software. This work was sponsored by MySQL. 19 */ 20 21 #include "portable.h" 22 23 #include <stdio.h> 24 #include <ac/string.h> 25 #include <ac/unistd.h> 26 27 #include "back-ndb.h" 28 29 extern "C" int 30 ndb_back_bind( Operation *op, SlapReply *rs ) 31 { 32 struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; 33 Entry e = {0}; 34 Attribute *a; 35 36 AttributeDescription *password = slap_schema.si_ad_userPassword; 37 38 NdbArgs NA; 39 40 Debug( LDAP_DEBUG_ARGS, 41 "==> " LDAP_XSTRING(ndb_back_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 = LDAP_SUCCESS; 49 50 default: 51 /* give the database a chance */ 52 break; 53 } 54 55 /* Get our NDB handle */ 56 rs->sr_err = ndb_thread_handle( op, &NA.ndb ); 57 58 e.e_name = op->o_req_dn; 59 e.e_nname = op->o_req_ndn; 60 NA.e = &e; 61 62 dn2entry_retry: 63 NA.txn = NA.ndb->startTransaction(); 64 rs->sr_text = NULL; 65 if( !NA.txn ) { 66 Debug( LDAP_DEBUG_TRACE, 67 LDAP_XSTRING(ndb_back_bind) ": startTransaction failed: %s (%d)\n", 68 NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 ); 69 rs->sr_err = LDAP_OTHER; 70 rs->sr_text = "internal error"; 71 goto done; 72 } 73 74 /* get entry */ 75 { 76 NdbRdns rdns; 77 rdns.nr_num = 0; 78 NA.rdns = &rdns; 79 NA.ocs = NULL; 80 rs->sr_err = ndb_entry_get_info( op, &NA, 0, NULL ); 81 } 82 switch(rs->sr_err) { 83 case 0: 84 break; 85 case LDAP_NO_SUCH_OBJECT: 86 rs->sr_err = LDAP_INVALID_CREDENTIALS; 87 goto done; 88 case LDAP_BUSY: 89 rs->sr_text = "ldap_server_busy"; 90 goto done; 91 #if 0 92 case DB_LOCK_DEADLOCK: 93 case DB_LOCK_NOTGRANTED: 94 goto dn2entry_retry; 95 #endif 96 default: 97 rs->sr_err = LDAP_OTHER; 98 rs->sr_text = "internal error"; 99 goto done; 100 } 101 102 rs->sr_err = ndb_entry_get_data( op, &NA, 0 ); 103 ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); 104 ber_dupbv( &op->oq_bind.rb_edn, &e.e_name ); 105 106 /* check for deleted */ 107 if ( is_entry_subentry( &e ) ) { 108 /* entry is an subentry, don't allow bind */ 109 Debug( LDAP_DEBUG_TRACE, "entry is subentry\n", 0, 110 0, 0 ); 111 rs->sr_err = LDAP_INVALID_CREDENTIALS; 112 goto done; 113 } 114 115 if ( is_entry_alias( &e ) ) { 116 /* entry is an alias, don't allow bind */ 117 Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); 118 rs->sr_err = LDAP_INVALID_CREDENTIALS; 119 goto done; 120 } 121 122 if ( is_entry_referral( &e ) ) { 123 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 124 0, 0 ); 125 rs->sr_err = LDAP_INVALID_CREDENTIALS; 126 goto done; 127 } 128 129 switch ( op->oq_bind.rb_method ) { 130 case LDAP_AUTH_SIMPLE: 131 a = attr_find( e.e_attrs, password ); 132 if ( a == NULL ) { 133 rs->sr_err = LDAP_INVALID_CREDENTIALS; 134 goto done; 135 } 136 137 if ( slap_passwd_check( op, &e, a, &op->oq_bind.rb_cred, 138 &rs->sr_text ) != 0 ) 139 { 140 /* failure; stop front end from sending result */ 141 rs->sr_err = LDAP_INVALID_CREDENTIALS; 142 goto done; 143 } 144 145 rs->sr_err = 0; 146 break; 147 148 default: 149 assert( 0 ); /* should not be reachable */ 150 rs->sr_err = LDAP_STRONG_AUTH_NOT_SUPPORTED; 151 rs->sr_text = "authentication method not supported"; 152 } 153 154 done: 155 NA.txn->close(); 156 if ( e.e_attrs ) { 157 attrs_free( e.e_attrs ); 158 e.e_attrs = NULL; 159 } 160 if ( rs->sr_err ) { 161 send_ldap_result( op, rs ); 162 } 163 /* front end will send result on success (rs->sr_err==0) */ 164 return rs->sr_err; 165 } 166