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
402 lines
16 KiB
Plaintext
7 years ago
|
<?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;
|
||
|
}
|
||
|
}
|