Skip to content
Snippets Groups Projects
Select Git revision
  • f9248db346f5b647c7c9e32b99cf6ef1faca2f52
  • main default protected
  • studip-rector
  • ci-opt
  • course-members-export-as-word
  • data-vue-app
  • pipeline-improvements
  • webpack-optimizations
  • rector
  • icon-renewal
  • http-client-and-factories
  • jsonapi-atomic-operations
  • vueify-messages
  • tic-2341
  • 135-translatable-study-areas
  • extensible-sorm-action-parameters
  • sorm-configuration-trait
  • jsonapi-mvv-routes
  • docblocks-for-magic-methods
19 results

PrivateKeys.php

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    Seminar_Auth.class.php 13.29 KiB
    <?php
    
    /**
     * Seminar_Auth.class.php
     *
     *
     * 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.
     *
     * @author      André Noack <noack@data-quest.de>
     * @copyright   2000 Stud.IP Core-Group
     * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
     */
    class Seminar_Auth
    {
        /**
         * @var string
         */
        public $classname;
    
        /**
         * @var string
         */
        public $error_msg = "";
    
        /**
         * @var array
         */
        protected $persistent_slots = ["auth", "classname"];
    
        /**
         * @var bool
         */
        protected $nobody = false; ## If true, a default auth is created...
    
        /**
         * @var string
         */
        protected $cancel_login = "cancel_login"; ## The name of a button that can be
        ## used to cancel a login form
        /**
         * @var array
         */
        public $auth = []; ## Data array
    
        /**
         *
         */
        function __construct()
        {
            $this->classname = get_class($this);
        }
    
        /**
         * @param $f
         * @return $this
         */
        function check_feature($f)
        {
            if ($this->classname != $f) {
                $clone = new $f;
                $clone->auth = $this->auth;
                return $clone;
            } else {
                return $this;
            }
        }
    
        /**
         * Check current auth state. Should be one of
         * 1) Not logged in (no valid auth info or auth expired)
         * 2) Logged in (valid auth info)
         * 3) Login in progress (if $this->cancel_login, revert to state 1)
    
         * @return int
         */
        protected function getState(): int
        {
            if ($this->is_authenticated()) {
                $uid = $this->auth['uid'];
                switch ($uid) {
                    case 'form':
                        # Login in progress
                        if (Request::option($this->cancel_login)) {
                            # If $this->cancel_login is set, delete all auth info and set
                            # state to "Not logged in", so eventually default or automatic
                            # authentication may take place
                            $this->unauth();
                            $state = 1;
                        } else {
                            # Set state to "Login in progress"
                            $state = 3;
                        }
                        break;
                    default:
                        # User is authenticated and auth not expired
                        $state = 2;
                        break;
                }
            } else {
                # User is not (yet) authenticated
                $this->unauth();
                $state = 1;
            }
    
            return $state;
        }
    
        /**
         * @return bool
         * @throws RuntimeException
         */
        public function start()
        {
            global $sess;
    
            switch ($this->getState()) {
                case 1:
                    # No valid auth info or auth is expired
    
                    # Check for user supplied automatic login procedure
                    if ($uid = $this->auth_preauth()) {
                        $this->auth["uid"] = $uid;
                        $sess->regenerate_session_id(['auth', '_language', 'phpCAS', 'contrast']);
                        $sess->freeze();
                        $GLOBALS['user'] = new Seminar_User($this->auth['uid']);
                        return true;
                    }
    
                    if ($this->nobody) {
                        # Authenticate as nobody
                        $this->auth["uid"] = "nobody";
                        return true;
                    } else {
                        # Show the login form
                        $this->auth_loginform();
                        $this->auth["uid"] = "form";
                        $sess->freeze();
                        exit;
                    }
                case 2:
                    # Valid auth info
                    # do nothin
                    break;
                case 3:
                    # Login in progress, check results and act accordingly
                    $uid = $this->auth_validatelogin();
                    if ($uid) {
                        $this->auth["uid"] = $uid;
                        $keep_session_vars = ['auth', 'forced_language', '_language', 'contrast'];
                        if ($this->auth['perm'] === 'root') {
                            $keep_session_vars[] = 'plugins_disabled';
                        }
                        $sess->regenerate_session_id($keep_session_vars);
                        $sess->freeze();
                        $GLOBALS['user'] = new Seminar_User($this->auth['uid']);
                        return true;
                    } else {
                        $this->auth_loginform();
                        $this->auth["uid"] = "form";
                        $sess->freeze();
                        exit;
                    }
                default:
                    # This should never happen. Complain.
                    throw new RuntimeException("Error in auth handling: invalid state reached.");
            }
    
            return false;
        }
    
    
        /**
         * @return array
         */
        function __sleep()
        {
            return $this->persistent_slots;
        }
    
    
        /**
         *
         */
        function unauth()
        {
            $this->auth = [];
            $this->auth["uid"] = "";
            $this->auth["perm"] = "";
        }
    
    
        /**
         *
         */
        function logout()
        {
            $_SESSION['auth'] = null;
            $this->unauth();
            $GLOBALS['auth'] = $this;
        }
    
        /**
         * @param $ok
         * @return bool
         */
        function login_if($ok)
        {
            if ($ok) {
                $this->unauth(); # We have to relogin, so clear current auth info
                $this->nobody = false; # We are forcing login, so default auth is
                # disabled
                $this->start(); # Call authentication code
            }
            return true;
        }
    
        /**
         * @return bool
         * @throws AccessDeniedException
         */
        function is_authenticated()
        {
            $cfg = Config::GetInstance();
            //check if the user got kicked meanwhile, or if user is locked out
            if (!empty($this->auth['uid']) && !in_array($this->auth['uid'], ['form', 'nobody'])) {
                $user = null;
                if (isset($GLOBALS['user']) && $GLOBALS['user']->id == $this->auth['uid']) {
                    $user = $GLOBALS['user'];
                } else {
                    $user = User::find($this->auth['uid']);
                }
                $exp_d = $user->username ? UserConfig::get($user->id)->EXPIRATION_DATE : 0;
                if (!$user->username || $user->locked || ($exp_d > 0 && $exp_d < time())) {
                    $this->unauth();
                }
            } elseif ($cfg->getValue('MAINTENANCE_MODE_ENABLE') && Request::username('loginname')) {
                $user = User::findByUsername(Request::username('loginname'));
            }
            if ($cfg->getValue('MAINTENANCE_MODE_ENABLE') && $user->perms != 'root') {
                $this->unauth();
                throw new AccessDeniedException(_("Das System befindet sich im Wartungsmodus. Zur Zeit ist kein Zugriff möglich."));
            }
            return @$this->auth['uid'] ? : false;
        }
    
        /**
         * @return bool
         */
        function auth_preauth()
        {
            // is Single Sign On activated?
            if (($provider = Request::option('sso'))) {
    
                $this->check_environment();
    
                Metrics::increment('core.sso_login.attempted');
    
                // then do login
                if (($authplugin = StudipAuthAbstract::GetInstance($provider))) {
                    $authplugin->authenticateUser('', '');
                    if ($authplugin->getUser()) {
                        $user = $authplugin->getStudipUser($authplugin->getUser());
                        $exp_d = UserConfig::get($user->id)->EXPIRATION_DATE;
                        if ($exp_d > 0 && $exp_d < time()) {
                            throw new AccessDeniedException(_('Dieses Benutzerkonto ist abgelaufen. Wenden Sie sich bitte an die Administration.'));
                        }
                        if ($user->locked == 1) {
                            throw new AccessDeniedException(_('Dieser Benutzer ist gesperrt! Wenden Sie sich bitte an die Administration.'));
                        }
                        $this->auth["jscript"] = true;
                        $this->auth["perm"] = $user->perms;
                        $this->auth["uname"] = $user->username;
                        $this->auth["auth_plugin"] = $user->auth_plugin;
                        $this->auth_set_user_settings($user);
    
                        Metrics::increment('core.sso_login.succeeded');
    
                        return $user->id;
                    }
                }
            }
    
            return false;
        }
    
        /**
         *
         */
        function auth_loginform()
        {
            if (Request::isXhr()) {
                if (Request::isDialog()) {
                    header('X-Location: ' . URLHelper::getURL($_SERVER['REQUEST_URI']));
                    page_close();
                    die();
                }
                throw new AccessDeniedException();
            }
    
            $this->check_environment();
    
            PageLayout::setBodyElementId('login');
    
            // load the default set of plugins
            PluginEngine::loadPlugins();
    
            if (Request::get('loginname') && !$_COOKIE[get_class($GLOBALS['sess'])]) {
                $login_template = $GLOBALS['template_factory']->open('nocookies');
            } else if (isset($this->need_email_activation)) {
                $this->unauth();
                header('Location: ' . URLHelper::getURL('activate_email.php?cancel_login=1&key=&uid=' . $this->need_email_activation));
                page_close();
                die();
            } else {
                unset($_SESSION['semi_logged_in']); // used by email activation
                $login_template = $GLOBALS['template_factory']->open('loginform');
                $login_template->set_attribute('loginerror', (isset($this->auth["uname"]) && $this->error_msg));
                $login_template->set_attribute('error_msg', $this->error_msg);
                $login_template->set_attribute('uname', (isset($this->auth["uname"]) ? $this->auth["uname"] : Request::username('loginname')));
                $login_template->set_attribute('self_registration_activated', Config::get()->ENABLE_SELF_REGISTRATION);
            }
            PageLayout::setHelpKeyword('Basis.AnmeldungLogin');
            $header_template = $GLOBALS['template_factory']->open('header');
            $header_template->current_page = _('Login');
            $header_template->link_params = ['cancel_login' => 1];
    
            include 'lib/include/html_head.inc.php';
            echo $header_template->render();
            echo $login_template->render();
            include 'lib/include/html_end.inc.php';
            page_close();
        }
    
        /**
         * @return bool
         */
        function auth_validatelogin()
        {
            //prevent replay attack
            if (!Seminar_Session::check_ticket(Request::option('login_ticket'))) {
                return false;
            }
    
            $this->check_environment();
    
            $this->auth["uname"] = Request::get('loginname'); // This provides access for "loginform.ihtml"
            $this->auth["jscript"] = Request::get('resolution') != "";
            $this->auth['devicePixelRatio'] = Request::float('device_pixel_ratio');
    
            $check_auth = StudipAuthAbstract::CheckAuthentication(Request::get('loginname'), Request::get('password'));
    
            if ($check_auth['uid']) {
                $uid = $check_auth['uid'];
                if ($check_auth['need_email_activation'] == $uid) {
                    $this->need_email_activation = $uid;
                    $_SESSION['semi_logged_in'] = $uid;
                    return false;
                }
                $user = $check_auth['user'];
                $this->auth["perm"] = $user->perms;
                $this->auth["uname"] = $user->username;
                $this->auth["auth_plugin"] = $user->auth_plugin;
                $this->auth_set_user_settings($user);
    
                Metrics::increment('core.login.succeeded');
    
                return $uid;
            } else {
                Metrics::increment('core.login.failed');
                $this->error_msg = $check_auth['error'];
                return false;
            }
        }
    
        /**
         * @param $user
         */
        function auth_set_user_settings($user)
        {
            $divided = explode("x", Request::get('resolution'));
            $this->auth["xres"] = ($divided[0] != 0) ? (int)$divided[0] : 1024; //default
            $this->auth["yres"] = ($divided[1] != 0) ? (int)$divided[1] : 768; //default
            // Change X-Resulotion on Multi-Screen Systems (as Matrox Graphic-Adapters are)
            if (($this->auth["xres"] / $this->auth["yres"]) > 2) {
                $this->auth["xres"] = $this->auth["xres"] / 2;
            }
            $user = User::toObject($user);
            //restore user-specific language preference
            if ($user->preferred_language) {
                // we found a stored setting for preferred language
                $_SESSION['_language'] = $user->preferred_language;
            }
        }
    
        /**
         * setup dummy user environment
         */
        function check_environment()
        {
            global $_language_path;
    
            if (!isset($GLOBALS['user']) || $GLOBALS['user']->id !== 'nobody') {
                $GLOBALS['user'] = new Seminar_User('nobody');
                $GLOBALS['perm'] = new Seminar_Perm();
                $GLOBALS['auth'] = $this;
            }
    
            if (empty($_SESSION['_language'])) {
                $_SESSION['_language'] = get_accepted_languages();
            }
    
            // init of output via I18N
            $_language_path = init_i18n($_SESSION['_language']);
            include 'config.inc.php';
    
            if (isset($_SESSION['contrast'])) {
                PageLayout::addStylesheet('accessibility.css');
            }
        }
    }