YubiKey support

This commit is contained in:
Roland Gruber 2018-12-31 10:51:44 +01:00
parent a55c337efd
commit fc24f4a2aa
6 changed files with 611 additions and 19 deletions

View File

@ -311,6 +311,10 @@ $helpArray = array (
"Text" => _('Protect the self service login with a captcha.')), "Text" => _('Protect the self service login with a captcha.')),
"523" => array ("Headline" => _('Base color'), "523" => array ("Headline" => _('Base color'),
"Text" => _('Background color for self service pages.')), "Text" => _('Background color for self service pages.')),
"524" => array ("Headline" => _('Client id'),
"Text" => _('Please enter your client id for the verification API.')),
"525" => array ("Headline" => _('Secret key'),
"Text" => _('Please enter your secret key for the verification API.')),
"550" => array ("Headline" => _("From address"), "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.")), "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"), "551" => array ("Headline" => _("Subject"),

View File

@ -53,6 +53,8 @@ interface TwoFactorProvider {
*/ */
public function verify2ndFactor($user, $password, $serial, $twoFactorInput); public function verify2ndFactor($user, $password, $serial, $twoFactorInput);
} }
/** /**
@ -223,6 +225,71 @@ class PrivacyIDEAProvider implements TwoFactorProvider {
} }
/**
* Authentication via YubiKeys.
*
* @author Roland Gruber
*/
class YubicoProvider implements TwoFactorProvider {
private $config;
/**
* Constructor.
*
* @param TwoFactorConfiguration $config configuration
*/
public function __construct(&$config) {
$this->config = $config;
}
/**
* {@inheritDoc}
* @see \LAM\LIB\TWO_FACTOR\TwoFactorProvider::getSerials()
*/
public function getSerials($user, $password) {
$keyAttributeName = strtolower('yubiKeyId');
$loginDn = $_SESSION['ldap']->getUserName();
$handle = getLDAPServerHandle();
$ldapData = ldapGetDN($loginDn, array($keyAttributeName), $handle);
if (empty($ldapData[$keyAttributeName])) {
return array();
}
return array(implode(', ', $ldapData[$keyAttributeName]));
}
/**
* {@inheritDoc}
* @see \LAM\LIB\TWO_FACTOR\TwoFactorProvider::verify2ndFactor()
*/
public function verify2ndFactor($user, $password, $serial, $twoFactorInput) {
include_once(__DIR__ . "/3rdParty/yubico/Yubico.php");
$serialData = $this->getSerials($user, $password);
if (empty($serialData)) {
return false;
}
$serials = explode(', ', $serialData[0]);
$serialMatched = false;
foreach ($serials as $serial) {
if (strpos($twoFactorInput, $serial) === 0) {
$serialMatched = true;
break;
}
}
if (!$serialMatched) {
throw new \Exception(_('YubiKey id does not match allowed list of key ids.'));
}
$url = $this->config->twoFactorAuthenticationURL;
$httpsverify = !$this->config->twoFactorAuthenticationInsecure;
$clientId = $this->config->twoFactorAuthenticationClientId;
$secretKey = $this->config->twoFactorAuthenticationSecretKey;
$auth = new \Auth_Yubico($clientId, $secretKey, $url, $httpsverify);
$auth->verify($twoFactorInput);
return true;
}
}
/** /**
* Returns the correct 2 factor provider. * Returns the correct 2 factor provider.
*/ */
@ -232,6 +299,8 @@ class TwoFactorProviderService {
const TWO_FACTOR_NONE = 'none'; const TWO_FACTOR_NONE = 'none';
/** 2factor authentication via privacyIDEA */ /** 2factor authentication via privacyIDEA */
const TWO_FACTOR_PRIVACYIDEA = 'privacyidea'; const TWO_FACTOR_PRIVACYIDEA = 'privacyidea';
/** 2factor authentication via YubiKey */
const TWO_FACTOR_YUBICO = 'yubico';
private $config; private $config;
@ -260,6 +329,9 @@ class TwoFactorProviderService {
if ($this->config->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA) { if ($this->config->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA) {
return new PrivacyIDEAProvider($this->config); return new PrivacyIDEAProvider($this->config);
} }
elseif ($this->config->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_YUBICO) {
return new YubicoProvider($this->config);
}
throw new \Exception('Invalid provider: ' . $this->config->twoFactorAuthentication); throw new \Exception('Invalid provider: ' . $this->config->twoFactorAuthentication);
} }
@ -270,11 +342,11 @@ class TwoFactorProviderService {
* @return TwoFactorConfiguration configuration * @return TwoFactorConfiguration configuration
*/ */
private function getConfigSelfService(&$profile) { private function getConfigSelfService(&$profile) {
$config = new TwoFactorConfiguration(); $tfConfig = new TwoFactorConfiguration();
$config->twoFactorAuthentication = $profile->twoFactorAuthentication; $tfConfig->twoFactorAuthentication = $profile->twoFactorAuthentication;
$config->twoFactorAuthenticationInsecure = $profile->twoFactorAuthenticationInsecure; $tfConfig->twoFactorAuthenticationInsecure = $profile->twoFactorAuthenticationInsecure;
$config->twoFactorAuthenticationURL = $profile->twoFactorAuthenticationURL; $tfConfig->twoFactorAuthenticationURL = $profile->twoFactorAuthenticationURL;
return $config; return $tfConfig;
} }
/** /**
@ -284,11 +356,13 @@ class TwoFactorProviderService {
* @return TwoFactorConfiguration configuration * @return TwoFactorConfiguration configuration
*/ */
private function getConfigAdmin($conf) { private function getConfigAdmin($conf) {
$config = new TwoFactorConfiguration(); $tfConfig = new TwoFactorConfiguration();
$config->twoFactorAuthentication = $conf->getTwoFactorAuthentication(); $tfConfig->twoFactorAuthentication = $conf->getTwoFactorAuthentication();
$config->twoFactorAuthenticationInsecure = $conf->getTwoFactorAuthenticationInsecure(); $tfConfig->twoFactorAuthenticationInsecure = $conf->getTwoFactorAuthenticationInsecure();
$config->twoFactorAuthenticationURL = $conf->getTwoFactorAuthenticationURL(); $tfConfig->twoFactorAuthenticationURL = $conf->getTwoFactorAuthenticationURL();
return $config; $tfConfig->twoFactorAuthenticationClientId = $conf->getTwoFactorAuthenticationClientId();
$tfConfig->twoFactorAuthenticationSecretKey = $conf->getTwoFactorAuthenticationSecretKey();
return $tfConfig;
} }
} }
@ -299,7 +373,30 @@ class TwoFactorProviderService {
* @author Roland Gruber * @author Roland Gruber
*/ */
class TwoFactorConfiguration { class TwoFactorConfiguration {
/**
* @var string provider id
*/
public $twoFactorAuthentication = null; public $twoFactorAuthentication = null;
/**
* @var service URL
*/
public $twoFactorAuthenticationURL = null; public $twoFactorAuthenticationURL = null;
/**
* @var disable certificate check
*/
public $twoFactorAuthenticationInsecure = false; public $twoFactorAuthenticationInsecure = false;
/**
* @var client ID for API access
*/
public $twoFactorAuthenticationClientId = null;
/**
* @var secret key for API access
*/
public $twoFactorAuthenticationSecretKey = null;
} }

351
lam/lib/3rdParty/yubico/Yubico.php vendored Normal file
View File

@ -0,0 +1,351 @@
<?php
/**
* Class for verifying Yubico One-Time-Passcodes
*
* @category Auth
* @package Auth_Yubico
* @author Simon Josefsson <simon@yubico.com>, Olov Danielson <olov@yubico.com>
* @author Roland Gruber
* @copyright 2007-2015 Yubico AB
* @copyright 2018 Roland Gruber
* @license https://opensource.org/licenses/bsd-license.php New BSD License
* @version 2.0
* @link https://www.yubico.com/
*
* Adapted for LAM.
*/
/**
* Class for verifying Yubico One-Time-Passcodes
*/
class Auth_Yubico {
/**
* Yubico client ID
*
* @var string
*/
private $clientId;
/**
* Yubico client key
*
* @var string
*/
private $clientKey;
/**
* URL part of validation server
*
* @var string
*/
private $url;
/**
* Last query to server
*
* @var string
*/
private $lastquery;
/**
* Response from server
*
* @var string
*/
private $response;
/**
* Flag whether to verify HTTPS server certificates or not.
*
* @var boolean
*/
private $httpsVerify;
/**
* Constructor
*
* Sets up the object
*
* @param string $id The client identity
* @param string $key The client MAC key
* @param string $url URL
* @param boolean $httpsverify Flag whether to use verify HTTPS
* server certificates
*/
public function __construct($id, $key, $url, $httpsverify) {
$this->clientId = $id;
$this->clientKey = base64_decode($key);
$this->httpsVerify = $httpsverify;
$this->url = $url;
}
/**
* Parse input string into password, yubikey prefix,
* ciphertext, and OTP.
*
* @param string Input string to parse
* @param string Optional delimiter re-class, default is '[:]'
* @return array Keyed array with fields
*/
private function parsePasswordOTP($str, $delim = '[:]') {
if (!preg_match("/^((.*)" . $delim . ")?(([cbdefghijklnrtuv]{0,12})([cbdefghijklnrtuv]{32}))$/i", $str, $matches)) {
/* Dvorak? */
if (!preg_match("/^((.*)" . $delim . ")?(([jxe\\.uidchtnbpygk]{0,12})([jxe\\.uidchtnbpygk]{32}))$/i", $str, $matches)) {
return false;
}
else {
$ret['otp'] = strtr($matches[3], "jxe.uidchtnbpygk", "cbdefghijklnrtuv");
}
}
else {
$ret['otp'] = $matches[3];
}
$ret['password'] = $matches[2];
$ret['prefix'] = $matches[4];
$ret['ciphertext'] = $matches[5];
return $ret;
}
/**
* Parse parameters from last response
*
* example: getParameters("timestamp", "sessioncounter", "sessionuse");
*
* @param array @parameters Array with strings representing
* parameters to parse
* @return array parameter array from last response
*/
private function getParameters($parameters) {
if ($parameters == null) {
$parameters = array(
'timestamp',
'sessioncounter',
'sessionuse'
);
}
$param_array = array();
foreach ($parameters as $param) {
if (!preg_match("/" . $param . "=([0-9]+)/", $this->response, $out)) {
throw new LAMException(_('Error'), 'Could not parse parameter ' . $param . ' from response');
}
$param_array[$param] = $out[1];
}
return $param_array;
}
/**
* Verify Yubico OTP against multiple URLs
* Protocol specification 2.0 is used to construct validation requests
*
* @param string $token Yubico OTP
* @param int $use_timestamp 1=>send request with &timestamp=1 to
* get timestamp and session information
* in the response
* @param string $sl Sync level in percentage between 0
* and 100 or "fast" or "secure".
* @param int $timeout Max number of seconds to wait
* for responses
*/
public function verify($token, $use_timestamp = null, $sl = null, $timeout = null) {
/* Construct parameters string */
$ret = $this->parsePasswordOTP($token);
if (!$ret) {
throw new LAMException(_('Error'), 'Could not parse Yubikey OTP');
}
$params = array(
'id' => $this->clientId,
'otp' => $ret['otp'],
'nonce' => md5(uniqid(getRandomNumber()))
);
/* Take care of protocol version 2 parameters */
if ($use_timestamp) {
$params['timestamp'] = 1;
}
if ($sl) {
$params['sl'] = $sl;
}
if ($timeout) {
$params['timeout'] = $timeout;
}
ksort($params);
$parameters = '';
foreach ($params as $p => $v) {
$parameters .= "&" . $p . "=" . $v;
}
$parameters = ltrim($parameters, "&");
/* Generate signature. */
if ($this->clientKey != "") {
$signature = base64_encode(hash_hmac('sha1', $parameters, $this->clientKey, true));
$signature = preg_replace('/\+/', '%2B', $signature);
$parameters .= '&h=' . $signature;
}
/* Generate and prepare request. */
$mh = curl_multi_init();
$ch = array();
$query = $this->url . "?" . $parameters;
$this->lastquery = $query;
logNewMessage(LOG_DEBUG, 'Yubico url: ' . $query);
$handle = curl_init($query);
curl_setopt($handle, CURLOPT_USERAGENT, "LAM Auth Yubico");
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
if (!$this->httpsVerify) {
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 0);
}
curl_setopt($handle, CURLOPT_FAILONERROR, true);
/*
* If timeout is set, we better apply it here as well
* in case the validation server fails to follow it.
*/
if ($timeout) {
curl_setopt($handle, CURLOPT_TIMEOUT, $timeout);
}
// TODO single curl call
curl_multi_add_handle($mh, $handle);
$ch[(int) $handle] = $handle;
/* Execute and read request. */
$this->response = null;
$replay = False;
$valid = False;
do {
/* Let curl do its work. */
while (($mrc = curl_multi_exec($mh, $active)) == CURLM_CALL_MULTI_PERFORM);
while ($info = curl_multi_info_read($mh)) {
if ($info['result'] == CURLE_OK) {
/* We have a complete response from one server. */
$str = curl_multi_getcontent($info['handle']);
logNewMessage(LOG_DEBUG, 'Yubico answer: ' . $str);
$cinfo = curl_getinfo($info['handle']);
if (preg_match("/status=([a-zA-Z0-9_]+)/", $str, $out)) {
$status = $out[1];
/*
* There are 3 cases.
*
* 1. OTP or Nonce values doesn't match - ignore
* response.
*
* 2. We have a HMAC key. If signature is invalid -
* ignore response. Return if status=OK/REPLAYED_OTP/BAD_OTP.
*
* 3. Return if status=OK or status=REPLAYED_OTP.
*/
if (!preg_match("/otp=" . $params['otp'] . "/", $str) || !preg_match("/nonce=" . $params['nonce'] . "/", $str)) {
/* Case 1. Ignore response. */
}
elseif ($this->clientKey != "") {
/* Case 2. Verify signature first */
$rows = explode("\r\n", trim($str));
$response = array();
foreach ($rows as $key => $val) {
/*
* = is also used in BASE64 encoding so we only replace the first = by # which is not
* used in BASE64
*/
$val = preg_replace('/=/', '#', $val, 1);
$row = explode("#", $val);
$response[$row[0]] = $row[1];
}
$parameters = array(
'nonce',
'otp',
'sessioncounter',
'sessionuse',
'sl',
'status',
't',
'timeout',
'timestamp'
);
sort($parameters);
$check = Null;
foreach ($parameters as $param) {
if (array_key_exists($param, $response)) {
if ($check) $check = $check . '&';
$check = $check . $param . '=' . $response[$param];
}
}
$checksignature = base64_encode(hash_hmac('sha1', utf8_encode($check), $this->clientKey, true));
if ($response['h'] == $checksignature) {
if ($status == 'REPLAYED_OTP') {
$this->response = $str;
$replay = True;
}
if ($status == 'OK') {
$this->response = $str;
$valid = True;
}
// TODO status BAD_OTP
}
else {
// TODO throw invalid signature exception
}
}
else {
/* Case 3. We check the status directly */
if ($status == 'REPLAYED_OTP') {
$this->response = $str;
$replay = True;
}
if ($status == 'OK') {
$this->response = $str;
$valid = True;
}
// TODO status BAD_OTP
}
}
if ($valid || $replay) {
/* We have status=OK or status=REPLAYED_OTP, return. */
foreach ($ch as $h) {
curl_multi_remove_handle($mh, $h);
curl_close($h);
}
curl_multi_close($mh);
if ($replay) {
throw new LAMException(_('Error'), 'OTP replay detected.');
}
if ($valid) {
return;
}
}
curl_multi_remove_handle($mh, $info['handle']);
curl_close($info['handle']);
unset($ch[(int) $info['handle']]);
}
curl_multi_select($mh);
}
}
while ($active);
/*
* Typically this is only reached
* when the timeout is reached and there is no
* OK/REPLAYED_REQUEST answer (think firewall).
*/
foreach ($ch as $h) {
curl_multi_remove_handle($mh, $h);
curl_close($h);
}
curl_multi_close($mh);
throw new LAMException(_('Error'), 'Invalid answer: ' . print_r($this->response, true));
}
}
?>

View File

@ -591,6 +591,8 @@ class LAMConfig {
private $twoFactorAuthentication = TwoFactorProviderService::TWO_FACTOR_NONE; private $twoFactorAuthentication = TwoFactorProviderService::TWO_FACTOR_NONE;
private $twoFactorAuthenticationURL = 'https://localhost'; private $twoFactorAuthenticationURL = 'https://localhost';
private $twoFactorAuthenticationClientId = null;
private $twoFactorAuthenticationSecretKey = null;
private $twoFactorAuthenticationInsecure = false; private $twoFactorAuthenticationInsecure = false;
private $twoFactorAuthenticationLabel = null; private $twoFactorAuthenticationLabel = null;
private $twoFactorAuthenticationOptional = false; private $twoFactorAuthenticationOptional = false;
@ -607,7 +609,7 @@ class LAMConfig {
'pwdResetAllowScreenPassword', 'pwdResetForcePasswordChange', 'pwdResetDefaultPasswordOutput', 'pwdResetAllowScreenPassword', 'pwdResetForcePasswordChange', 'pwdResetDefaultPasswordOutput',
'scriptUserName', 'scriptSSHKey', 'scriptSSHKeyPassword', 'twoFactorAuthentication', 'twoFactorAuthenticationURL', 'scriptUserName', 'scriptSSHKey', 'scriptSSHKeyPassword', 'twoFactorAuthentication', 'twoFactorAuthenticationURL',
'twoFactorAuthenticationInsecure', 'twoFactorAuthenticationLabel', 'twoFactorAuthenticationOptional', 'twoFactorAuthenticationInsecure', 'twoFactorAuthenticationLabel', 'twoFactorAuthenticationOptional',
'twoFactorAuthenticationCaption', 'referentialIntegrityOverlay' 'twoFactorAuthenticationCaption', 'twoFactorAuthenticationClientId', 'twoFactorAuthenticationSecretKey', 'referentialIntegrityOverlay'
); );
@ -867,6 +869,8 @@ class LAMConfig {
if (!in_array("pwdResetDefaultPasswordOutput", $saved)) array_push($file_array, "\n" . "pwdResetDefaultPasswordOutput: " . $this->pwdResetDefaultPasswordOutput . "\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("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("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("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("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("twoFactorAuthenticationOptional", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationOptional: " . $this->twoFactorAuthenticationOptional . "\n");
@ -2151,7 +2155,7 @@ class LAMConfig {
/** /**
* Returns the authentication URL. * Returns the authentication URL.
* *
* @return string $twoFactorAuthenticationURL authentication URL * @return string authentication URL
*/ */
public function getTwoFactorAuthenticationURL() { public function getTwoFactorAuthenticationURL() {
return $this->twoFactorAuthenticationURL; return $this->twoFactorAuthenticationURL;
@ -2166,10 +2170,46 @@ class LAMConfig {
$this->twoFactorAuthenticationURL = $twoFactorAuthenticationURL; $this->twoFactorAuthenticationURL = $twoFactorAuthenticationURL;
} }
/**
* Sets the client id.
*
* @param string $clientId client id
*/
public function setTwoFactorAuthenticationClientId($clientId) {
$this->twoFactorAuthenticationClientId = $clientId;
}
/**
* Returns the client id.
*
* @return string client id
*/
public function getTwoFactorAuthenticationClientId() {
return $this->twoFactorAuthenticationClientId;
}
/**
* Sets the secret key.
*
* @param string $secretKey secret key
*/
public function setTwoFactorAuthenticationSecretKey($secretKey) {
$this->twoFactorAuthenticationSecretKey = $secretKey;
}
/**
* Returns the secret key.
*
* @return string secret key
*/
public function getTwoFactorAuthenticationSecretKey() {
return $this->twoFactorAuthenticationSecretKey;
}
/** /**
* Returns if SSL certificate verification is turned off. * Returns if SSL certificate verification is turned off.
* *
* @return bool $twoFactorAuthenticationInsecure SSL certificate verification is turned off * @return bool SSL certificate verification is turned off
*/ */
public function getTwoFactorAuthenticationInsecure() { public function getTwoFactorAuthenticationInsecure() {
return $this->twoFactorAuthenticationInsecure; return $this->twoFactorAuthenticationInsecure;
@ -2187,7 +2227,7 @@ class LAMConfig {
/** /**
* Returns the authentication label. * Returns the authentication label.
* *
* @return string $twoFactorAuthenticationLabel authentication label * @return string authentication label
*/ */
public function getTwoFactorAuthenticationLabel() { public function getTwoFactorAuthenticationLabel() {
return $this->twoFactorAuthenticationLabel; return $this->twoFactorAuthenticationLabel;
@ -2205,7 +2245,7 @@ class LAMConfig {
/** /**
* Returns if 2nd factor is optional. * Returns if 2nd factor is optional.
* *
* @return bool $twoFactorAuthenticationOptional 2nd factor is optional * @return bool 2nd factor is optional
*/ */
public function getTwoFactorAuthenticationOptional() { public function getTwoFactorAuthenticationOptional() {
return $this->twoFactorAuthenticationOptional; return $this->twoFactorAuthenticationOptional;
@ -2223,7 +2263,7 @@ class LAMConfig {
/** /**
* Returns the caption HTML. * Returns the caption HTML.
* *
* @return string $twoFactorAuthenticationCaption caption HTML * @return string caption HTML
*/ */
public function getTwoFactorAuthenticationCaption() { public function getTwoFactorAuthenticationCaption() {
return $this->twoFactorAuthenticationCaption; return $this->twoFactorAuthenticationCaption;

View File

@ -22,7 +22,7 @@ use \htmlGroup;
/* /*
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/)
Copyright (C) 2003 - 2017 Roland Gruber Copyright (C) 2003 - 2018 Roland Gruber
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -460,19 +460,29 @@ if (extension_loaded('curl')) {
$twoFactorOptions = array( $twoFactorOptions = array(
_('None') => TwoFactorProviderService::TWO_FACTOR_NONE, _('None') => TwoFactorProviderService::TWO_FACTOR_NONE,
'privacyIDEA' => TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA, 'privacyIDEA' => TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA,
'YubiKey' => TwoFactorProviderService::TWO_FACTOR_YUBICO,
); );
$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', 'twoFactorOptional', 'twoFactorCaption') TwoFactorProviderService::TWO_FACTOR_NONE => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorClientId', 'twoFactorSecretKey')
)); ));
$twoFactorSelect->setTableRowsToShow(array( $twoFactorSelect->setTableRowsToShow(array(
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel', 'twoFactorOptional', 'twoFactorCaption') TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
)); ));
$row->add($twoFactorSelect, 12); $row->add($twoFactorSelect, 12);
$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);
$twoFactorClientId = new htmlResponsiveInputField(_("Client id"), 'twoFactorClientId', $conf->getTwoFactorAuthenticationClientId(), '524');
$row->add($twoFactorClientId, 12);
$twoFactorSecretKey = new htmlResponsiveInputField(_("Secret key"), 'twoFactorSecretKey', $conf->getTwoFactorAuthenticationSecretKey(), '525');
$row->add($twoFactorSecretKey, 12);
$twoFactorLabel = new htmlResponsiveInputField(_("Label"), 'twoFactorLabel', $conf->getTwoFactorAuthenticationLabel(), '517'); $twoFactorLabel = new htmlResponsiveInputField(_("Label"), 'twoFactorLabel', $conf->getTwoFactorAuthenticationLabel(), '517');
$row->add($twoFactorLabel, 12); $row->add($twoFactorLabel, 12);
$row->add(new htmlResponsiveInputCheckbox('twoFactorOptional', $conf->getTwoFactorAuthenticationOptional(), _('Optional'), '519'), 12); $row->add(new htmlResponsiveInputCheckbox('twoFactorOptional', $conf->getTwoFactorAuthenticationOptional(), _('Optional'), '519'), 12);
@ -677,6 +687,8 @@ function checkInput() {
if (extension_loaded('curl')) { if (extension_loaded('curl')) {
$conf->setTwoFactorAuthentication($_POST['twoFactor']); $conf->setTwoFactorAuthentication($_POST['twoFactor']);
$conf->setTwoFactorAuthenticationURL($_POST['twoFactorURL']); $conf->setTwoFactorAuthenticationURL($_POST['twoFactorURL']);
$conf->setTwoFactorAuthenticationClientId($_POST['twoFactorClientId']);
$conf->setTwoFactorAuthenticationSecretKey($_POST['twoFactorSecretKey']);
$conf->setTwoFactorAuthenticationInsecure(isset($_POST['twoFactorInsecure']) && ($_POST['twoFactorInsecure'] == 'on')); $conf->setTwoFactorAuthenticationInsecure(isset($_POST['twoFactorInsecure']) && ($_POST['twoFactorInsecure'] == 'on'));
$conf->setTwoFactorAuthenticationLabel($_POST['twoFactorLabel']); $conf->setTwoFactorAuthenticationLabel($_POST['twoFactorLabel']);
$conf->setTwoFactorAuthenticationOptional(isset($_POST['twoFactorOptional']) && ($_POST['twoFactorOptional'] == 'on')); $conf->setTwoFactorAuthenticationOptional(isset($_POST['twoFactorOptional']) && ($_POST['twoFactorOptional'] == 'on'));

View File

@ -499,6 +499,94 @@ class LAMConfigTest extends PHPUnit_Framework_TestCase {
$this->assertEquals($val, $this->lAMConfig->getHttpAuthentication()); $this->assertEquals($val, $this->lAMConfig->getHttpAuthentication());
} }
/**
* Tests LAMConfig->getTwoFactorAuthentication() and LAMConfig->setTwoFactorAuthentication()
*/
public function testTwoFactorAuthentication() {
$val = '2fid';
$this->lAMConfig->setTwoFactorAuthentication($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthentication());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthentication());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationURL() and LAMConfig->setTwoFactorAuthenticationURL()
*/
public function testTwoFactorAuthenticationURL() {
$val = 'http://example.com';
$this->lAMConfig->setTwoFactorAuthenticationURL($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationURL());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationURL());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationClientId() and LAMConfig->setTwoFactorAuthenticationClientId()
*/
public function testTwoFactorAuthenticationClientId() {
$val = '1234';
$this->lAMConfig->setTwoFactorAuthenticationClientId($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationClientId());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationClientId());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationSecretKey() and LAMConfig->setTwoFactorAuthenticationSecretKey()
*/
public function testTwoFactorAuthenticationSecretKey() {
$val = '3333key';
$this->lAMConfig->setTwoFactorAuthenticationSecretKey($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationSecretKey());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationSecretKey());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationInsecure() and LAMConfig->setTwoFactorAuthenticationInsecure()
*/
public function testTwoFactorAuthenticationInsecure() {
$val = true;
$this->lAMConfig->setTwoFactorAuthenticationInsecure($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationInsecure());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationInsecure());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationLabel() and LAMConfig->setTwoFactorAuthenticationLabel()
*/
public function testTwoFactorAuthenticationLabel() {
$val = '2falabel';
$this->lAMConfig->setTwoFactorAuthenticationLabel($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationLabel());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationLabel());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationOptional() and LAMConfig->setTwoFactorAuthenticationOptional()
*/
public function testTwoFactorAuthenticationOptional() {
$val = true;
$this->lAMConfig->setTwoFactorAuthenticationOptional($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationOptional());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationOptional());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationCaption() and LAMConfig->setTwoFactorAuthenticationCaption()
*/
public function testTwoFactorAuthenticationCaption() {
$val = '2facaption';
$this->lAMConfig->setTwoFactorAuthenticationCaption($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationCaption());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationCaption());
}
/** /**
* Tests LAMConfig->getLamProMailFrom() and LAMConfig->setLamProMailFrom() * Tests LAMConfig->getLamProMailFrom() and LAMConfig->setLamProMailFrom()
*/ */