LoginAction.class.php (39965B)
1 <?php 2 3 namespace cms\action; 4 5 6 use cms\model\User; 7 use cms\model\Project; 8 use cms\model\Group; 9 use cms\model\Value; 10 use cms\model\Element; 11 use cms\model\Page; 12 use cms\model\BaseObject; 13 use cms\model\Language; 14 use cms\model\Model; 15 16 17 use \database\Database; 18 use \DB; 19 use \DbUpdate; 20 use \Exception; 21 use \Http; 22 use \InternalAuth; 23 use \Logger; 24 use \ObjectNotFoundException; 25 use \OpenRatException; 26 use \security\Password; 27 use \Session; 28 use \Html; 29 use \Mail; 30 use \Text; 31 32 33 // OpenRat Content Management System 34 // Copyright (C) 2002-2007 Jan Dankert, jandankert@jandankert.de 35 // 36 // This program is free software; you can redistribute it and/or 37 // modify it under the terms of the GNU General Public License 38 // as published by the Free Software Foundation; version 2. 39 // 40 // This program is distributed in the hope that it will be useful, 41 // but WITHOUT ANY WARRANTY; without even the implied warranty of 42 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 43 // GNU General Public License for more details. 44 // 45 // You should have received a copy of the GNU General Public License 46 // along with this program; if not, write to the Free Software 47 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 48 49 50 define('PROJECTID_ADMIN',-1); 51 52 /** 53 * Action-Klasse fuer die Start-Action 54 * @author $Author$ 55 * @version $Revision$ 56 * @package openrat.actions 57 */ 58 59 class LoginAction extends BaseAction 60 { 61 public $security = Action::SECURITY_GUEST; 62 63 64 public function __construct() 65 { 66 parent::__construct(); 67 } 68 69 70 71 /** 72 * Führt ein Login durch. 73 * @param $name string Benutzername 74 * @param $pw string Password 75 * @param $pw1 string new Password 76 * @param $pw2 string new Password repeated 77 * @return bool 78 * @throws ObjectNotFoundException 79 */ 80 private function checkLogin($name, $pw, $pw1, $pw2 ) 81 { 82 Logger::debug( "Login user: '$name'.'" ); 83 84 global $conf; 85 global $SESS; 86 87 unset( $SESS['user'] ); 88 89 90 $db = db_connection(); 91 92 if ( !is_object($db) ) 93 { 94 $this->addNotice('database','','DATABASE_CONNECTION_ERROR',OR_NOTICE_ERROR,array(),array('no connection')); 95 //$this->callSubAction('showlogin'); 96 return false; 97 } 98 99 if ( !$db->available ) 100 { 101 $this->addNotice('database',$db->conf['description'],'DATABASE_CONNECTION_ERROR',OR_NOTICE_ERROR,array(),array('Database Error: '.$db->error)); 102 //$this->callSubAction('showlogin'); 103 return false; 104 } 105 106 $ip = getenv("REMOTE_ADDR"); 107 108 $user = new User(); 109 $user->name = $name; 110 111 $ok = $user->checkPassword( $pw ); 112 113 $mustChangePassword = $user->mustChangePassword; 114 115 if ( $mustChangePassword ) 116 { 117 // Der Benutzer hat zwar ein richtiges Kennwort eingegeben, aber dieses ist abgelaufen. 118 // Wir versuchen hier, das neue zu setzen (sofern eingegeben). 119 if ( empty($pw1) ) 120 { 121 } 122 elseif ( $pw1 != $pw2 ) 123 { 124 $this->addValidationError('password1','PASSWORDS_DO_NOT_MATCH'); 125 $this->addValidationError('password2',''); 126 } 127 elseif ( strlen($pw2) < $conf['security']['password']['min_length'] ) 128 { 129 $this->addValidationError('password1','PASSWORD_MINLENGTH',array('minlength'=>$conf['security']['password']['min_length'])); 130 $this->addValidationError('password2',''); 131 } 132 else 133 { 134 // Kennw?rter identisch und lang genug. 135 $user->setPassword( $pw1,true ); 136 137 // Das neue Kennwort ist gesetzt, die Anmeldung ist also doch noch gelungen. 138 $ok = true; 139 $mustChangePassword = false; 140 141 $pw = $pw1; 142 } 143 } 144 145 // Falls Login erfolgreich 146 if ( $ok ) 147 { 148 // Login war erfolgreich! 149 $user->load(); 150 $user->setCurrent(); 151 152 if ($user->passwordAlgo != Password::bestAlgoAvailable() ) 153 // Re-Hash the password with a better hash algo. 154 $user->setPassword($pw); 155 156 157 Logger::info( "login successful for {$user->name} from IP $ip" ); 158 159 return true; 160 } 161 else 162 { 163 Logger::info( "login failed for user {$user->name} from IP $ip" ); 164 165 return false; 166 } 167 } 168 169 170 /** 171 * Anzeigen der Loginmaske. 172 * 173 * Es wird nur die Loginmaske angezeigt. 174 * @throws OpenRatException 175 */ 176 function loginView() 177 { 178 // Hier nie "304 not modified" setzen, da sonst keine 179 // Login-Fehlermeldung erscheinen kann. 180 global $conf; 181 182 $sso = $conf['security']['sso']; 183 $ssl = $conf['security']['ssl']; 184 185 $ssl_trust = false; 186 $ssl_user_var = ''; 187 extract( $ssl, EXTR_PREFIX_ALL, 'ssl' ); 188 189 if ( $sso['enable'] ) 190 { 191 $authid = $this->getRequestVar( $sso['auth_param_name']); 192 193 if ( empty( $authid) ) 194 throw new \SecurityException( 'no authorization data (no auth-id)'); 195 196 if ( $sso['auth_param_serialized'] ) 197 $authid = unserialize( $authid ); 198 199 $purl = parse_url($sso['url']); 200 // Verbindung zu URL herstellen. 201 $errno=0; $errstr=''; 202 $fp = fsockopen ($purl['host'],80, $errno, $errstr, 30); 203 if ( !$fp ) 204 { 205 echo "Connection failed: $errstr ($errno)"; 206 } 207 else 208 { 209 $http_get = $purl['path']; 210 if ( !empty($purl['query']) ) 211 $http_get .= '?'.$purl['query']; 212 213 $header = array(); 214 215 $header[] = "GET $http_get HTTP/1.0"; 216 $header[] ="Host: ".$purl['host']; 217 $header[] = "User-Agent: Mozilla/5.0 (OpenRat CMS Single Sign-on Check)"; 218 $header[] = "Connection: Close"; 219 220 if ( $sso['cookie'] ) 221 { 222 $cookie = 'Cookie: '; 223 if ( is_array($authid)) 224 foreach( $authid as $cookiename=>$cookievalue) 225 $cookie .= $cookiename.'='.$cookievalue."; "; 226 else 227 $cookie .= $sso['cookie_name'].'='.$authid; 228 229 $header[] = $cookie; 230 } 231 232 fputs ($fp, implode("\r\n",$header)."\r\n\r\n"); 233 234 $inhalt=array(); 235 while (!feof($fp)) { 236 $inhalt[] = fgets($fp,128); 237 } 238 fclose($fp); 239 240 $html = implode('',$inhalt); 241 if ( !preg_match($sso['expect_regexp'],$html) ) 242 throw new \SecurityException('auth failed'); 243 $treffer=0; 244 if ( !preg_match($sso['username_regexp'],$html,$treffer) ) 245 throw new \SecurityException('auth failed'); 246 if ( !isset($treffer[1]) ) 247 throw new \SecurityException('authorization failed'); 248 249 $username = $treffer[1]; 250 251 $user = User::loadWithName( $username ); 252 253 if ( ! $user->isValid( )) 254 throw new \SecurityException('authorization failed: user not found: '.$username); 255 256 $user->setCurrent(); 257 258 $this->callSubAction('show'); 259 } 260 } 261 262 elseif ( $ssl_trust ) 263 { 264 if ( empty($ssl_user_var) ) 265 throw new \LogicException( 'please set environment variable name in ssl-configuration.' ); 266 267 $username = getenv( $ssl_user_var ); 268 269 if ( empty($username) ) 270 throw new \SecurityException( 'no username in client certificate ('.$ssl_user_var.') (or there is no client certificate...?)' ); 271 272 $user = User::loadWithName( $username ); 273 274 if ( !$user->isValid() ) 275 throw new \LogicException( 'unknown username: '.$username ); 276 277 $user->setCurrent(); 278 279 $this->callSubAction('show'); 280 } 281 282 $dbids = array(); 283 284 $databases = Conf()->get('database'); 285 286 if ( !is_array($databases)) 287 throw new \LogicException("Corrupt configuration: Databases configuration must be an array."); 288 289 290 foreach( $databases as $dbid => $dbconf ) 291 { 292 if ( !is_array($dbconf)) 293 throw new \LogicException("Corrup configuration: Database configuration '".$dbid."' must be an array.'"); 294 295 $dbconf += $conf['database-default']['defaults']; // Add Default-Values 296 297 if ( is_array($dbconf) && $dbconf['enabled'] ) // Database-Connection is enabled 298 $dbids[$dbid] = array( 299 'key' => $dbid, 300 'value' => !$dbconf['name'] ? $dbid : Text::maxLength($dbconf['name']), 301 'title' => $dbconf['description'] 302 ); 303 } 304 305 306 if ( empty($dbids) ) 307 $this->addNotice('','','no_database_configuration',OR_NOTICE_WARN); 308 309 if ( !isset($this->templateVars['login_name']) && isset($_COOKIE['or_username']) ) 310 $this->setTemplateVar('login_name',$_COOKIE['or_username']); 311 312 if ( !isset($this->templateVars['login_name']) ) 313 $this->setTemplateVar('login_name',@$conf['security']['default']['username']); 314 315 if ( @$this->templateVars['login_name']== @$conf['security']['default']['username']) 316 $this->setTemplateVar('login_password',@$conf['security']['default']['password']); 317 318 $this->setTemplateVar( 'dbids',$dbids ); 319 320 // Database was already connected in the Dispatcher. So we MUST have a db connection here. 321 $db = Session::getDatabase(); 322 $this->setTemplateVar('dbid',$db->id); 323 324 325 // Den Benutzernamen aus dem Client-Zertifikat lesen und in die Loginmaske eintragen. 326 $ssl_user_var = $conf['security']['ssl']['client_cert_dn_env']; 327 if ( !empty($ssl_user_var) ) 328 { 329 $username = getenv( $ssl_user_var ); 330 331 if ( empty($username) ) 332 { 333 // Nothing to do. 334 // if user has no valid client cert he could not access this form. 335 } 336 else { 337 338 // Benutzername ist in Eingabemaske unver�nderlich 339 $this->setTemplateVar('force_username',true); 340 $this->setTemplateVar('login_name' ,$username); 341 } 342 343 } 344 345 $this->setTemplateVar('objectid' ,$this->getRequestVar('objectid' ,OR_FILTER_NUMBER) ); 346 $this->setTemplateVar('projectid' ,$this->getRequestVar('projectid' ,OR_FILTER_NUMBER) ); 347 $this->setTemplateVar('modelid' ,$this->getRequestVar('modelid' ,OR_FILTER_NUMBER) ); 348 $this->setTemplateVar('languageid',$this->getRequestVar('languageid',OR_FILTER_NUMBER) ); 349 350 $this->setTemplateVar('register' ,$conf['login' ]['register' ]); 351 $this->setTemplateVar('send_password',$conf['login' ]['send_password']); 352 353 // Versuchen, einen Benutzernamen zu ermitteln, der im Eingabeformular vorausgewählt wird. 354 $modules = $conf['security']['preselect']['modules']; 355 356 $username = ''; 357 foreach( $modules as $module) 358 { 359 Logger::debug('Preselecting module: '.$module); 360 $moduleClass = $module.'Auth'; 361 /** @var \Auth $auth */ 362 $auth = new $moduleClass; 363 $username = $auth->username(); 364 365 if ( !empty($username) ) 366 { 367 Logger::debug('Preselecting User '.$username); 368 break; // Benutzername gefunden. 369 } 370 } 371 372 $this->setTemplateVar('login_name',$username); 373 } 374 375 376 377 /** 378 * Anzeigen der Loginmaske. 379 * 380 * Es wird nur die Loginmaske angezeigt. 381 * Hier nie "304 not modified" setzen, da sonst keine 382 * Login-Fehlermeldung erscheinen kann 383 */ 384 function openidView() 385 { 386 global $conf; 387 388 foreach( $conf['database'] as $dbname=>$dbconf ) 389 { 390 if ( is_array($dbconf) && $dbconf['enabled'] ) 391 $dbids[$dbname] = array('key' =>$dbname, 392 'value'=>Text::maxLength($dbconf['description']), 393 'title'=>$dbconf['description'].(isset($dbconf['host'])?' ('.$dbconf['host'].')':'') ); 394 } 395 396 $openid_provider = array(); 397 foreach( explode(',',$conf['security']['openid']['provider']['name']) as $provider ) 398 $openid_provider[$provider] = config('security','openid','provider.'.$provider.'.name'); 399 $this->setTemplateVar('openid_providers',$openid_provider); 400 $this->setTemplateVar('openid_user_identity',config('security','openid','user_identity')); 401 //$this->setTemplateVar('openid_provider','identity'); 402 403 404 if ( empty($dbids) ) 405 $this->addNotice('','','no_database_configuration',OR_NOTICE_WARN); 406 407 if ( !isset($_COOKIE['or_username']) ) 408 $this->setTemplateVar('login_name',$_COOKIE['or_username']); 409 else 410 $this->setTemplateVar('login_name',$conf['security']['default']['username']); 411 412 $this->setTemplateVar( 'dbids',$dbids ); 413 414 $db = db(); 415 if ( is_object($db) ) 416 $this->setTemplateVar('actdbid',$db->id); 417 else 418 $this->setTemplateVar('actdbid',$conf['database']['default']); 419 420 $this->setTemplateVar('objectid' ,$this->getRequestVar('objectid' ,OR_FILTER_NUMBER) ); 421 $this->setTemplateVar('projectid' ,$this->getRequestVar('projectid' ,OR_FILTER_NUMBER) ); 422 $this->setTemplateVar('modelid' ,$this->getRequestVar('modelid' ,OR_FILTER_NUMBER) ); 423 $this->setTemplateVar('languageid',$this->getRequestVar('languageid',OR_FILTER_NUMBER) ); 424 425 } 426 427 428 429 /** 430 * Erzeugt eine Anwendungsliste. 431 * TODO: unused at the moment 432 */ 433 function applications() 434 { 435 global $conf; 436 437 // Diese Seite gilt pro Sitzung. 438 $user = Session::getUser(); 439 $userGroups = $user->getGroups(); 440 $this->lastModified( $user->loginDate ); 441 442 // Applikationen ermitteln 443 $list = array(); 444 foreach( $conf['applications'] as $id=>$app ) 445 { 446 if ( !is_array($app) ) 447 continue; 448 449 if ( isset($app['group']) ) 450 if ( !in_array($app['group'],$userGroups) ) 451 continue; // Keine Berechtigung, da Benutzer nicht in Gruppe vorhanden. 452 453 $p = array(); 454 $p['url'] = $app['url']; 455 $p['description'] = @$app['description']; 456 if ( isset($app['param']) ) 457 { 458 $p['url'] .= strpos($p['url'],'?')!==false?'&':'?'; 459 $p['url'] .= $app['param'].'='.session_id(); 460 } 461 $p['name'] = $app['name']; 462 463 $list[] = $p; 464 } 465 466 467 $this->setTemplateVar('applications',$list); 468 } 469 470 471 472 473 /** 474 * Open-Id Login, ?berpr?fen der Anmeldung.<br> 475 * Spezifikation: http://openid.net/specs/openid-authentication-1_1.html<br> 476 * Kapitel "4.4. check_authentication"<br> 477 * <br> 478 * Im 2. Schritt (Mode "id_res") erfolgte ein Redirect vom Open-Id Provider an OpenRat zur?ck.<br> 479 * Wir befinden uns nun im darauf folgenden Request des Browsers.<br> 480 * <br> 481 * Es muss noch beim OpenId-Provider die Best?tigung eingeholt werden, danach ist der 482 * Benutzer angemeldet.<br> 483 */ 484 public function openidloginView() 485 { 486 global $conf; 487 $openId = Session::get('openid'); 488 489 if ( !$openId->checkAuthentication() ) 490 { 491 throw new \SecurityException('OpenId-Login failed' ); 492 } 493 494 //Html::debug($openId); 495 496 // Anmeldung wurde mit "is_valid:true" best?tigt. 497 // Der Benutzer ist jetzt eingeloggt. 498 $username = $openId->getUserFromIdentiy(); 499 500 Logger::debug("OpenId-Login successful for $username"); 501 502 if ( empty($username) ) 503 { 504 // Es konnte kein Benutzername ermittelt werden. 505 throw new \SecurityException('no username supplied by openid provider' ); 506 } 507 508 $user = User::loadWithName( $username ); 509 510 if ( $user->userid <=0) 511 { 512 // Benutzer ist (noch) nicht vorhanden. 513 if ( $conf['security']['openid']['add']) // Anlegen? 514 { 515 $user->name = $username; 516 $user->add(); 517 518 $user->mail = @$openId->info['email']; 519 $user->fullname = @$openId->info['fullname']; 520 $user->save(); // Um E-Mail zu speichern (wird bei add() nicht gemacht) 521 } 522 else 523 { 524 Logger::debug("OpenId-Login failed for $username"); 525 // Benutzer ist nicht in Benutzertabelle vorhanden (und angelegt werden soll er auch nicht). 526 throw new \SecurityException('user',$username,'LOGIN_OPENID_FAILED','error',array('name'=>$username) ); 527 } 528 } 529 else 530 { 531 // Benutzer ist bereits vorhanden. 532 if ( @$conf['security']['openid']['update_user']) 533 { 534 $user->fullname = @$openId->info['fullname']; 535 $user->mail = @$openId->info['email']; 536 $user->save(); 537 } 538 } 539 540 Logger::info("User login successful: ".$username); 541 $user->setCurrent(); // Benutzer ist jetzt in der Sitzung. 542 543 $this->setStyle( $user->style ); 544 545 $server = Http::getServer(); 546 Logger::debug("Redirecting to $server"); 547 header('Location: '.slashify($server) ); 548 exit(); 549 } 550 551 552 /** 553 * Login. 554 */ 555 function openidPost() 556 { 557 global $conf; 558 559 Session::setUser(''); 560 561 if ( $conf['login']['nologin'] ) 562 throw new \SecurityException('login disabled'); 563 564 $openid_user = $this->getRequestVar('openid_url' ); 565 $loginName = $this->getRequestVar('login_name' ,OR_FILTER_ALPHANUM); 566 $loginPassword = $this->getRequestVar('login_password',OR_FILTER_ALPHANUM); 567 $newPassword1 = $this->getRequestVar('password1' ,OR_FILTER_ALPHANUM); 568 $newPassword2 = $this->getRequestVar('password2' ,OR_FILTER_ALPHANUM); 569 570 // Cookie setzen 571 $this->setCookie('or_username',$loginName ); 572 573 // Login mit Open-Id. 574 if ( $this->hasRequestVar('openid_provider') && ($this->getRequestVar('openid_provider') != 'identity' || !empty($openid_user)) ) 575 { 576 $openId = new OpenId($this->getRequestVar('openid_provider'),$openid_user); 577 578 if ( ! $openId->login() ) 579 { 580 $this->addNotice('user',$openid_user,'LOGIN_OPENID_FAILED','error',array('name'=>$openid_user),array($openId->error) ); 581 $this->addValidationError('openid_url',''); 582 $this->callSubAction('showlogin'); 583 return; 584 } 585 586 Session::set('openid',$openId); 587 $this->redirect( $openId->getRedirectUrl() ); 588 return; 589 } 590 } 591 592 593 /** 594 * Synchronisiert die bisherigen Gruppen des Benutzers mit den Gruppen, die sich aus der Authentifzierung ergeben haben. 595 * 596 * @param $user User Benutzerobjekt 597 * @param $groups array $groups Einfaches Array von Gruppennamen. 598 */ 599 private function checkGroups($user, $groups) 600 { 601 if ( $groups == null ) 602 return; 603 604 $oldGroups = $user->getGroups(); 605 606 foreach( $oldGroups as $id=>$name) 607 { 608 if ( !in_array($name,$groups) ) 609 $user->delGroup($id); 610 } 611 612 foreach( $groups as $name) 613 { 614 if ( ! in_array($name,$oldGroups)) 615 { 616 try 617 { 618 $group = Group::loadWithName( $name ); 619 $user->addGroup($group->groupid); 620 } 621 catch (ObjectNotFoundException $e) 622 { 623 // Gruppe fehlt. Anlegen? 624 if ( config('ldap','authorize','auto_add' ) ) 625 { 626 // Die Gruppe in der OpenRat-Datenbank hinzufuegen. 627 $g = new Group(); 628 $g->name = $group; 629 $g->add(); // Gruppe hinzufuegen 630 $user->addGroup($g->groupid); // Und Gruppe dem Benutzer hinzufuegen. 631 } 632 633 } 634 } 635 } 636 } 637 638 639 /** 640 * Login. 641 * Zuerst wird die Datenbankverbindung aufgebaut und falls notwendig, aktualisiert. 642 */ 643 function loginPost() 644 { 645 global $conf; 646 647 Session::setUser(''); // Altes Login entfernen. 648 649 if ( $conf['login']['nologin'] ) 650 throw new \SecurityException('login disabled'); 651 652 $loginName = $this->getRequestVar('login_name' ,OR_FILTER_ALPHANUM); 653 $loginPassword = $this->getRequestVar('login_password',OR_FILTER_ALPHANUM); 654 $newPassword1 = $this->getRequestVar('password1' ,OR_FILTER_ALPHANUM); 655 $newPassword2 = $this->getRequestVar('password2' ,OR_FILTER_ALPHANUM); 656 $token = $this->getRequestVar('user_token' ,OR_FILTER_ALPHANUM); 657 658 // Der Benutzer hat zwar ein richtiges Kennwort eingegeben, aber dieses ist abgelaufen. 659 // Wir versuchen hier, das neue zu setzen (sofern eingegeben). 660 if ( empty($newPassword1) ) 661 { 662 // Kein neues Kennwort, 663 // nichts zu tun... 664 } 665 else 666 { 667 $auth = new InternalAuth(); 668 669 if ( $auth->login($loginName, $loginPassword,$token) || $auth->mustChangePassword ) 670 { 671 if ( $newPassword1 != $newPassword2 ) 672 { 673 $this->addValidationError('password1','PASSWORDS_DO_NOT_MATCH'); 674 $this->addValidationError('password2',''); 675 return; 676 } 677 elseif ( strlen($newPassword1) < $conf['security']['password']['min_length'] ) 678 { 679 $this->addValidationError('password1','PASSWORD_MINLENGTH',array('minlength'=>$conf['security']['password']['min_length'])); 680 $this->addValidationError('password2',''); 681 return; 682 } 683 else 684 { 685 // Kennwoerter identisch und lang genug. 686 $user = User::loadWithName($loginName); 687 $user->setPassword( $newPassword1,true ); 688 689 // Das neue gesetzte Kennwort für die weitere Authentifizierung benutzen. 690 $loginPassword = $newPassword1; 691 } 692 } 693 else 694 { 695 // Anmeldung gescheitert. 696 $this->addNotice('user',$loginName,'LOGIN_FAILED','error',array('name'=>$loginName) ); 697 $this->addValidationError('login_name' ,''); 698 $this->addValidationError('login_password',''); 699 return; 700 } 701 } 702 703 // Cookie setzen 704 $this->setCookie('or_username',$loginName ); 705 $this->setCookie('or_dbid' ,$this->getRequestVar('dbid')); 706 707 // Authentifizierungs-Module. 708 $modules = $conf['security']['authenticate']['modules']; 709 710 $loginOk = false; 711 $mustChangePassword = false; 712 $tokenFailed = false; 713 $groups = null; 714 $lastModule = null; 715 716 // Jedes Authentifizierungsmodul durchlaufen, bis ein Login erfolgreich ist. 717 foreach( $modules as $module) 718 { 719 $moduleClass = $module.'Auth'; 720 $auth = new $moduleClass; 721 Logger::info('Trying to login with module '.$moduleClass); 722 $loginStatus = $auth->login( $loginName,$loginPassword, $token ); 723 $loginOk = $loginStatus === true || $loginStatus === OR_AUTH_STATUS_SUCCESS; 724 725 if ( $loginStatus === OR_AUTH_STATUS_PW_EXPIRED ) 726 $mustChangePassword = true; 727 if ( $loginStatus === OR_AUTH_STATUS_TOKEN_NEEDED ) 728 $tokenFailed = true; 729 730 if ( $loginOk ) 731 { 732 Logger::info('Login successful for '.$loginName); 733 $lastModule = $module; 734 735 if ( isset($auth->groups ) ) 736 $groups = $auth->groups; 737 738 break; // Login erfolgreich, erstes Modul gewinnt. 739 } 740 } 741 742 /* 743 $loginOk = $this->checkLogin( $loginName, 744 $loginPassword, 745 $newPassword1, 746 $newPassword2 ); 747 */ 748 749 750 if ( $loginOk ) 751 { 752 753 try 754 { 755 // Benutzer über den Benutzernamen laden. 756 $user = User::loadWithName($loginName); 757 $user->loginModuleName = $lastModule; 758 $user->setCurrent(); 759 $user->updateLoginTimestamp(); 760 761 if ($user->passwordAlgo != Password::bestAlgoAvailable() ) 762 // Re-Hash the password with a better hash algo. 763 $user->setPassword($loginPassword); 764 765 } 766 catch( ObjectNotFoundException $ex ) 767 { 768 // Benutzer wurde zwar authentifiziert, ist aber in der 769 // internen Datenbank nicht vorhanden 770 if ( $conf['security']['newuser']['autoadd'] ) 771 { 772 // Neue Benutzer in die interne Datenbank uebernehmen. 773 $user = new User(); 774 $user->name = $loginName; 775 $user->fullname = $loginName; 776 $user->add(); 777 $user->save(); 778 } 779 else 780 { 781 // Benutzer soll nicht angelegt werden. 782 // Daher ist die Anmeldung hier gescheitert. 783 $loginOk = false; 784 } 785 } 786 } 787 788 Password::delay(); 789 790 $ip = getenv("REMOTE_ADDR"); 791 792 if ( !$loginOk ) 793 { 794 // Anmeldung nicht erfolgreich 795 796 Logger::debug("Login failed for user '$loginName' from IP $ip"); 797 798 if ( $tokenFailed ) 799 { 800 // Token falsch. 801 $this->addNotice('user',$loginName,'LOGIN_FAILED_TOKEN_FAILED','error' ); 802 $this->addValidationError('user_token',''); 803 } 804 elseif ( $mustChangePassword ) 805 { 806 // Anmeldung gescheitert, Benutzer muss Kennwort ?ndern. 807 $this->addNotice('user',$loginName,'LOGIN_FAILED_MUSTCHANGEPASSWORD','error' ); 808 $this->addValidationError('password1',''); 809 $this->addValidationError('password2',''); 810 } 811 else 812 { 813 // Anmeldung gescheitert. 814 $this->addNotice('user',$loginName,'LOGIN_FAILED','error',array('name'=>$loginName) ); 815 $this->addValidationError('login_name' ,''); 816 $this->addValidationError('login_password',''); 817 } 818 819 return; 820 } 821 else 822 { 823 824 Logger::debug("Login successful for user '$loginName' from IP $ip"); 825 826 $this->checkGroups( $user, $groups ); 827 828 if ( $this->hasRequestVar('remember') ) 829 { 830 // Cookie setzen 831 $this->setCookie('or_username',$user->name ); 832 $this->setCookie('or_token' ,$user->createNewLoginToken() ); 833 } 834 835 // Anmeldung erfolgreich. 836 if ( config()->subset('security')->is('renew_session_login',false) ) 837 $this->recreateSession(); 838 839 $this->addNotice('user',$user->name,'LOGIN_OK',OR_NOTICE_OK,array('name'=>$user->fullname)); 840 841 $this->setStyle( $user->style ); // Benutzer-Style setzen 842 843 $config = Session::getConfig(); 844 $language = new \language\Language(); 845 $config['language'] = $language->getLanguage($user->language); 846 $config['language']['language_code'] = $user->language; 847 Session::setConfig( $config ); 848 } 849 850 } 851 852 853 /** 854 * Benutzer meldet sich ab. 855 */ 856 public function logoutPost() 857 { 858 global $conf; 859 860 $user = Session::getUser(); 861 if ( is_object($user) ) 862 $this->setTemplateVar('login_username',$user->name); 863 864 if ( config()->subset('security')->is('renew_session_logout',false) ) 865 $this->recreateSession(); 866 867 if ( @$conf['theme']['compiler']['compile_at_logout'] ) 868 { 869 foreach( $conf['action'] as $actionName => $actionConfig ) 870 { 871 foreach( $actionConfig as $subActionName=>$subaction ) 872 { 873 if ( is_array($subaction) && 874 !isset($subaction['goto' ]) && 875 !isset($subaction['direct']) && 876 !isset($subaction['action']) && 877 !isset($subaction['async' ]) && 878 !isset($subaction['alias' ]) && 879 $subActionName != 'menu' ) 880 { 881 $engine = new template_engine\TemplateEngine(); 882 $engine->compile( strtolower(str_replace('Action','',$actionName)).'/'.$subActionName); 883 } 884 } 885 } 886 } 887 888 // Login-Token löschen: 889 // Wenn der Benutzer sich abmelden will, dann soll auch die automatische 890 // Anmeldung deaktiviert werden. 891 892 // Bestehendes Login-Token aus dem Cookie lesen und aus der Datenbank löschen. 893 list( $selector,$token ) = array_pad( explode('.',@$_COOKIE['or_token']),2,''); 894 895 if ( $selector ) 896 $this->currentUser->deleteLoginToken( $selector ); 897 898 // Cookie mit Logintoken löschen. 899 $this->setCookie('or_token' ,null ); 900 901 //session_unset(); 902 Session::setUser(null); 903 904 // Umleiten auf eine definierte URL.s 905 $redirect_url = @$conf['security']['logout']['redirect_url']; 906 907 if ( !empty($redirect_url) ) 908 { 909 $this->redirect($redirect_url); 910 } 911 912 // Style zurücksetzen. 913 // Der Style des Benutzers koennte auch stehen bleiben. Aber dann gäbe es Rückschlüsse darauf, wer zuletzt angemeldet war (Sicherheit!). 914 $this->setStyle( config('interface','style','default') ); 915 916 $this->addNotice('user',$user->name,'LOGOUT_OK',OR_NOTICE_OK); 917 918 } 919 920 921 922 /** 923 * Benutzer meldet sich ab. 924 */ 925 function logoutView() 926 { 927 } 928 929 930 /** 931 * Ausgeben von maschinenlesbaren Benutzerinformationen. 932 * 933 * Diese Funktion dient dem Single-Signon f?r fremde Anwendungen, welche 934 * die Benutzerinformationen des angemeldeten Benutzers aus dieser 935 * Anwendung auslesen k?nnen. 936 */ 937 function userinfo() 938 { 939 $user = Session::getUser(); 940 $info = array('username' => $user->name, 941 'fullname' => $user->fullname, 942 'mail' => $user->mail, 943 'telephone' => $user->tel, 944 'style' => $user->style, 945 'admin' => $user->isAdmin?'true':'false', 946 'ldap' => $user->ldap_dn, 947 'groups' => implode(',',$user->getGroups()), 948 'description'=> $user->desc 949 ); 950 951 // Wenn der HTTP-Parameter "xml" vorhanden ist, dann geben wir die 952 // Informationen per XML aus. 953 if ( $this->hasRequestVar('xml') ) 954 { 955 header('Content-Type: text/xml'); 956 echo '<userinfo>'; 957 foreach( $info as $n=>$i ) 958 echo '<'.$n.'>'.$i.'</'.$n.'>'."\n"; 959 echo '</userinfo>'; 960 961 } 962 963 // Sonst normale Textausgabe im INI-Datei-Format. 964 else 965 { 966 header('Content-Type: text/plain'); 967 foreach( $info as $n=>$i ) 968 echo $n.'="'.$i."\"\n"; 969 } 970 971 exit; // Fertig. 972 } 973 974 975 function project() 976 { 977 $user = Session::getUser(); 978 if ( ! is_object($user) ) 979 { 980 $this->callSubAction('show'); 981 return; 982 } 983 984 $this->evaluateRequestVars( array('projectid'=>$this->getRequestId()) ); 985 986 Session::setUser( $user ); 987 } 988 989 990 function object() 991 { 992 $user = Session::getUser(); 993 if ( ! is_object($user) ) 994 { 995 $this->callSubAction('show'); 996 return; 997 } 998 999 $this->evaluateRequestVars( array('objectid'=>$this->getRequestId()) ); 1000 1001 Session::setUser( $user ); 1002 } 1003 1004 1005 function language() 1006 { 1007 $user = Session::getUser(); 1008 if ( ! is_object($user) ) 1009 { 1010 $this->callSubAction('show'); 1011 return; 1012 } 1013 1014 $this->evaluateRequestVars( array(REQ_PARAM_LANGUAGE_ID=>$this->getRequestId()) ); 1015 } 1016 1017 1018 function model() 1019 { 1020 $user = Session::getUser(); 1021 if ( ! is_object($user) ) 1022 { 1023 $this->callSubAction('show'); 1024 return; 1025 } 1026 1027 $this->evaluateRequestVars( array(REQ_PARAM_MODEL_ID=>$this->getRequestId()) ); 1028 1029 $user = Session::getUser(); 1030 } 1031 1032 1033 /** 1034 * Auswerten der Request-Variablen. 1035 * 1036 * @param Array $add 1037 */ 1038 function evaluateRequestVars( $add = array() ) 1039 { 1040 } 1041 1042 1043 function showtree() 1044 { 1045 Session::set('showtree',true ); 1046 } 1047 1048 1049 function hidetree() 1050 { 1051 Session::set('showtree',false ); 1052 } 1053 1054 1055 function switchuser() 1056 { 1057 $user = Session::getUser(); 1058 1059 if ( ! $user->isAdmin ) 1060 throw new \SecurityException("Switching the user is only possible for admins."); 1061 1062 $this->recreateSession(); 1063 1064 $newUser = new User( $this->getRequestId() ); 1065 $newUser->load(); 1066 1067 $newUser->setCurrent(); 1068 } 1069 1070 1071 function show() 1072 { 1073 global $conf; 1074 global $PHP_AUTH_USER; 1075 global $PHP_AUTH_PW; 1076 1077 $user = Session::getUser(); 1078 // Gast-Login 1079 if ( ! is_object($user) ) 1080 { 1081 if ( $conf['security']['guest']['enable'] ) 1082 { 1083 $username = $conf['security']['guest']['user']; 1084 $user = User::loadWithName($username); 1085 if ( $user->userid > 0 ) 1086 $user->setCurrent(); 1087 else 1088 { 1089 Logger::warn('Guest login failed, user not found: '.$username); 1090 $this->addNotice('user',$username,'LOGIN_FAILED',OR_NOTICE_WARN,array('name'=>$username) ); 1091 $user = null; 1092 } 1093 } 1094 } 1095 1096 if ( ! is_object($user) ) 1097 { 1098 switch( $conf['security']['login']['type'] ) 1099 { 1100 1101 // Authorization ueber HTTP 1102 // 1103 case 'http': 1104 $ok = false; 1105 1106 if ( isset($_SERVER['PHP_AUTH_USER']) ) 1107 { 1108 $ok = $this->checkLogin( $_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'] ); 1109 } 1110 1111 if ( ! $ok ) 1112 { 1113 header( 'WWW-Authenticate: Basic realm="'.OR_TITLE.' - '.lang('HTTP_REALM').'"' ); 1114 header( 'HTTP/1.0 401 Unauthorized' ); 1115 echo 'Authorization Required!'; 1116 exit; 1117 } 1118 break; 1119 1120 case 'form': 1121 // Benutzer ist nicht angemeldet 1122 $this->callSubAction( 'showlogin' ); // Anzeigen der Login-Maske 1123 return; 1124 break; 1125 1126 default: 1127 throw new \LogicException('Unknown auth-type: '.$conf['security']['login']['type'].'. Please check the configuration setting /security/login/type' ); 1128 } 1129 } 1130 1131 if ( $user->mustChangePassword ) 1132 { 1133 $this->addNotice( 'user',$user->name,'PASSWORD_TIMEOUT','warn' ); 1134 $this->callSubAction( 'changepassword' ); // Zwang, das Kennwort zu ?ndern. 1135 } 1136 1137 // Seite ?ndert sich nur 1x pro Session 1138 $this->lastModified( $user->loginDate ); 1139 1140 } 1141 1142 1143 1144 /** 1145 * Maske anzeigen, um Benutzer zu registrieren. 1146 */ 1147 public function registerView() 1148 { 1149 1150 } 1151 1152 1153 /** 1154 * Registriercode erzeugen und per E-Mail dem Benutzer mitteilen. 1155 * Maske anzeigen, damit Benuter Registriercode anzeigen kann. 1156 */ 1157 public function registercodeView() 1158 { 1159 global $conf; 1160 foreach( $conf['database'] as $dbname=>$dbconf ) 1161 { 1162 if ( is_array($dbconf) && $dbconf['enabled'] ) 1163 $dbids[$dbname] = $dbconf['description']; 1164 } 1165 1166 $this->setTemplateVar( 'dbids',$dbids ); 1167 1168 $db = db(); 1169 if ( is_object($db) ) 1170 $this->setTemplateVar('actdbid',$db->id); 1171 else 1172 $this->setTemplateVar('actdbid',$conf['database-defaults']['default-id']); 1173 1174 1175 1176 } 1177 1178 1179 1180 public function registerPost() 1181 { 1182 global $conf; 1183 1184 Session::set('registerMail',$this->getRequestVar('mail') ); 1185 1186 srand ((double)microtime()*1000003); 1187 $registerCode = rand(); 1188 1189 Session::set('registerCode',$registerCode ); 1190 1191 $email_address = $this->getRequestVar('mail',OR_FILTER_MAIL); 1192 1193 if ( ! Mail::checkAddress($email_address) ) 1194 { 1195 $this->addValidationError('mail'); 1196 return; 1197 } 1198 1199 // E-Mail and die eingegebene Adresse verschicken 1200 $mail = new Mail($email_address, 1201 'register_commit_code','register_commit_code'); 1202 $mail->setVar('code',$registerCode); // Registrierungscode als Text-Variable 1203 1204 if ( $mail->send() ) 1205 { 1206 $this->addNotice('','','mail_sent',OR_NOTICE_OK); 1207 } 1208 else 1209 { 1210 $this->addNotice('','','mail_not_sent',OR_NOTICE_ERROR,array(),$mail->error); 1211 return; 1212 } 1213 } 1214 1215 1216 /** 1217 * Benutzerregistierung. 1218 * Benutzer hat Best?tigungscode erhalten und eingegeben. 1219 */ 1220 function registercodePost() 1221 { 1222 global $conf; 1223 1224 $origRegisterCode = Session::get('registerCode'); 1225 $inputRegisterCode = $this->getRequestVar('code'); 1226 1227 if ( $origRegisterCode != $inputRegisterCode ) 1228 { 1229 // Best?tigungscode stimmt nicht. 1230 $this->addValidationError('code','code_not_match'); 1231 return; 1232 } 1233 1234 // Best?tigungscode stimmt ?berein. 1235 // Neuen Benutzer anlegen. 1236 1237 if ( !$this->hasRequestVar('username') ) 1238 { 1239 $this->addValidationError('username'); 1240 return; 1241 } 1242 1243 $user = User::loadWithName( $this->getRequestVar('username') ); 1244 if ( $user->isValid() ) 1245 { 1246 $this->addValidationError('username','USER_ALREADY_IN_DATABASE'); 1247 return; 1248 } 1249 1250 if ( strlen($this->getRequestVar('password')) < $conf['security']['password']['min_length'] ) 1251 { 1252 $this->addValidationError('password','password_minlength',array('minlength'=>$conf['security']['password']['min_length'])); 1253 return; 1254 } 1255 1256 $newUser = new User(); 1257 $newUser->name = $this->getRequestVar('username'); 1258 $newUser->add(); 1259 1260 $newUser->mail = Session::get('registerMail'); 1261 $newUser->save(); 1262 1263 $newUser->setPassword( $this->getRequestVar('password'),true ); 1264 1265 $this->addNotice('user',$newUser->name,'user_added','ok'); 1266 } 1267 1268 1269 1270 /** 1271 * Vergessenes Kennwort zusenden lassen. 1272 */ 1273 function passwordView() 1274 { 1275 // TODO: Attribut "Password" abfragen 1276 foreach( config('database') as $dbname=>$dbconf ) 1277 { 1278 $dbconf = $dbconf + config('database-default','defaults'); 1279 if ( $dbconf['enabled'] ) 1280 $dbids[$dbname] = $dbconf['description']; 1281 } 1282 1283 $this->setTemplateVar( 'dbids',$dbids ); 1284 1285 1286 $db = db(); 1287 1288 if ( is_object($db) ) 1289 $this->setTemplateVar('actdbid',$db->id); 1290 else 1291 $this->setTemplateVar('actdbid',config('database-default','default-id')); 1292 } 1293 1294 1295 1296 /** 1297 * Einen Kennwort-Anforderungscode an den Benutzer senden. 1298 */ 1299 function passwordPost() 1300 { 1301 if ( !$this->hasRequestVar('username') ) 1302 { 1303 $this->addValidationError('username'); 1304 return; 1305 } 1306 1307 $user = User::loadWithName( $this->getRequestVar("username") ); 1308 // Html::debug($user); 1309 Password::delay(); 1310 if ( $user->isValid() ) 1311 { 1312 srand ((double)microtime()*1000003); 1313 $code = rand(); 1314 $this->setSessionVar("password_commit_code",$code); 1315 1316 $eMail = new Mail( $user->mail,'password_commit_code' ); 1317 $eMail->setVar('name',$user->getName()); 1318 $eMail->setVar('code',$code); 1319 if ( $eMail->send() ) 1320 $this->addNotice('user',$user->getName(),'mail_sent',OR_NOTICE_OK); 1321 else 1322 $this->addNotice('user',$user->getName(),'mail_not_sent',OR_NOTICE_ERROR,array(),$eMail->error); 1323 1324 } 1325 else 1326 { 1327 //$this->addNotice('','user','username_not_found'); 1328 // Trotzdem vort?uschen, eine E-Mail zu senden, damit die G?ltigkeit 1329 // eines Benutzernamens nicht von au?en gepr?ft werden kann. 1330 // 1331 $this->addNotice('user',$this->getRequestVar("username"),'mail_sent'); 1332 1333 } 1334 1335 $this->setSessionVar("password_commit_name",$user->name); 1336 } 1337 1338 1339 1340 /** 1341 * Anzeige Formular zum Eingeben des Kennwort-Codes. 1342 * 1343 */ 1344 function passwordcodeView() 1345 { 1346 1347 } 1348 1349 1350 /** 1351 * Neues Kennwort erzeugen und dem Benutzer zusenden. 1352 */ 1353 function passwordcodePost() 1354 { 1355 $username = $this->getSessionVar("password_commit_name"); 1356 1357 if ( $this->getRequestVar("code")=='' || 1358 $this->getSessionVar("password_commit_code") != $this->getRequestVar("code") ) 1359 { 1360 $this->addValidationError('code','PASSWORDCODE_NOT_MATCH'); 1361 return; 1362 } 1363 1364 $user = User::loadWithName( $username ); 1365 1366 if ( !$user->isValid() ) 1367 { 1368 // Benutzer konnte nicht geladen werden. 1369 $this->addNotice('user',$username,'error',OR_NOTICE_ERROR); 1370 return; 1371 } 1372 1373 $newPw = User::createPassword(); // Neues Kennwort erzeugen. 1374 1375 $eMail = new Mail( $user->mail,'password_new' ); 1376 $eMail->setVar('name' ,$user->getName()); 1377 $eMail->setVar('password',$newPw ); 1378 1379 if ( $eMail->send() ) 1380 { 1381 $user->setPassword( $newPw, false ); // Kennwort muss beim n?. Login ge?ndert werden. 1382 $this->addNotice('user',$username,'mail_sent',OR_NOTICE_OK); 1383 } 1384 else 1385 { 1386 // Sollte eigentlich nicht vorkommen, da der Benutzer ja auch schon den 1387 // Code per E-Mail erhalten hat. 1388 $this->addNotice('user',$username,'error',OR_NOTICE_ERROR,array(),$eMail->error); 1389 } 1390 } 1391 1392 1393 /** 1394 * Erzeugt eine neue Sitzung. 1395 */ 1396 function recreateSession() 1397 { 1398 1399 session_regenerate_id(true); 1400 } 1401 1402 1403 function licenseView() 1404 { 1405 $software = array(); 1406 1407 $software[] = array('name' =>'OpenRat Content Management System', 1408 'url' =>'http://www.openrat.de/', 1409 'license'=>'GPL v2'); 1410 $software[] = array('name' =>'jQuery Core Javascript Framework', 1411 'url' =>'http://jquery.com/', 1412 'license'=>'MPL, GPL v2'); 1413 $software[] = array('name' =>'jQuery UI Javascript Framework', 1414 'url' =>'http://jqueryui.com/', 1415 'license'=>'MPL, GPL v2'); 1416 $software[] = array('name' =>'GeSHi - Generic Syntax Highlighter', 1417 'url' =>'http://qbnz.com/highlighter/', 1418 'license'=>'GPL v2'); 1419 $software[] = array('name' =>'TAR file format', 1420 'url' =>'http://www.phpclasses.org/package/529', 1421 'license'=>'LGPL'); 1422 $software[] = array('name' =>'JSON file format', 1423 'url' =>'http://pear.php.net/pepr/pepr-proposal-show.php?id=198', 1424 'license'=>'BSD'); 1425 1426 $this->setTemplateVar('software',$software); 1427 1428 1429 1430 $this->setTemplateVar('time' ,date('r') ); 1431 $this->setTemplateVar('os' ,php_uname('s') ); 1432 $this->setTemplateVar('release' ,php_uname('r') ); 1433 $this->setTemplateVar('machine' ,php_uname('m') ); 1434 $this->setTemplateVar('version' , phpversion() ); 1435 1436 $this->setTemplateVar('cms_name' , Conf()->subset('application')->get('name' ) ); 1437 $this->setTemplateVar('cms_version' , Conf()->subset('application')->get('version' ) ); 1438 $this->setTemplateVar('cms_operator', Conf()->subset('application')->get('operator') ); 1439 1440 $user = Session::getUser(); 1441 if ( !empty($user) ) 1442 { 1443 $this->setTemplateVar('user_login' , $user->loginDate ); 1444 $this->setTemplateVar('user_name' , $user->name ); 1445 $this->setTemplateVar('user_fullname', $user->fullname ); 1446 } 1447 1448 } 1449 1450 } 1451 1452