You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

402 lines
16 KiB
Plaintext

<?php
class ldapHelper extends WireData implements Module, ConfigurableModule
{
protected $ldapSession = null;
protected $host, $port, $defaultLoginDomain, $userDefaultRoles, $protocol, $debugMode, $useV3, $admin, $secret, $ldapSetting, $userdn;
public $message;
public static function getModuleInfo() {
return array(
'title' => __('LDAP Helper'),
'version' => '006',
'author' => 'Kreativmonkey',
'summary' => __('Hendle LDAP Communication for Processwire'),
'singular' => true,
'autoload' => true
);
}
public function ___install() {
if (!function_exists('ldap_connect'))
throw new WireException ('Please make sure that extension php_ldap is loaded.');
}
public function init() {
if (isset ($this->data ['host'])) {
$host = explode(':', str_replace(array(
'ldap://',
'ldaps://'
), array(
'',
''
), $this->data ['host']));
$this->protocol = (empty ($this->data ['useSSL'])) ? 'ldap://' : 'ldaps://';
$this->host = $host [0];
$this->port = empty ($host [1]) ? 389 : $host [1];
}
$this->debugMode = empty ($this->data ['debug']);
if (isset ($this->data ['loginDomain']))
$this->defaultLoginDomain = $this->data ['loginDomain'];
if (isset ($this->data ['userdn']))
$this->userdn = $this->data ['userdn'];
if (isset ($this->data ['admin']))
$this->admin = $this->data ['admin'];
if (isset ($this->data ['secret']))
$this->secret = $this->data ['secret'];
if (isset ($this->data ['useV3']))
$this->useV3 = $this->data ['useV3'];
if (isset ($this->data ['ldapSetting']))
$this->ldapSetting = $this->data ['ldapSetting'];
$this->userDefaultRoles = new WireArray ();
if (isset ($this->data ['userDefaultRoles'])) {
foreach ($this->data ['userDefaultRoles'] as $x) {
$role = $this->roles->get($x);
$this->userDefaultRoles->add($role);
}
}
$this->userDefaultRoles->add($this->roles->getGuestRole());
$this->userDefaultRoles = $this->userDefaultRoles->unique();
$this->pages->addHookBefore("delete", $this, "ldapHelperDeleteUser");
$this->addHookAfter('Modules::saveModuleConfigData', $this, 'hookModuleSave');
$this->session->addHookAfter('login', $this, 'ldapHelperLogin');
$this->addHookBefore("Password::setPassword", $this, 'ldapHelperChangePw');
}
public function ldapHelperRegistradeUser(Array $user) {
$username = $user["username"];
// LDAP user anlegen
$info["objectclass"][0] = "top";
$info["objectclass"][1] = "person";
$info["objectclass"][2] = "organizationalPerson";
$info["objectclass"][3] = "inetorgperson";
$info["cn"] = $user["firstname"];
$info["sn"] = $user["lastname"];
$info["givenName"] = $user["username"];
$info["description"] = "ffmyk";
$password = $this->makeSshaPassword($user["password"]);
// If you have the plain text password instead, you could use:
$info['userPassword'] = $password;
// Connect to LDAP Server
if(!$connect = $this->ldapHelperConnect()) return false;
// bind mit passendem dn für aktulisierenden Zugriff
if(!$r= $this->ldapHelperWrite($connect)) return false;
// Add User to the Database
if(!$r= ldap_add($connect, "uid=$username,$this->userdn", $info)){
$massage = ldap_err2str(ldap_errno($connect));
$this->log->save('ldap_helper', "Create User failed $ldapMassage");
return false;
}
$this->log->save('ldap_helper', "Create User: $username");
// Verbindung schließen
ldap_close($connect);
// Registrierung erfolgreich
return true;
}
public function ldapHelperLogin(HookEvent $event){
if($event->return) return;
$username = $event->arguments[0];
$password = $event->arguments[1];
if(!$con = $this->ldapHelperConnect()) return; // Connection Failed
$user_search = ldap_search($con,"dc=ffmyk,dc=de","(|(uid=$username))");
$user_entry = ldap_first_entry($con, $user_search);
$user_dn = ldap_get_dn($con, $user_entry);
if(@ldap_bind($con, $user_dn, $password)){
$wireUserName = $this->sanitizer->pageName($username);
$user = $this->users->get("name=$wireUserName");
if($user instanceof NullPage){
// Search the LDAP Entry
$first_name = ldap_get_values($con, $user_entry, "cn");
$last_name = ldap_get_values($con, $user_entry, "sn");
// Add ldap user to ProcessWire
$new_user = new User();
$new_user->of(false);
$new_user->name = $wireUserName;
$new_user->firstname = $first_name;
$new_user->lastname = $last_name;
$new_user->pass = $password;
$new_user->addRole("user");
$new_user->admin_theme = "AdminThemeReno";
$new_user->save();
$new_user->of(true);
} else {
// Set new Password
$user->of(false);
$user->pass = $password;
if($user->isChanged('pass')){
$user->save();
$this->message($this->_('Password changed success.'));
}
$user->of(true);
}
$user = $this->session->login($wireUserName, $password);
$event->return = $user;
$this->message($this->_('Logged in via LDAP.'));
return;
} else {
$this->message("Bitte Registriere dich.");
}
}
/**
* Change the Password for the LDAP User
* $username = Ldap uid
* $newPassword = the new Password to set for the User
* $newPasswordCnt = double check the new Password
*
* return
* string
*/
public function ldapHelperChangePw($username, $newPassword, $newPasswordCnt) {
$user = wire('users')->get("name=$username");
$dn = $this->userdn;
if($user instanceof NullPage) return "User dosn't exist.";
if(empty($newPassword) | empty($newPasswordCnt)) {
$this->message = "Not enouth values.";
return false;
}
// check if new Password match
if($newPassword != $newPasswordCnt) {
$this->message = "Password doesn't match.";
return false;
}
// Connect to LDAP Server
if(!$con = $this->ldapHelperConnect()) {
$this->message = "Verbindungsprobleme, bitte versuche es später noch einmal.";
return false;
}
// Search for the user in the ldap Directory
$user_search = ldap_search($con,$dn,"(|(uid=$username))"); // Ressource ID:
$user_get = ldap_get_entries($con,$user_search); // array with all entries
$user_entry = ldap_first_entry($con, $user_search); // array with ressource
$user_dn = ldap_get_dn($con, $user_entry); // uid=$userid,ou=People,dc=ffmyk,dc=de
$user_id = $user_get[0]["uid"][0]; // the user ID
$user_givenName = $user_get[0]["givenname"][0]; // Given name from user
$user_search_array = array("*", "ou", "uid");
$user_search_filter = "(|(uid=$user_id))";
$user_search_opt = ldap_search($con, $user_dn, $user_search_filter, $user_search_array); // array ressource
$user_get_opt = ldap_get_entries($con,$user_search_opt); // array with the entrie
$encoded_password = $this->makeSshaPassword($newPassword);
$entry = array();
$entry["userPassword"] = "$encoded_password";
// bind mit passendem dn für aktulisierenden Zugriff
if(!$r= $this->ldapHelperWrite($con)) {
$this->message = "Verbindungsprobleme.";
return false;
}
if(ldap_modify($con,$user_dn,$entry) === false){
$error = ldap_error($con);
$errno = ldap_errno($con);
$this->log->save('ldap_helper', "$username - Your password cannot be change, please contact the administrator.");
$this->log->save('ldap_helper', "$errno - $error");
$this->message = "Dein Password konnte nicht gespeichert werden. Bitte kontaktiere den Administrator";
return false;
} else {
$this->message = "Dein Password wurde geändert, du kannst dich nun mit dem neuen Password einloggen.";
return true;
}
}
public function ldapHelperDeleteUser(HookEvent $event) {
$page = $event->arguments("page");
if (!$page->id && !$page->template->name === "user") return; // Return if User is not deleted
$username = $page->name;
// bind mit passendem dn für aktualisierenden Zugriff
$connect = $this->ldapHelperConnect();
$r= $this->ldapHelperWrite($connect);
$user_search = ldap_search($connect,"dc=ffmyk,dc=de","(|(uid=$user))");
$user_entry = ldap_first_entry($connect, $user_search);
// Delete User from LDAP
$dn= ldap_get_dn($connect, $user_entry);
if(ldap_delete( $connect , $dn )){
$this->message("Delete LDAP User: $username");
$this->log->save('ldap_helper', "Delete User: $username");
} else {
$errno = ldap_errno($connect); // Error code
$error = ldap_error($connect); // Error text
$this->message("Delete LDAP User failed $error ($errno)");
$this->log->save('ldap_helper', "Delete User failed $error ($errno)");
}
ldap_close($connect);
}
protected function makeSshaPassword($password) {
mt_srand((double)microtime()*1000000);
$salt = pack("CCCC", mt_rand(), mt_rand(), mt_rand(), mt_rand());
$hash = "{SSHA}" . base64_encode(pack("H*", sha1($password . $salt)) . $salt);
return $hash;
}
protected function ldapHelperConnect() {
if ($this->debugMode) ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7); // LDAP DebugMode
if(!$connection = ldap_connect($this->host, $this->port)) return $this->log->save('LDAP', printf(__("Failed to connect LDAP %d pages."), ldap_err2str(ldap_errno($connection)))); // Annahme: der LDAP Server befindet sich auf diesem Host
if ($this->useV3) ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3); // Set LDAP_PROTOCOL_VERSION
return $connection;
}
protected function ldapHelperWrite($ds) {
if(empty($ds)) return;
return ldap_bind($ds,"$this->admin", "$this->secret");
}
public function validateConfiguration() {
$connection = $this->ldapHelperConnect();
if (!$connection) {
return;
}
$this->message($this->_('Successfully connected to LDAP server.'));
$bind = $this->ldapHelperWrite($connection);
$ldapMessage = ldap_err2str(ldap_errno($connection));
$this->message("Bind $ldapMessage");
}
public function hookModuleSave(HookEvent $event) {
$className = $event->arguments [0];
if ($className != get_class($this)) return;
$this->validateConfiguration();
}
static public function getModuleConfigInputfields(array $data) {
$inputfields = new InputfieldWrapper ();
$hostField = wire('modules')->get('InputfieldText');
$hostField->name = 'host';
$hostField->columnWidth = 80;
$hostField->label = __('LDAP Server');
$hostField->required = 1;
if (isset ($data ['host']))
$hostField->value = $data ['host'];
$hostField->description = __('The hostname of your LDAP server. This can be either an ip address or a domain name. Supply a custom port (different than 389) separated with a colon. Examples: 10.0.0.1, controller.domain.com, controller.domain.com:388');
$inputfields->add($hostField);
$useSSLField = wire('modules')->get('InputfieldCheckbox');
$useSSLField->name = 'useSSL';
$useSSLField->columnWidth = 20;
$useSSLField->label = __('Use SSL?');
$useSSLField->description = __('Connects to the LDAP Server via SSL.');
if (isset ($data ['useSSL']) && $data ['useSSL'] == 1)
$useSSLField->checked = 1;
$inputfields->add($useSSLField);
$defaultLoginDomainField = wire('modules')->get('InputfieldText');
$defaultLoginDomainField->name = 'loginDomain';
$defaultLoginDomainField->label = __('Default Login Domain');
$defaultLoginDomainField->columnWidth = 40;
$defaultLoginDomainField->required = 1;
if (isset ($data ['loginDomain']))
$defaultLoginDomainField->value = $data ['loginDomain'];
$defaultLoginDomainField->description = __('This is the domain name used by default if the user does not supply a domain name. It will be added to the username, e.g. username@domainname.com');
$inputfields->add($defaultLoginDomainField);
$adminLoginField = wire('modules')->get('InputfieldText');
$adminLoginField->name = 'userdn';
$adminLoginField->columnWidth = 40;
$adminLoginField->label = __('LDAP User DN');
$adminLoginField->required = 1;
if (isset ($data ['userdn']))
$adminLoginField->value = $data ['userdn'];
$adminLoginField->description = __('The DN for the user. Example: ou=Person,dc=domain,dc=com');
$inputfields->add($adminLoginField);
$useV3Field = wire('modules')->get('InputfieldCheckbox');
$useV3Field->name = 'useV3';
$useV3Field->columnWidth = 20;
$useV3Field->label = __('Use Protocol V3?');
$useV3Field->description = __('Use LDAP Protocol V3.');
if (isset ($data ['useV3']) && $data ['useV3'] == 1)
$useV3Field->checked = 1;
$inputfields->add($useV3Field);
$adminLoginField = wire('modules')->get('InputfieldText');
$adminLoginField->name = 'admin';
$adminLoginField->columnWidth = 50;
$adminLoginField->label = __('LDAP Admin DN');
$adminLoginField->required = 1;
if (isset ($data ['admin']))
$adminLoginField->value = $data ['admin'];
$adminLoginField->description = __('An LDAP account with access to add/edit/delet users. Example: cn=accountmanager,dc=domain,dc=com');
$inputfields->add($adminLoginField);
$secretField = wire('modules')->get('InputfieldText');
$secretField->attr ('type','password');
$secretField->name = 'secret';
$secretField->columnWidth = 50;
$secretField->label = __('LDAP Admin Secret');
$secretField->description = __('Needet to use with LDAP Admin to add/edit/delete users.');
if (isset ($data ['secret']))
$secretField->value = $data ['secret'];
$inputfields->add($secretField);
$ldapSettingField = wire('modules')->get('InputfieldTextarea');
$ldapSettingField->name = 'ldapSetting';
$ldapSettingField->columnWidth = 50;
$ldapSettingField->label = __('Entry Setup');
$ldapSettingField->description = __('The Entry Setup for LDAP Users. Includes objectClass, uid, cn... one per Line. Set Variables @variable@.');
if (isset ($data ['ldapSetting']))
$ldapSettingField->value = $data ['ldapSetting'];
$inputfields->add($ldapSettingField);
$userDefaultRolesField = wire('modules')->get('InputfieldPageListSelectMultiple');
$userDefaultRolesField->name = 'userDefaultRoles';
$userDefaultRolesField->label = __('Default Roles for new Users');
$userDefaultRolesField->description = __('These user roles will be applied to all new LDAP users. Please note that the guest role is applied automatically.');
$userDefaultRolesField->parent_id = wire('roles')->getGuestRole()->parent_id;
if (isset ($data ['userDefaultRoles']))
$userDefaultRolesField->value = $data ['userDefaultRoles'];
$inputfields->add($userDefaultRolesField);
$debugField = wire('modules')->get('InputfieldCheckbox');
$debugField->name = 'debug';
$debugField->collapsed = Inputfield::collapsedYes;
$debugField->label = __('Debug Mode');
$debugField->description = __('Turns on the debug mode so you can see the output of PHP\'s ldap module in the apache log.');
if (isset ($data ['debug']) && $data ['debug'] == 1)
$debugField->checked = 1;
$inputfields->add($debugField);
return $inputfields;
}
}