├── EE1 └── core │ ├── extensions │ └── ext.nce_ldap.php │ └── language │ └── english │ └── lang.nce_ldap.php ├── EE2 └── core │ └── expressionengine │ └── third_party │ └── nce_ldap │ ├── ext.nce_ldap.php │ └── language │ └── english │ └── lang.nce_ldap.php └── README.md /EE1/core/extensions/ext.nce_ldap.php: -------------------------------------------------------------------------------- 1 | Custom admin email message 36 | * - Notifications: 37 | * Adds to session data $_SESSION['ldap_message'] which can be used later for notification purposes 38 | * - Use of character encoding for sent data (and ability to change in settings) 39 | * PHP uses 'UTF-8' encoding; Windows server uses 'Windows-1252' encoding. 40 | * Using the iconv PHP module, settings data saved in 'UTF-8' is dynamically encoded to 'Windows-1252' when being sent. 41 | * 42 | */ 43 | 44 | class Nce_ldap { 45 | 46 | var $settings = array(); 47 | var $name = 'LDAP authentication'; 48 | var $version = '1.3'; 49 | var $description = 'Handles LDAP login / account creation'; 50 | var $settings_exist = 'y'; 51 | var $docs_url = 'http://github.com/designbyfront/LDAP-Authentication-for-ExpressionEngine/issues'; 52 | var $debug = FALSE; 53 | 54 | // If you are looking here to edit the settings, you can always just change them in Extensions settings page :) 55 | var $admin_email = 'admin@your_site.com'; // Change your_site.com to your sites domain 56 | var $from_email = 'ldap@your_site.com'; // Change your_site.com to your sites domain 57 | var $mail_host = 'your_mail_host'; // Change your_mail_host to name / ip address of your mail host 58 | var $mail_message = "This is an automated message from the ExpressionEngine LDAP authentication system.\n-------------------------\n\n{name} has just logged in for the first time. This has created an ExpressionEngine account for them using their LDAP details.\nTo complete their account details, please log in to http://{host} and update their member group, profile and 'people' weblog entry.\nTheir username is: {username}"; 59 | var $use_ldap_account_creation = 'yes'; 60 | var $ldap_host = 'ldap://your_ldap_host'; // Change your_ldap_host to name / ip address of your LDAP host 61 | var $ldap_port = '389'; // Change if your LDAP port is different 62 | var $ldap_search_base = 'ldap_search_base'; // Change to your LDAP search base 63 | var $ldap_search_user = 'ldap_search_user'; // Change to your LDAP search user 64 | var $ldap_search_password = 'ldap_search_password'; // Change to your LDAP search password 65 | var $ldap_username_attribute = 'ldap_username_attribute'; // Change to your LDAP username attribute 66 | var $ldap_character_encode = 'Windows-1252'; 67 | var $no_ldap_login_message = 'LDAP authentication seems to be down at the moment. Please contact your administrator.'; 68 | var $first_time_login_message = 'This is your first time logging in! Your account has been automatically created for you, but your administrator may still need to alter your settings. Please contact them if you require more access.'; 69 | var $created_user_group = '5'; // User group id (members) 70 | 71 | // PHP4 Constructor 72 | function Nce_ldap($settings = '') 73 | { 74 | $this->settings = $settings; 75 | } 76 | 77 | 78 | // ---------------------- 79 | 80 | 81 | /** 82 | * EE method called when the extension is activated 83 | */ 84 | function activate_extension () 85 | { 86 | global $DB; 87 | 88 | $settings = array(); 89 | $settings['admin_email'] = $this->admin_email; 90 | $settings['from_email'] = $this->from_email; 91 | $settings['mail_host'] = $this->mail_host; 92 | $settings['mail_message'] = $this->mail_message; 93 | $settings['use_ldap_account_creation'] = $this->use_ldap_account_creation; 94 | $settings['ldap_host'] = $this->ldap_host; 95 | $settings['ldap_port'] = $this->ldap_port; 96 | $settings['ldap_search_base'] = $this->ldap_search_base; 97 | $settings['ldap_search_user'] = $this->ldap_search_user; 98 | $settings['ldap_search_password'] = $this->ldap_search_password; 99 | $settings['ldap_username_attribute'] = $this->ldap_username_attribute; 100 | $settings['ldap_character_encode'] = $this->ldap_character_encode; 101 | $settings['no_ldap_login_message'] = $this->no_ldap_login_message; 102 | $settings['first_time_login_message'] = $this->first_time_login_message; 103 | $settings['created_user_group'] = $this->created_user_group; 104 | 105 | $hooks = array( 106 | 'login_authenticate_start' => 'login_authenticate_start', 107 | 'member_member_login_start' => 'member_member_login_start' 108 | ); 109 | 110 | foreach ($hooks as $hook => $method) 111 | { 112 | $DB->query($DB->insert_string('exp_extensions', 113 | array( 114 | 'extension_id' => '', 115 | 'class' => __CLASS__, 116 | 'method' => $method, 117 | 'hook' => $hook, 118 | 'settings' => serialize($settings), 119 | 'priority' => 10, 120 | 'version' => $this->version, 121 | 'enabled' => "y" 122 | ) 123 | )); 124 | } 125 | } 126 | 127 | 128 | // ---------------------- 129 | 130 | 131 | /** 132 | * EE method called when the extension is updated 133 | */ 134 | function update_extension($current = '') 135 | { 136 | global $DB; 137 | 138 | if ($current == '' OR $current == $this->version) 139 | return FALSE; 140 | 141 | $DB->query('UPDATE exp_extensions SET version = \''.$DB->escape_str($this->version).'\' WHERE class = \''.$DB->escape_str(__CLASS__).'\''); 142 | } 143 | 144 | 145 | // ---------------------- 146 | 147 | 148 | /** 149 | * EE method called when the extension is disabled 150 | */ 151 | function disable_extension() 152 | { 153 | global $DB; 154 | 155 | $DB->query('DELETE FROM exp_extensions WHERE class = \''.$DB->escape_str(__CLASS__).'\''); 156 | } 157 | 158 | 159 | // ---------------------- 160 | 161 | 162 | /** 163 | * Configuration for the extension settings page 164 | */ 165 | function settings() 166 | { 167 | $settings = array(); 168 | $settings['ldap_host'] = $this->ldap_host; 169 | $settings['ldap_port'] = $this->ldap_port; 170 | $settings['ldap_search_base'] = $this->ldap_search_base; 171 | $settings['ldap_search_user'] = $this->ldap_search_user; 172 | $settings['ldap_search_password'] = $this->ldap_search_password; 173 | $settings['ldap_username_attribute'] = $this->ldap_username_attribute; 174 | $settings['ldap_character_encode'] = $this->ldap_character_encode; 175 | $settings['use_ldap_account_creation'] = array('r', array('yes' => 'yes_ldap_account_creation', 176 | 'no' => 'no_ldap_account_creation'), 177 | 'yes'); 178 | $settings['admin_email'] = $this->admin_email; 179 | $settings['from_email'] = $this->from_email; 180 | $settings['mail_host'] = $this->mail_host; 181 | $settings['mail_message'] = array('t', $this->mail_message); 182 | $settings['no_ldap_login_message'] = array('t', $this->no_ldap_login_message); 183 | $settings['first_time_login_message'] = array('t', $this->first_time_login_message); 184 | $settings['created_user_group'] = $this->created_user_group; 185 | 186 | return $settings; 187 | } 188 | 189 | 190 | // ---------------------- 191 | 192 | 193 | /** 194 | * Called by the member_member_login_start hook 195 | */ 196 | function member_member_login_start() 197 | { 198 | return $this->login_authenticate_start(); 199 | } 200 | 201 | 202 | // ---------------------- 203 | 204 | 205 | /** 206 | * Called by the login_authenticate_start hook 207 | */ 208 | function login_authenticate_start() 209 | { 210 | global $IN; 211 | 212 | $provided_username = $IN->GBL('username', 'POST'); 213 | $provided_password = $IN->GBL('password', 'POST'); 214 | 215 | // Multiple LDAP servers 216 | $ldap_hosts = explode(',', $this->settings['ldap_host']); 217 | foreach ($ldap_hosts as $ldap_host) 218 | { 219 | $connection = $this->create_connection($ldap_host, $this->settings['ldap_port'], $this->settings['ldap_search_user'], $this->settings['ldap_search_password']); 220 | $result = $this->authenticate_user($connection, $provided_username, $provided_password, $this->settings['ldap_username_attribute'], $this->settings['ldap_search_base']); 221 | if ($result['authenticated']) 222 | break; 223 | } 224 | 225 | if ($this->debug) 226 | { 227 | echo'
';
228 | 			var_dump($result);
229 | 			echo'
'; 230 | } 231 | 232 | if ($result['authenticated']) 233 | { 234 | $this->sync_user_details($result); 235 | } 236 | else 237 | { 238 | $this->debug_print('Could not authenticate username \''.$provided_username.'\' with LDAP'); 239 | } 240 | $this->close_connection($connection); 241 | 242 | if ($this->debug) 243 | exit(); 244 | } 245 | 246 | 247 | // ---------------------- 248 | 249 | 250 | function sync_user_details($user_info) 251 | { 252 | global $FNS, $DB; 253 | // Sync EE password to match LDAP (if account exists) 254 | $encrypted_password = $FNS->hash(stripslashes($user_info['password'])); 255 | $sql = 'UPDATE exp_members SET password = \''.$DB->escape_str($encrypted_password).'\' WHERE username = \''.$DB->escape_str($user_info['username']).'\''; 256 | $this->debug_print('Updating user with SQL: '.$sql); 257 | $DB->query($sql); 258 | 259 | // now we might want to do some EE account creation 260 | if ($this->settings['use_ldap_account_creation'] === 'yes') 261 | { 262 | $this->create_ee_user($user_info, $encrypted_password); 263 | } 264 | 265 | } 266 | 267 | 268 | // ---------------------- 269 | 270 | 271 | function create_ee_user($user_info, $encrypted_password) 272 | { 273 | global $LOC, $FNS, $DB, $STAT, $SESS, $LANG; 274 | 275 | $sql = 'SELECT \'username\' FROM exp_members WHERE username = \''.$DB->escape_str($user_info['username']).'\''; 276 | $this->debug_print('Checking for existing user with SQL: '.$sql); 277 | $query = $DB->query($sql); 278 | 279 | // user doesn't exist in exp_members table, so we will create an EE account 280 | if ($query->num_rows === 0) 281 | { 282 | $this->debug_print('Using LDAP for account creation...'); 283 | $unique_id = $FNS->random('encrypt'); 284 | $join_date = $LOC->now; 285 | 286 | $sql = 'INSERT INTO exp_members SET '. 287 | 'username = \''.$DB->escape_str($user_info['username']).'\', '. 288 | 'password = \''.$DB->escape_str($encrypted_password).'\', '. 289 | 'unique_id = \''.$DB->escape_str($unique_id).'\', '. 290 | 'group_id = \''.$DB->escape_str($this->settings['created_user_group']).'\', '. 291 | 'screen_name = \''.$DB->escape_str($user_info['cn'][0]).'\', '. 292 | 'email = \''.$DB->escape_str($user_info['mail'][0]).'\', '. 293 | 'ip_address = \'0.0.0.0\', '. 294 | 'join_date = \''.$DB->escape_str($join_date).'\', '. 295 | 'language = \'english\', '. 296 | 'timezone = \'UTC\', '. 297 | 'time_format = \'eu\''; 298 | 299 | $this->debug_print('Inserting user with SQL: '.$sql); 300 | $query = $DB->query($sql); 301 | 302 | $member_id = $DB->insert_id; 303 | if ($member_id > 0) // update other relevant fields 304 | { 305 | $sql = 'UPDATE exp_members SET photo_filename = \'photo_'.$member_id.'.jpg\', photo_width = \'90\', photo_height = \'120\''; 306 | $query = $DB->query($sql); 307 | 308 | $DB->query('INSERT INTO exp_member_data SET member_id = '.$DB->escape_str($member_id)); 309 | $DB->query('INSERT INTO exp_member_homepage SET member_id = '.$DB->escape_str($member_id)); 310 | 311 | $STAT->update_member_stats(); 312 | 313 | $this->settings['mail_message'] = str_replace('{name}', $user_info['cn'][0], $this->settings['mail_message']); 314 | $this->settings['mail_message'] = str_replace('{username}', $user_info['username'], $this->settings['mail_message']); 315 | $this->settings['mail_message'] = str_replace('{host}', $_SERVER['HTTP_HOST'], $this->settings['mail_message']); 316 | 317 | // Email the admin with the details of the new user 318 | ini_set('SMTP', $this->settings['mail_host']); 319 | $headers = 'From: '.$this->settings['from_email']."\r\n" . 320 | 'X-Mailer: PHP/' . phpversion(); 321 | $success = mail( 322 | $this->settings['admin_email'], 323 | 'New member \''.$user_info['username'].'\' on http://'.$_SERVER['HTTP_HOST'], 324 | $this->settings['mail_message'], 325 | $headers 326 | ); 327 | session_start(); 328 | $_SESSION['ldap_message'] = $this->settings['first_time_login_message']; 329 | } 330 | else 331 | { 332 | exit('Could not create user account for '.$user_info['username'].'
'."\n"); 333 | } 334 | } 335 | } 336 | 337 | 338 | // ---------------------- 339 | 340 | 341 | function authenticate_user($conn, $username, $password, $ldap_username_attribute, $ldap_search_base) 342 | { 343 | global $SESS, $FNS, $EXT, $IN; 344 | 345 | $this->debug_print('Searching for attribute '.$ldap_username_attribute.'='.$username.' ...'); 346 | // Search username entry 347 | $result = ldap_search($conn, $ldap_search_base, $ldap_username_attribute.'='.$username); 348 | $this->debug_print('Search result is: '.$result); 349 | 350 | // Search not successful (server down?), so do nothing - standard MySQL authentication can take over 351 | if ($result === FALSE) 352 | { 353 | session_start(); 354 | $_SESSION['ldap_message'] = $this->settings['no_ldap_login_message']; 355 | return array('authenticated' => false); 356 | } 357 | 358 | $this->debug_print('Number of entires returned is '.ldap_count_entries($conn, $result)); 359 | // username not found, so do nothing - standard MySQL authentication can take over 360 | if (ldap_count_entries($conn, $result) < 1) 361 | { 362 | return array('authenticated' => false); 363 | } 364 | 365 | $this->debug_print('Getting entries for \''.$username.'\' ...'); 366 | $info = ldap_get_entries($conn, $result); // entry for username found in directory, retrieve entries 367 | $user_info = $info[0]; 368 | $this->debug_print('Data for '.$info["count"].' items returned
'); 369 | 370 | $user_info['username'] = $username; 371 | $user_info['password'] = $password; 372 | // Authenticate LDAP user against password submitted on login 373 | $dn = $user_info['dn']; 374 | $success = @ldap_bind($conn, $dn, $this->ldap_encode($password)); // bind with user credentials 375 | 376 | if (!$success) 377 | { 378 | $this->debug_print('Error binding with supplied password (dn: '.$dn.') ERROR: '.ldap_error($conn)); 379 | } 380 | 381 | $user_info['authenticated'] = $success; 382 | return $user_info; 383 | } 384 | 385 | 386 | // ---------------------- 387 | 388 | 389 | function create_connection($ldap_host, $ldap_port, $ldap_search_user, $ldap_search_password) 390 | { 391 | $this->debug_print('Connecting to LDAP...'); 392 | $conn = ldap_connect($ldap_host, $ldap_port) or 393 | die('Could not connect to host: '.$ldap_host.':'.$ldap_port.'
'."\n"); 394 | $this->debug_print('connect result is '.$conn); 395 | 396 | // Perform bind with search user 397 | if (empty($ldap_search_user)) 398 | { 399 | $this->debug_print('Binding anonymously...'); 400 | $success = ldap_bind($conn); // this is an "anonymous" bind, typically read-only access 401 | } 402 | else 403 | { 404 | $this->debug_print('Binding with user: ['.$ldap_search_user.']-['.$ldap_search_password.'] ...'); 405 | $success = ldap_bind($conn, $this->ldap_encode($ldap_search_user), $this->ldap_encode($ldap_search_password)); // bind with credentials 406 | } 407 | $this->debug_print('Bind result is '.$success); 408 | return $conn; 409 | } 410 | 411 | 412 | // ---------------------- 413 | 414 | 415 | function close_connection($conn) 416 | { 417 | $this->debug_print('Closing connection...'); 418 | ldap_close($conn) or 419 | die('Could not close the LDAP connection
'."\n"); 420 | } 421 | 422 | 423 | // ---------------------- 424 | 425 | 426 | function debug_print($message, $br="
\n") 427 | { 428 | if ($this->debug) 429 | { 430 | if (is_array($message)) 431 | { 432 | print('
');
433 | 				print_r($message);
434 | 				print('
'.$br); 435 | } 436 | else 437 | { 438 | print($message.' '.$br); 439 | } 440 | } 441 | } 442 | 443 | 444 | function ldap_encode($text) 445 | { 446 | return iconv("UTF-8", $this->settings['ldap_character_encode'], $text); 447 | } 448 | 449 | 450 | } 451 | // END CLASS Nce_ldap 452 | 453 | /* End of file ext.nce_ldap.php */ 454 | /* Location: ./system/extensions/ext.nce_ldap.php */ -------------------------------------------------------------------------------- /EE1/core/language/english/lang.nce_ldap.php: -------------------------------------------------------------------------------- 1 | 'Server Address [e.g. ldap://myhost] (comma separate for multiple servers)', 6 | 'ldap_port' => 'Port number [default = 389]', 7 | 'ldap_search_base' => 'Search base', 8 | 'ldap_search_user' => 'LDAP user (leave blank for anonymous binding)', 9 | 'ldap_search_password' => 'LDAP password (leave blank for anonymous binding)', 10 | 'ldap_username_attribute' => 'Attribute in the directory to identify your users', 11 | 'ldap_character_encode' => 'LDAP encoding type', 12 | 'use_ldap_account_creation' => 'Use LDAP for account creation', 13 | 'created_user_group' => 'Group ID to assign newly created users', 14 | 15 | 'admin_email' => 'Address to send system notifications (e.g. when new user regsitered via LDAP)', 16 | 'from_email' => 'System notifications will appear to be from', 17 | 'mail_host' => 'SMTP mail host', 18 | 'mail_message' => 'System notifications sent to EE administrator when new account created', 19 | 20 | 'no_ldap_login_message' => 'Message attached to user session object when LDAP server is down', 21 | 'first_time_login_message' => 'Message attached to user session object on first log in (ie. when preferences have not been set)', 22 | 23 | 'yes_ldap_account_creation' => 'Yes', 24 | 'no_ldap_account_creation' => 'No', 25 | 26 | '' => '' 27 | ); 28 | // end array 29 | 30 | /* End of file lang.cp_zendesk.php */ 31 | /* Location: ./system/language/english/lang.cp_zendesk.php */ -------------------------------------------------------------------------------- /EE2/core/expressionengine/third_party/nce_ldap/ext.nce_ldap.php: -------------------------------------------------------------------------------- 1 | Custom admin email message 36 | * - Notifications: 37 | * Adds to session data $_SESSION['ldap_message'] which can be used later for notification purposes 38 | * - Use of character encoding for sent data (and ability to change in settings) 39 | * PHP uses 'UTF-8' encoding; Windows server uses 'Windows-1252' encoding. 40 | * Using the iconv PHP module, settings data saved in 'UTF-8' is dynamically encoded to 'Windows-1252' when being sent. 41 | * 42 | */ 43 | 44 | class Nce_ldap_ext { 45 | 46 | var $settings = array(); 47 | var $name = 'LDAP authentication'; 48 | var $version = '1.3'; 49 | var $description = 'Handles LDAP login / account creation'; 50 | var $settings_exist = 'y'; 51 | var $docs_url = 'http://github.com/designbyfront/LDAP-Authentication-for-ExpressionEngine/issues'; 52 | var $debug = FALSE; 53 | 54 | // If you are looking here to edit the settings, you can always just change them in Extensions settings page :) 55 | var $admin_email = 'admin@your_site.com'; // Change your_site.com to your sites domain 56 | var $from_email = 'ldap@your_site.com'; // Change your_site.com to your sites domain 57 | var $mail_host = 'your_mail_host'; // Change your_mail_host to name / ip address of your mail host 58 | var $mail_message = "This is an automated message from the ExpressionEngine LDAP authentication system.\n-------------------------\n\n{name} has just logged in for the first time. This has created an ExpressionEngine account for them using their LDAP details.\nTo complete their account details, please log in to http://{host} and update their member group, profile and 'people' weblog entry.\nTheir username is: {username}"; 59 | var $use_ldap_account_creation = 'yes'; 60 | var $ldap_host = 'ldap://your_ldap_host'; // Change your_ldap_host to name / ip address of your LDAP host 61 | var $ldap_port = '389'; // Change if your LDAP port is different 62 | var $ldap_search_base = 'ldap_search_base'; // Change to your LDAP search base 63 | var $ldap_search_user = 'ldap_search_user'; // Change to your LDAP search user 64 | var $ldap_search_password = 'ldap_search_password'; // Change to your LDAP search password 65 | var $ldap_username_attribute = 'ldap_username_attribute'; // Change to your LDAP username attribute 66 | var $ldap_character_encode = 'Windows-1252'; 67 | var $no_ldap_login_message = 'LDAP authentication seems to be down at the moment. Please contact your administrator.'; 68 | var $first_time_login_message = 'This is your first time logging in! Your account has been automatically created for you, but your administrator may still need to alter your settings. Please contact them if you require more access.'; 69 | var $created_user_group = '5'; // User group id (members) 70 | 71 | // PHP4 Constructor 72 | function Nce_ldap_ext($settings = '') 73 | { 74 | $this->EE =& get_instance(); 75 | $this->settings = $settings; 76 | } 77 | 78 | 79 | // ---------------------- 80 | 81 | 82 | /** 83 | * EE method called when the extension is activated 84 | */ 85 | function activate_extension () 86 | { 87 | $settings = array(); 88 | $settings['admin_email'] = $this->admin_email; 89 | $settings['from_email'] = $this->from_email; 90 | $settings['mail_host'] = $this->mail_host; 91 | $settings['mail_message'] = $this->mail_message; 92 | $settings['use_ldap_account_creation'] = $this->use_ldap_account_creation; 93 | $settings['ldap_host'] = $this->ldap_host; 94 | $settings['ldap_port'] = $this->ldap_port; 95 | $settings['ldap_search_base'] = $this->ldap_search_base; 96 | $settings['ldap_search_user'] = $this->ldap_search_user; 97 | $settings['ldap_search_password'] = $this->ldap_search_password; 98 | $settings['ldap_username_attribute'] = $this->ldap_username_attribute; 99 | $settings['ldap_character_encode'] = $this->ldap_character_encode; 100 | $settings['no_ldap_login_message'] = $this->no_ldap_login_message; 101 | $settings['first_time_login_message'] = $this->first_time_login_message; 102 | $settings['created_user_group'] = $this->created_user_group; 103 | 104 | $hooks = array( 105 | 'login_authenticate_start' => 'login_authenticate_start', 106 | 'member_member_login_start' => 'member_member_login_start' 107 | ); 108 | 109 | foreach ($hooks as $hook => $method) 110 | { 111 | $this->EE->db->query($this->EE->db->insert_string('exp_extensions', 112 | array( 113 | 'extension_id' => '', 114 | 'class' => __CLASS__, 115 | 'method' => $method, 116 | 'hook' => $hook, 117 | 'settings' => serialize($settings), 118 | 'priority' => 10, 119 | 'version' => $this->version, 120 | 'enabled' => "y" 121 | ) 122 | )); 123 | } 124 | } 125 | 126 | 127 | // ---------------------- 128 | 129 | 130 | /** 131 | * EE method called when the extension is updated 132 | */ 133 | function update_extension($current = '') 134 | { 135 | if ($current == '' OR $current == $this->version) 136 | return FALSE; 137 | 138 | $this->EE->db->query('UPDATE exp_extensions SET version = \''.$this->EE->db->escape_str($this->version).'\' WHERE class = \''.$this->EE->db->escape_str(__CLASS__).'\''); 139 | } 140 | 141 | 142 | // ---------------------- 143 | 144 | 145 | /** 146 | * EE method called when the extension is disabled 147 | */ 148 | function disable_extension() 149 | { 150 | $this->EE->db->query('DELETE FROM exp_extensions WHERE class = \''.$this->EE->db->escape_str(__CLASS__).'\''); 151 | } 152 | 153 | 154 | // ---------------------- 155 | 156 | 157 | /** 158 | * Configuration for the extension settings page 159 | */ 160 | function settings() 161 | { 162 | $settings = array(); 163 | $settings['ldap_host'] = $this->ldap_host; 164 | $settings['ldap_port'] = $this->ldap_port; 165 | $settings['ldap_search_base'] = $this->ldap_search_base; 166 | $settings['ldap_search_user'] = $this->ldap_search_user; 167 | $settings['ldap_search_password'] = $this->ldap_search_password; 168 | $settings['ldap_username_attribute'] = $this->ldap_username_attribute; 169 | $settings['ldap_character_encode'] = $this->ldap_character_encode; 170 | $settings['use_ldap_account_creation'] = array('r', array('yes' => 'yes_ldap_account_creation', 171 | 'no' => 'no_ldap_account_creation'), 172 | 'yes'); 173 | $settings['admin_email'] = $this->admin_email; 174 | $settings['from_email'] = $this->from_email; 175 | $settings['mail_host'] = $this->mail_host; 176 | $settings['mail_message'] = array('t', $this->mail_message); 177 | $settings['no_ldap_login_message'] = array('t', $this->no_ldap_login_message); 178 | $settings['first_time_login_message'] = array('t', $this->first_time_login_message); 179 | $settings['created_user_group'] = $this->created_user_group; 180 | 181 | return $settings; 182 | } 183 | 184 | 185 | // ---------------------- 186 | 187 | 188 | /** 189 | * Called by the member_member_login_start hook 190 | */ 191 | function member_member_login_start() 192 | { 193 | return $this->login_authenticate_start(); 194 | } 195 | 196 | 197 | // ---------------------- 198 | 199 | 200 | /** 201 | * Called by the login_authenticate_start hook 202 | */ 203 | function login_authenticate_start() 204 | { 205 | $provided_username = $this->EE->input->post('username'); 206 | $provided_password = $this->EE->input->post('password'); 207 | 208 | // Multiple LDAP servers 209 | $ldap_hosts = explode(',', $this->settings['ldap_host']); 210 | foreach ($ldap_hosts as $ldap_host) 211 | { 212 | $connection = $this->create_connection($ldap_host, $this->settings['ldap_port'], $this->settings['ldap_search_user'], $this->settings['ldap_search_password']); 213 | $result = $this->authenticate_user($connection, $provided_username, $provided_password, $this->settings['ldap_username_attribute'], $this->settings['ldap_search_base']); 214 | if ($result['authenticated']) 215 | break; 216 | } 217 | 218 | if ($this->debug) 219 | { 220 | echo'
';
221 | 			var_dump($result);
222 | 			echo'
'; 223 | } 224 | 225 | if ($result['authenticated']) 226 | { 227 | $this->sync_user_details($result); 228 | } 229 | else 230 | { 231 | $this->debug_print('Could not authenticate username \''.$provided_username.'\' with LDAP'); 232 | } 233 | $this->close_connection($connection); 234 | 235 | if ($this->debug) 236 | exit(); 237 | } 238 | 239 | 240 | // ---------------------- 241 | 242 | 243 | function sync_user_details($user_info) 244 | { 245 | // Sync EE password to match LDAP (if account exists) 246 | $encrypted_password = $this->EE->functions->hash(stripslashes($user_info['password'])); 247 | $sql = 'UPDATE exp_members SET password = \''.$this->EE->db->escape_str($encrypted_password).'\' WHERE username = \''.$this->EE->db->escape_str($user_info['username']).'\''; 248 | $this->debug_print('Updating user with SQL: '.$sql); 249 | $this->EE->db->query($sql); 250 | 251 | // now we might want to do some EE account creation 252 | if ($this->settings['use_ldap_account_creation'] === 'yes') 253 | { 254 | $this->create_ee_user($user_info, $encrypted_password); 255 | } 256 | 257 | } 258 | 259 | 260 | // ---------------------- 261 | 262 | 263 | function create_ee_user($user_info, $encrypted_password) 264 | { 265 | $sql = 'SELECT \'username\' FROM exp_members WHERE username = \''.$this->EE->db->escape_str($user_info['username']).'\''; 266 | $this->debug_print('Checking for existing user with SQL: '.$sql); 267 | $query = $this->EE->db->query($sql); 268 | 269 | // user doesn't exist in exp_members table, so we will create an EE account 270 | if ($query->num_rows === 0) 271 | { 272 | $this->debug_print('Using LDAP for account creation...'); 273 | 274 | $data['screen_name'] = $user_info['cn'][0]; 275 | $data['username'] = $user_info['username']; 276 | $data['password'] = $encrypted_password; 277 | $data['email'] = $user_info['mail'][0]; 278 | $data['ip_address'] = '0.0.0.0'; 279 | $data['unique_id'] = $this->EE->functions->random('encrypt'); 280 | $data['join_date'] = $this->EE->localize->now; 281 | $data['language'] = 'english'; 282 | $data['timezone'] = 'UTC'; 283 | $data['daylight_savings'] = 'n'; 284 | $data['time_format'] = 'eu'; 285 | $data['group_id'] = $this->settings['created_user_group']; 286 | 287 | $this->debug_print('Inserting user with data: '.print_r($data, TRUE)); 288 | 289 | $this->EE->load->model('member_model'); 290 | $member_id = $this->EE->member_model->create_member($data); 291 | if ($member_id > 0) // update other relevant fields 292 | { 293 | $sql = 'UPDATE exp_members SET photo_filename = \'photo_'.$member_id.'.jpg\', photo_width = \'90\', photo_height = \'120\''; 294 | $query = $this->EE->db->query($sql); 295 | 296 | //$this->EE->db->query('INSERT INTO exp_member_data SET member_id = '.$this->EE->db->escape_str($member_id)); 297 | //$this->EE->db->query('INSERT INTO exp_member_homepage SET member_id = '.$this->EE->db->escape_str($member_id)); 298 | 299 | $this->EE->stats->update_member_stats(); 300 | 301 | $this->settings['mail_message'] = str_replace('{name}', $user_info['cn'][0], $this->settings['mail_message']); 302 | $this->settings['mail_message'] = str_replace('{username}', $user_info['username'], $this->settings['mail_message']); 303 | $this->settings['mail_message'] = str_replace('{host}', $_SERVER['HTTP_HOST'], $this->settings['mail_message']); 304 | 305 | // Email the admin with the details of the new user 306 | ini_set('SMTP', $this->settings['mail_host']); 307 | $headers = 'From: '.$this->settings['from_email']."\r\n" . 308 | 'X-Mailer: PHP/' . phpversion(); 309 | $success = mail( 310 | $this->settings['admin_email'], 311 | 'New member \''.$user_info['username'].'\' on http://'.$_SERVER['HTTP_HOST'], 312 | $this->settings['mail_message'], 313 | $headers 314 | ); 315 | $this->EE->session->userdata['ldap_message'] = $this->settings['first_time_login_message']; 316 | } 317 | else 318 | { 319 | exit('Could not create user account for '.$user_info['username'].'
'."\n"); 320 | } 321 | } 322 | } 323 | 324 | 325 | // ---------------------- 326 | 327 | 328 | function authenticate_user($conn, $username, $password, $ldap_username_attribute, $ldap_search_base) 329 | { 330 | $this->debug_print('Searching for attribute '.$ldap_username_attribute.'='.$username.' ...'); 331 | // Search username entry 332 | $result = ldap_search($conn, $ldap_search_base, $ldap_username_attribute.'='.$username); 333 | $this->debug_print('Search result is: '.$result); 334 | 335 | // Search not successful (server down?), so do nothing - standard MySQL authentication can take over 336 | if ($result === FALSE) 337 | { 338 | $this->EE->session->userdata['ldap_message'] = $this->settings['no_ldap_login_message']; 339 | return array('authenticated' => false); 340 | } 341 | 342 | $this->debug_print('Number of entires returned is '.ldap_count_entries($conn, $result)); 343 | // username not found, so do nothing - standard MySQL authentication can take over 344 | if (ldap_count_entries($conn, $result) < 1) 345 | { 346 | return array('authenticated' => false); 347 | } 348 | 349 | $this->debug_print('Getting entries for \''.$username.'\' ...'); 350 | $info = ldap_get_entries($conn, $result); // entry for username found in directory, retrieve entries 351 | $user_info = $info[0]; 352 | $this->debug_print('Data for '.$info["count"].' items returned
'); 353 | 354 | $user_info['username'] = $username; 355 | $user_info['password'] = $password; 356 | // Authenticate LDAP user against password submitted on login 357 | $dn = $user_info['dn']; 358 | $success = @ldap_bind($conn, $dn, $this->ldap_encode($password)); // bind with user credentials 359 | 360 | if (!$success) 361 | { 362 | $this->debug_print('Error binding with supplied password (dn: '.$dn.') ERROR: '.ldap_error($conn)); 363 | } 364 | 365 | $user_info['authenticated'] = $success; 366 | return $user_info; 367 | } 368 | 369 | 370 | // ---------------------- 371 | 372 | 373 | function create_connection($ldap_host, $ldap_port, $ldap_search_user, $ldap_search_password) 374 | { 375 | $this->debug_print('Connecting to LDAP...'); 376 | $conn = ldap_connect($ldap_host, $ldap_port) or 377 | die('Could not connect to host: '.$ldap_host.':'.$ldap_port.'
'."\n"); 378 | $this->debug_print('connect result is '.$conn); 379 | 380 | // Perform bind with search user 381 | if (empty($ldap_search_user)) 382 | { 383 | $this->debug_print('Binding anonymously...'); 384 | $success = ldap_bind($conn); // this is an "anonymous" bind, typically read-only access 385 | } 386 | else 387 | { 388 | $this->debug_print('Binding with user: ['.$ldap_search_user.']-['.$ldap_search_password.'] ...'); 389 | $success = ldap_bind($conn, $this->ldap_encode($ldap_search_user), $this->ldap_encode($ldap_search_password)); // bind with credentials 390 | } 391 | $this->debug_print('Bind result is '.$success); 392 | return $conn; 393 | } 394 | 395 | 396 | // ---------------------- 397 | 398 | 399 | function close_connection($conn) 400 | { 401 | $this->debug_print('Closing connection...'); 402 | ldap_close($conn) or 403 | die('Could not close the LDAP connection
'."\n"); 404 | } 405 | 406 | 407 | // ---------------------- 408 | 409 | 410 | function debug_print($message, $br="
\n") 411 | { 412 | if ($this->debug) 413 | { 414 | if (is_array($message)) 415 | { 416 | print('
');
417 | 				print_r($message);
418 | 				print('
'.$br); 419 | } 420 | else 421 | { 422 | print($message.' '.$br); 423 | } 424 | } 425 | } 426 | 427 | 428 | function ldap_encode($text) 429 | { 430 | return iconv("UTF-8", $this->settings['ldap_character_encode'], $text); 431 | } 432 | 433 | 434 | } 435 | // END CLASS Nce_ldap 436 | 437 | /* End of file ext.nce_ldap.php */ 438 | /* Location: ./system/expressionengine/third_party/nce_ldap/ext.nce_ldap.php */ -------------------------------------------------------------------------------- /EE2/core/expressionengine/third_party/nce_ldap/language/english/lang.nce_ldap.php: -------------------------------------------------------------------------------- 1 | 'Server Address [e.g. ldap://myhost] (comma separate for multiple servers)', 6 | 'ldap_port' => 'Port number [default = 389]', 7 | 'ldap_search_base' => 'Search base', 8 | 'ldap_search_user' => 'LDAP user (leave blank for anonymous binding)', 9 | 'ldap_search_password' => 'LDAP password (leave blank for anonymous binding)', 10 | 'ldap_username_attribute' => 'Attribute in the directory to identify your users', 11 | 'ldap_character_encode' => 'LDAP encoding type', 12 | 'use_ldap_account_creation' => 'Use LDAP for account creation', 13 | 'created_user_group' => 'Group ID to assign newly created users', 14 | 15 | 'admin_email' => 'Address to send system notifications (e.g. when new user regsitered via LDAP)', 16 | 'from_email' => 'System notifications will appear to be from', 17 | 'mail_host' => 'SMTP mail host', 18 | 'mail_message' => 'System notifications sent to EE administrator when new account created', 19 | 20 | 'no_ldap_login_message' => 'Message attached to user session object when LDAP server is down [Use Extension_msg extension to display message]', 21 | 'first_time_login_message' => 'Message attached to user session object on first log in (ie. when preferences have not been set) [Use Extension_msg extension to display message]', 22 | 23 | 'yes_ldap_account_creation' => 'Yes', 24 | 'no_ldap_account_creation' => 'No', 25 | 26 | '' => '' 27 | ); 28 | // end array 29 | 30 | /* End of file lang.nce_ldap.php */ 31 | /* Location: ./system/expressionengine/third_party/nce_ldap/language/english/lang.nce_ldap.php */ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## LDAP Authentication for ExpressionEngine ## 2 | 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). 3 | 4 | Available in both EE1 and EE2 versions. 5 | 6 | ## Installation ## 7 | 8 | Choose EE1 or EE2 (depending on your installation).
9 | Use the structure provided to place the files within your current EE installation.
10 | Enable the extension in your EE control panel. 11 | 12 | ## Support ## 13 | 14 | For more information and support, please use the [issues page](http://github.com/designbyfront/LDAP-Authentication-for-ExpressionEngine/issues) or contact us at info@designbyfront.com 15 | 16 | ## License and Attribution ## 17 | 18 | This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported. 19 | To view a copy of this license, visit [http://creativecommons.org/licenses/by-sa/3.0/](http://creativecommons.org/licenses/by-sa/3.0/) 20 | or send a letter to `Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA` 21 | 22 | This extension extends and modifies the functionality of [NCE LDAP](http://code.google.com/p/ee-ldap-extension/)
23 | Released under: `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` 24 | 25 | **No Warranty**
26 | As this program is licensed free of charge, there is no warranty for the program, to the extent permitted by applicable law. Except when otherwise stated in writing the copyright holders and/or other parties provide the program "as is" without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of the program is with you. should the program prove defective, you assume the cost of all necessary servicing, repair or correction.
27 | In no event unless required by applicable law or agreed to in writing will any copyright holder, or any other party who may modify and/or redistribute the program as permitted above, be liable to you for damages, including any general, special, incidental or consequential damages arising out of the use or inability to use the program (including but not limited to loss of data or data being rendered inaccurate or losses sustained by you or third parties or a failure of the program to operate with any other programs), even if such holder or other party has been advised of the possibility of such damages. 28 | 29 | ## Created by Front ### 30 | 31 | Useful, memorable and satisfying things for the web
32 | We create amazing online experiences that delight users and help our clients grow. 33 | 34 | [Web Design](http://www.designbyfront.com) by Front --------------------------------------------------------------------------------