mirror of
https://github.com/snipe/snipe-it.git
synced 2025-03-05 20:52:15 -08:00
Reworked LDAP login. Fixes #2218
LDAP no longer fails completely when the connection settings are wrong, or when app key is messed up. Rather than auth as the admin user and search, we auth as the user themselves. Admin auth is only for LDAP sync now. This should mean much fewer problems with donked LDAP settings and login.
This commit is contained in:
parent
b5d3843b7c
commit
4233c781ac
|
@ -6,6 +6,7 @@ use Validator;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Foundation\Auth\ThrottlesLogins;
|
use Illuminate\Foundation\Auth\ThrottlesLogins;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
|
use App\Models\Ldap;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Config;
|
use Config;
|
||||||
|
@ -15,6 +16,8 @@ use Redirect;
|
||||||
use Log;
|
use Log;
|
||||||
use View;
|
use View;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller handles authentication for the user, including local
|
* This controller handles authentication for the user, including local
|
||||||
* database users and LDAP users.
|
* database users and LDAP users.
|
||||||
|
@ -61,120 +64,13 @@ class AuthController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticates a user to LDAP
|
|
||||||
*
|
|
||||||
* @param $username
|
|
||||||
* @param $password
|
|
||||||
* @param bool|false $returnUser
|
|
||||||
* @return bool true if the username and/or password provided are valid
|
|
||||||
* false if the username and/or password provided are invalid
|
|
||||||
* array of ldap_attributes if $returnUser is true
|
|
||||||
*/
|
|
||||||
function ldap($username, $password, $returnUser = false)
|
|
||||||
{
|
|
||||||
|
|
||||||
$ldaphost = Setting::getSettings()->ldap_server;
|
|
||||||
$ldaprdn = Setting::getSettings()->ldap_uname;
|
|
||||||
$ldappass = \Crypt::decrypt(Setting::getSettings()->ldap_pword);
|
|
||||||
$baseDn = Setting::getSettings()->ldap_basedn;
|
|
||||||
$filterQuery = Setting::getSettings()->ldap_auth_filter_query . $username;
|
|
||||||
$ldapversion = Setting::getSettings()->ldap_version;
|
|
||||||
$ldap_server_cert_ignore = Setting::getSettings()->ldap_server_cert_ignore;
|
|
||||||
|
|
||||||
// If we are ignoring the SSL cert we need to setup the environment variable
|
|
||||||
// before we create the connection
|
|
||||||
if ($ldap_server_cert_ignore) {
|
|
||||||
putenv('LDAPTLS_REQCERT=never');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connecting to LDAP
|
|
||||||
$connection = ldap_connect($ldaphost) or die("Could not connect to {$ldaphost}");
|
|
||||||
// Needed for AD
|
|
||||||
ldap_set_option($connection, LDAP_OPT_REFERRALS, 0);
|
|
||||||
ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, $ldapversion);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ($connection) {
|
|
||||||
// binding to ldap server
|
|
||||||
$ldapbind = ldap_bind($connection, $ldaprdn, $ldappass);
|
|
||||||
if (($results = @ldap_search($connection, $baseDn, $filterQuery)) != false) {
|
|
||||||
$entry = ldap_first_entry($connection, $results);
|
|
||||||
if (($userDn = @ldap_get_dn($connection, $entry)) != false) {
|
|
||||||
if (($isBound = ldap_bind($connection, $userDn, $password)) == "true") {
|
|
||||||
return $returnUser ?
|
|
||||||
array_change_key_case(ldap_get_attributes($connection, $entry), CASE_LOWER)
|
|
||||||
: true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
LOG::error($e->getMessage());
|
|
||||||
}
|
|
||||||
ldap_close($connection);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create user from LDAP attributes
|
|
||||||
*
|
|
||||||
* @param $ldapatttibutes
|
|
||||||
* @return array|bool
|
|
||||||
*/
|
|
||||||
function createUserFromLdap($ldapatttibutes)
|
|
||||||
{
|
|
||||||
//Get LDAP attribute config
|
|
||||||
$ldap_result_username = Setting::getSettings()->ldap_username_field;
|
|
||||||
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
|
|
||||||
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
|
|
||||||
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
|
|
||||||
$ldap_result_email = Setting::getSettings()->ldap_email;
|
|
||||||
|
|
||||||
//Get LDAP user data
|
|
||||||
$item = array();
|
|
||||||
$item["username"] = isset($ldapatttibutes[$ldap_result_username][0]) ? $ldapatttibutes[$ldap_result_username][0] : "";
|
|
||||||
$item["employee_number"] = isset($ldapatttibutes[$ldap_result_emp_num][0]) ? $ldapatttibutes[$ldap_result_emp_num][0] : "";
|
|
||||||
$item["lastname"] = isset($ldapatttibutes[$ldap_result_last_name][0]) ? $ldapatttibutes[$ldap_result_last_name][0] : "";
|
|
||||||
$item["firstname"] = isset($ldapatttibutes[$ldap_result_first_name][0]) ? $ldapatttibutes[$ldap_result_first_name][0] : "";
|
|
||||||
$item["email"] = isset($ldapatttibutes[$ldap_result_email][0]) ? $ldapatttibutes[$ldap_result_email][0] : "" ;
|
|
||||||
|
|
||||||
//create user
|
|
||||||
if (!empty($item["username"])) {
|
|
||||||
//$pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 10);
|
|
||||||
|
|
||||||
$newuser = array(
|
|
||||||
'first_name' => $item["firstname"],
|
|
||||||
'last_name' => $item["lastname"],
|
|
||||||
'username' => $item["username"],
|
|
||||||
'email' => $item["email"],
|
|
||||||
'employee_num' => $item["employee_number"],
|
|
||||||
'password' => bcrypt(Input::get("password")), //$pass,
|
|
||||||
'activated' => 1,
|
|
||||||
'permissions' => ["user" => 1], //'{"user":1}',
|
|
||||||
'notes' => 'Imported from LDAP'
|
|
||||||
);
|
|
||||||
User::save($newuser);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new Cartalyst\Sentry\Users\UserNotFoundException();
|
|
||||||
}
|
|
||||||
|
|
||||||
//$item["note"] = "<strong>created</strong>";
|
|
||||||
$credentials = array(
|
|
||||||
'username' => $item["username"],
|
|
||||||
'password' => Input::get("password")//$pass,
|
|
||||||
);
|
|
||||||
return $credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account sign in form processing.
|
* Account sign in form processing.
|
||||||
*
|
*
|
||||||
* @return Redirect
|
* @return Redirect
|
||||||
*/
|
*/
|
||||||
public function login()
|
public function login(Request $request)
|
||||||
{
|
{
|
||||||
$validator = $this->validator(Input::all());
|
$validator = $this->validator(Input::all());
|
||||||
|
|
||||||
|
@ -186,21 +82,43 @@ class AuthController extends Controller
|
||||||
if (Setting::getSettings()->ldap_enabled=='1') {
|
if (Setting::getSettings()->ldap_enabled=='1') {
|
||||||
|
|
||||||
LOG::debug("LDAP is enabled.");
|
LOG::debug("LDAP is enabled.");
|
||||||
// Check if the user exists in the database
|
// Check if the user exists in the database
|
||||||
$user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->first();
|
$user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->first();
|
||||||
LOG::debug("Auth lookup complete");
|
LOG::debug("Local auth lookup complete");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'));
|
||||||
|
LOG::debug("Binding user to LDAP.");
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
LOG::debug("User ".Input::get('username').' did not authenticate successfully against LDAP.');
|
||||||
|
//$ldap_error = $e->getMessage();
|
||||||
|
// return redirect()->back()->withInput()->with('error',$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// The user does not exist in the database. Try to get them from LDAP.
|
// The user does not exist in the database. Try to get them from LDAP.
|
||||||
// If user does not exist and authenticates sucessfully with LDAP we
|
// If user does not exist and authenticates sucessfully with LDAP we
|
||||||
// will create it on the fly and sign in with default permissions
|
// will create it on the fly and sign in with default permissions
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
LOG::debug("Local user ".Input::get('username')." does not exist");
|
LOG::debug("Local user ".Input::get('username')." does not exist");
|
||||||
if ($userattr = $this->ldap(Input::get('username'), Input::get('password'), true)) {
|
|
||||||
LOG::debug("Creating local user from authenticated LDAP user.");
|
try {
|
||||||
$credentials = $this->createUserFromLdap($userattr);
|
|
||||||
} else {
|
if ($userattr = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'))) {
|
||||||
LOG::debug("User did not authenticate correctly against LDAP. No local user was created.");
|
LOG::debug("Creating local user ".Input::get('username'));
|
||||||
|
|
||||||
|
if ($newuser = Ldap::createUserFromLdap($userattr)) {
|
||||||
|
LOG::debug("Local user created..");
|
||||||
|
} else {
|
||||||
|
LOG::debug("Could not create local user.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LOG::debug("User did not authenticate correctly against LDAP. No local user was created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->withInput()->with('error',$e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user exists and they were imported from LDAP already
|
// If the user exists and they were imported from LDAP already
|
||||||
|
@ -208,15 +126,14 @@ class AuthController extends Controller
|
||||||
|
|
||||||
LOG::debug("Local user ".Input::get('username')." exists in database. Authenticating existing user against LDAP.");
|
LOG::debug("Local user ".Input::get('username')." exists in database. Authenticating existing user against LDAP.");
|
||||||
|
|
||||||
if ($this->ldap(Input::get('username'), Input::get('password'))) {
|
if (Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'))) {
|
||||||
LOG::debug("Valid LDAP login. Updating the local data.");
|
LOG::debug("Valid LDAP login. Updating the local data.");
|
||||||
$user = User::find($user->id); //need the Sentry object, not the Eloquent object, to access critical password hashing functions
|
$user = User::find($user->id); //need the Sentry object, not the Eloquent object, to access critical password hashing functions
|
||||||
$user->password = bcrypt(Input::get('password'));
|
$user->password = bcrypt($request->input('password'));
|
||||||
$user->ldap_import = 1;
|
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
LOG::debug("User did not authenticate correctly against LDAP. Local user was not updated.");
|
LOG::debug("User ".Input::get('username')." did not authenticate correctly against LDAP. Local user was not updated.");
|
||||||
}// End LDAP auth
|
}// End LDAP auth
|
||||||
|
|
||||||
} // End if(!user)
|
} // End if(!user)
|
||||||
|
|
|
@ -15,6 +15,7 @@ use App\Models\Statuslabel;
|
||||||
use App\Http\Requests\SaveUserRequest;
|
use App\Http\Requests\SaveUserRequest;
|
||||||
use App\Http\Requests\UpdateUserRequest;
|
use App\Http\Requests\UpdateUserRequest;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\Ldap;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Config;
|
use Config;
|
||||||
use Crypt;
|
use Crypt;
|
||||||
|
@ -1097,24 +1098,27 @@ class UsersController extends Controller
|
||||||
* @since [v1.8]
|
* @since [v1.8]
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function getLDAP()
|
public function getLDAP(Request $request)
|
||||||
{
|
{
|
||||||
// Get all the available groups
|
|
||||||
//s$groups = Sentry::getGroupProvider()->findAll();
|
|
||||||
// Selected groups
|
|
||||||
$selectedGroups = Input::old('groups', array());
|
|
||||||
// Get all the available permissions
|
|
||||||
$permissions = config('permissions');
|
|
||||||
//$this->encodeAllPermissions($permissions);
|
|
||||||
// Selected permissions
|
|
||||||
$selectedPermissions = Input::old('permissions', array('superuser' => -1));
|
|
||||||
//$this->encodePermissions($selectedPermissions);
|
|
||||||
|
|
||||||
$location_list = Helper::locationsList();
|
$location_list = Helper::locationsList();
|
||||||
|
|
||||||
// Show the page
|
try {
|
||||||
return View::make('users/ldap', compact('groups', 'selectedGroups', 'permissions', 'selectedPermissions'))
|
$ldapconn = Ldap::connectToLdap();
|
||||||
->with('location_list', $location_list);
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->route('users')->with('error',$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
Ldap::bindAdminToLdap($ldapconn);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
//$request->session()->flash('error', $e->getMessage());
|
||||||
|
return redirect()->route('users')->with('error',$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return View::make('users/ldap')
|
||||||
|
->with('location_list', $location_list);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,15 +1154,6 @@ class UsersController extends Controller
|
||||||
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
|
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
|
||||||
ini_set('memory_limit', '500M');
|
ini_set('memory_limit', '500M');
|
||||||
|
|
||||||
$location_id = e(Input::get('location_id'));
|
|
||||||
|
|
||||||
$ldap_version = Setting::getSettings()->ldap_version;
|
|
||||||
$url = Setting::getSettings()->ldap_server;
|
|
||||||
$username = Setting::getSettings()->ldap_uname;
|
|
||||||
$password = Crypt::decrypt(Setting::getSettings()->ldap_pword);
|
|
||||||
$base_dn = Setting::getSettings()->ldap_basedn;
|
|
||||||
$filter = Setting::getSettings()->ldap_filter;
|
|
||||||
|
|
||||||
$ldap_result_username = Setting::getSettings()->ldap_username_field;
|
$ldap_result_username = Setting::getSettings()->ldap_username_field;
|
||||||
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
|
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
|
||||||
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
|
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
|
||||||
|
@ -1166,78 +1161,26 @@ class UsersController extends Controller
|
||||||
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag_field;
|
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag_field;
|
||||||
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
|
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
|
||||||
$ldap_result_email = Setting::getSettings()->ldap_email;
|
$ldap_result_email = Setting::getSettings()->ldap_email;
|
||||||
$ldap_server_cert_ignore = Setting::getSettings()->ldap_server_cert_ignore;
|
|
||||||
|
|
||||||
// If we are ignoring the SSL cert we need to setup the environment variable
|
|
||||||
// before we create the connection
|
$location_id = e(Input::get('location_id'));
|
||||||
if ($ldap_server_cert_ignore) {
|
|
||||||
putenv('LDAPTLS_REQCERT=never');
|
try {
|
||||||
|
$ldapconn = Ldap::connectToLdap();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->withInput()->with('error',$e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to LDAP server
|
try {
|
||||||
$ldapconn = @ldap_connect($url);
|
$ldap_bind = Ldap::bindAdminToLdap($ldapconn);
|
||||||
|
} catch (\Exception $e) {
|
||||||
// Needed for AD
|
return redirect()->back()->withInput()->with('error',$e->getMessage());
|
||||||
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
|
|
||||||
|
|
||||||
if (!$ldapconn) {
|
|
||||||
return redirect()->route('users')->with('error', trans('admin/users/message.error.ldap_could_not_connect'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set options
|
|
||||||
$ldapopt = @ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, $ldap_version);
|
|
||||||
if (!$ldapopt) {
|
|
||||||
return redirect()->route('users')->with('error', trans('admin/users/message.error.ldap_could_not_connect'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Binding to ldap server
|
|
||||||
$ldapbind = @ldap_bind($ldapconn, $username, $password);
|
|
||||||
|
|
||||||
Log::error(ldap_errno($ldapconn));
|
|
||||||
if (!$ldapbind) {
|
|
||||||
return redirect()->route('users')->with('error', trans('admin/users/message.error.ldap_could_not_bind').ldap_error($ldapconn));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up LDAP pagination for very large databases
|
|
||||||
// @author Richard Hofman
|
|
||||||
$page_size = 500;
|
|
||||||
$cookie = '';
|
|
||||||
$result_set = array();
|
|
||||||
$global_count = 0;
|
|
||||||
|
|
||||||
// Perform the search
|
|
||||||
do {
|
|
||||||
// Paginate (non-critical, if not supported by server)
|
|
||||||
ldap_control_paged_result($ldapconn, $page_size, false, $cookie);
|
|
||||||
|
|
||||||
$search_results = ldap_search($ldapconn, $base_dn, '('.$filter.')');
|
|
||||||
|
|
||||||
if (!$search_results) {
|
|
||||||
return redirect()->route('users')->with('error', trans('admin/users/message.error.ldap_could_not_search').ldap_error($ldapconn));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get results from page
|
|
||||||
$results = ldap_get_entries($ldapconn, $search_results);
|
|
||||||
if (!$results) {
|
|
||||||
return redirect()->route('users')->with('error', trans('admin/users/message.error.ldap_could_not_get_entries').ldap_error($ldapconn));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add results to result set
|
|
||||||
$global_count += $results['count'];
|
|
||||||
$result_set = array_merge($result_set, $results);
|
|
||||||
|
|
||||||
ldap_control_paged_result_response($ldapconn, $search_results, $cookie);
|
|
||||||
|
|
||||||
} while ($cookie !== null && $cookie != '');
|
|
||||||
|
|
||||||
|
|
||||||
// Clean up after search
|
|
||||||
$result_set['count'] = $global_count;
|
|
||||||
$results = $result_set;
|
|
||||||
ldap_control_paged_result($ldapconn, 0);
|
|
||||||
|
|
||||||
$summary = array();
|
$summary = array();
|
||||||
|
|
||||||
|
$results = Ldap::findLdapUsers();
|
||||||
|
|
||||||
for ($i = 0; $i < $results["count"]; $i++) {
|
for ($i = 0; $i < $results["count"]; $i++) {
|
||||||
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
|
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue