diff --git a/authentication/ldap/controller.php b/authentication/ldap/controller.php new file mode 100644 index 0000000000000000000000000000000000000000..d01b105b5e88ce3f6e007b87755f01a38b2df498 --- /dev/null +++ b/authentication/ldap/controller.php @@ -0,0 +1,147 @@ +<?php +namespace Concrete\Package\LdapLogin\Authentication\Ldap; + +use Concrete\Core\Authentication\AuthenticationTypeController; +use User; +use UserInfo; +use View; +use Config; +use Loader; +use Exception; + + +class Controller extends AuthenticationTypeController { + + const YUBIKEY_VERIFY_URL = "http://api.yubico.com/wsapi/2.0/verify"; + + public function getHandle() { + return 'ldap'; + } + + public function view() { + + } + + public function edit() + { + $this->set('form', \Loader::helper('form')); + $this->set('ldapServerURI', \Config::get('auth.ldap.ldapServerURI', '')); + $this->set('ldapBaseDN', \Config::get('auth.ldap.ldapBaseDN', '')); + $this->set('ldapBindDN', \Config::get('auth.ldap.ldapBindDN', '')); + $this->set('ldapBindPassword', \Config::get('auth.ldap.ldapBindPassword', '')); + $this->set('ldapSearchFilter', \Config::get('auth.ldap.ldapSearchFilter', '')); + $this->set('yubikeyEnabled',\Config::get('auth.ldap.yubikeyEnabled', false)); + $this->set('yubikeyClientID',\Config::get('auth.ldap.yubikeyClientID', '')); + $this->set('yubikeySecretKey',\Config::get('auth.ldap.yubikeySecretKey', '')); + $this->set('yubikeyServerURI',\Config::get('auth.ldap.yubikeyServerURI', '')); + $this->set('yubikeyAllowEmptyKey',\Config::get('auth.ldap.yubikeyAllowEmptyKey', false)); + + } + + public function saveAuthenticationType($args) + { + \Config::save('auth.ldap.ldapServerURI',$args['ldapServerURI']); + \Config::save('auth.ldap.ldapBaseDN',$args['ldapBaseDN']); + \Config::save('auth.ldap.ldapBindDN',$args['ldapBindDN']); + \Config::save('auth.ldap.ldapBindPassword',$args['ldapBindPassword']); + \Config::save('auth.ldap.ldapSearchFilter',$args['ldapSearchFilter']); + \Config::save('auth.ldap.yubikeyEnabled',$args['yubikeyEnabled']); + \Config::save('auth.ldap.yubikeyClientID',$args['yubikeyClientID']); + \Config::save('auth.ldap.yubikeySecretKey',$args['yubikeySecretKey']); + \Config::save('auth.ldap.yubikeyServerURI',$args['yubikeyServerURI']); + \Config::save('auth.ldap.yubikeyAllowEmptyKey',$args['yubikeyAllowEmptyKey']); + } + + public function getAuthenticationTypeIconHTML() { + return ""; + } + + private function __connect() { + if (!is_object($this->ldap_conn)) { + $this->ldap_conn = ldap_connect(\Config::get('auth.ldap.ldapServerURI','')) + or die(t('Connection to LDAP Server failed.')); + ldap_set_option($this->ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3); + $bindDN = \Config::get('auth.ldap.ldapBindDN', ''); + $bindPW = \Config::get('auth.ldap.ldapBindPassword', ''); + if ($bindDN) { + $this->ldap_bind = ldap_bind($this->ldap_conn,$bindDN,$bindPW); + } else { + $this->ldap_bind = ldap_bind($this->ldap_conn); + } + if (!$this->ldap_bind) { + throw new Exception(t("Binding with LDAP Server failed.")); + } + } + } + + + public function authenticate() { + $post = $this->post(); + if (!isset($post['uName']) || !isset($post['uPassword'])) { + throw new Exception(t('Please provide both username and password.')); + } + $uName = $post['uName']; + $uPassword = $post['uPassword']; + $this->__connect(); + $search_result = ldap_search($this->ldap_conn,\Config::get('auth.ldap.ldapBaseDN', ''), + "(uid=$uName)"); + if (ldap_count_entries($this->ldap_conn,$search_result)!=1) { + throw new \Exception(t('Invalid username or password.')); + } + $entry = ldap_first_entry($this->ldap_conn,$search_result); + + $user_bind = ldap_bind($this->ldap_conn,ldap_get_dn($this->ldap_conn,$entry),$uPassword); + if (!$user_bind) { + throw new \Exception(t('Invalid username or password.')); + } + $userInfo = UserInfo::getByUserName($uName); + if (!is_object($userInfo)) { + throw new \Exception(t('Invalid username or password.')); + } + + + $user = User::loginByUserID($userInfo->uID); + if (!is_object($user) || !($user instanceof User) || $user->isError()) { + switch ($user->getError()) { + case USER_SESSION_EXPIRED: + throw new \Exception(t('Your session has expired. Please sign in again.')); + break; + case USER_NON_VALIDATED: + throw new \Exception(t( + 'This account has not yet been validated. Please check the email associated with this account and follow the link it contains.')); + break; + case USER_INVALID: + if (Config::get('concrete.user.registration.email_registration')) { + throw new \Exception(t('Invalid email address or password.')); + } else { + throw new \Exception(t('Invalid username or password.')); + } + break; + case USER_INACTIVE: + throw new \Exception(t('This user is inactive. Please contact us regarding this account.')); + break; + } + } + if ($post['uMaintainLogin']) { + $user->setAuthTypeCookie('concrete'); + } + return $user; + } + + public function deauthenticate(User $u) { + + } + + public function isAuthenticated(User $u) { + + } + + public function buildHash(User $u) { + return ""; + } + + public function verifyHash(User $u, $hash) { + return false; + } +} +?> diff --git a/authentication/ldap/form.php b/authentication/ldap/form.php new file mode 100644 index 0000000000000000000000000000000000000000..73470afa3700851f2957f0f782c285324c3d0b79 --- /dev/null +++ b/authentication/ldap/form.php @@ -0,0 +1,44 @@ +<?php +defined('C5_EXECUTE') or die('Access denied.'); +$form = Loader::helper('form'); +?> + +<form method='post' + action='<?= View::url('/login', 'authenticate', $this->getAuthenticationTypeHandle()) ?>'> + <div class="form-group concrete-login"> + <span><?= t('Sign in with a ldap account.') ?> </span> + <hr> + </div> + <div class="form-group"> + <input name="uName" class="form-control col-sm-12" + placeholder="<?= Config::get('concrete.user.registration.email_registration') ? t('Email Address') : t('Username')?>" /> + </div> + + <div class="form-group"> + <label> </label> + <input name="uPassword" class="form-control" type="password" + placeholder="<?=t('Password')?>" /> + </div> + + <?php + if (isset($locales) && is_array($locales) && count($locales) > 0) { + ?> + <div class="form-group"> + <label for="USER_LOCALE" class="control-label"><?= t('Language') ?></label> + <?= $form->select('USER_LOCALE', $locales) ?> + </div> + <?php + } + ?> + + <div class="form-group"> + <button class="btn btn-primary"><?= t('Log in') ?></button> + <a href="<?= View::url('/login', 'concrete', 'forgot_password') ?>" class="btn pull-right"><?= t('Forgot Password') ?></a> + </div> + + <script type="text/javascript"> + document.querySelector('input[name=uName]').focus(); + </script> + + <?php Loader::helper('validation/token')->output('login_' . $this->getAuthenticationTypeHandle()); ?> +</form> diff --git a/authentication/ldap/type_form.php b/authentication/ldap/type_form.php new file mode 100644 index 0000000000000000000000000000000000000000..75ac8fe4c244afb993d64dbe0f72dc667ff92498 --- /dev/null +++ b/authentication/ldap/type_form.php @@ -0,0 +1,61 @@ +<?php defined('C5_EXECUTE') or die('Access denied.'); ?> +<fieldset> + <legend><?= t("LDAP Server Configuration")?></legend> + <div class='form-group'> + <?= $form->label('ldapServerURI', t('LDAP Server URI')) ?> + <?= $form->text('ldapServerURI', $ldapServerURI) ?> + </div> + <div class='form-group'> + <?= $form->label('ldapBaseDN', t('LDAP Base DN')) ?> + <?= $form->text('ldapBaseDN', $ldapBaseDN) ?> + </div> + <div class='form-group'> + <?= $form->label('ldapBindDN', t('LDAP Bind DN')) ?> + <?= $form->text('ldapBindDN', $ldapBindDN) ?> + </div> + <div class='form-group'> + <?= $form->label('ldapBindPassword', t('LDAP Bind Password')) ?> + <?= $form->text('ldapBindPassword', $ldapBindPassword) ?> + </div> + <div class='form-group'> + <?= $form->label('ldapSearchFilter', t('LDAP Search Filter')) ?> + <?= $form->text('ldapSearchFilter', $ldapSearchFilter) ?> + </div> +</fieldset> +<fieldset> + <legend>Yubikey Configuration</legend> + <div class='form-group'> + <?= $form->label('yubikeyEnabled', t('Enable Yubikey')) ?> + <?= $form->checkbox('yubikeyEnabled', 1, $yubikeyEnabled) ?> + </div> + <div id="yubikey-options" style="display: <?= $yubikeyEnabled ? 'block' : 'none' ?>;"> + <div class='form-group'> + <?= $form->label('yubikeyClientID', t('Yubikey Client ID')) ?> + <?= $form->text('yubikeyClientID', $yubikeyClientID) ?> + </div> + <div class='form-group'> + <?= $form->label('yubikeySecretKey', t('Yubikey Secret Key')) ?> + <?= $form->text('yubikeySecretKey', $yubikeySecretKey) ?> + </div> + <div class='form-group'> + <?= $form->label('yubikeyServerURI', t('Yubikey Verify URI')) ?> + <?= $form->text('yubikeyServerURI', $yubikeyServerURI) ?> + </div> + <div class='form-group'> + <?= $form->label('yubikeyLDAPAtttribute', t('Yubikey LDAP Attribute')) ?> + <?= $form->text('yubikeyLDAPAtttribute', $yubikeyLDAPAtttribute) ?> + </div> + <div class='form-group'> + <?= $form->label('yubikeyAllowEmptyKey', t('Allow login with no Yubikey specified')) ?> + <?= $form->checkbox('yubikeyAllowEmptyKey', 1, $yubikeyAllowEmptyKey) ?> + </div> + </div> + <script> + $('#yubikeyEnabled').click(function(){ + if ( $(this).is(':checked') ) + $('#yubikey-options').show() + else + $('#yubikey-options').hide(); + }); + </script> +</fieldset> diff --git a/controller.php b/controller.php new file mode 100644 index 0000000000000000000000000000000000000000..dfd9b3bc17553d9bec8b624515ea09738b0ef767 --- /dev/null +++ b/controller.php @@ -0,0 +1,36 @@ +<?php +namespace Concrete\Package\LdapLogin; + +use Concrete\Core\Package\Package; +use Concrete\Core\Authentication\AuthenticationType; + + +defined('C5_EXECUTE') or die(_('Access denied.')); + +class Controller extends Package { + + protected $pkgHandle = 'ldap_login'; + protected $appVersionRequired = '5.7.2'; + protected $pkgVersion = '1.0'; + + public function getPackageDescription() { + return t("Add LDAP login functionality."); + } + + public function getPackageName() { + return "LDAP Login"; + } + + public function install() { + $pkg = parent::install(); + $at = AuthenticationType::add('ldap','LDAP',0,$pkg); + } + + public function uninstall() { + $at = AuthenticationType::getByHandle('ldap'); + $at->delete(); + parent::uninstall(); + } + +} +?>