_authenticated = false;
// Load options from WordPress-DB.
$this->_load_options();
// Connect to Active Directory
$this->_adldap = new adLDAP(array(
"account_suffix" => $this->_account_suffix,
"base_dn" => $this->_base_dn,
"domain_controllers" => explode(';', $this->_domain_controllers),
"ad_username" => $this->_bind_user, // AD Bind User
"ad_password" => $this->_bind_pwd, // password
"ad_port" => $this->_port, // AD port
"use_tls" => $this->_use_tls // secure?
));
// Check for maximum login attempts
if ($this->_max_login_attempts > 0) {
$failed_logins = $this->_get_failed_logins_within_block_time($username);
if ($failed_logins >= $this->_max_login_attempts) {
$this->_authenticated = false;
// e-mail notfications if user is blocked
if ($this->_user_notification) {
$this->_notify_user($username);
}
if ($this->_admin_notification) {
$this->_notify_admin($username);
}
// Show the blocking page to the user
$this->_display_blocking_page($username);
die(); // important !
}
}
// This is where the action is.
if ( $this->_adldap->authenticate($username, $password) )
{
$this->_authenticated = true;
}
if ( $this->_authenticated == false )
{
$this->_authenticated = false;
$this->_store_failed_login($username);
return false;
}
// Cleanup old database entries
$this->_cleanup_failed_logins($username);
// Check the authorization
if ($this->_authorize_by_group) {
if ($this->_check_authorization_by_group($username)) {
$this->_authenticated = true;
} else {
$this->_authenticated = false;
return false;
}
}
$ad_username = $username;
// should the account suffix be used for the new username?
if ($this->_append_suffix_to_new_users) {
$username .= $this->_account_suffix;
}
// Create new users automatically, if configured
$user = get_userdatabylogin($username);
if (! $user OR ($user->user_login != $username)) {
$user_role = $this->_get_user_role_equiv($ad_username);
if ($this->_auto_create_user || $user_role != '' ) {
// create user
$userinfo = $this->_adldap->user_info($ad_username, array('sn', 'givenname', 'mail', 'displayName', 'description', 'cn'));
$userinfo = $userinfo[0];
$email = $userinfo['mail'][0];
$first_name = $userinfo['givenname'][0];
$last_name = $userinfo['sn'][0];
$display_name = $this->_get_display_name_from_AD($username, $userinfo);
$this->_create_user($ad_username, $email, $first_name, $last_name, $display_name, $user_role);
} else {
// Bail out to avoid showing the login form
return new WP_Error('invalid_username', __('ERROR: This user exists in Active Directory, but has not been granted access to this installation of WordPress.'));
}
} else {
// update known users if configured
if ($this->_auto_create_user AND $this->_auto_update_user) {
// Update users role
$user_role = $this->_get_user_role_equiv($ad_username);
$userinfo = $this->_adldap->user_info($ad_username, array('sn', 'givenname', 'mail', 'displayName', 'description', 'cn'));
$userinfo = $userinfo[0];
//TODO: Implement to choose display_name
/*echo '
';
print_r($userinfo);
echo '
';
die();*/
$email = $userinfo['mail'][0];
$first_name = $userinfo['givenname'][0];
$last_name = $userinfo['sn'][0];
$common_name = $userinfo['cn'][0];
$display_name = $this->_get_display_name_from_AD($username, $userinfo);
$this->_update_user($ad_username, $email, $first_name, $last_name, $display_name, $user_role);
}
}
}
/*
* Skip the password check, since we've externally authenticated.
*/
public function override_password_check($check, $password, $hash, $user_id) {
if ( $this->_authenticated == true )
{
return true;
}
else
{
return $check;
}
}
/*
* Generate a password for the user. This plugin does not
* require the user to enter this value, but we want to set it
* to something nonobvious.
*/
public function generate_password($username, $password1, $password2) {
$password1 = $password2 = $this->_get_password();
}
/*
* Used to disable certain display elements, e.g. password
* fields on profile screen.
*/
public function disable_password_fields($show_password_fields) {
return false;
}
/*
* Used to disable certain login functions, e.g. retrieving a
* user's password.
*/
public function disable_function() {
die('Disabled');
}
/**
* Adding the needed table to database and store the db version in the
* options table on plugin activation.
*/
public static function activate() {
global $wpdb;
//$table_name = $wpdb->prefix . ADIntegrationPlugin::$table_name;
$table_name = $wpdb->prefix . ADIntegrationPlugin::TABLE_NAME;
if (($wpdb->get_var("show tables like '$table_name'") != $table_name) OR (get_option('AD_Integration_db_version') != ADIntegrationPlugin::DB_VERSION)) {
$sql = 'CREATE TABLE ' . $table_name . ' (
id bigint(20) NOT NULL AUTO_INCREMENT,
user_login varchar(60),
failed_login_time bigint(11),
UNIQUE KEY id (id)
);';
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// store db version in the options
add_option('AD_Integration_db_version', ADIntegrationPlugin::DB_VERSION, 'Version of the table structure');
}
}
/**
* Delete the table from database and delete the db version from the
* options table on plugin deactivation.
*/
public static function deactivate() {
global $wpdb;
//$table_name = $wpdb->prefix . ADIntegrationPlugin::$table_name;
$table_name = $wpdb->prefix . ADIntegrationPlugin::TABLE_NAME;
// drop table
$wpdb->query('DROP TABLE IF EXISTS '.$table_name);
// delete option
delete_option('AD_Integration_db_version');
}
/**
* removes the plugin options from options table.
*/
public static function uninstall($echo=false) {
$options = array(
'AD_Integration_account_suffix','AD_Integration_auto_create_user','AD_Integration_auto_update_user',
'AD_Integration_append_suffix_to_new_users',
'AD_Integration_domain_controllers',
'AD_Integration_base_dn',
'AD_Integration_role_equivalent_groups',
'AD_Integration_default_email_domain',
'AD_Integration_port',
'AD_Integration_bind_user',
'AD_Integration_bind_pwd',
'AD_Integration_use_tls',
'AD_Integration_authorize_by_group',
'AD_Integration_authorization_group',
'AD_Integration_max_login_attempts',
'AD_Integration_block_time',
'AD_Integration_user_notification',
'AD_Integration_admin_notification',
'AD_Integration_admin_email',
'AD_Integration_display_name'
);
foreach($options as $option) {
$delete_setting = delete_option($option);
if ($echo) {
if($delete_setting) {
echo '';
printf(__('Setting Key \'%s\' has been deleted.', 'MiniMetaWidget'), "{$setting}");
echo '
';
} else {
echo '';
printf(__('Error deleting Setting Key \'%s\'.', 'MiniMetaWidget'), "{$setting}");
echo '
';
}
}
}
}
/**
* Shows the contexual help on the options screen.
*
* @param $help
* @param $screen
* @return string help message
*/
function contextual_help ($help, $screen) {
if ($screen == 'settings_page_' . ADINTEGRATION_FOLDER . '/ad-integration') {
$help .= '' . __('Active Directory Integration Help','ad-integration') . '
';
}
return $help;
}
/*************************************************************
* Functions
*************************************************************/
/**
* Loads the options from WordPress-DB
*/
protected function _load_options() {
$this->_auto_create_user = (bool)get_option('AD_Integration_auto_create_user');
$this->_auto_update_user = (bool)get_option('AD_Integration_auto_update_user');
$this->_account_suffix = get_option('AD_Integration_account_suffix');
$this->_append_suffix_to_new_users = get_option('AD_Integration_append_suffix_to_new_users');
$this->_domain_controllers = get_option('AD_Integration_domain_controllers');
$this->_base_dn = get_option('AD_Integration_base_dn');
$this->_bind_user = get_option('AD_Integration_bind_user');
$this->_bind_pwd = get_option('AD_Integration_bind_pwd');
$this->_port = get_option('AD_Integration_port');
$this->_use_tls = get_option('AD_Integration_use_tls');
$this->_default_email_domain = get_option('AD_Integration_default_email_domain');
$this->_authorize_by_group = (bool)get_option('AD_Integration_authorize_by_group');
$this->_authorization_group = get_option('AD_Integration_authorization_group');
$this->_role_equivalent_groups = get_option('AD_Integration_role_equivalent_groups');
$this->_max_login_attempts = (int)get_option('AD_Integration_max_login_attempts');
$this->_block_time = (int)get_option('AD_Integration_block_time');
$this->_user_notification = (bool)get_option('AD_Integration_user_notification');
$this->_admin_notification = (bool)get_option('AD_Integration_admin_notification');
$this->_admin_email = get_option('AD_Integration_admin_email');
$this->_display_name = get_option('AD_Integration_display_name');
}
/**
* Determine the display_name to be stored in WP database.
* @param $username the username used to login
* @param $userinfo the array with data returned from AD
* @return string display_name
*/
protected function _get_display_name_from_AD($username, $userinfo) {
if (($this->_display_name == '') OR ($this->_display_name == 'sAMAccountName')) {
return $username;
}
$display_name = $userinfo[$this->_display_name][0];
if ($display_name == '') {
return $username;
} else {
return $display_name;
}
}
/**
* Stores the username and the current time in the db.
*
* @param $username
* @return unknown_type
*/
protected function _store_failed_login($username) {
global $wpdb;
//$table_name = $wpdb->prefix . $this->table_name;
$table_name = $wpdb->prefix . ADIntegrationPlugin::TABLE_NAME;
$sql = "INSERT INTO $table_name (user_login, failed_login_time) VALUES ('" . $wpdb->escape($username)."'," . time() . ")";
$result = $wpdb->query($sql);
}
/**
* Determines the number of failed login attempts of specific user within a specific time from now to the past.
*
* @param $username
* @param $seconds number of seconds
* @return number of failed login attempts
*/
protected function _get_failed_logins_within_block_time($username) {
global $wpdb;
//$table_name = $wpdb->prefix . $this->table_name;
$table_name = $wpdb->prefix . ADIntegrationPlugin::TABLE_NAME;
$time = time() - (int)$this->_block_time;
$sql = "SELECT count(*) AS count from $table_name WHERE user_login = '".$wpdb->escape($username)."' AND failed_login_time >= $time";
return $wpdb->get_var($sql);
}
/**
* Deletes entries from store where the time of failed logins is more than the specified block time ago.
* Deletes also all entries of a user, if its username is given .
*
* @param $username
* @return
*/
protected function _cleanup_failed_logins($username = NULL) {
global $wpdb;
//$table_name = $wpdb->prefix . $this->table_name;
$table_name = $wpdb->prefix . ADIntegrationPlugin::TABLE_NAME;
$time = time() - $this->_block_time;
$sql = "DELETE FROM $table_name WHERE failed_login_time < $time";
if ($username != NULL) {
$sql .= " OR user_login = '".$wpdb->escape($username)."'";
}
$results = $wpdb->query($sql);
}
/**
* Get the rest of the time an account is blocked.
*
* @param $username
* @return int seconds the account is blocked, or 0
*/
protected function _get_rest_of_blocking_time($username) {
global $wpdb;
//$table_name = $wpdb->prefix . $this->_table_name;
$table_name = $wpdb->prefix . ADIntegrationPlugin::TABLE_NAME;
$sql = "SELECT max(failed_login_time) FROM $table_name WHERE user_login = '".$wpdb->escape($username)."'";
$max_time = $wpdb->get_var($sql);
if ($max_time == NULL ) {
return 0;
}
return ($max_time + $this->_block_time) - time();
}
/**
* Generate a random password.
*
* @param int $length Length of the password
* @return password as string
*/
protected function _get_password($length = 10) {
return substr(md5(uniqid(microtime())), 0, $length);
}
/*
* Create a new WordPress account for the specified username.
*/
protected function _create_user($username, $email, $first_name, $last_name, $display_name = '', $role = '') {
$password = $this->_get_password();
if ( $email == '' )
{
$email = $username . '@' . $this->_default_email_domain;
}
// append account suffix to new users?
if ($this->_append_suffix_to_new_users) {
$username .= $this->_account_suffix;
}
require_once(ABSPATH . WPINC . DIRECTORY_SEPARATOR . 'registration.php');
wp_create_user($username, $password, $email);
$user_id = username_exists($username);
if ( !$user_id ) {
die("Error creating user!");
} else {
update_usermeta($user_id, 'first_name', $first_name);
update_usermeta($user_id, 'last_name', $last_name);
// set display_name
if ($display_name != '') {
wp_update_user(array('ID' => $user_id, 'display_name' => $display_name));
}
// set role
if ( $role != '' )
{
wp_update_user(array("ID" => $user_id, "role" => $role));
}
}
}
/**
* Updates a specific Wordpress user account
*/
protected function _update_user($username, $email, $first_name, $last_name, $display_name='', $role = '') {
if ( $email == '' )
{
$email = $username . '@' . $this->_default_email_domain;
}
if ($this->_append_suffix_to_new_users) {
$username .= $this->_account_suffix;
}
require_once(ABSPATH . WPINC . DIRECTORY_SEPARATOR . 'registration.php');
$user_id = username_exists($username);
if ( !$user_id ) {
die('Error updating user!');
} else {
update_usermeta($user_id, 'first_name', $first_name);
update_usermeta($user_id, 'last_name', $last_name);
// set display_name
if ($display_name != '') {
wp_update_user(array('ID' => $user_id, 'display_name' => $display_name));
}
// set role
if ( $role != '' )
{
wp_update_user(array('ID' => $user_id, 'role' => $role));
}
}
}
/**
* Checks if the user is member of the group allowed to login
*
* @param $username
* @return boolean
*/
protected function _check_authorization_by_group($username) {
if ($this->_authorize_by_group) {
return $this->_adldap->user_ingroup($username, $this->_authorization_group, true);
} else {
return true;
}
}
/**
* Get the first matching role from the list of role equivalent groups the user belongs to.
*
* @param $ad_username
* @return string matching role
*/
protected function _get_user_role_equiv($ad_username) {
$role_equiv_groups = explode(';', $this->_role_equivalent_groups);
$user_role = '';
foreach ($role_equiv_groups as $whatever => $role_group)
{
$role_group = explode('=', $role_group);
if ( count($role_group) != 2 )
{
next;
}
$ad_group = $role_group[0];
$corresponding_role = $role_group[1];
if ( $this->_adldap->user_ingroup($ad_username, $ad_group, true ) )
{
$user_role = $corresponding_role;
break;
}
}
return $user_role;
}
/**
* Send an email to the user who's account is blocked
*
* @param $username string
* @return unknown_type
*/
protected function _notify_user($username)
{
// if auto creation is enabled look for the user in AD
$auto_create_user = (bool)get_option('AD_Integration_auto_create_user');
if ($this->_auto_create_user) {
$userinfo = $this->_adldap->user_info($username, array("sn", "givenname", "mail"));
if ($userinfo) {
$userinfo = $userinfo[0];
$email = $userinfo['mail'][0];
$first_name = $userinfo['givenname'][0];
$last_name = $userinfo['sn'][0];
} else {
return false;
}
} else {
// auto creation is disabled, so look for the user in local database
require_once(ABSPATH . WPINC . DIRECTORY_SEPARATOR . 'registration.php');
$user_id = username_exists($username);
if ($user_id) {
$user_info = get_userdata($user_id);
$last_name = $user_info->last_name;
$first_name = $user_info->first_name;
$email = $user_info->user_email;
} else {
return false;
}
}
// do we have a correct email address?
if (is_email($email)) {
$blog_url = get_bloginfo('url');
$blog_name = get_bloginfo('name');
$blog_domain = preg_replace ('/^(http:\/\/)(.+)\/.*$/i','$2', $blog_url);
$subject = '['.$blog_name.'] '.__('Account blocked','ad-integration');
$body = sprintf(__('Someone tried to login to %s (%s) with your username (%s) - but in vain. For security reasons your account is now blocked for %d seconds.','ad-integration'), $blog_name, $blog_url, $username, $this->_block_time);
$body .= "\n\r";
$body .= __('THIS IS A SYSTEM GENERATED E-MAIL, PLEASE DO NOT RESPOND TO THE E-MAIL ADDRESS SPECIFIED ABOVE.','ad-integration');
$header = 'From: "WordPress" \r\n";
return wp_mail($email, $subject, $body, $header);
} else {
return false;
}
}
/**
* Notify administrator(s) by e-mail if an account is blocked
*
* @param $username username of the blocked account
* @return boolean false if no e-mail is sent, true on success
*/
protected function _notify_admin($username)
{
$arrEmail = array(); // list of recipients
if ($this->_admin_notification) {
$email = $this->_admin_email;
// Should we use Blog-Administrator's e-mail
if (trim($email) == '') {
// Is this an e-mail address?
if (is_email($email)) {
$arrEmail[0] = trim(get_bloginfo('admin_email '));
}
} else {
// Using own list of notification recipients
$arrEmail = explode(";",$email);
// remove wrong e-mail addresses from array
for ($x=0; $x < count($arrEmail); $x++) {
$arrEmail[$x] = trim($arrEmail[$x]); // remove possible whitespaces
if (!is_email($arrEmail[$x])) {
unset($arrEmail[$x]);
}
}
}
// Do we have valid e-mail addresses?
if (count($arrEmail) > 0) {
if ($this->_auto_create_user) {
// auto creation is enabled, so look for the user in AD
$userinfo = $this->_adldap->user_info($username, array("sn", "givenname", "mail"));
if ($userinfo) {
$userinfo = $userinfo[0];
$first_name = $userinfo['givenname'][0];
$last_name = $userinfo['sn'][0];
} else {
return false;
}
} else {
// auto creation is disabled, so look for the user in local database
require_once(ABSPATH . WPINC . DIRECTORY_SEPARATOR . 'registration.php');
$user_id = username_exists($username);
if ($user_id) {
$user_info = get_userdata($user_id);
$last_name = $user_info->last_name;
$first_name = $user_info->first_name;
} else {
return false;
}
}
$blog_url = get_bloginfo('url');
$blog_name = get_bloginfo('name');
$blog_domain = preg_replace ('/^(http:\/\/)(.+)\/.*$/i','$2', $blog_url);
$subject = '['.$blog_name.'] '.__('Account blocked','ad-integration');
$body = sprintf(__('Someone tried to login to %s (%s) with the username "%s" (%s %s) - but in vain. For security reasons this account is now blocked for %d seconds.','ad-integration'), $blog_name, $blog_url, $username, $first_name, $last_name, $this->_block_time);
$body .= "\n\r";
$body .= sprintf(__('The login attempt was made from IP-Address: %s','ad-integration'), $_SERVER['REMOTE_ADDR']);
$body .= "\n\r";
$body .= __('THIS IS A SYSTEM GENERATED E-MAIL, PLEASE DO NOT RESPOND TO THE E-MAIL ADDRESS SPECIFIED ABOVE.','ad-integration');
$header = 'From: "WordPress" \r\n";
// send e-mails
$blnSuccess = true;
foreach($arrEmail AS $email) {
$blnSuccess = ($blnSuccess AND wp_mail($email, $subject, $body, $header));
}
return $blnSuccess;
} else {
return false;
}
} else {
return false;
}
return true;
}
/**
* Show a blocking page for blocked accounts.
*
* @param $username
*/
protected function _display_blocking_page($username) {
$seconds = $this->_get_rest_of_blocking_time($username);
?>
>
›
_load_options();
?>