diff --git a/lam/HISTORY b/lam/HISTORY
index bd9b08dd..b770a043 100644
--- a/lam/HISTORY
+++ b/lam/HISTORY
@@ -1,5 +1,6 @@
September 2019 6.9
- Group account types can show member+owner count in list view
+ - 2-factor authentication: user name attribute for privacyIDEA can be specified
- LAM Pro:
-> New self service settings for login and main page footer
diff --git a/lam/docs/manual-sources/chapter-configuration.xml b/lam/docs/manual-sources/chapter-configuration.xml
index 974cb3fb..5a7c9c25 100644
--- a/lam/docs/manual-sources/chapter-configuration.xml
+++ b/lam/docs/manual-sources/chapter-configuration.xml
@@ -636,6 +636,11 @@
Base URL: please enter the URL of your privacyIDEA
instance
+
+
+ User name attribute: please enter the LDAP attribute name
+ that contains the user ID (e.g. "uid")
+
YubiKey:
diff --git a/lam/docs/manual-sources/chapter-selfService.xml b/lam/docs/manual-sources/chapter-selfService.xml
index 240ba73d..cab1f47a 100644
--- a/lam/docs/manual-sources/chapter-selfService.xml
+++ b/lam/docs/manual-sources/chapter-selfService.xml
@@ -334,6 +334,11 @@
Base URL: please enter the URL of your privacyIDEA
instance
+
+
+ User name attribute: please enter the LDAP attribute name
+ that contains the user ID (e.g. "uid")
+
YubiKey:
diff --git a/lam/docs/manual-sources/images/conf7.png b/lam/docs/manual-sources/images/conf7.png
index 718b0773..3b5d7891 100644
Binary files a/lam/docs/manual-sources/images/conf7.png and b/lam/docs/manual-sources/images/conf7.png differ
diff --git a/lam/help/help.inc b/lam/help/help.inc
index 8f828079..797f0bd7 100644
--- a/lam/help/help.inc
+++ b/lam/help/help.inc
@@ -323,6 +323,8 @@ $helpArray = array (
"Text" => _('This text is displayed as footer on the self service login page.')),
"527" => array ("Headline" => _('Main page footer'),
"Text" => _('This text is displayed as footer on the self service main page.')),
+ "528" => array ("Headline" => _('User name attribute'),
+ "Text" => _('The attribute (e.g. "uid") that contains the user name for the 2-factor service.')),
"550" => array ("Headline" => _("From address"),
"Text" => _("This email address will be set as sender address of all password mails. If empty the system default (php.ini) will be used.")),
"551" => array ("Headline" => _("Subject"),
diff --git a/lam/lib/2factor.inc b/lam/lib/2factor.inc
index 0cbaee92..417e6831 100644
--- a/lam/lib/2factor.inc
+++ b/lam/lib/2factor.inc
@@ -53,8 +53,6 @@ interface TwoFactorProvider {
*/
public function verify2ndFactor($user, $password, $serial, $twoFactorInput);
-
-
}
/**
@@ -79,8 +77,27 @@ class PrivacyIDEAProvider implements TwoFactorProvider {
*/
public function getSerials($user, $password) {
logNewMessage(LOG_DEBUG, 'PrivacyIDEAProvider: Getting serials for ' . $user);
- $token = $this->authenticate($user, $password);
- return $this->getSerialsForUser($user, $token);
+ $loginAttribute = $this->getLoginAttributeValue($user);
+ $token = $this->authenticate($loginAttribute, $password);
+ return $this->getSerialsForUser($loginAttribute, $token);
+ }
+
+ /**
+ * Returns the value of the user attribute in LDAP.
+ *
+ * @param string $userDn user DN
+ * @return string user name
+ */
+ private function getLoginAttributeValue($userDn) {
+ $attrName = $this->config->twoFactorAuthenticationSerialAttributeName;
+ $userData = ldapGetDN($userDn, array($attrName));
+ if (empty($userData[$attrName])) {
+ return null;
+ }
+ if (is_array($userData[$attrName])) {
+ return $userData[$attrName][0];
+ }
+ return $userData[$attrName];
}
/**
@@ -89,7 +106,8 @@ class PrivacyIDEAProvider implements TwoFactorProvider {
*/
public function verify2ndFactor($user, $password, $serial, $twoFactorInput) {
logNewMessage(LOG_DEBUG, 'PrivacyIDEAProvider: Checking 2nd factor for ' . $user);
- $token = $this->authenticate($user, $password);
+ $loginAttribute = $this->getLoginAttributeValue($user);
+ $token = $this->authenticate($loginAttribute, $password);
return $this->verify($token, $serial, $twoFactorInput);
}
@@ -360,6 +378,13 @@ class TwoFactorProviderService {
$tfConfig->twoFactorAuthenticationSerialAttributeName = 'yubiKeyId';
}
}
+ if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA) {
+ $attrName = $profile->twoFactorAuthenticationAttribute;
+ if (empty($attrName)) {
+ $attrName = 'uid';
+ }
+ $tfConfig->twoFactorAuthenticationSerialAttributeName = strtolower($attrName);
+ }
return $tfConfig;
}
@@ -385,6 +410,9 @@ class TwoFactorProviderService {
$tfConfig->twoFactorAuthenticationSerialAttributeName = 'yubiKeyId';
}
}
+ if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA) {
+ $tfConfig->twoFactorAuthenticationSerialAttributeName = strtolower($conf->getTwoFactorAuthenticationAttribute());
+ }
return $tfConfig;
}
diff --git a/lam/lib/account.inc b/lam/lib/account.inc
index d822ae75..9e36d88a 100644
--- a/lam/lib/account.inc
+++ b/lam/lib/account.inc
@@ -881,7 +881,7 @@ function searchLDAPPaged($server, $dn, $filter, $attributes, $attrsOnly, $limit)
*/
function ldapGetDN($dn, $attributes = array('dn'), $handle = null) {
if ($handle == null) {
- $handle = $_SESSION['ldap']->server();
+ $handle = getLDAPServerHandle();
}
$return = null;
$sr = @ldap_read($handle, escapeDN($dn), 'objectClass=*', $attributes, 0, 0, 0, LDAP_DEREF_NEVER);
diff --git a/lam/lib/config.inc b/lam/lib/config.inc
index 5c7b4db6..540a7d69 100644
--- a/lam/lib/config.inc
+++ b/lam/lib/config.inc
@@ -598,6 +598,7 @@ class LAMConfig {
private $twoFactorAuthenticationLabel = null;
private $twoFactorAuthenticationOptional = false;
private $twoFactorAuthenticationCaption = '';
+ private $twoFactorAuthenticationAttribute = '';
/** List of all settings in config file */
private $settings = array("ServerURL", "useTLS", "followReferrals", 'pagedResults', "Passwd", "Admins", "treesuffix",
@@ -610,7 +611,8 @@ class LAMConfig {
'pwdResetAllowScreenPassword', 'pwdResetForcePasswordChange', 'pwdResetDefaultPasswordOutput',
'scriptUserName', 'scriptSSHKey', 'scriptSSHKeyPassword', 'twoFactorAuthentication', 'twoFactorAuthenticationURL',
'twoFactorAuthenticationInsecure', 'twoFactorAuthenticationLabel', 'twoFactorAuthenticationOptional',
- 'twoFactorAuthenticationCaption', 'twoFactorAuthenticationClientId', 'twoFactorAuthenticationSecretKey', 'referentialIntegrityOverlay'
+ 'twoFactorAuthenticationCaption', 'twoFactorAuthenticationClientId', 'twoFactorAuthenticationSecretKey',
+ 'twoFactorAuthenticationAttribute', 'referentialIntegrityOverlay'
);
@@ -868,14 +870,33 @@ class LAMConfig {
if (!in_array("pwdResetAllowScreenPassword", $saved)) array_push($file_array, "\n" . "pwdResetAllowScreenPassword: " . $this->pwdResetAllowScreenPassword . "\n");
if (!in_array("pwdResetForcePasswordChange", $saved)) array_push($file_array, "\n" . "pwdResetForcePasswordChange: " . $this->pwdResetForcePasswordChange . "\n");
if (!in_array("pwdResetDefaultPasswordOutput", $saved)) array_push($file_array, "\n" . "pwdResetDefaultPasswordOutput: " . $this->pwdResetDefaultPasswordOutput . "\n");
- if (!in_array("twoFactorAuthentication", $saved)) array_push($file_array, "\n" . "twoFactorAuthentication: " . $this->twoFactorAuthentication . "\n");
- if (!in_array("twoFactorAuthenticationURL", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationURL: " . $this->twoFactorAuthenticationURL . "\n");
- if (!in_array("twoFactorAuthenticationClientId", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationClientId: " . $this->twoFactorAuthenticationClientId . "\n");
- if (!in_array("twoFactorAuthenticationSecretKey", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationSecretKey: " . $this->twoFactorAuthenticationSecretKey . "\n");
- if (!in_array("twoFactorAuthenticationInsecure", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationInsecure: " . $this->twoFactorAuthenticationInsecure . "\n");
- if (!in_array("twoFactorAuthenticationLabel", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationLabel: " . $this->twoFactorAuthenticationLabel . "\n");
- if (!in_array("twoFactorAuthenticationOptional", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationOptional: " . $this->twoFactorAuthenticationOptional . "\n");
- if (!in_array("twoFactorAuthenticationCaption", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationCaption: " . $this->twoFactorAuthenticationCaption . "\n");
+ if (!in_array("twoFactorAuthentication", $saved)) {
+ array_push($file_array, "\n" . "twoFactorAuthentication: " . $this->twoFactorAuthentication . "\n");
+ }
+ if (!in_array("twoFactorAuthenticationURL", $saved)) {
+ array_push($file_array, "\n" . "twoFactorAuthenticationURL: " . $this->twoFactorAuthenticationURL . "\n");
+ }
+ if (!in_array("twoFactorAuthenticationClientId", $saved)) {
+ array_push($file_array, "\n" . "twoFactorAuthenticationClientId: " . $this->twoFactorAuthenticationClientId . "\n");
+ }
+ if (!in_array("twoFactorAuthenticationSecretKey", $saved)) {
+ array_push($file_array, "\n" . "twoFactorAuthenticationSecretKey: " . $this->twoFactorAuthenticationSecretKey . "\n");
+ }
+ if (!in_array("twoFactorAuthenticationInsecure", $saved)) {
+ array_push($file_array, "\n" . "twoFactorAuthenticationInsecure: " . $this->twoFactorAuthenticationInsecure . "\n");
+ }
+ if (!in_array("twoFactorAuthenticationLabel", $saved)) {
+ array_push($file_array, "\n" . "twoFactorAuthenticationLabel: " . $this->twoFactorAuthenticationLabel . "\n");
+ }
+ if (!in_array("twoFactorAuthenticationOptional", $saved)) {
+ array_push($file_array, "\n" . "twoFactorAuthenticationOptional: " . $this->twoFactorAuthenticationOptional . "\n");
+ }
+ if (!in_array("twoFactorAuthenticationCaption", $saved)) {
+ array_push($file_array, "\n" . "twoFactorAuthenticationCaption: " . $this->twoFactorAuthenticationCaption . "\n");
+ }
+ if (!in_array("twoFactorAuthenticationAttribute", $saved)) {
+ array_push($file_array, "\n" . "twoFactorAuthenticationAttribute: " . $this->twoFactorAuthenticationAttribute . "\n");
+ }
// check if all module settings were added
$m_settings = array_keys($this->moduleSettings);
for ($i = 0; $i < sizeof($m_settings); $i++) {
@@ -2280,6 +2301,27 @@ class LAMConfig {
$this->twoFactorAuthenticationCaption = $twoFactorAuthenticationCaption;
}
+ /**
+ * Returns the user attribute.
+ *
+ * @return string user attribute
+ */
+ public function getTwoFactorAuthenticationAttribute() {
+ if (empty($this->twoFactorAuthenticationAttribute)) {
+ return 'uid';
+ }
+ return $this->twoFactorAuthenticationAttribute;
+ }
+
+ /**
+ * Sets the user attribute.
+ *
+ * @param string $twoFactorAuthenticationAttribute user attribute
+ */
+ public function setTwoFactorAuthenticationAttribute($twoFactorAuthenticationAttribute) {
+ $this->twoFactorAuthenticationAttribute = $twoFactorAuthenticationAttribute;
+ }
+
}
diff --git a/lam/lib/selfService.inc b/lam/lib/selfService.inc
index 5e35c503..bbf379aa 100644
--- a/lam/lib/selfService.inc
+++ b/lam/lib/selfService.inc
@@ -451,6 +451,7 @@ class selfServiceProfile {
public $twoFactorAuthenticationCaption = '';
public $twoFactorAuthenticationClientId = '';
public $twoFactorAuthenticationSecretKey = '';
+ public $twoFactorAuthenticationAttribute = 'uid';
/** provider for captcha (-/google) */
public $captchaProvider = '-';
@@ -510,6 +511,7 @@ class selfServiceProfile {
$this->twoFactorAuthenticationCaption = '';
$this->twoFactorAuthenticationClientId = '';
$this->twoFactorAuthenticationSecretKey = '';
+ $this->twoFactorAuthenticationAttribute = 'uid';
$this->captchaProvider = '-';
$this->reCaptchaSiteKey = '';
$this->reCaptchaSecretKey = '';
diff --git a/lam/templates/config/confmain.php b/lam/templates/config/confmain.php
index c79e62be..ed87aa79 100644
--- a/lam/templates/config/confmain.php
+++ b/lam/templates/config/confmain.php
@@ -466,16 +466,19 @@ if (extension_loaded('curl')) {
$twoFactorSelect->setHasDescriptiveElements(true);
$twoFactorSelect->setTableRowsToHide(array(
TwoFactorProviderService::TWO_FACTOR_NONE => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
- 'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
- TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorClientId', 'twoFactorSecretKey')
+ 'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
+ TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorClientId', 'twoFactorSecretKey'),
+ TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorAttribute'),
));
$twoFactorSelect->setTableRowsToShow(array(
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
- 'twoFactorOptional', 'twoFactorCaption'),
+ 'twoFactorOptional', 'twoFactorCaption', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
));
$row->add($twoFactorSelect, 12);
+ $twoFactorAttribute = new htmlResponsiveInputField(_("User name attribute"), 'twoFactorAttribute', $conf->getTwoFactorAuthenticationAttribute(), '528');
+ $row->add($twoFactorAttribute, 12);
$twoFactorUrl = new htmlResponsiveInputField(_("Base URL"), 'twoFactorURL', $conf->getTwoFactorAuthenticationURL(), '515');
$twoFactorUrl->setRequired(true);
$row->add($twoFactorUrl, 12);
diff --git a/lam/templates/login.php b/lam/templates/login.php
index 2188a989..31968804 100644
--- a/lam/templates/login.php
+++ b/lam/templates/login.php
@@ -572,12 +572,6 @@ if(isset($_POST['checklogin'])) {
}
else {
$_SESSION['2factorRequired'] = true;
- if (($_SESSION['config']->getLoginMethod() == LAMConfig::LOGIN_SEARCH) && ($_SESSION['config']->getHttpAuthentication() == 'true')) {
- $_SESSION['user2factor'] = $_SERVER['PHP_AUTH_USER'];
- }
- else {
- $_SESSION['user2factor'] = $_POST['username'];
- }
metaRefresh("./login2Factor.php");
}
die();
diff --git a/lam/templates/login2Factor.php b/lam/templates/login2Factor.php
index 9f4b4383..7088338b 100644
--- a/lam/templates/login2Factor.php
+++ b/lam/templates/login2Factor.php
@@ -46,10 +46,7 @@ setlanguage();
$config = $_SESSION['config'];
$password = $_SESSION['ldap']->getPassword();
-$user = $_SESSION['user2factor'];
-if (get_preg($user, 'dn')) {
- $user = extractRDNValue($user);
-}
+$user = $_SESSION['ldap']->getUserName();
// get serials
try {
@@ -69,7 +66,6 @@ $twoFactorLabel = empty($twoFactorLabelConfig) ? _('PIN+Token') : $twoFactorLabe
if (sizeof($serials) == 0) {
if ($config->getTwoFactorAuthenticationOptional()) {
unset($_SESSION['2factorRequired']);
- unset($_SESSION['user2factor']);
metaRefresh("main.php");
die();
}
@@ -104,7 +100,6 @@ if (isset($_POST['submit'])) {
}
if ($twoFactorValid) {
unset($_SESSION['2factorRequired']);
- unset($_SESSION['user2factor']);
metaRefresh("main.php");
die();
}
diff --git a/lam/tests/lib/LAMConfigTest.php b/lam/tests/lib/LAMConfigTest.php
index 9a661b2e..58e94bf5 100644
--- a/lam/tests/lib/LAMConfigTest.php
+++ b/lam/tests/lib/LAMConfigTest.php
@@ -3,7 +3,7 @@
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
- Copyright (C) 2016 - 2017 Roland Gruber
+ Copyright (C) 2016 - 2019 Roland Gruber
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -587,6 +587,17 @@ class LAMConfigTest extends PHPUnit_Framework_TestCase {
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationCaption());
}
+ /**
+ * Tests LAMConfig->getTwoFactorAuthenticationAttribute() and LAMConfig->setTwoFactorAuthenticationAttribute()
+ */
+ public function testTwoFactorAuthenticationAttribute() {
+ $val = 'user';
+ $this->lAMConfig->setTwoFactorAuthenticationAttribute($val);
+ $this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationAttribute());
+ $this->doSave();
+ $this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationAttribute());
+ }
+
/**
* Tests LAMConfig->getLamProMailFrom() and LAMConfig->setLamProMailFrom()
*/