diff --git a/composer.json b/composer.json index ba9f55ed8f91f27725ee503617571e8e73839e02..569f700e9f7b30681f2ad566daea7937cd8f8674 100644 --- a/composer.json +++ b/composer.json @@ -47,6 +47,7 @@ "slim/slim": "4.7.1", "php-di/php-di": "6.3.4", "symfony/console": "5.3.6", - "symfony/process": "^5.4" + "symfony/process": "^5.4", + "jumbojett/openid-connect-php": "^0.9.2" } } diff --git a/composer.lock b/composer.lock index 83fc9e51262501f07a3686237b78328422552b95..3ec63574b50a15c4bde663554e1067519672e966 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "59006c71d43d6f32f0445636c803208d", + "content-hash": "2fa6a856bbe442274874aeabe26f054b", "packages": [ { "name": "algo26-matthias/idna-convert", @@ -545,6 +545,48 @@ }, "time": "2019-08-18T20:01:55+00:00" }, + { + "name": "jumbojett/openid-connect-php", + "version": "v0.9.5", + "source": { + "type": "git", + "url": "https://github.com/jumbojett/OpenID-Connect-PHP.git", + "reference": "14991f706675b13dd1f72291bfd779f144454d64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jumbojett/OpenID-Connect-PHP/zipball/14991f706675b13dd1f72291bfd779f144454d64", + "reference": "14991f706675b13dd1f72291bfd779f144454d64", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "paragonie/random_compat": ">=2", + "php": ">=5.4", + "phpseclib/phpseclib": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8", + "roave/security-advisories": "dev-master" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "Bare-bones OpenID Connect client", + "support": { + "issues": "https://github.com/jumbojett/OpenID-Connect-PHP/issues", + "source": "https://github.com/jumbojett/OpenID-Connect-PHP/tree/v0.9.5" + }, + "time": "2021-11-24T16:11:49+00:00" + }, { "name": "kub-at/php-simple-html-dom-parser", "version": "1.9.1", diff --git a/config/config_defaults.inc.php b/config/config_defaults.inc.php index 14c1757e69a48c3c5ed9dfd6b4dfc9fceafbe0d0..2b6f2cae6d9308ce64c8a97127adeec27b47dd76 100644 --- a/config/config_defaults.inc.php +++ b/config/config_defaults.inc.php @@ -326,6 +326,26 @@ $STUDIP_AUTH_CONFIG_CAS = array("host" => "cas.studip.de", "auth_user_md5.Email" => array("callback" => "getUserData", "map_args" => "email"), "auth_user_md5.perms" => array("callback" => "getUserData", "map_args" => "status"))); +//example of OpenID Connect +$STUDIP_AUTH_CONFIG_GOOGLE = [ + 'provider_url' => 'https://accounts.google.com', + 'client_id' => '', + 'client_secret' => '', + 'plugin_class' => 'StudipAuthOIDC', + 'plugin_name' => 'google', + 'domain' => 'google', + 'plugin_fullname' => 'Google', + 'login_description' => 'Login with Google', + 'ssl_options' => ['certPath' => null, 'verifyPeer' => true, 'verifyHost' => true], + 'user_data_mapping' => + ['auth_user_md5.username' => ['callback' => 'dummy', 'map_args' => ''], + 'auth_user_md5.password' => ['callback' => 'dummy', 'map_args' => ''], + 'auth_user_md5.Email' => ['callback' => 'getUserData', 'map_args' => 'email'], + 'auth_user_md5.Nachname' => ['callback' => 'getUserData', 'map_args' => 'family_name'], + 'auth_user_md5.Vorname' => ['callback' => 'getUserData', 'map_args' => 'given_name'] + ] + ]; + $STUDIP_AUTH_CONFIG_LTI = [ 'consumer_keys' => [ // 'domain' is optional, default is value of consumer_key diff --git a/lib/classes/auth_plugins/StudipAuthAbstract.class.php b/lib/classes/auth_plugins/StudipAuthAbstract.class.php index 3af55c56d16a731585634cbb459f40e97285f9f8..008ed870967af72fe79df431751645fc1c33b723 100644 --- a/lib/classes/auth_plugins/StudipAuthAbstract.class.php +++ b/lib/classes/auth_plugins/StudipAuthAbstract.class.php @@ -1,8 +1,4 @@ <?php -# Lifter003: TEST -# Lifter007: TODO -# Lifter010: DONE - no html - // +---------------------------------------------------------------------------+ // This file is part of Stud.IP // StudipAuthAbstract.class.php @@ -26,39 +22,37 @@ // +---------------------------------------------------------------------------+ /** -* abstract base class for authentication plugins -* -* abstract base class for authentication plugins -* to write your own authentication plugin, derive it from this class and -* implement the following abstract methods: isUsedUsername($username) and -* isAuthenticated($username, $password, $jscript) -* don't forget to call the parents constructor if you implement your own, php -* won't do that for you ! -* -* @abstract -* @access public -* @author André Noack <noack@data-quest.de> -* @package -*/ -class StudipAuthAbstract { + * abstract base class for authentication plugins + * + * abstract base class for authentication plugins + * to write your own authentication plugin, derive it from this class and + * implement the following abstract methods: isUsedUsername($username) and + * isAuthenticated($username, $password, $jscript) + * don't forget to call the parents constructor if you implement your own, php + * won't do that for you ! + * + * @abstract + * @author André Noack <noack@data-quest.de> + * @package + */ +class StudipAuthAbstract +{ /** - * contains error message, if authentication fails - * - * - * @access public - * @var string - */ - var $error_msg; + * contains error message, if authentication fails + * + * + * @var string $error_msg + */ + public $error_msg; /** - * indicates whether the authenticated user logs in for the first time - * - * - * @access public - * @var bool - */ - var $is_new_user = false; + * indicates whether the authenticated user logs in for the first time + * + * + * @var bool $is_new_user + */ + public $is_new_user = false; /** * array of user domains to assign to each user, can be set in local.inc @@ -66,76 +60,75 @@ class StudipAuthAbstract { * @access public * @var array $user_domains */ - var $user_domains; + public $user_domains; /** - * associative array with mapping for database fields - * - * associative array with mapping for database fields, - * should be set in local.inc - * structure : - * array("<table name>.<field name>" => array( "callback" => "<name of callback method used for data retrieval>", - * "map_args" => "<arguments passed to callback method>")) - * @access public - * @var array $user_data_mapping - */ - var $user_data_mapping = null; + * associative array with mapping for database fields + * + * associative array with mapping for database fields, + * should be set in local.inc + * structure : + * array('<table name>.<field name>' => array( 'callback' => '<name of callback method used for data retrieval>', + * 'map_args' => '<arguments passed to callback method>')) + * @var array $user_data_mapping + */ + public $user_data_mapping = null; /** - * name of the plugin - * - * name of the plugin (last part of class name) is set in the constructor - * @access public - * @var string - */ - var $plugin_name; + * name of the plugin + * + * name of the plugin (last part of class name) is set in the constructor + * @var string $plugin_name + */ + public $plugin_name; /** - * text, which precedes error message for the plugin - * - * - * @access public - * @var string - */ - var $error_head; + * text, which precedes error message for the plugin + * + * + * @var string $error_head + */ + public $error_head; + /** + * @var $plugin_instances + */ private static $plugin_instances; /** - * static method to instantiate and retrieve a reference to an object (singleton) - * - * use always this method to instantiate a plugin object, it will ensure that only one object of each - * plugin will exist - * @access public - * @static - * @param string name of plugin, if omitted an array with all plugin objects will be returned - * @return mixed either a reference to the plugin with the passed name, or an array with references to all plugins - */ - static function getInstance($plugin_name = false) + * static method to instantiate and retrieve a reference to an object (singleton) + * + * always use this method to instantiate a plugin object, it will ensure that only one object of each + * plugin will exist + * @param string $plugin_name name of plugin, if omitted an array with all plugin objects will be returned + * @return mixed either a reference to the plugin with the passed name, or an array with references to all plugins + */ + public static function getInstance($plugin_name = false) { if (!is_array(self::$plugin_instances)) { - foreach($GLOBALS['STUDIP_AUTH_PLUGIN'] as $plugin) { - $plugin = "StudipAuth" . $plugin; - include_once "lib/classes/auth_plugins/" . $plugin . ".class.php"; - self::$plugin_instances[mb_strtoupper($plugin)] = new $plugin; + foreach ($GLOBALS['STUDIP_AUTH_PLUGIN'] as $plugin) { + $config = $GLOBALS['STUDIP_AUTH_CONFIG_' . strtoupper($plugin)]; + $plugin_class = $config['plugin_class'] ?? 'StudipAuth' . $plugin; + if (empty($config['plugin_name'])) { + $config['plugin_name'] = strtolower($plugin); + } + self::$plugin_instances[strtoupper($plugin)] = new $plugin_class($config); } } - return ($plugin_name) ? self::$plugin_instances[mb_strtoupper("StudipAuth" . $plugin_name)] : self::$plugin_instances; + return ($plugin_name) ? self::$plugin_instances[strtoupper($plugin_name)] : self::$plugin_instances; } /** - * static method to check authentication in all plugins - * - * if authentication fails in one plugin, the error message is stored and the next plugin is used - * if authentication succeeds, the uid element in the returned array will contain the Stud.IP user id - * - * @access public - * @static - * @param string the username to check - * @param string the password to check - * @return array structure: array('uid'=>'string <Stud.IP user id>','error'=>'string <error message>','is_new_user'=>'bool') - */ - static function CheckAuthentication($username, $password) + * static method to check authentication in all plugins + * + * if authentication fails in one plugin, the error message is stored and the next plugin is used + * if authentication succeeds, the uid element in the returned array will contain the Stud.IP user id + * + * @param string $username the username to check + * @param string $password the password to check + * @return array structure: array('uid'=>'string <Stud.IP user id>','error'=>'string <error message>','is_new_user'=>'bool') + */ + public static function CheckAuthentication($username, $password) { $plugins = StudipAuthAbstract::GetInstance(); @@ -157,63 +150,60 @@ class StudipAuthAbstract { $exp_d = UserConfig::get($user['user_id'])->EXPIRATION_DATE; if ($exp_d > 0 && $exp_d < time()) { - $error .= _("Dieses Benutzerkonto ist abgelaufen.<br> Wenden Sie sich bitte an die Administration.") . "<BR>"; + $error .= _('Dieses Benutzerkonto ist abgelaufen.<br> Wenden Sie sich bitte an die Administration.') . '<BR>'; return ['uid' => false, 'error' => $error]; - } else if ($locked == "1") { - $error .= _("Dieser Benutzer ist gesperrt! Wenden Sie sich bitte an die Administration.") . "<BR>"; + } else if ($locked) { + $error .= _('Dieser Benutzer ist gesperrt! Wenden Sie sich bitte an die Administration.') . '<BR>'; return ['uid' => false, 'error' => $error]; } else if ($key != '') { return ['uid' => $uid, 'user' => $user, 'error' => $error, 'need_email_activation' => $uid]; } else if ($checkIPRange && !self::CheckIPRange()) { - $error .= _("Der Login in Ihren Account ist aus diesem Netzwerk nicht erlaubt.") . "<BR>"; + $error .= _('Der Login in Ihren Account ist aus diesem Netzwerk nicht erlaubt.') . '<BR>'; return ['uid' => false, 'error' => $error]; } } return ['uid' => $uid, 'user' => $user, 'error' => $error, 'is_new_user' => $object->is_new_user]; } else { - $error .= (($object->error_head) ? ("<b>" . $object->error_head . ":</b> ") : "") . $object->error_msg . "<br>"; + $error .= (($object->error_head) ? ('<b>' . $object->error_head . ':</b> ') : '') . $object->error_msg . '<br>'; } } return ['uid' => $uid, 'error' => $error]; } /** - * static method to check if passed username is used in external data sources - * - * all plugins are checked, the error messages are stored and returned - * - * @access public - * @static - * @param string the username - * @return array - */ - static function CheckUsername($username) + * static method to check if passed username is used in external data sources + * + * all plugins are checked, the error messages are stored and returned + * + * @param string $username the username + * @return array + */ + public static function CheckUsername($username) { $plugins = StudipAuthAbstract::GetInstance(); $error = false; $found = false; foreach ($plugins as $object) { if ($found = $object->isUsedUsername($username)) { - return ['found' => $found,'error' => $error]; + return ['found' => $found, 'error' => $error]; } else { - $error .= (($object->error_head) ? ("<b>" . $object->error_head . ":</b> ") : "") . $object->error_msg . "<br>"; + $error .= (($object->error_head) ? ('<b>' . $object->error_head . ':</b> ') : '') . $object->error_msg . '<br>'; } } - return ['found' => $found,'error' => $error]; + return ['found' => $found, 'error' => $error]; } + /** - * static method to check for a mapped field - * - * this method checks in the plugin with the passed name, if the passed - * Stud.IP DB field is mapped to an external data source - * - * @access public - * @static - * @param string the name of the db field must be in form '<table name>.<field name>' - * @param string the name of the plugin to check - * @return bool true if the field is mapped, else false - */ - static function CheckField($field_name,$plugin_name) + * static method to check for a mapped field + * + * this method checks in the plugin with the passed name, if the passed + * Stud.IP DB field is mapped to an external data source + * + * @param string the name of the db field must be in form '<table name>.<field name>' + * @param string the name of the plugin to check + * @return bool true if the field is mapped, else false + */ + public static function CheckField($field_name, $plugin_name) { if (!$plugin_name) { return false; @@ -230,7 +220,7 @@ class StudipAuthAbstract { public static function CheckIPRange() { $ip = $_SERVER['REMOTE_ADDR']; - $version = mb_substr_count($ip, ':') > 1 ? 'V6' : 'V4'; // valid ip v6 addresses have atleast two colons + $version = substr_count($ip, ':') > 1 ? 'V6' : 'V4'; // valid ip v6 addresses have atleast two colons $method = 'CheckIPRange' . $version; if (is_array($GLOBALS['LOGIN_IP_RANGES'][$version])) { foreach ($GLOBALS['LOGIN_IP_RANGES'][$version] as $range) { @@ -275,53 +265,51 @@ class StudipAuthAbstract { $start = inet_pton($range['start']); $end = inet_pton($range['end']); - return mb_strlen($ipv6) === mb_strlen($start) - && $ipv6 >= $start && $ipv6 <= $end; + return strlen($ipv6) === strlen($start) + && $ipv6 >= $start && $ipv6 <= $end; } /** - * Constructor - * - * the constructor is private, you should use StudipAuthAbstract::GetInstance($plugin_name) - * to get a reference to a plugin object. Make sure the constructor in the base class is called - * when deriving your own plugin class, it assigns the settings from local.inc as members of the plugin - * each key of the $STUDIP_AUTH_CONFIG_<plugin name> array will become a member of the object - * - * @access private - * - */ - function __construct() + * Constructor + * + * you should use StudipAuthAbstract::GetInstance($plugin_name) + * to get a reference to a plugin object. Make sure the constructor in the base class is called + * when deriving your own plugin class, it assigns the settings from local.inc as members of the plugin + * each key of the $STUDIP_AUTH_CONFIG_<plugin name> array will become a member of the object + * + * @param array $config + */ + public function __construct($config = []) { - $this->plugin_name = mb_strtolower(mb_substr(get_class($this),10)); //get configuration array set in local inc - $config_var = $GLOBALS["STUDIP_AUTH_CONFIG_" . mb_strtoupper($this->plugin_name)]; + if (empty($config)) { + $this->plugin_name = strtolower(substr(get_class($this), 10)); + $config = $GLOBALS['STUDIP_AUTH_CONFIG_' . strtoupper($this->plugin_name)]; + } //assign each key in the config array as a member of the plugin object - if (isset($config_var)) { - foreach ($config_var as $key => $value) { - $this->$key = $value; - } + foreach ($config as $key => $value) { + $this->$key = $value; } } /** - * authentication method - * - * this method authenticates the passed username, it is used by StudipAuthAbstract::CheckAuthentication() - * if authentication succeeds it calls StudipAuthAbstract::doDataMapping() to map data fields - * if the authenticated user logs in for the first time it calls StudipAuthAbstract::doNewUserInit() to - * initialize the new user - * @access private - * @param string the username to check - * @param string the password to check - * @return string if authentication succeeds the Stud.IP user , else false - */ - function authenticateUser($username, $password) + * authentication method + * + * this method authenticates the passed username, it is used by StudipAuthAbstract::CheckAuthentication() + * if authentication succeeds it calls StudipAuthAbstract::doDataMapping() to map data fields + * if the authenticated user logs in for the first time it calls StudipAuthAbstract::doNewUserInit() to + * initialize the new user + * @param string $username the username to check + * @param string $password the password to check + * @return string if authentication succeeds the Stud.IP user , else false + */ + public function authenticateUser($username, $password) { $username = $this->verifyUsername($username); if ($this->isAuthenticated($username, $password)) { if ($user = $this->getStudipUser($username)) { $this->doDataMapping($user); - if ($this->is_new_user){ + if ($this->is_new_user) { $this->doNewUserInit($user); } $this->setUserDomains($user); @@ -333,24 +321,24 @@ class StudipAuthAbstract { } /** - * method to retrieve the Stud.IP user id to a given username - * - * - * @access private - * @param string the username - * @return User the Stud.IP or false if an error occurs - */ + * method to retrieve the Stud.IP user id to a given username + * + * + * @access private + * @param string the username + * @return User the Stud.IP or false if an error occurs + */ function getStudipUser($username) { $user = User::findByUsername($username); if ($user) { $auth_plugin = $user->auth_plugin; if ($auth_plugin === null) { - $this->error_msg = _("Dies ist ein vorläufiger Benutzer.") . "<br>"; + $this->error_msg = _('Dies ist ein vorläufiger Benutzer.') . '<br>'; return false; } - if ($auth_plugin != $this->plugin_name){ - $this->error_msg = sprintf(_("Dieser Benutzername wird bereits über %s authentifiziert!"),$auth_plugin) . "<br>"; + if ($auth_plugin != $this->plugin_name) { + $this->error_msg = sprintf(_('Dieser Benutzername wird bereits über %s authentifiziert!'), $auth_plugin) . '<br>'; return false; } return $user; @@ -387,9 +375,10 @@ class StudipAuthAbstract { * This method sets the user domains for the current user. * * @access private - * @param User the user object + * @param User the user object */ - function setUserDomains ($user) { + function setUserDomains($user) + { $user_domains = $this->getUserDomains(); $uid = $user->id; if (isset($user_domains)) { @@ -419,37 +408,43 @@ class StudipAuthAbstract { /** * Get the user domains to assign to the current user. */ - function getUserDomains () + function getUserDomains() { return $this->user_domains; } /** - * this method handles the data mapping - * - * for each entry in $this->user_data_mapping the according callback will be invoked - * the return value of the callback method is then written to the db field, which is specified - * in the key of the array - * - * @access private - * @param User the user object - * @return bool - */ + * this method handles the data mapping + * + * for each entry in $this->user_data_mapping the according callback will be invoked + * the return value of the callback method is then written to the db field, which is specified + * in the key of the array + * + * @access private + * @param User the user object + * @return bool + */ function doDataMapping($user) { if ($user && is_array($this->user_data_mapping)) { - foreach($this->user_data_mapping as $key => $value){ + foreach ($this->user_data_mapping as $key => $value) { + $callback = null; if (method_exists($this, $value['callback'])) { - $split = explode(".",$key); + $callback = [$this, $value['callback']]; + } else if (is_callable($value['callback'])) { + $callback = $value['callback']; + } + if ($callback) { + $split = explode('.', $key); $table = $split[0]; $field = $split[1]; - if ($table == 'auth_user_md5' || $table == 'user_info') { - $mapped_value = call_user_func([$this, $value['callback']],$value['map_args']); + if ($table === 'auth_user_md5' || $table === 'user_info') { + $mapped_value = call_user_func($callback, $value['map_args']); if (isset($mapped_value)) { $user->setValue($field, $mapped_value); } } else { - call_user_func([$this, $value['callback']],[$table,$field,$user,$value['map_args']]); + call_user_func($callback, [$table, $field, $user, $value['map_args']]); } } } @@ -459,30 +454,30 @@ class StudipAuthAbstract { } /** - * method to check, if a given db field is mapped by the plugin - * - * - * @access private - * @param string the name of the db field (<table_name>.<field_name>) - * @return bool true if the field is mapped - */ + * method to check, if a given db field is mapped by the plugin + * + * + * @access private + * @param string the name of the db field (<table_name>.<field_name>) + * @return bool true if the field is mapped + */ function isMappedField($name) { return isset($this->user_data_mapping[$name]); } /** - * method to eliminate bad characters in the given username - * - * - * @access private - * @param string the username - * @return string the username - */ + * method to eliminate bad characters in the given username + * + * + * @access private + * @param string the username + * @return string the username + */ function verifyUsername($username) { - if($this->username_case_insensitiv) $username = mb_strtolower($username); - if ($this->bad_char_regex){ + if ($this->username_case_insensitiv) $username = mb_strtolower($username); + if ($this->bad_char_regex) { return preg_replace($this->bad_char_regex, '', $username); } else { return trim($username); @@ -490,32 +485,33 @@ class StudipAuthAbstract { } /** - * method to check, if username is used - * - * abstract MUST be realized - * - * @access private - * @param string the username - * @return bool true if the username exists - */ + * method to check, if username is used + * + * abstract MUST be realized + * + * @access private + * @param string the username + * @return bool true if the username exists + */ function isUsedUsername($username) { - $this->error_msg = sprintf(_("Methode %s nicht implementiert!"),get_class($this) . "::isUsedUsername()"); + $this->error_msg = sprintf(_('Methode %s nicht implementiert!'), get_class($this) . '::isUsedUsername()'); return false; } /** - * method to check the authentication of a given username and a given password - * - * abstract, MUST be realized - * - * @access private - * @param string the username - * @param string the password - * @return bool true if authentication succeeds - */ - function isAuthenticated($username, $password) { - $this->error = sprintf(_("Methode %s nicht implementiert!"),get_class($this) . "::isAuthenticated()"); + * method to check the authentication of a given username and a given password + * + * abstract, MUST be realized + * + * @access private + * @param string the username + * @param string the password + * @return bool true if authentication succeeds + */ + function isAuthenticated($username, $password) + { + $this->error = sprintf(_('Methode %s nicht implementiert!'), get_class($this) . '::isAuthenticated()'); return false; } } diff --git a/lib/classes/auth_plugins/StudipAuthCAS.class.php b/lib/classes/auth_plugins/StudipAuthCAS.class.php index d28cc3e7711d041593aab71f1857fb90523f4334..620f12e19ce211fe2509e13b5d3c170bd20dc5a0 100644 --- a/lib/classes/auth_plugins/StudipAuthCAS.class.php +++ b/lib/classes/auth_plugins/StudipAuthCAS.class.php @@ -3,37 +3,43 @@ # Lifter003: TODO # Lifter010: TODO /** -* Stud.IP authentication against CAS Server -* -* @access public -* @author Dennis Reil <dennis.reil@offis.de> -* @package -*/ + * Stud.IP authentication against CAS Server + * + * @access public + * @author Dennis Reil <dennis.reil@offis.de> + * @package + */ require_once 'composer/jasig/phpcas/CAS.php'; require_once 'lib/classes/cas/CAS_PGTStorage_Cache.php'; -class StudipAuthCAS extends StudipAuthSSO { +class StudipAuthCAS extends StudipAuthSSO +{ - var $host; - var $port; - var $uri; - var $cacert; + public $host; + public $port; + public $uri; + public $cacert; - var $cas; - var $userdata; + public $cas; + public $userdata; /** - * Constructor - * - * - * @access public - * - */ - function __construct() { - parent::__construct(); - - if (Request::option('sso')) { + * Constructor + * + * + * + */ + public function __construct($config = []) + { + parent::__construct($config); + if (!isset($this->plugin_fullname)) { + $this->plugin_fullname = _('CAS'); + } + if (!isset($this->login_description)) { + $this->login_description = _('für Single Sign On mit CAS'); + } + if (Request::get('sso') === $this->plugin_name) { $this->cas = new CAS_Client(CAS_VERSION_2_0, $this->proxy, $this->host, $this->port, $this->uri, false); if ($this->proxy) { @@ -68,22 +74,22 @@ class StudipAuthCAS extends StudipAuthSSO { return $this->getUser(); } - function getUserData($key){ - $userdataclassname = $GLOBALS["STUDIP_AUTH_CONFIG_CAS"]["user_data_mapping_class"]; - if (empty($userdataclassname)){ - echo ("ERROR: no userdataclassname specified."); + function getUserData($key) + { + $userdataclassname = $this->user_data_mapping_class; + if (!class_exists($userdataclassname)) { + Log::ERROR($this->plugin_name . ': no userdataclassname specified or found.'); return; } - require_once($userdataclassname . ".class.php"); // get the userdata - if (empty($this->userdata)){ + if (empty($this->userdata)) { $this->userdata = new $userdataclassname(); } - $result = $this->userdata->getUserData($key, $this->cas->getUser()); - return $result; + return $this->userdata->getUserData($key, $this->cas->getUser()); } - function logout(){ + function logout() + { // do a global cas logout $this->cas = new CAS_Client(CAS_VERSION_2_0, false, $this->host, $this->port, $this->uri, false); $this->cas->logout(); diff --git a/lib/classes/auth_plugins/StudipAuthLdap.class.php b/lib/classes/auth_plugins/StudipAuthLdap.class.php index 3958560e738a5b5b30b58f8da9a175e8d23baf8e..5721cf44e87980166f901dc3d85062ae80dbca32 100644 --- a/lib/classes/auth_plugins/StudipAuthLdap.class.php +++ b/lib/classes/auth_plugins/StudipAuthLdap.class.php @@ -1,7 +1,4 @@ <?php -# Lifter007: TODO -# Lifter003: TODO -# Lifter010: TODO // +---------------------------------------------------------------------------+ // This file is part of Stud.IP // StudipAuthLdap.class.php @@ -25,39 +22,27 @@ // +---------------------------------------------------------------------------+ /** -* Stud.IP authentication against LDAP Server -* -* Stud.IP authentication against LDAP Server -* -* @access public -* @author André Noack <noack@data-quest.de> -* @package -*/ -class StudipAuthLdap extends StudipAuthAbstract { - - var $anonymous_bind = true; - - var $host; - var $base_dn; - var $username_attribute = 'uid'; - var $ldap_filter; - var $bad_char_regex = '/[^0-9_a-zA-Z]/'; - - var $conn = null; - var $user_data = null; + * Stud.IP authentication against LDAP Server + * + * Stud.IP authentication against LDAP Server + * + * @access public + * @author André Noack <noack@data-quest.de> + * @package + */ +class StudipAuthLdap extends StudipAuthAbstract +{ - /** - * Constructor - * - * - * @access public - * - */ - function __construct() - { - //calling the baseclass constructor - parent::__construct(); - } + public $anonymous_bind = true; + + public $host; + public $base_dn; + public $username_attribute = 'uid'; + public $ldap_filter; + public $bad_char_regex = '/[^0-9_a-zA-Z]/'; + + public $conn = null; + public $user_data = null; function getLdapFilter($username) @@ -76,16 +61,16 @@ class StudipAuthLdap extends StudipAuthAbstract { function doLdapConnect() { if (!($this->conn = ldap_connect($this->host))) { - $this->error_msg = _("Keine Verbindung zum LDAP Server möglich."); + $this->error_msg = _('Keine Verbindung zum LDAP Server möglich.'); return false; } - if (!($r = ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3))){ - $this->error_msg = _("Setzen der LDAP Protokolversion fehlgeschlagen."); + if (!($r = ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3))) { + $this->error_msg = _('Setzen der LDAP Protokolversion fehlgeschlagen.'); return false; } if ($this->start_tls) { if (!ldap_start_tls($this->conn)) { - $this->error_msg = _("\"Start TLS\" fehlgeschlagen."); + $this->error_msg = _('"Start TLS" fehlgeschlagen.'); return false; } } @@ -94,60 +79,60 @@ class StudipAuthLdap extends StudipAuthAbstract { function getUserDn($username) { - $user_dn = ""; + $user_dn = ''; - if ($this->anonymous_bind){ - if (!($r = @ldap_bind($this->conn))){ - $this->error_msg =_("Anonymer Bind fehlgeschlagen.") . $this->getLdapError(); + if ($this->anonymous_bind) { + if (!($r = @ldap_bind($this->conn))) { + $this->error_msg = _('Anonymer Bind fehlgeschlagen.') . $this->getLdapError(); return false; } - if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))){ - $this->error_msg = _("Anonymes Durchsuchen des LDAP Baumes fehlgeschlagen.") .$this->getLdapError(); + if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))) { + $this->error_msg = _('Anonymes Durchsuchen des LDAP Baumes fehlgeschlagen.') . $this->getLdapError(); return false; } - if (!ldap_count_entries($this->conn, $result)){ - $this->error_msg = sprintf(_("%s wurde nicht unterhalb von %s gefunden."), $username, $this->base_dn); + if (!ldap_count_entries($this->conn, $result)) { + $this->error_msg = sprintf(_('%s wurde nicht unterhalb von %s gefunden.'), $username, $this->base_dn); return false; } - if (!($entry = @ldap_first_entry($this->conn, $result))){ + if (!($entry = @ldap_first_entry($this->conn, $result))) { $this->error_msg = $this->getLdapError(); return false; } - if (!($user_dn = @ldap_get_dn($this->conn, $entry))){ + if (!($user_dn = @ldap_get_dn($this->conn, $entry))) { $this->error_msg = $this->getLdapError(); return false; } } else { - $user_dn = $this->username_attribute . "=" . $username . "," . $this->base_dn; + $user_dn = $this->username_attribute . '=' . $username . ',' . $this->base_dn; } return $user_dn; } function doLdapBind($username, $password) { - if (!$this->doLdapConnect()){ + if (!$this->doLdapConnect()) { return false; } - if (!($user_dn = $this->getUserDn($username))){ + if (!($user_dn = $this->getUserDn($username))) { return false; } - if (!$password){ - $this->error_msg = _("Kein Passwort eingegeben."); //some ldap servers seem to allow binding with a user dn and without a password, if anonymous bind is enabled + if (!$password) { + $this->error_msg = _('Kein Passwort eingegeben.'); //some ldap servers seem to allow binding with a user dn and without a password, if anonymous bind is enabled return false; } - if (!($r = @ldap_bind($this->conn, $user_dn, $password))){ - if(ldap_errno($this->conn) == 49) { - $this->error_msg = _("Bitte überprüfen Sie ihre Zugangsdaten."); + if (!($r = @ldap_bind($this->conn, $user_dn, $password))) { + if (ldap_errno($this->conn) == 49) { + $this->error_msg = _('Bitte überprüfen Sie ihre Zugangsdaten.'); } - $this->error_msg = _("Anmeldung fehlgeschlagen.") . $this->getLdapError(); + $this->error_msg = _('Anmeldung fehlgeschlagen.') . $this->getLdapError(); return false; } - if (!($result = @ldap_search($this->conn, $user_dn, "objectclass=*"))){ - $this->error_msg = _("Abholen der Benutzer Attribute fehlgeschlagen.") .$this->getLdapError(); + if (!($result = @ldap_search($this->conn, $user_dn, 'objectclass=*'))) { + $this->error_msg = _('Abholen der Benutzer Attribute fehlgeschlagen.') . $this->getLdapError(); return false; } - if (@ldap_count_entries($this->conn, $result)){ - if (!($info = @ldap_get_entries($this->conn, $result))){ + if (@ldap_count_entries($this->conn, $result)) { + if (!($info = @ldap_get_entries($this->conn, $result))) { $this->error_msg = $this->getLdapError(); return false; } @@ -157,15 +142,15 @@ class StudipAuthLdap extends StudipAuthAbstract { } /** - * - * - * - * @access private - * - */ + * + * + * + * @access private + * + */ function isAuthenticated($username, $password) { - if (!$this->doLdapBind($username,$password)){ + if (!$this->doLdapBind($username, $password)) { ldap_unbind($this->conn); return false; } @@ -174,12 +159,11 @@ class StudipAuthLdap extends StudipAuthAbstract { } - function doLdapMap($map_params) { if (isset($this->user_data[$map_params][0])) { $ret = $this->user_data[$map_params][0]; - if ($ret[0] == ':') { + if ($ret[0] === ':') { $ret = base64_decode($ret); } } @@ -202,23 +186,23 @@ class StudipAuthLdap extends StudipAuthAbstract { function isUsedUsername($username) { - if (!$this->anonymous_bind){ - $this->error = _("Kann den Benutzernamen nicht überprüfen, anonymous_bind ist ausgeschaltet!"); + if (!$this->anonymous_bind) { + $this->error = _('Kann den Benutzernamen nicht überprüfen, anonymous_bind ist ausgeschaltet!'); return false; } - if (!$this->doLdapConnect()){ + if (!$this->doLdapConnect()) { return false; } - if (!($r = @ldap_bind($this->conn))){ - $this->error = _("Anonymer Bind fehlgeschlagen.") . $this->getLdapError(); + if (!($r = @ldap_bind($this->conn))) { + $this->error = _('Anonymer Bind fehlgeschlagen.') . $this->getLdapError(); return false; } - if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))){ - $this->error = _("Anonymes Durchsuchen des LDAP Baumes fehlgeschlagen.") .$this->getLdapError(); + if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))) { + $this->error = _('Anonymes Durchsuchen des LDAP Baumes fehlgeschlagen.') . $this->getLdapError(); return false; } - if (!ldap_count_entries($this->conn, $result)){ - $this->error_msg = _("Der Benutzername wurde nicht gefunden."); + if (!ldap_count_entries($this->conn, $result)) { + $this->error_msg = _('Der Benutzername wurde nicht gefunden.'); return false; } return true; @@ -226,6 +210,6 @@ class StudipAuthLdap extends StudipAuthAbstract { function getLdapError() { - return _("<br>LDAP Fehler: ") . ldap_error($this->conn) ." (#" . ldap_errno($this->conn) . ")"; + return _('<br>LDAP Fehler: ') . ldap_error($this->conn) . ' (#' . ldap_errno($this->conn) . ')'; } } diff --git a/lib/classes/auth_plugins/StudipAuthLdapReadAndBind.class.php b/lib/classes/auth_plugins/StudipAuthLdapReadAndBind.class.php index 25e87399d648bf27f95f9853e81b171e756ef413..742f0cba4a65177ccd5fb0421a3e50d5b0d7a050 100644 --- a/lib/classes/auth_plugins/StudipAuthLdapReadAndBind.class.php +++ b/lib/classes/auth_plugins/StudipAuthLdapReadAndBind.class.php @@ -26,61 +26,51 @@ // +---------------------------------------------------------------------------+ /** -* Stud.IP authentication against LDAP Server -* -* Stud.IP authentication against LDAP Server using read-only account and -* following user bind -* -* @access public -* @author André Noack <noack@data-quest.de> -* @package -*/ -class StudipAuthLdapReadAndBind extends StudipAuthLdap { + * Stud.IP authentication against LDAP Server + * + * Stud.IP authentication against LDAP Server using read-only account and + * following user bind + * + * @access public + * @author André Noack <noack@data-quest.de> + * @package + */ +class StudipAuthLdapReadAndBind extends StudipAuthLdap +{ - var $anonymous_bind = false; + public $anonymous_bind = false; - var $reader_dn; - var $reader_password; + public $reader_dn; + public $reader_password; - /** - * Constructor - * - * - * @access public - * - */ - function __construct() { - //calling the baseclass constructor - parent::__construct(); - } - - - function getUserDn($username){ - $user_dn = ""; - if (!($r = @ldap_bind($this->conn, $this->reader_dn, $this->reader_password))){ - $this->error_msg = sprintf(_("Anmeldung von %s fehlgeschlagen."),$this->reader_dn) . $this->getLdapError(); + function getUserDn($username) + { + $user_dn = ''; + if (!($r = @ldap_bind($this->conn, $this->reader_dn, $this->reader_password))) { + $this->error_msg = sprintf(_('Anmeldung von %s fehlgeschlagen.'), $this->reader_dn) . $this->getLdapError(); return false; } - if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))){ - $this->error_msg = _("Durchsuchen des LDAP Baumes fehlgeschlagen.") .$this->getLdapError(); + if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))) { + $this->error_msg = _('Durchsuchen des LDAP Baumes fehlgeschlagen.') . $this->getLdapError(); return false; } - if (!ldap_count_entries($this->conn, $result)){ - $this->error_msg = sprintf(_("%s wurde nicht unterhalb von %s gefunden."), $username, $this->base_dn); + if (!ldap_count_entries($this->conn, $result)) { + $this->error_msg = sprintf(_('%s wurde nicht unterhalb von %s gefunden.'), $username, $this->base_dn); return false; } - if (!($entry = @ldap_first_entry($this->conn, $result))){ + if (!($entry = @ldap_first_entry($this->conn, $result))) { $this->error_msg = $this->getLdapError(); return false; } - if (!($user_dn = @ldap_get_dn($this->conn, $entry))){ + if (!($user_dn = @ldap_get_dn($this->conn, $entry))) { $this->error_msg = $this->getLdapError(); return false; } return $user_dn; } - function isUsedUsername($username){ + function isUsedUsername($username) + { if (!$this->doLdapConnect()) { return false; } diff --git a/lib/classes/auth_plugins/StudipAuthOIDC.class.php b/lib/classes/auth_plugins/StudipAuthOIDC.class.php new file mode 100644 index 0000000000000000000000000000000000000000..adfe9c9a4b092fa848b2fb7bdce4ecfae5e8331f --- /dev/null +++ b/lib/classes/auth_plugins/StudipAuthOIDC.class.php @@ -0,0 +1,112 @@ +<?php +/* + * StudipAuthOpenID.class.php - Stud.IP authentication using OpenID Connect + * Copyright (c) 2021 André Noack <noack@data-quest.de> + * + * 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 the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +use Jumbojett\OpenIDConnectClient; +use Jumbojett\OpenIDConnectClientException; + +class StudipAuthOIDC extends StudipAuthSSO +{ + /** + * @var OpenIDConnectClient + */ + private $oidc; + + /** + * @var string + */ + public $provider_url; + /** + * @var string + */ + public $client_id; + /** + * @var string + */ + public $client_secret; + + + /** + * @param array $config + */ + public function __construct($config = []) + { + parent::__construct($config); + if (Request::get('sso') === $this->plugin_name) { + $this->oidc = new OpenIDConnectClient($this->provider_url, $this->client_id, $this->client_secret); + if (isset($this->ssl_options)) { + foreach ($this->ssl_options as $option_key => $option_value) { + if (isset($option_value)) { + $this->oidc->{'set' . $option_key}($option_value); + } + } + if (Config::get()->HTTP_PROXY) { + $this->oidc->setHttpProxy(Config::get()->HTTP_PROXY); + } + $return_url = URLHelper::getScriptURL($GLOBALS['ABSOLUTE_URI_STUDIP'] . 'index.php', ['sso' => $this->plugin_name, 'again' => 'yes']); + $this->oidc->setRedirectURL($return_url); + $this->oidc->addScope(['openid', 'email', 'profile']); + } + } + } + + /** + * Validate the username passed to the auth plugin. + * + * @param string $username + * + * @return string username openid attribute user_id@domain + * + * @throws OpenIDConnectClientException + */ + public function verifyUsername($username) + { + + $this->oidc->authenticate(); + $this->userdata = (array)$this->oidc->requestUserInfo(); + if (isset($this->userdata['sub'])) { + return $this->userdata['username'] = $this->userdata['sub'] . '@' . $this->domain; + } else { + return null; + } + } + + /** + * Return the current username of the pending authentication request. + */ + public function getUser() + { + return $this->userdata['username']; + } + + /** + * Get the user domains to assign to the current user (if any). + * + * @return array array of user domain names + */ + public function getUserDomains() + { + return $this->domain ? [$this->domain] : null; + } + + /** + * Callback that can be used in user_data_mapping array. + * + * @see https://openid.net/specs/openid-connect-basic-1_0.html#StandardClaims + * + * @param string key + * + * @return string parameter value (null if not set) + */ + public function getUserData($key) + { + return $this->userdata[$key]; + } +} diff --git a/lib/classes/auth_plugins/StudipAuthSSO.class.php b/lib/classes/auth_plugins/StudipAuthSSO.class.php index 65e8cd1c14f8eb816fbfb3aaab3f47203a054505..752fa59a1b45511d14ddf5c47f3bde2b7e5ba8fe 100644 --- a/lib/classes/auth_plugins/StudipAuthSSO.class.php +++ b/lib/classes/auth_plugins/StudipAuthSSO.class.php @@ -17,6 +17,16 @@ */ abstract class StudipAuthSSO extends StudipAuthAbstract { + /** + * @var string the descriptive name of the authentication plugin + */ + public $plugin_fullname; + + /** + * @var string a short description, when present it is shown on the login page + */ + public $login_description; + /** * Return the current username. */ diff --git a/lib/classes/auth_plugins/StudipAuthShib.class.php b/lib/classes/auth_plugins/StudipAuthShib.class.php index 5ac00ed365a3ed9fd26d531d15013667ff26e29b..8f31eef5237337670bbe55b604f553de4aabdce6 100644 --- a/lib/classes/auth_plugins/StudipAuthShib.class.php +++ b/lib/classes/auth_plugins/StudipAuthShib.class.php @@ -14,28 +14,39 @@ class StudipAuthShib extends StudipAuthSSO { - var $env_remote_user = 'HTTP_REMOTE_USER'; - var $local_domain; - var $session_initiator; - var $validate_url; - var $userdata; + public $env_remote_user = 'HTTP_REMOTE_USER'; + public $local_domain; + public $session_initiator; + public $validate_url; + public $userdata; + public $username_attribute = 'username'; /** * Constructor: read auth information from remote SP. */ - function __construct() + public function __construct($config = []) { - parent::__construct(); + parent::__construct($config); - if (Request::option('sso') && isset($this->validate_url) && isset($_REQUEST['token'])) { + if (!isset($this->plugin_fullname)) { + $this->plugin_fullname = _('Shibboleth'); + } + if (!isset($this->login_description)) { + $this->login_description = _('für Single Sign On mit Shibboleth'); + } + + if (Request::get('sso') === $this->plugin_name && isset($this->validate_url) && isset($_REQUEST['token'])) { $context = get_default_http_stream_context($this->validate_url); - $auth = file_get_contents($this->validate_url.'/'.$_REQUEST['token'], false, $context); + $auth = file_get_contents($this->validate_url . '/' . $_REQUEST['token'], false, $context); $this->userdata = json_decode($auth, true); + if ($this->username_attribute !== 'username') { + $this->userdata['username'] = $this->userdata[$this->username_attribute]; + } if (isset($this->local_domain)) { $this->userdata['username'] = - str_replace('@'.$this->local_domain, '', $this->userdata['username']); + str_replace('@' . $this->local_domain, '', $this->userdata['username']); } } } @@ -43,7 +54,7 @@ class StudipAuthShib extends StudipAuthSSO /** * Return the current username. */ - function getUser () + function getUser() { return $this->userdata['username']; } @@ -51,7 +62,7 @@ class StudipAuthShib extends StudipAuthSSO /** * Return the current URL (including parameters). */ - function getURL () + function getURL() { $url = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http'; $url .= '://'; @@ -64,7 +75,7 @@ class StudipAuthShib extends StudipAuthSSO if ($_SERVER['HTTPS'] == 'on' && $_SERVER['SERVER_PORT'] != 443 || $_SERVER['HTTPS'] != 'on' && $_SERVER['SERVER_PORT'] != 80) { - $url .= ':'.$_SERVER['SERVER_PORT']; + $url .= ':' . $_SERVER['SERVER_PORT']; } $url .= $_SERVER['REQUEST_URI']; @@ -75,7 +86,7 @@ class StudipAuthShib extends StudipAuthSSO * Validate the username passed to the auth plugin. * Note: This triggers authentication if needed. */ - function verifyUsername ($username) + function verifyUsername($username) { if (isset($this->userdata)) { // use cached user information @@ -89,15 +100,15 @@ class StudipAuthShib extends StudipAuthSSO } if (empty($remote_user) || isset($this->validate_url)) { - if ($_REQUEST['sso'] == 'shib') { + if (Request::get('sso') === $this->plugin_name) { // force Shibboleth authentication (lazy session) $shib_url = $this->session_initiator; - $shib_url .= mb_strpos($shib_url, '?') === false ? '?' : '&'; - $shib_url .= 'target='.urlencode($this->getURL()); + $shib_url .= strpos($shib_url, '?') === false ? '?' : '&'; + $shib_url .= 'target=' . urlencode($this->getURL()); // break redirection loop in case of misconfiguration - if (mb_strstr($_SERVER['HTTP_REFERER'], 'target=') == false) { - header('Location: '.$shib_url); + if (strstr($_SERVER['HTTP_REFERER'], 'target=') === false) { + header('Location: ' . $shib_url); echo '<html></html>'; exit(); } @@ -107,10 +118,6 @@ class StudipAuthShib extends StudipAuthSSO return NULL; } - if (isset($this->local_domain)) { - $remote_user = str_replace('@'.$this->local_domain, '', $remote_user); - } - // import authentication information $this->userdata['username'] = $remote_user; @@ -121,13 +128,20 @@ class StudipAuthShib extends StudipAuthSSO } } + if ($this->username_attribute !== 'username') { + $this->userdata['username'] = $this->userdata[$this->username_attribute]; + } + if (isset($this->local_domain)) { + $this->userdata['username'] = + str_replace('@' . $this->local_domain, '', $this->userdata['username']); + } return $this->getUser(); } /** * Get the user domains to assign to the current user. */ - function getUserDomains () + function getUserDomains() { $user = $this->getUser(); $pos = mb_strpos($user, '@'); @@ -142,7 +156,7 @@ class StudipAuthShib extends StudipAuthSSO /** * Callback that can be used in user_data_mapping array. */ - function getUserData ($key) + function getUserData($key) { $data = explode(';', $this->userdata[$key]); diff --git a/lib/classes/auth_plugins/StudipAuthStandard.class.php b/lib/classes/auth_plugins/StudipAuthStandard.class.php index c195053cfc99d6bfd46c18ecbc0eac9447bdf9df..1a2c2bae5569f73a6d41f150ffe841e70867325d 100644 --- a/lib/classes/auth_plugins/StudipAuthStandard.class.php +++ b/lib/classes/auth_plugins/StudipAuthStandard.class.php @@ -38,18 +38,6 @@ class StudipAuthStandard extends StudipAuthAbstract var $bad_char_regex = false; - /** - * Constructor - * - * - * @access public - * - */ - function __construct() - { - parent::__construct(); - } - /** * * @@ -61,19 +49,19 @@ class StudipAuthStandard extends StudipAuthAbstract { $user = User::findByUsername($username); if (!$user || !$password || mb_strlen($password) > 72) { - $this->error_msg= _("Ungültige Benutzername/Passwort-Kombination!") ; + $this->error_msg= _('Ungültige Benutzername/Passwort-Kombination!') ; return false; - } elseif ($user->username != $username) { - $this->error_msg = _("Bitte achten Sie auf korrekte Groß-Kleinschreibung beim Username!"); + } elseif ($user->username !== $username) { + $this->error_msg = _('Bitte achten Sie auf korrekte Groß-Kleinschreibung beim Username!'); return false; - } elseif (!is_null($user->auth_plugin) && $user->auth_plugin != "standard") { - $this->error_msg = sprintf(_("Dieser Benutzername wird bereits über %s authentifiziert!"),$user->auth_plugin) ; + } elseif (!is_null($user->auth_plugin) && $user->auth_plugin !== 'standard') { + $this->error_msg = sprintf(_('Dieser Benutzername wird bereits über %s authentifiziert!'),$user->auth_plugin) ; return false; } else { $pass = $user->password; // Password is stored as a md5 hash } $hasher = UserManagement::getPwdHasher(); - $old_style_check = (mb_strlen($pass) == 32 && md5($password) == $pass); + $old_style_check = (strlen($pass) === 32 && md5($password) === $pass); $migrated_check = $hasher->CheckPassword(md5($password), $pass); $check = $hasher->CheckPassword($password, $pass); $old_encoding_check = $hasher->CheckPassword(legacy_studip_utf8decode($password), $pass); @@ -85,7 +73,7 @@ class StudipAuthStandard extends StudipAuthAbstract } if (!($check || $migrated_check || $old_style_check || $old_encoding_check)) { - $this->error_msg= _("Das Passwort ist falsch!"); + $this->error_msg= _('Das Passwort ist falsch!'); return false; } else { return true; diff --git a/lib/navigation/LoginNavigation.php b/lib/navigation/LoginNavigation.php index cc6372bace3530f003407b6e14ef93f3f6b2e0bc..db212364ccc0141dd244624231f51318b40172f9 100644 --- a/lib/navigation/LoginNavigation.php +++ b/lib/navigation/LoginNavigation.php @@ -27,16 +27,12 @@ class LoginNavigation extends Navigation $navigation->setDescription(_('für registrierte NutzerInnen')); $this->addSubNavigation('login', $navigation); - if (in_array('CAS', $GLOBALS['STUDIP_AUTH_PLUGIN'])) { - $navigation = new Navigation(_('Login'), 'index.php?again=yes&sso=cas'); - $navigation->setDescription(_('für Single Sign On mit CAS')); - $this->addSubNavigation('login_cas', $navigation); - } - - if (in_array('Shib', $GLOBALS['STUDIP_AUTH_PLUGIN'])) { - $navigation = new Navigation(_('Shibboleth Login'), 'index.php?again=yes&sso=shib'); - $navigation->setDescription(_('für Single Sign On mit Shibboleth')); - $this->addSubNavigation('login_shib', $navigation); + foreach (StudipAuthAbstract::getInstance() as $auth_plugin) { + if ($auth_plugin instanceof StudipAuthSSO && isset($auth_plugin->login_description)) { + $navigation = new Navigation($auth_plugin->plugin_fullname . ' ' . _('Login'), 'index.php?again=yes&sso=' . $auth_plugin->plugin_name); + $navigation->setDescription($auth_plugin->login_description); + $this->addSubNavigation('login_' . $auth_plugin->plugin_name, $navigation); + } } if (Config::get()->ENABLE_SELF_REGISTRATION) {