Merge remote-tracking branch 'origin/develop' into webauthn

Conflicts:
	lam/lib/2factor.inc
This commit is contained in:
Roland Gruber 2019-11-17 21:41:40 +01:00
commit e471b5586d
7 changed files with 72 additions and 31 deletions

View File

@ -1,6 +1,7 @@
December 2019 7.0 December 2019 7.0
- Lamdaemon can be configured with directory prefix for homedirs - Lamdaemon can be configured with directory prefix for homedirs
- Account list filters match on substrings instead of whole value - Account list filters match on substrings instead of whole value
- YubiKey: support to configure multiple verification servers
- Fixed bugs: - Fixed bugs:
-> Missing CSS for Duo -> Missing CSS for Duo
-> Editing of DNs with comma on Windows (210) -> Editing of DNs with comma on Windows (210)

View File

@ -659,7 +659,7 @@
<para>Configuration options:</para> <para>Configuration options:</para>
<para>privacyIDEA:</para> <para><emphasis role="bold">privacyIDEA</emphasis></para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -686,16 +686,21 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>YubiKey:</para> <para><emphasis role="bold">YubiKey</emphasis></para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>Base URL: please enter the URL of your YubiKey verfication <para>Base URLs: please enter the URL(s) of your YubiKey
server. For YubiKey cloud this is verification server(s). If you run a custom verification API such
"https://api.yubico.com/wsapi/2.0/verify". If you run a custom as yubiserver then enter its URL (e.g.
verification API such as yubiserver then enter its URL (e.g.
http://www.example.com:8000/wsapi/2.0/verify). The URL needs to http://www.example.com:8000/wsapi/2.0/verify). The URL needs to
end with "/wsapi/2.0/verify".</para> end with "/wsapi/2.0/verify". For YubiKey cloud these are
"https://api.yubico.com/wsapi/2.0/verify",
"https://api2.yubico.com/wsapi/2.0/verify",
"https://api3.yubico.com/wsapi/2.0/verify",
"https://api4.yubico.com/wsapi/2.0/verify" and
"https://api5.yubico.com/wsapi/2.0/verify". Enter one URL per
line.</para>
</listitem> </listitem>
<listitem> <listitem>
@ -722,7 +727,7 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>Duo:</para> <para><emphasis role="bold">Duo</emphasis></para>
<para>This requires to register a new "Web SDK" application in your <para>This requires to register a new "Web SDK" application in your
Duo admin panel.</para> Duo admin panel.</para>

View File

@ -331,7 +331,7 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>privacyIDEA:</para> <para><emphasis role="bold">privacyIDEA</emphasis></para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -358,16 +358,21 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>YubiKey:</para> <para><emphasis role="bold">YubiKey</emphasis></para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>Base URL: please enter the URL of your YubiKey verfication <para>Base URLs: please enter the URL(s) of your YubiKey
server. For YubiKey cloud this is verification server(s). If you run a custom verification API such
"https://api.yubico.com/wsapi/2.0/verify". If you run a custom as yubiserver then enter its URL (e.g.
verification API such as yubiserver then enter its URL (e.g.
http://www.example.com:8000/wsapi/2.0/verify). The URL needs to http://www.example.com:8000/wsapi/2.0/verify). The URL needs to
end with "/wsapi/2.0/verify".</para> end with "/wsapi/2.0/verify". For YubiKey cloud these are
"https://api.yubico.com/wsapi/2.0/verify",
"https://api2.yubico.com/wsapi/2.0/verify",
"https://api3.yubico.com/wsapi/2.0/verify",
"https://api4.yubico.com/wsapi/2.0/verify" and
"https://api5.yubico.com/wsapi/2.0/verify". Enter one URL per
line.</para>
</listitem> </listitem>
<listitem> <listitem>
@ -394,7 +399,7 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>Duo:</para> <para><emphasis role="bold">Duo</emphasis></para>
<para>This requires to register a new "Web SDK" application in your <para>This requires to register a new "Web SDK" application in your
Duo admin panel.</para> Duo admin panel.</para>

View File

@ -301,6 +301,8 @@ $helpArray = array (
"Text" => _('You can enable 2-factor authentication here (e.g. via mobile device).')), "Text" => _('You can enable 2-factor authentication here (e.g. via mobile device).')),
"515" => array ("Headline" => _('Base URL'), "515" => array ("Headline" => _('Base URL'),
"Text" => _('URL of external 2-factor authentication service.')), "Text" => _('URL of external 2-factor authentication service.')),
"515a" => array ("Headline" => _('Base URLs'),
"Text" => _('URLs of external 2-factor authentication service. Enter one per line.')),
"516" => array ("Headline" => _('Disable certificate check'), "516" => array ("Headline" => _('Disable certificate check'),
"Text" => _('This will disable the check of the SSL certificates for the 2-factor authentication service. Not recommended for production usage.')), "Text" => _('This will disable the check of the SSL certificates for the 2-factor authentication service. Not recommended for production usage.')),
"517" => array ("Headline" => _('Label'), "517" => array ("Headline" => _('Label'),

View File

@ -5,6 +5,7 @@ use \LAMConfig;
use \htmlScript; use \htmlScript;
use \htmlIframe; use \htmlIframe;
use \htmlImage; use \htmlImage;
use \LAMException;
/* /*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
@ -356,14 +357,23 @@ class YubicoProvider extends BaseProvider {
if (!$serialMatched) { if (!$serialMatched) {
throw new \Exception(_('YubiKey id does not match allowed list of key ids.')); throw new \Exception(_('YubiKey id does not match allowed list of key ids.'));
} }
$url = $this->config->twoFactorAuthenticationURL; $urls = $this->config->twoFactorAuthenticationURL;
shuffle($urls);
$httpsverify = !$this->config->twoFactorAuthenticationInsecure; $httpsverify = !$this->config->twoFactorAuthenticationInsecure;
$clientId = $this->config->twoFactorAuthenticationClientId; $clientId = $this->config->twoFactorAuthenticationClientId;
$secretKey = $this->config->twoFactorAuthenticationSecretKey; $secretKey = $this->config->twoFactorAuthenticationSecretKey;
foreach ($urls as $url) {
try {
$auth = new \Auth_Yubico($clientId, $secretKey, $url, $httpsverify); $auth = new \Auth_Yubico($clientId, $secretKey, $url, $httpsverify);
$auth->verify($twoFactorInput); $auth->verify($twoFactorInput);
return true; return true;
} }
catch (LAMException $e) {
logNewMessage(LOG_DEBUG, 'Unable to verify 2FA: ' . $e->getMessage());
}
}
return false;
}
} }
@ -597,7 +607,12 @@ class TwoFactorProviderService {
$tfConfig->isSelfService = true; $tfConfig->isSelfService = true;
$tfConfig->twoFactorAuthentication = $profile->twoFactorAuthentication; $tfConfig->twoFactorAuthentication = $profile->twoFactorAuthentication;
$tfConfig->twoFactorAuthenticationInsecure = $profile->twoFactorAuthenticationInsecure; $tfConfig->twoFactorAuthenticationInsecure = $profile->twoFactorAuthenticationInsecure;
if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_YUBICO) {
$tfConfig->twoFactorAuthenticationURL = explode("\r\n", $profile->twoFactorAuthenticationURL);
}
else {
$tfConfig->twoFactorAuthenticationURL = $profile->twoFactorAuthenticationURL; $tfConfig->twoFactorAuthenticationURL = $profile->twoFactorAuthenticationURL;
}
$tfConfig->twoFactorAuthenticationClientId = $profile->twoFactorAuthenticationClientId; $tfConfig->twoFactorAuthenticationClientId = $profile->twoFactorAuthenticationClientId;
$tfConfig->twoFactorAuthenticationSecretKey = $profile->twoFactorAuthenticationSecretKey; $tfConfig->twoFactorAuthenticationSecretKey = $profile->twoFactorAuthenticationSecretKey;
if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_YUBICO) { if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_YUBICO) {
@ -631,7 +646,12 @@ class TwoFactorProviderService {
$tfConfig->isSelfService = false; $tfConfig->isSelfService = false;
$tfConfig->twoFactorAuthentication = $conf->getTwoFactorAuthentication(); $tfConfig->twoFactorAuthentication = $conf->getTwoFactorAuthentication();
$tfConfig->twoFactorAuthenticationInsecure = $conf->getTwoFactorAuthenticationInsecure(); $tfConfig->twoFactorAuthenticationInsecure = $conf->getTwoFactorAuthenticationInsecure();
if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_YUBICO) {
$tfConfig->twoFactorAuthenticationURL = explode("\r\n", $conf->getTwoFactorAuthenticationURL());
}
else {
$tfConfig->twoFactorAuthenticationURL = $conf->getTwoFactorAuthenticationURL(); $tfConfig->twoFactorAuthenticationURL = $conf->getTwoFactorAuthenticationURL();
}
$tfConfig->twoFactorAuthenticationClientId = $conf->getTwoFactorAuthenticationClientId(); $tfConfig->twoFactorAuthenticationClientId = $conf->getTwoFactorAuthenticationClientId();
$tfConfig->twoFactorAuthenticationSecretKey = $conf->getTwoFactorAuthenticationSecretKey(); $tfConfig->twoFactorAuthenticationSecretKey = $conf->getTwoFactorAuthenticationSecretKey();
if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_YUBICO) { if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_YUBICO) {
@ -670,7 +690,7 @@ class TwoFactorConfiguration {
public $twoFactorAuthentication = null; public $twoFactorAuthentication = null;
/** /**
* @var service URL * @var string|array service URL(s)
*/ */
public $twoFactorAuthenticationURL = null; public $twoFactorAuthenticationURL = null;

View File

@ -2368,7 +2368,7 @@ class LAMConfig {
* @return string authentication URL * @return string authentication URL
*/ */
public function getTwoFactorAuthenticationURL() { public function getTwoFactorAuthenticationURL() {
return $this->twoFactorAuthenticationURL; return implode("\r\n", explode(LAMConfig::LINE_SEPARATOR, $this->twoFactorAuthenticationURL));
} }
/** /**
@ -2377,7 +2377,7 @@ class LAMConfig {
* @param string $twoFactorAuthenticationURL authentication URL * @param string $twoFactorAuthenticationURL authentication URL
*/ */
public function setTwoFactorAuthenticationURL($twoFactorAuthenticationURL) { public function setTwoFactorAuthenticationURL($twoFactorAuthenticationURL) {
$this->twoFactorAuthenticationURL = $twoFactorAuthenticationURL; $this->twoFactorAuthenticationURL = implode(LAMConfig::LINE_SEPARATOR, explode("\r\n", $twoFactorAuthenticationURL));
} }
/** /**

View File

@ -470,16 +470,16 @@ if (extension_loaded('curl')) {
$twoFactorSelect = new htmlResponsiveSelect('twoFactor', $twoFactorOptions, array($conf->getTwoFactorAuthentication()), _('Provider'), '514'); $twoFactorSelect = new htmlResponsiveSelect('twoFactor', $twoFactorOptions, array($conf->getTwoFactorAuthentication()), _('Provider'), '514');
$twoFactorSelect->setHasDescriptiveElements(true); $twoFactorSelect->setHasDescriptiveElements(true);
$twoFactorSelect->setTableRowsToHide(array( $twoFactorSelect->setTableRowsToHide(array(
TwoFactorProviderService::TWO_FACTOR_NONE => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel', TwoFactorProviderService::TWO_FACTOR_NONE => array('twoFactorURL', 'twoFactorURLs', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'), 'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorClientId', 'twoFactorSecretKey'), TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURLs', 'twoFactorClientId', 'twoFactorSecretKey'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorAttribute'), TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURL', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorOptional', 'twoFactorInsecure'), TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorURLs', 'twoFactorOptional', 'twoFactorInsecure'),
)); ));
$twoFactorSelect->setTableRowsToShow(array( $twoFactorSelect->setTableRowsToShow(array(
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel', TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorAttribute'), 'twoFactorOptional', 'twoFactorCaption', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel', TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURLs', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'), 'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorURL', 'twoFactorLabel', TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorURL', 'twoFactorLabel',
'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'), 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
@ -490,6 +490,9 @@ if (extension_loaded('curl')) {
$twoFactorUrl = new htmlResponsiveInputField(_("Base URL"), 'twoFactorURL', $conf->getTwoFactorAuthenticationURL(), '515'); $twoFactorUrl = new htmlResponsiveInputField(_("Base URL"), 'twoFactorURL', $conf->getTwoFactorAuthenticationURL(), '515');
$twoFactorUrl->setRequired(true); $twoFactorUrl->setRequired(true);
$row->add($twoFactorUrl, 12); $row->add($twoFactorUrl, 12);
$twoFactorUrl = new htmlResponsiveInputTextarea('twoFactorURLs', $conf->getTwoFactorAuthenticationURL(), '80', '4', _("Base URLs"), '515a');
$twoFactorUrl->setRequired(true);
$row->add($twoFactorUrl, 12);
$twoFactorClientId = new htmlResponsiveInputField(_("Client id"), 'twoFactorClientId', $conf->getTwoFactorAuthenticationClientId(), '524'); $twoFactorClientId = new htmlResponsiveInputField(_("Client id"), 'twoFactorClientId', $conf->getTwoFactorAuthenticationClientId(), '524');
$row->add($twoFactorClientId, 12); $row->add($twoFactorClientId, 12);
$twoFactorSecretKey = new htmlResponsiveInputField(_("Secret key"), 'twoFactorSecretKey', $conf->getTwoFactorAuthenticationSecretKey(), '525'); $twoFactorSecretKey = new htmlResponsiveInputField(_("Secret key"), 'twoFactorSecretKey', $conf->getTwoFactorAuthenticationSecretKey(), '525');
@ -725,7 +728,12 @@ function checkInput() {
// 2-factor // 2-factor
if (extension_loaded('curl')) { if (extension_loaded('curl')) {
$conf->setTwoFactorAuthentication($_POST['twoFactor']); $conf->setTwoFactorAuthentication($_POST['twoFactor']);
if ($_POST['twoFactor'] === TwoFactorProviderService::TWO_FACTOR_YUBICO) {
$conf->setTwoFactorAuthenticationURL($_POST['twoFactorURLs']);
}
else {
$conf->setTwoFactorAuthenticationURL($_POST['twoFactorURL']); $conf->setTwoFactorAuthenticationURL($_POST['twoFactorURL']);
}
$conf->setTwoFactorAuthenticationClientId($_POST['twoFactorClientId']); $conf->setTwoFactorAuthenticationClientId($_POST['twoFactorClientId']);
$conf->setTwoFactorAuthenticationSecretKey($_POST['twoFactorSecretKey']); $conf->setTwoFactorAuthenticationSecretKey($_POST['twoFactorSecretKey']);
$conf->setTwoFactorAuthenticationInsecure(isset($_POST['twoFactorInsecure']) && ($_POST['twoFactorInsecure'] == 'on')); $conf->setTwoFactorAuthenticationInsecure(isset($_POST['twoFactorInsecure']) && ($_POST['twoFactorInsecure'] == 'on'));