diff options
-rw-r--r-- | inc/crypto.inc.php | 29 | ||||
-rw-r--r-- | inc/user.inc.php | 43 | ||||
-rw-r--r-- | modules/edit.inc.php | 41 | ||||
-rw-r--r-- | modules/login.inc.php | 7 | ||||
-rw-r--r-- | modules/main.inc.php | 74 | ||||
-rw-r--r-- | modules/register.inc.php | 2 | ||||
-rw-r--r-- | shib/api.php | 2 | ||||
-rw-r--r-- | style/default.css | 4 | ||||
-rw-r--r-- | templates/main/guest.html | 2 | ||||
-rw-r--r-- | templates/main/logged-in-testacc.html | 53 |
10 files changed, 229 insertions, 28 deletions
diff --git a/inc/crypto.inc.php b/inc/crypto.inc.php new file mode 100644 index 0000000..56f5073 --- /dev/null +++ b/inc/crypto.inc.php @@ -0,0 +1,29 @@ +<?php + +class Crypto +{ + + /** + * Hash given string using crypt's $6$, + * which translates to ~130 bit salt + * and 5000 rounds of hashing with SHA-512. + */ + public static function hash6($password) + { + $salt = substr(str_replace('+', '.', base64_encode(pack('N4', mt_rand(), mt_rand(), mt_rand(), mt_rand()))), 0, 16); + $hash = crypt($password, '$6$' . $salt); + if (strlen($hash) < 60) Util::traceError('Error hashing password using SHA-512'); + return $hash; + } + + /** + * Check if the given password matches the given cryp hash. + * Useful for checking a hashed password. + */ + public static function verify($password, $hash) + { + return crypt($password, $hash) === $hash; + } + +} + diff --git a/inc/user.inc.php b/inc/user.inc.php index 496857e..ef29003 100644 --- a/inc/user.inc.php +++ b/inc/user.inc.php @@ -46,6 +46,13 @@ class User return (int)self::$user['userid']; } + public static function getMail() + { + if (!isset(self::$user['email'])) + return false; + return self::$user['email']; + } + public static function getName() { if (!self::isLoggedIn()) @@ -115,8 +122,9 @@ class User if (Session::getUid() === false) return false; // Try user from local DB - self::$user = Database::queryFirst('SELECT userid, shibid, login, firstname, lastname, email FROM user WHERE userid = :uid LIMIT 1', array('uid' => Session::getUid())); - return self::$user !== false; + self::$user = Database::queryFirst('SELECT userid, shibid, login, organizationid AS organization, firstname, lastname, email FROM user WHERE userid = :uid LIMIT 1', array('uid' => Session::getUid())); + self::$isInDb = self::$user !== false; + return self::$isInDb; } // Try bwIDM etc. if (!$hasSession) { @@ -190,12 +198,35 @@ class User } } + public static function updatePassword($pass) + { + if (!self::isLoggedIn() || self::$isShib || !self::$isInDb) + return false; + $pw = Crypto::hash6($pass); + $ret = Database::exec('UPDATE user SET password = :pass WHERE userid = :user LIMIT 1', array( + 'pass' => $pw, + 'user' => self::getId() + )); + return $ret == 1; + } + + + public static function updateMail($mail) + { + if (!self::isLoggedIn() || self::$isShib || !self::$isInDb) + return false; + $ret = Database::exec('UPDATE user SET email = :mail WHERE userid = :user LIMIT 1', array( + 'mail' => $mail, + 'user' => self::getId() + )); + return $ret == 1 || $mail === self::get('email'); + } public static function login($user, $pass) { $ret = Database::queryFirst('SELECT userid, password FROM user WHERE login = :user LIMIT 1', array(':user' => $user)); if ($ret === false) return false; - if (!Crypto::verify($pass, $ret['passwd'])) + if (!Crypto::verify($pass, $ret['password'])) return false; Session::create(); Session::setUid($ret['userid']); @@ -212,7 +243,11 @@ class User @setcookie($name, '', time() - 8640000, null, null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', true); } Session::delete(); - Header('Location: ?do=Logout&noredirect=yes'); + if (self::$isShib) { + Header('Location: ?do=Logout&noredirect=yes'); + } else { + Header('Location: ?do=Main'); + } exit(0); } diff --git a/modules/edit.inc.php b/modules/edit.inc.php new file mode 100644 index 0000000..e3770ce --- /dev/null +++ b/modules/edit.inc.php @@ -0,0 +1,41 @@ +<?php + +class Page_Edit extends Page +{ + + public function doPreprocess() + { + if (!User::load()) { + Message::addError('Sie sind nicht angemeldet'); + Util::redirect('?do=Main'); + } + // See which attributes we are allowed to edit + $shib = User::isShibbolethAuth(); + $pw1 = Request::post('pass1'); + $pw2 = Request::post('pass2'); + $mail = Request::post('email'); + if ((!empty($pw1) || !empty($pw2)) && !$shib) { + if ($pw1 !== $pw2) { + Message::addError('Ihr Passwort wurde nicht verändert, da die Passwortwiederholung nicht mit dem Passwort übereinstimmt'); + } else if (mb_strlen($pw1) < 3) { + Message::addError('Ihr Passwort ist zu kurz'); + } else if (!User::updatePassword($pw1)) { + Message::addError('Datenbankfehler beim Aktualisieren des Passworts'); + } else { + Message::addSuccess('Ihr Passwort wurde aktualisiert und ist ab sofort gültig'); + } + } + if ($mail !== false && $mail !== User::getMail()) { + $mail = trim($mail); + if (!preg_match('/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}/i', $mail)) { + Message::addError('Ihre e-Mail-Adresse wurde nicht aktualisiert, da Sie ein ungültiges Format hat'); + } else { + User::updateMail($mail); + Message::addSuccess('Ihr e-Mail-Adresse wurde aktualisiert'); + } + } + Util::redirect('?do=Main'); + } + +} + diff --git a/modules/login.inc.php b/modules/login.inc.php index 517ce4e..37b005f 100644 --- a/modules/login.inc.php +++ b/modules/login.inc.php @@ -7,6 +7,13 @@ class Page_Login extends Page { if (User::load()) Util::redirect('?do=Main'); + if (Request::post('action') === 'login') { + if (User::login(Request::post('user'), Request::post('pass'))) + Util::redirect('?do=Main'); + sleep(2); + Message::addError('Benutzername oder Passwort falsch'); + Util::redirect('?do=Login'); + } } public function doRender() diff --git a/modules/main.inc.php b/modules/main.inc.php index 3f77d7b..c1382e6 100644 --- a/modules/main.inc.php +++ b/modules/main.inc.php @@ -11,30 +11,62 @@ class Page_Main extends Page protected function doRender() { Render::addTemplate('main/_page'); - if (User::isLoggedIn()) { - // Logged in user -- - if (User::getOrganization() !== false) { - // Organization is known, show signup form - if (User::isShibbolethAuth() && !User::isInDatabase()) { - // User comes via Shibboleth and is not known yet - $data = User::getData(); - $data['organization'] = User::getOrganizationName(); - Render::addTemplate('main/deploy', $data); - } else if (User::isInDatabase()) { - // User is known from DB at least - Render::addTemplate('main/logged-in'); - } - } else if (User::getRemoteOrganizationId() !== false) { - // Organization is not known, see if we at least have an idea - Message::addWarning('Ihre Hochschule/Einrichtung {{0}} ist leider nicht bekannt. Bitte kontaktieren Sie den Support.', User::getRemoteOrganizationId()); - } else { - // No idea where the user is coming from - Message::addError('Ihr IdP sendet leider keine Informationen über Ihre Hochschul-/Einrichtungszugehörigkeit'); - } - } else { + if (!User::isLoggedIn()) { // Guest Render::addTemplate('main/guest'); + return; + } + // Logged in user -- + if (User::isLocalOnly()) { + // Local test account + $this->renderLocalAccount(); + return; + } + if (!User::isShibbolethAuth()) { + // Should not be possible + Message::addError('Sie sind nicht korrekt authentifiziert. Bitte melden Sie sich erneut an.'); + Session::delete(); + return; + } + // --- Below here we know the user via shibboleth + if (User::isInDatabase()) { + // User is also in DB, so he signed up for the service + $this->renderShibbolethRegistered(); + return; } + // User is not in DB, so he might want so sign up for the service - see if conditions are met + if (User::getOrganization() !== false) { + // Organization is known, show signup form + $this->renderShibbolethUnregistered(); + return; + } + // Nothing we can do here, show error message :-( + if (User::getRemoteOrganizationId() !== false) { + // Organization is not known, see if we at least have an idea + Message::addWarning('Ihre Hochschule/Einrichtung {{0}} ist leider nicht bekannt. Bitte kontaktieren Sie den Support.', User::getRemoteOrganizationId()); + } else { + // No idea where the user is coming from + Message::addError('Ihr IdP sendet leider keine Informationen über Ihre Hochschul-/Einrichtungszugehörigkeit'); + } + } + + private function renderShibbolethRegistered() + { + Render::addTemplate('main/logged-in'); + } + + private function renderShibbolethUnregistered() + { + $data = User::getData(); + $data['organization'] = User::getOrganizationName(); + Render::addTemplate('main/deploy', $data); + } + + private function renderLocalAccount() + { + $data = User::getData(); + $data['organization'] = User::getOrganizationName(); + Render::addTemplate('main/logged-in-testacc', $data); } } diff --git a/modules/register.inc.php b/modules/register.inc.php index ca5f4bf..3dd3b89 100644 --- a/modules/register.inc.php +++ b/modules/register.inc.php @@ -11,7 +11,7 @@ class Page_Register extends Page Util::redirect('?do=Main'); } if (!User::isShibbolethAuth()) - Util::redirect('/secure-all/?do=Main'); + Util::redirect(CONFIG_PREFIX . 'shib/?do=Main'); if (Request::post('agb') === 'on') { // Put stuff in DB User::deploy(Request::post('share') !== 'on'); diff --git a/shib/api.php b/shib/api.php index 0c2a297..58b9c80 100644 --- a/shib/api.php +++ b/shib/api.php @@ -38,7 +38,7 @@ if (empty($_SERVER['persistent-id'])) { // Not found, so we don't know which satellite to use $response['status'] = 'unregistered'; $response['id'] = $shibId; - $response['url'] = 'https://bwlp-masterserver.ruf.uni-freiburg.de/secure-all/'; + $response['url'] = 'https://bwlp-masterserver.ruf.uni-freiburg.de/webif/'; } else { // Found, see if we got personal information, either temporarily through metadata, or from database $firstName = $user['firstname']; diff --git a/style/default.css b/style/default.css index 07e8a44..1a68547 100644 --- a/style/default.css +++ b/style/default.css @@ -43,6 +43,10 @@ p { border-top-right-radius: 0; } +span.form-control { + color: #777; +} + .form-narrow { max-width: 600px; padding: 10px; diff --git a/templates/main/guest.html b/templates/main/guest.html index 76b77ab..14cc902 100644 --- a/templates/main/guest.html +++ b/templates/main/guest.html @@ -1,7 +1,7 @@ <div class="form-narrow"> Sie sind nicht authentifiziert. Bitte wählen Sie: <ul> - <li><a href="shib/">Anmelden oder Registrieren über bwIDM</a></li> + <li><a href="shib/">Anmelden oder registrieren über bwIDM</a></li> <li><a href="?do=Login">Anmelden mit einem bwLehrpool-Testaccount</a></li> </ul> </div> diff --git a/templates/main/logged-in-testacc.html b/templates/main/logged-in-testacc.html new file mode 100644 index 0000000..a9e6f28 --- /dev/null +++ b/templates/main/logged-in-testacc.html @@ -0,0 +1,53 @@ +<p> + Sie sind mit Ihrem Test-Account <b>{{login}}</b> angemeldet. Sie können Ihr Passwort oder Ihre e-Mail-Adresse ändern. +</p> + +<form method="post" action="?do=Edit"> + <input type="hidden" name="token" value="{{token}}"> + <div class="form-narrow"> + + <div class="group-group"> + <div class="input-group"> + <span class="input-group-addon slx-ga"> + Einrichtung + </span> + <span class="form-control">{{organization}}</span> + </div> + <div class="input-group"> + <span class="input-group-addon slx-ga"> + Vorname + </span> + <span class="form-control">{{firstname}}</span> + </div> + <div class="input-group"> + <span class="input-group-addon slx-ga"> + Nachname + </span> + <span class="form-control">{{lastname}}</span> + </div> + <div class="input-group"> + <span class="input-group-addon slx-ga"> + Mail + </span> + <input class="form-control" type="text" name="email" value="{{email}}" pattern="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}"> + </div> + <div class="input-group"> + <span class="input-group-addon slx-ga"> + Passwort + </span> + <input class="form-control" type="password" name="pass1"> + </div> + <div class="input-group"> + <span class="input-group-addon slx-ga"> + Wiederholen + </span> + <input class="form-control" type="password" name="pass2"> + </div> + </div> + + <div class="pull-right"> + <button type="submit" class="btn btn-primary">Speichern</button> + </div> + + </div> +</form> |