Subversion Repositories oidplus

Rev

Rev 496 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. if (!defined('INSIDE_OIDPLUS')) die();
  21.  
  22. class OIDplusPagePublicLogin extends OIDplusPagePluginPublic {
  23.  
  24.         public function action($actionID, $params) {
  25.                 // === RA LOGIN/LOGOUT ===
  26.  
  27.                 if ($actionID == 'ra_login') {
  28.                         if (OIDplus::baseConfig()->getValue('RECAPTCHA_ENABLED', false)) {
  29.                                 $secret=OIDplus::baseConfig()->getValue('RECAPTCHA_PRIVATE', '');
  30.                                 $response=$params["captcha"];
  31.                                 $verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$response}");
  32.                                 $captcha_success=json_decode($verify);
  33.                                 if ($captcha_success->success==false) {
  34.                                         throw new OIDplusException(_L('CAPTCHA not successfully verified'));
  35.                                 }
  36.                         }
  37.  
  38.                         $email = $params['email'];
  39.                         $ra = new OIDplusRA($email);
  40.  
  41.                         if (empty($email)) {
  42.                                 throw new OIDplusException(_L('Please enter a valid email address'));
  43.                         }
  44.  
  45.                         if ($ra->checkPassword($params['password'])) {
  46.                                 OIDplus::logger()->log("[OK]RA($email)!", "RA '$email' logged in");
  47.                                 OIDplus::authUtils()::raLogin($email);
  48.  
  49.                                 OIDplus::db()->query("UPDATE ###ra set last_login = ".OIDplus::db()->sqlDate()." where email = ?", array($email));
  50.  
  51.                                 return array("status" => 0);
  52.                         } else {
  53.                                 if (OIDplus::config()->getValue('log_failed_ra_logins', false)) {
  54.                                         if ($ra->existing()) {
  55.                                                 OIDplus::logger()->log("[WARN]A!", "Failed login to RA account '$email' (wrong password)");
  56.                                         } else {
  57.                                                 OIDplus::logger()->log("[WARN]A!", "Failed login to RA account '$email' (RA not existing)");
  58.                                         }
  59.                                 }
  60.                                 throw new OIDplusException(_L('Wrong password or user not registered'));
  61.                         }
  62.  
  63.                 } else if ($actionID == 'ra_logout') {
  64.  
  65.                         $email = $params['email'];
  66.  
  67.                         OIDplus::logger()->log("[OK]RA($email)!", "RA '$email' logged out");
  68.                         OIDplus::authUtils()::raLogout($email);
  69.                         return array("status" => 0);
  70.                 }
  71.  
  72.                 // === ADMIN LOGIN/LOGOUT ===
  73.  
  74.                 else if ($actionID == 'admin_login') {
  75.                         if (OIDplus::baseConfig()->getValue('RECAPTCHA_ENABLED', false)) {
  76.                                 $secret=OIDplus::baseConfig()->getValue('RECAPTCHA_PRIVATE', '');
  77.                                 $response=$params["captcha"];
  78.                                 $verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$response}");
  79.                                 $captcha_success=json_decode($verify);
  80.                                 if ($captcha_success->success==false) {
  81.                                         throw new OIDplusException(_L('CAPTCHA not successfully verified'));
  82.                                 }
  83.                         }
  84.  
  85.                         if (OIDplus::authUtils()::adminCheckPassword($params['password'])) {
  86.                                 OIDplus::logger()->log("[OK]A!", "Admin logged in");
  87.                                 OIDplus::authUtils()::adminLogin();
  88.                                 return array("status" => 0);
  89.                         } else {
  90.                                 if (OIDplus::config()->getValue('log_failed_admin_logins', false)) {
  91.                                         OIDplus::logger()->log("[WARN]A!", "Failed login to admin account");
  92.                                 }
  93.                                 throw new OIDplusException(_L('Wrong password'));
  94.                         }
  95.                 }
  96.                 else if ($actionID == 'admin_logout') {
  97.                         OIDplus::logger()->log("[OK]A!", "Admin logged out");
  98.                         OIDplus::authUtils()::adminLogout();
  99.                         return array("status" => 0);
  100.                 }
  101.                 else {
  102.                         throw new OIDplusException(_L('Unknown action ID'));
  103.                 }
  104.         }
  105.  
  106.         public function init($html=true) {
  107.                 OIDplus::config()->prepareConfigKey('log_failed_ra_logins', 'Log failed RA logins', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
  108.                         if (!is_numeric($value) || (($value != 0) && (($value != 1)))) {
  109.                                 throw new OIDplusException(_L('Valid values: 0 (off) or 1 (on).'));
  110.                         }
  111.                 });
  112.                 OIDplus::config()->prepareConfigKey('log_failed_admin_logins', 'Log failed Admin logins', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
  113.                         if (!is_numeric($value) || (($value != 0) && (($value != 1)))) {
  114.                                 throw new OIDplusException(_L('Valid values: 0 (off) or 1 (on).'));
  115.                         }
  116.                 });
  117.         }
  118.  
  119.         public function gui($id, &$out, &$handled) {
  120.                 $ary = explode('$', $id);
  121.                 if (isset($ary[1])) {
  122.                         $id = $ary[0];
  123.                         $tab = $ary[1];
  124.                 } else {
  125.                         $tab = 'ra';
  126.                 }
  127.                 if ($id === 'oidplus:login') {
  128.                         $handled = true;
  129.                         $out['title'] = _L('Login');
  130.                         $out['icon']  = OIDplus::webpath(__DIR__).'login_big.png';
  131.  
  132.                         $out['text'] = '';
  133.  
  134.                         $out['text'] .= '<noscript>';
  135.                         $out['text'] .= '<p>'._L('You need to enable JavaScript to use the login area.').'</p>';
  136.                         $out['text'] .= '</noscript>';
  137.  
  138.                         $out['text'] .= '<div id="loginArea" style="visibility: hidden"><div id="loginTab" class="container" style="width:100%;">';
  139.                         $out['text'] .= (OIDplus::baseConfig()->getValue('RECAPTCHA_ENABLED', false) ?
  140.                                         '<script> grecaptcha.render(document.getElementById("g-recaptcha"), { "sitekey" : "'.OIDplus::baseConfig()->getValue('RECAPTCHA_PUBLIC', '').'" }); </script>'.
  141.                                         '<p>'._L('Before logging in, please solve the following CAPTCHA').'</p>'.
  142.                                         '<div id="g-recaptcha" class="g-recaptcha" data-sitekey="'.OIDplus::baseConfig()->getValue('RECAPTCHA_PUBLIC', '').'"></div>' : '');
  143.                         $out['text'] .= '<br>';
  144.  
  145.                         // ---------------- Tab control
  146.                         $out['text'] .= OIDplus::gui()->tabBarStart();
  147.                         $out['text'] .= OIDplus::gui()->tabBarElement('ra',    _L('Login as RA'),            $tab === 'ra');
  148.                         $out['text'] .= OIDplus::gui()->tabBarElement('admin', _L('Login as administrator'), $tab === 'admin');
  149.                         $out['text'] .= OIDplus::gui()->tabBarEnd();
  150.                         $out['text'] .= OIDplus::gui()->tabContentStart();
  151.                         // ---------------- "RA" tab
  152.                         $tabcont = '<h2>'._L('Login as RA').'</h2>';
  153.                         $login_list = OIDplus::authUtils()->loggedInRaList();
  154.                         if (count($login_list) > 0) {
  155.                                 foreach ($login_list as $x) {
  156.                                         $tabcont .= '<p>'._L('You are logged in as %1','<b>'.$x->raEmail().'</b>').' (<a href="#" onclick="return raLogout('.js_escape($x->raEmail()).');">'._L('Logout').'</a>)</p>';
  157.                                 }
  158.                                 $tabcont .= '<p>'._L('If you have more accounts, you can log in with another account here.').'</p>';
  159.                         } else {
  160.                                 $tabcont .= '<p>'._L('Enter your email address and your password to log in as Registration Authority.').'</p>';
  161.                         }
  162.                         $tabcont .= '<form action="javascript:void(0);" onsubmit="return raLoginOnSubmit(this);">';
  163.                         $tabcont .= '<div><label class="padding_label">'._L('E-Mail').':</label><input type="text" name="email" value="" id="raLoginEMail"></div>';
  164.                         $tabcont .= '<div><label class="padding_label">'._L('Password').':</label><input type="password" name="password" value="" id="raLoginPassword"></div>';
  165.                         $tabcont .= '<br><input type="submit" value="'._L('Login').'"><br><br>';
  166.                         $tabcont .= '</form>';
  167.                         $tabcont .= '<p><a '.OIDplus::gui()->link('oidplus:forgot_password').'>'._L('Forgot password?').'</a><br>';
  168.  
  169.                         $invitePlugin = OIDplus::getPluginByOid('1.3.6.1.4.1.37476.2.5.2.4.2.92'); // OIDplusPageRaInvite
  170.                         if (!is_null($invitePlugin) && OIDplus::config()->getValue('ra_invitation_enabled')) {
  171.                                 $tabcont .= '<abbr title="'._L('To receive login data, the superior RA needs to send you an invitation. After creating or updating your OID, the system will ask them if they want to send you an invitation. If they accept, you will receive an email with an activation link. Alternatively, the system admin can create your account manually in the administrator control panel.').'">'._L('How to register?').'</abbr></p>';
  172.                         } else {
  173.                                 $tabcont .= '<abbr title="'._L('Since invitations are disabled at this OIDplus system, the system administrator needs to create your account manually in the administrator control panel.').'">'._L('How to register?').'</abbr></p>';
  174.                         }
  175.  
  176.                         if ($tab === 'ra') {
  177.                                 $alt_logins_html = array();
  178.                                 foreach (OIDplus::getPagePlugins() as $plugin) {
  179.                                         if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.5')) {
  180.                                                 $logins = $plugin->alternativeLoginMethods();
  181.                                                 foreach ($logins as $data) {
  182.                                                         if (isset($data[2]) && !empty($data[2])) {
  183.                                                                 $img = '<img src="'.$data[2].'" alt="'.htmlentities($data[1]).'"> ';
  184.                                                         } else {
  185.                                                                 $img = '';
  186.                                                         }
  187.                                                         $alt_logins_html[] = $img.'<a '.OIDplus::gui()->link($data[0]).'>'.htmlentities($data[1]).'</a>';
  188.                                                 }
  189.                                         }
  190.                                 }
  191.                                 if (count($alt_logins_html) > 0) {
  192.                                         $tabcont .= '<p>'._L('Alternative login methods').':<br>';
  193.                                         foreach ($alt_logins_html as $alt_login) {
  194.                                                 $tabcont .= $alt_login.'<br>';
  195.                                         }
  196.                                         $tabcont .= '</p>';
  197.                                 }
  198.                         }
  199.  
  200.                         $out['text'] .= OIDplus::gui()->tabContentPage('ra', $tabcont, $tab === 'ra');
  201.                         // ---------------- "Administrator" tab
  202.                         $tabcont = '<h2>'._L('Login as administrator').'</h2>';
  203.                         if (OIDplus::authUtils()::isAdminLoggedIn()) {
  204.                                 $tabcont .= '<p>'._L('You are logged in as administrator.').'</p>';
  205.                                 $tabcont .= '<a href="#" onclick="return adminLogout();">'._L('Logout').'</a>';
  206.                         } else {
  207.                                 $tabcont .= '<form action="javascript:void(0);" onsubmit="return adminLoginOnSubmit(this);">';
  208.                                 $tabcont .= '<div><label class="padding_label">'._L('Password').':</label><input type="password" name="password" value="" id="adminLoginPassword"></div>';
  209.                                 $tabcont .= '<br><input type="submit" value="'._L('Login').'"><br><br>';
  210.                                 $tabcont .= '</form>';
  211.                                 $tabcont .= '<p><a '.OIDplus::gui()->link('oidplus:forgot_password_admin').'>'._L('Forgot password?').'</a><br>';
  212.                         }
  213.                         $out['text'] .= OIDplus::gui()->tabContentPage('admin', $tabcont, $tab === 'admin');
  214.                         $out['text'] .= OIDplus::gui()->tabContentEnd();
  215.                         // ---------------- Tab control END
  216.  
  217.                         $out['text'] .= '</div><br>';
  218.  
  219.                         $mins = ceil(OIDplus::baseConfig()->getValue('SESSION_LIFETIME', 30*60)/60);
  220.                         $out['text'] .= '<p><font size="-1">'._L('<i>Privacy information</i>: By using the login functionality, you are accepting that a "session cookie" is temporarily stored in your browser. The session cookie is a small text file that is sent to this website every time you visit it, to identify you as an already logged in user. It does not track any of your online activities outside OIDplus. The cookie will be destroyed when you log out or after an inactivity of %1 minutes.', $mins);
  221.                         $privacy_document_file = 'OIDplus/privacy_documentation.html';
  222.                         $resourcePlugin = OIDplus::getPluginByOid('1.3.6.1.4.1.37476.2.5.2.4.1.500'); // OIDplusPagePublicResources
  223.                         if (!is_null($resourcePlugin) && file_exists(OIDplus::localpath().'res/'.$privacy_document_file)) {
  224.                                 $out['text'] .= ' <a '.OIDplus::gui()->link('oidplus:resources$'.$privacy_document_file.'#cookies').'>'._L('More information about the cookies used').'</a>';
  225.                         }
  226.                         $out['text'] .= '</font></p></div>';
  227.  
  228.                         $out['text'] .= '<script>document.getElementById("loginArea").style.visibility = "visible";</script>';
  229.                 }
  230.         }
  231.  
  232.         public function publicSitemap(&$out) {
  233.                 $out[] = 'oidplus:login';
  234.         }
  235.  
  236.         public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {
  237.                 $loginChildren = array();
  238.  
  239.                 if (OIDplus::authUtils()::isAdminLoggedIn()) {
  240.                         $ra_roots = array();
  241.  
  242.                         foreach (OIDplus::getPagePlugins() as $plugin) {
  243.                                 if (is_subclass_of($plugin, OIDplusPagePluginAdmin::class)) {
  244.                                         $plugin->tree($ra_roots);
  245.                                 }
  246.                         }
  247.  
  248.                         $ra_roots[] = array(
  249.                                 'id'       => 'oidplus:logout$admin',
  250.                                 'icon'     => OIDplus::webpath(__DIR__).'treeicon_logout.png',
  251.                                 'conditionalselect' => 'adminLogout()', // defined in oidplus_base.js
  252.                                 'text'     => _L('Log out')
  253.                         );
  254.                         $loginChildren[] = array(
  255.                                 'id'       => 'oidplus:dummy$'.md5(rand()),
  256.                                 'text'     => _L("Logged in as admin"),
  257.                                 'icon'     => OIDplus::webpath(__DIR__).'treeicon_admin.png',
  258.                                 'conditionalselect' => 'false', // dummy node that can't be selected
  259.                                 'state'    => array("opened" => true),
  260.                                 'children' => $ra_roots
  261.                         );
  262.                 }
  263.  
  264.                 foreach (OIDplus::authUtils()::loggedInRaList() as $ra) {
  265.                         $ra_email = $ra->raEmail();
  266.                         $ra_roots = array();
  267.  
  268.                         foreach (OIDplus::getPagePlugins() as $plugin) {
  269.                                 if (is_subclass_of($plugin, OIDplusPagePluginRa::class)) {
  270.                                         $plugin->tree($ra_roots, $ra_email);
  271.                                 }
  272.                         }
  273.  
  274.                         $ra_roots[] = array(
  275.                                 'id'       => 'oidplus:logout$'.$ra_email,
  276.                                 'conditionalselect' => 'raLogout('.js_escape($ra_email).')', // defined in oidplus_base.js
  277.                                 'icon'     => OIDplus::webpath(__DIR__).'treeicon_logout.png',
  278.                                 'text'     => _L('Log out')
  279.                         );
  280.                         foreach (OIDplusObject::getRaRoots($ra_email) as $loc_root) {
  281.                                 $ico = $loc_root->getIcon();
  282.                                 $ra_roots[] = array(
  283.                                         'id' => 'oidplus:raroot$'.$loc_root->nodeId(),
  284.                                         'text' => _L('Jump to RA root %1',$loc_root->objectTypeTitleShort().' '.$loc_root->crudShowId(OIDplusObject::parse($loc_root::root()))),
  285.                                         'conditionalselect' => 'openOidInPanel('.js_escape($loc_root->nodeId()).', true);',
  286.                                         'icon' => !is_null($ico) ? $ico : OIDplus::webpath(__DIR__).'treeicon_link.png'
  287.                                 );
  288.                         }
  289.                         $ra_email_or_name = (new OIDplusRA($ra_email))->raName();
  290.                         if ($ra_email_or_name == '') $ra_email_or_name = $ra_email;
  291.                         $loginChildren[] = array(
  292.                                 'id'       => 'oidplus:dummy$'.md5(rand()),
  293.                                 'text'     => _L('Logged in as %1',htmlentities($ra_email_or_name)),
  294.                                 'icon'     => OIDplus::webpath(__DIR__).'treeicon_ra.png',
  295.                                 'conditionalselect' => 'false', // dummy node that can't be selected
  296.                                 'state'    => array("opened" => true),
  297.                                 'children' => $ra_roots
  298.                         );
  299.                 }
  300.  
  301.                 $json[] = array(
  302.                         'id'       => 'oidplus:login',
  303.                         'icon'     => OIDplus::webpath(__DIR__).'treeicon_login.png',
  304.                         'text'     => _L('Login'),
  305.                         'state'    => array("opened" => count($loginChildren)>0),
  306.                         'children' => $loginChildren
  307.                 );
  308.  
  309.                 return true;
  310.         }
  311.  
  312.         public function tree_search($request) {
  313.                 return false;
  314.         }
  315. }
  316.