Created
December 10, 2014 18:30
-
-
Save anonymous/b61376e81144608f2fe0 to your computer and use it in GitHub Desktop.
another one.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php if ( ! defined('EXT') ) exit('Invalid file request'); | |
/** FINAL | |
* LDAP Authentication | |
* | |
* ### EE 2.1 version ### | |
* | |
* Based on: NCE LDAP | |
* http://code.google.com/p/ee-ldap-extension/ | |
* License: "if you've used this module and found that it needed something then please hand it back so that it can be shared with the world" | |
* Site: http://code.google.com/p/ee-ldap-extension/wiki/Introduction | |
* | |
* An ExpressionEngine Extension that allows the authentication of users via LDAP | |
* LDAP details are copied to the EE database before standard MySQL authentication is performed | |
* If user is not found on LDAP, MySQL authentication will still be performed (useful for EE users not in LDAP) | |
* | |
* Dependancy: iconv PHP module | |
* | |
* @package DesignByFront | |
* @author Alistair Brown | |
* @author Alex Glover | |
* @link http://github.com/designbyfront/LDAP-Authentication-for-ExpressionEngine | |
* @since Version 1.3 | |
* | |
* LDAPS Instructions - http://github.com/designbyfront/LDAP-Authentication-for-ExpressionEngine/issues/closed#issue/1 | |
* | |
* Enhancements to original: | |
* - Upgraded to EE2 | |
* - Authentication against multiple LDAP servers | |
* - Non-LDAP user login (remove restriction) | |
* - Authentication even with LDAP server downtime (remove restriction) | |
* - Use EE global classes (rather then PHP global variables) | |
* - DB protection against injection (however unlikely) | |
* - Better code structure using functions | |
* - More settings control: | |
* - Use of character encoding for sent data (and ability to change in settings) | |
* PHP uses 'UTF-8' encoding; Windows server uses 'Windows-1252' encoding. | |
* Using the iconv PHP module, settings data saved in 'UTF-8' is dynamically encoded to 'Windows-1252' when being sent. | |
* | |
*/ | |
class Nce_ldap_ext { | |
/* | |
// PHP4 Constructor | |
function Nce_ldap_ext($settings = '') | |
{ | |
$this->EE =& get_instance(); | |
$this->settings = $settings; | |
} | |
*/ | |
var $name = 'UNT LDAP auth (front ldap mod)'; | |
var $version = '1.4'; | |
var $description = 'Handles LDAP login / account creation. Modified by Blair'; | |
var $settings_exist = 'y'; | |
var $docs_url = 'http://github.com/designbyfront/LDAP-Authentication-for-ExpressionEngine/issues'; | |
var $settings = array(); | |
var $use_ldap_account_creation = 'yes'; | |
var $ldap_character_encode = 'Windows-1252'; | |
var $groupID_facultystaff = 9; | |
var $groupID_student = 8; | |
var $groupID_alumni = 4; | |
var $debug = TRUE; | |
function __construct() | |
{ | |
$this->EE =& get_instance(); | |
$this->settings = $settings; | |
} | |
// ---------------------- | |
/** | |
* EE method called when the extension is activated | |
*/ | |
function activate_extension () | |
{ | |
$settings['use_ldap_account_creation'] = $this->use_ldap_account_creation; | |
$settings['ldap_character_encode'] = $this->ldap_character_encode; | |
$settings['groupID_facultystaff'] = $this->groupID_facultystaff; | |
$settings['groupID_student'] = $this->groupID_student; | |
$settings['groupID_alumni'] = $this->groupID_alumni; | |
$hooks = array( | |
'login_authenticate_start' => 'login_authenticate_start', | |
'member_member_login_start' => 'member_member_login_start' | |
); | |
foreach ($hooks as $hook => $method) | |
{ | |
$this->EE->db->query($this->EE->db->insert_string('exp_extensions', | |
array( | |
'extension_id' => '', | |
'class' => __CLASS__, | |
'method' => $method, | |
'hook' => $hook, | |
'settings' => serialize($settings), | |
'priority' => 10, | |
'version' => $this->version, | |
'enabled' => "y" | |
) | |
)); | |
} | |
} | |
// ---------------------- | |
/** | |
* EE method called when the extension is updated | |
*/ | |
function update_extension($current = '') | |
{ | |
if ($current == '' OR $current == $this->version) | |
return FALSE; | |
$this->EE->db->query('UPDATE exp_extensions SET version = \''.$this->EE->db->escape_str($this->version).'\' WHERE class = \''.$this->EE->db->escape_str(__CLASS__).'\''); | |
} | |
// ---------------------- | |
/** | |
* EE method called when the extension is disabled | |
*/ | |
function disable_extension() | |
{ | |
$this->EE->db->query('DELETE FROM exp_extensions WHERE class = \''.$this->EE->db->escape_str(__CLASS__).'\''); | |
} | |
// ---------------------- | |
/** | |
* Configuration for the extension settings page | |
*/ | |
function settings() | |
{ | |
$settings['ldap_character_encode'] = $this->ldap_character_encode; | |
$settings['groupID_facultystaff'] = $this->groupID_facultystaff; | |
$settings['groupID_student'] = $this->groupID_student; | |
$settings['groupID_alumni'] = $this->groupID_alumni; | |
$settings['use_ldap_account_creation'] = array('r', array('yes' => 'yes_ldap_account_creation', | |
'no' => 'no_ldap_account_creation'), | |
'yes'); | |
return $settings; | |
} | |
// ---------------------- | |
/** | |
* Called by the member_member_login_start hook | |
*/ | |
function member_member_login_start() | |
{ | |
return $this->login_authenticate_start(); | |
} | |
// ---------------------- | |
/** | |
* Called by the login_authenticate_start hook | |
*/ | |
function login_authenticate_start() | |
{ | |
$user_info = array(); | |
$user_info['username'] = ee()->input->post('username', TRUE); | |
$user_info['password'] = ee()->input->post('password', TRUE); | |
$result = $this->authenticate_user($user_info); | |
$everything = array_merge($result, $user_info); | |
if ($this->debug) | |
{ | |
echo 'Dump of varible:'; | |
echo'<pre>'; | |
var_dump($everything); | |
echo'</pre>'; | |
} | |
if ($result['authenticated']) | |
{ | |
$this->debug_print('Authenticated. Trying to sync \''.$user_info['username'].'\' with EE member system...'); | |
$this->sync_user_details($everything); | |
} | |
else | |
{ | |
$this->debug_print('Could not authenticate username \''.$user_info['username'].'\' with LDAP'); | |
} | |
//$this->close_connection($connection); | |
if ($this->debug) | |
exit(); | |
} | |
// ---------------------- | |
function sync_user_details($user_info) | |
{ | |
// Sync EE password to match LDAP (if account exists) | |
$user_info['encrypted_password'] = hash('sha1',stripslashes($user_info['password'])); | |
// Get the password information from Auth | |
$this->EE->load->library('auth'); | |
$user_info['hashed_password'] = $this->EE->auth->hash_password($user_info['password']); | |
$sql = 'UPDATE exp_members SET password = \''.$this->EE->db->escape_str($user_info['encrypted_password']).'\' WHERE username = \''.$this->EE->db->escape_str($user_info['username']).'\''; | |
$this->debug_print('Updating user with SQL: '.$sql); | |
$this->EE->db->query($sql); | |
// now we might want to do some EE account creation | |
if ($this->settings['use_ldap_account_creation'] === 'yes') | |
{ | |
$this->debug_print('Attempting to create EE user...'); | |
$this->create_ee_user($user_info); | |
} | |
/* Add a check if they are alumni or not */ | |
if( isset($user_info['edupersonaffiliation'][0]) OR $user_info['edupersonaffiliation'][0] != "") | |
{ /* Do nothing */ | |
} else { | |
// Set the user group to be for former studnets/faculy/staff | |
$sql = 'UPDATE exp_members SET group_id = 7 WHERE username = \''.$this->EE->db->escape_str($user_info['username']).'\''; | |
$this->debug_print('Member affiliation could not be found, so user must not be active. Setting group. Updating using query: '.$sql); | |
$this->EE->db->query($sql); | |
} | |
} | |
// ---------------------- This section was heavily modified in order to handle the two directories. Outside the tree, this is the only way to do this. | |
function create_ee_user($user_info) | |
{ | |
$sql = 'SELECT \'username\' FROM exp_members WHERE username = \''.$this->EE->db->escape_str($user_info['username']).'\''; | |
$this->debug_print('Checking for existing user with SQL: '.$sql); | |
$query = $this->EE->db->query($sql); | |
// user doesn't exist in exp_members table, so we will create an EE account | |
if ($query->num_rows === 0) | |
{ | |
$this->debug_print('Using LDAP for account creation...'); | |
$data['username'] = $user_info['username']; | |
$data['password'] = $user_info['encrypted_password']; | |
$data['email'] = $user_info['mail'][0]; | |
//$data['salt'] = $user_info['hashed_password']; | |
$data['ip_address'] = $this->EE->input->ip_address(); | |
$data['unique_id'] = $this->EE->functions->random('encrypt'); | |
$data['crypt_key'] = $this->EE->functions->random('encrypt', 16); | |
$data['join_date'] = $this->EE->localize->now; | |
$data['language'] = $this->EE->config->item('deft_lang'); | |
$data['timezone'] = $this->EE->config->item('default_site_timezone'); | |
$data['time_format'] = $this->EE->config->item('time_format') ? $this->EE->config->item('time_format') : 'us'; | |
$data['screen_name'] = $user_info['givenname'][0]." ".$user_info['sn'][0]; | |
//$custom_data['a_field'] = $user_info['edupersonaffiliation'][0] . ',' . $user_info['edupersonaffiliation'][1]; | |
$custom_data['first_name'] = $user_info['givenname'][0]; | |
$custom_data['last_name'] = $user_info['sn'][0]; | |
// Eval if user is student or staff | |
if ($user_info['i_am_a'] == 'student') | |
{ | |
//ExpressionEngine group ID = Students | |
$data['group_id'] = $this->$settings['groupID_student']; | |
} | |
if ($user_info['i_am_a'] == 'staff') | |
{ | |
//ExpressionEngine group ID = staff | |
$data['group_id'] = $this->$settings['groupID_facultystaff']; | |
} | |
if ($user_info['i_am_a'] == '') | |
{ | |
//ExpressionEngine group ID = Guest | |
$data['group_id'] = $this->$settings['groupID_alumni']; | |
} | |
// add in any optional data. Name of field => Value it needs to be. Set it ahead of time. | |
$opt_data = array( | |
//'m_field_id_14' => $custom_data['a_field'], | |
'm_field_id_4' => $custom_data['first_name'], | |
'm_field_id_5' => $custom_data['last_name'], | |
); | |
$this->debug_print('Inserting user with data:<pre> '.print_r($data, TRUE).'</pre><br /><pre>'.print_r($custom_data, TRUE).'</pre><br /><pre>'.print_r($opt_data, TRUE).'</pre>'); | |
$this->EE->load->model('member_model'); | |
$member_id = $this->EE->member_model->create_member($data, $opt_data); | |
$this->debug_print('Member ID: '.$member_id); | |
if ($member_id > 0) // update other relevant fields | |
{ | |
//$sql = 'UPDATE exp_members SET photo_filename = \'photo_'.$member_id.'.jpg\', photo_width = \'90\', photo_height = \'120\''; | |
//$query = $this->EE->db->query($sql); | |
} | |
else | |
{ | |
exit('Could not create user account for '.$user_info['username'].'<br/>'."\n"); | |
} | |
} | |
$this->debug_print('Done with create ee user function, moving on.'); | |
} | |
// ---------------------- | |
function authenticate_user($user_info) | |
{ | |
$login_settings = array(); | |
// First try the students directory. | |
$login_settings['ds'] = ldap_connect("students.ad.unt.edu", 389); | |
$login_settings['dn'] = "dc=students,dc=ad,dc=unt,dc=edu"; | |
$login_settings['search_dir'] = 'student'; | |
$bind_result = ldap_bind($login_settings['ds'] , $user_info['username'].'@students.ad.unt.edu', $user_info['password']); | |
$this->debug_print("Student bind result: $bind_result"); | |
//If the login was correct, assume they were a student with the correct login. | |
if ($bind_result){ | |
return $this->greedy_ldap_grab($login_settings, $user_info); | |
} | |
// If it didn't work, then try the other directory. | |
if (!$bind_result) { | |
$this->debug_print('Bind not succesfull to student directory, moving to the faculty-staff directory.'); | |
// Connect to unt.ad.unt.edu | |
$login_settings['ds'] = ldap_connect("unt.ad.unt.edu", 389); | |
$login_settings['dn'] = "dc=unt,dc=ad,dc=unt,dc=edu"; | |
$login_settings['search_dir'] = 'staff'; | |
$bind_result = ldap_bind($login_settings['ds'] , $user_info['username'].'@unt.ad.unt.edu', $user_info['password']); | |
$this->debug_print("UNT bind result: $bind_result"); | |
if ($bind_result) | |
{ | |
return $this->greedy_ldap_grab($login_settings, $user_info); | |
} else { | |
$this->debug_print("Not able to bind to either directory."); | |
} | |
} | |
} | |
// ---------------------- | |
function greedy_ldap_grab($login_settings, $user_info) | |
{ | |
$this->debug_print('Starting Greedy LDAP Grab...'); | |
$filter = "(cn={$user_info['username']})"; | |
$this->debug_print('Filter: ' . $filter); | |
// The fields to pull from the directory entry. | |
$attributes = array('givenName','mail','sn','cn','edupersonaffiliation'); | |
// Actually do the search of the user, and pull the above info. | |
$result = ldap_search($login_settings['ds'], $login_settings['dn'], $filter); | |
$this->debug_print("Result: {$result}"); | |
// If the search comes up empty, end and report the error. | |
if (ldap_count_entries($login_settings['ds'], $result) != 1) | |
{ | |
return array('authenticated' => false); | |
} | |
// If no error searching: | |
// Get all the entries that match. | |
$info = ldap_get_entries($login_settings['ds'], $result); | |
// Since there could be more than one, only use the first entry it finds. | |
$user_info = $info[0]; | |
$this->debug_print('Data for '.$info["count"].' items returned<br/>'); | |
// If everything goes well, then you are assigned a value. | |
$user_info['i_am_a'] = $login_settings['search_dir']; | |
$this->debug_print("You are a ".$login_settings['search_dir']); | |
$user_info['authenticated'] = true; | |
//Close Connection | |
$this->debug_print('Closing connection...'); | |
ldap_close($login_settings['ds']) or | |
die('Could not close the LDAP connection<br/>'."\n"); | |
$this->debug_print('Returning user info from Greedy.'); | |
return $user_info; | |
} | |
/** ORG | |
function authenticate_user($conn, $username, $password, $ldap_username_attribute, $ldap_search_base) | |
{ | |
$this->debug_print('Searching for attribute '.$ldap_username_attribute.'='.$username.' ...'); | |
// Search username entry | |
$result = ldap_search($conn, $ldap_search_base, $ldap_username_attribute.'='.$username); | |
$this->debug_print('Search result is: '.$result); | |
// Search not successful (server down?), so do nothing - standard MySQL authentication can take over | |
if ($result === FALSE) | |
{ | |
$this->EE->session->userdata['ldap_message'] = $this->settings['no_ldap_login_message']; | |
return array('authenticated' => false); | |
} | |
$this->debug_print('Number of entires returned is '.ldap_count_entries($conn, $result)); | |
// username not found, so do nothing - standard MySQL authentication can take over | |
if (ldap_count_entries($conn, $result) < 1) | |
{ | |
return array('authenticated' => false); | |
} | |
$this->debug_print('Getting entries for \''.$username.'\' ...'); | |
$info = ldap_get_entries($conn, $result); // entry for username found in directory, retrieve entries | |
$user_info = $info[0]; | |
$this->debug_print('Data for '.$info["count"].' items returned<br/>'); | |
$user_info['username'] = $username; | |
$user_info['password'] = $password; | |
// Authenticate LDAP user against password submitted on login | |
$dn = $user_info['dn']; | |
$success = @ldap_bind($conn, $dn, $this->ldap_encode($password)); // bind with user credentials | |
if (!$success) | |
{ | |
$this->debug_print('Error binding with supplied password (dn: '.$dn.') ERROR: '.ldap_error($conn)); | |
} | |
$user_info['authenticated'] = $success; | |
return $user_info; | |
} | |
**/ | |
function debug_print($message, $br="<br/>\n") | |
{ | |
if ($this->debug) | |
{ | |
if (is_array($message)) | |
{ | |
print('<pre>'); | |
print_r($message); | |
print('</pre>'.$br); | |
} | |
else | |
{ | |
print($message.' '.$br); | |
} | |
} | |
} | |
function ldap_encode($text) | |
{ | |
return iconv("UTF-8", $this->settings['ldap_character_encode'], $text); | |
} | |
} | |
// END CLASS Nce_ldap | |
/* End of file ext.nce_ldap.php */ | |
/* Location: ./system/expressionengine/third_party/nce_ldap/ext.nce_ldap.php */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment