254 lines
8.8 KiB
PHP
254 lines
8.8 KiB
PHP
<?php #lib/10_login.php
|
|
|
|
/********************************************************************************
|
|
* Content: Login related functions *
|
|
* Author: Nils Otterpohl *
|
|
* Last modification: 24.06.2019 *
|
|
* Version: alpha (incomplete, tested, commented) *
|
|
********************************************************************************/
|
|
|
|
function lgnGenHash($password, $salt, $iterations, $length = 32, $algo = "sha256") {
|
|
return hash_pbkdf2($algo, $password, $salt, $iterations, $length*2);
|
|
}
|
|
|
|
function lgnGenSalt($length = 16) {
|
|
return bin2hex(random_bytes($length));
|
|
}
|
|
function lgnTransformPassword($password = "") {
|
|
$salt = lgnGenSalt();
|
|
if ($password=="")
|
|
$password = lgnGenSalt(8);
|
|
return array(
|
|
"password" => $password,
|
|
"iterations" => DESIRED_ITERATIONS,
|
|
"salt" => $salt,
|
|
"hash" => lgnGenHash($password, $salt, DESIRED_ITERATIONS)
|
|
);
|
|
}
|
|
|
|
function lgnSecSessionStart() {
|
|
// Copied and adjusted after https://de.wikihow.com/Ein-sicheres-Login-Skript-mit-PHP-und-MySQL-erstellen
|
|
|
|
// Zwingt die Sessions nur Cookies zu benutzen.
|
|
if (ini_set("session.use_only_cookies", 1) === FALSE) {
|
|
exit();
|
|
}
|
|
|
|
// Holt Cookie-Parameter.
|
|
$cookieParams = session_get_cookie_params();
|
|
// Erstes true = Nur https Zugriff, Zweites true = Blockt JavaScript Zugriff
|
|
session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], true, true);
|
|
$sessionName = "SessionOfHigherSecureness";
|
|
session_name($sessionName);
|
|
session_start(); // Startet die PHP-Sitzung
|
|
session_regenerate_id(); // Erneuert die Session, löscht die alte.
|
|
}
|
|
|
|
function lgnRegenerateToken() {
|
|
if (isset($_SESSION["secTokenUse"])) {
|
|
$_SESSION["secTokenVerify"] = $_SESSION["secTokenUse"];
|
|
} else {
|
|
$_SESSION["secTokenVerify"] = "";
|
|
}
|
|
$_SESSION["secTokenUse"] = lgnGenSalt(16);
|
|
}
|
|
|
|
function lgnLogin($mysqli, $login, $password) {
|
|
// Copied and adjusted after https://de.wikihow.com/Ein-sicheres-Login-Skript-mit-PHP-und-MySQL-erstellen
|
|
// and https://github.com/nextcloud/user_external/blob/master/lib/webdavauth.php
|
|
|
|
// Das Benutzen vorbereiteter Statements verhindert SQL-Injektion.
|
|
$login = strtolower($login);
|
|
$login = str_replace("@feuerwehr-bs.net", "", $login);
|
|
|
|
if ($stmt = $mysqli->prepare("SELECT p.ID, p.login FROM Personal p WHERE p.login = ? LIMIT 1")) {
|
|
$stmt->bind_param("s", $login); // Bind "$login" to parameter.
|
|
$stmt->execute(); // Führe die vorbereitete Anfrage aus.
|
|
$stmt->store_result();
|
|
|
|
// hole Variablen von result.
|
|
$stmt->bind_result($userID, $userLogin);
|
|
$stmt->fetch();
|
|
|
|
if ($stmt->num_rows == 1) {
|
|
$url= 'https://'.urlencode($userLogin).':'.urlencode($password).'@feuerwehr-bs.net/webdav';
|
|
$headers = get_headers($url);
|
|
if($headers === false) {
|
|
addError("loginFailed", 'ERROR: Not possible to connect to WebDAV Url: "https://feuerwehr-bs.net/webdav"');
|
|
return false;
|
|
}
|
|
$returnCode= substr($headers[0], 9, 3);
|
|
|
|
if(substr($returnCode, 0, 1) === '2') {
|
|
// Passwort ist korrekt!
|
|
|
|
// Hole den user-agent string des Benutzers.
|
|
$userBrowser = $_SERVER["HTTP_USER_AGENT"];
|
|
// XSS-Schutz, denn eventuell wird der Wert gedruckt
|
|
$userID = preg_replace("/[^0-9]+/", "", $userID);
|
|
$_SESSION["userID"] = $userID;
|
|
// XSS-Schutz, denn eventuell wird der Wert gedruckt
|
|
$userLogin = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $userLogin);
|
|
$_SESSION["userLogin"] = $userLogin;
|
|
|
|
// Generiere einen Hash aus dem Passwort mit zufälligem Salt und speichere ihn in der Datenbank
|
|
$hash = lgnGenHash($password, lgnGenSalt(), DESIRED_ITERATIONS);
|
|
$_SESSION["loginString"] = lgnGenHash($hash, $userBrowser, 10, 64, "sha512");
|
|
$mysqli->query("REPLACE INTO sys_iservhashes(ID, Hash) VALUES ('".$userID."', '".$hash."')");
|
|
|
|
// Login erfolgreich.
|
|
return true;
|
|
} else {
|
|
// Passwort ist nicht korrekt
|
|
addError("loginFailed", " Passwort nicht korrekt. Fehlercode (bitte an Nils senden): ".$returnCode);
|
|
}
|
|
} else {
|
|
addError("loginFailed", "Benutzername inkorrekt ".$login);
|
|
}
|
|
}
|
|
if ($mysqli->error!="") {
|
|
addError("mysql", $mysqli->error);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function lgnLogout() {
|
|
// Setze alle Session-Werte zurück
|
|
$_SESSION = array();
|
|
|
|
// hole Session-Parameter
|
|
$params = session_get_cookie_params();
|
|
|
|
// Lösche das aktuelle Cookie.
|
|
setcookie(
|
|
session_name(),
|
|
'',
|
|
time() - 42000,
|
|
$params["path"],
|
|
$params["domain"],
|
|
$params["secure"],
|
|
$params["httponly"]
|
|
);
|
|
|
|
// Vernichte die Session
|
|
session_destroy();
|
|
header('Location: index.php');
|
|
}
|
|
|
|
function lgnChangePass($mysqli, $userID, $passOld, $passNew, $passRepeat) {
|
|
$ret = false;
|
|
if ($passOld==$passNew) {
|
|
addError("passChangeFail", "Neues und altes Passwort sind nicht unterschiedlich?");
|
|
} else if (strlen($passNew)<12) {
|
|
addError("passChangeFail", "Passwort muss mindestens 12 Zeichen haben!");
|
|
} else if ($passNew!=$passRepeat) {
|
|
addError("passChangeFail", "Passwortwiederholung falsch!");
|
|
} else {
|
|
if ($stmt = $mysqli->prepare("SELECT iterations, salt, hash FROM users WHERE ID = ? LIMIT 1")) {
|
|
$stmt->bind_param("i", $_SESSION["userID"]);
|
|
$stmt->execute();
|
|
$stmt->store_result();
|
|
$stmt->bind_result($passIterations, $passSalt, $passHash);
|
|
$stmt->fetch();
|
|
|
|
if ($stmt->num_rows == 1) {
|
|
if (lgnGenHash($passOld, $passSalt, $passIterations)!=$passHash) {
|
|
addError("passChangeFail", "Altes Passwort inkorrekt!");
|
|
} else {
|
|
$newSalt = lgnGenSalt();
|
|
$newHash = lgnGenHash($passNew, $newSalt, DESIRED_ITERATIONS);
|
|
$mysqli->query("UPDATE users SET iterations='".DESIRED_ITERATIONS."', salt='".$newSalt."', hash='".$newHash."' "
|
|
."WHERE ID='".$_SESSION["userID"]."'");
|
|
$userBrowser = $_SERVER["HTTP_USER_AGENT"];
|
|
$_SESSION["loginString"] = lgnGenHash($newHash, $userBrowser, 10, 64, "sha512");
|
|
$ret = true;
|
|
}
|
|
}
|
|
} else {
|
|
addError("passChangeFailed", $mysqli->error);
|
|
}
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
function lgnCheckBrute($mysqli, $userID) {
|
|
// Copied and adjusted after https://de.wikihow.com/Ein-sicheres-Login-Skript-mit-PHP-und-MySQL-erstellen
|
|
// Hole den aktuellen Zeitstempel
|
|
|
|
// Alle Login-Versuche der letzten zwei Stunden werden gezählt.
|
|
if ($stmt = $mysqli->prepare("SELECT time FROM failedlogins WHERE ID = ? AND time > DATE_SUB(NOW(), INTERVAL 2 HOUR)")) {
|
|
$stmt->bind_param("i", $userID);
|
|
|
|
// Führe die vorbereitet Abfrage aus.
|
|
$stmt->execute();
|
|
$stmt->store_result();
|
|
|
|
// Wenn es mehr als 5 fehlgeschlagene Versuche gab
|
|
if ($stmt->num_rows > 5) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function lgnCheckLogin($mysqli) {
|
|
// Überprüfe, ob alle Session-Variablen gesetzt sind
|
|
if (isset($_SESSION["userID"], $_SESSION["userLogin"], $_SESSION["loginString"])) {
|
|
$userID = $_SESSION["userID"];
|
|
$loginString = $_SESSION["loginString"];
|
|
$userLogin = $_SESSION["userLogin"];
|
|
|
|
// Hole den user-agent string des Benutzers.
|
|
$userBrowser = $_SERVER["HTTP_USER_AGENT"];
|
|
|
|
// Die UserID wird hier nochmal abgerufen, damit dem Rückgabewert der Funktion vertraut werden kann
|
|
if ($stmt = $mysqli->prepare("SELECT ID, Hash FROM sys_iservhashes WHERE ID = ? LIMIT 1")) {
|
|
$stmt->bind_param("i", $userID);
|
|
$stmt->execute();
|
|
$stmt->store_result();
|
|
|
|
if ($stmt->num_rows == 1) {
|
|
// Wenn es den Benutzer gibt, hole die Variablen von result.
|
|
$stmt->bind_result($uID, $uHash);
|
|
$stmt->fetch();
|
|
|
|
if (lgnGenHash($uHash, $userBrowser, 10, 64, "sha512") == $loginString) {
|
|
// Eingeloggt!!!!
|
|
return $uID;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Nicht eingeloggt
|
|
if ($mysqli->error!="") {
|
|
addError("mysql", $mysqli->error);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function lgnCheckRight($mysqli, $right, $userID = null) {
|
|
if ($right==null) {
|
|
return true;
|
|
}
|
|
if ($userID==null) {
|
|
$userID = lgnCheckLogin($mysqli);
|
|
}
|
|
$query = "SELECT b.name FROM Personal p "
|
|
."LEFT JOIN link_Personal_Personalgruppen lpp ON p.ID=lpp.Personal "
|
|
."LEFT JOIN link_Berechtigungen_Personalgruppen lbp ON lbp.Personalgruppen = lpp.Personalgruppen "
|
|
."LEFT JOIN Berechtigungen b ON b.ID = lbp.Berechtigungen "
|
|
."WHERE p.ID = ".$userID." and b.Name ";
|
|
if (is_array($right)) {
|
|
$query.= "IN ('".implode("', '", $right)."')";
|
|
} else {
|
|
$query.= "= '".$right."'";
|
|
}
|
|
if ($res = $mysqli->query($query)) {
|
|
if ($res->num_rows>0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
?>
|