diff --git a/addKey.php b/addKey.php
index ce1a1ff..c90d6e2 100644
--- a/addKey.php
+++ b/addKey.php
@@ -14,7 +14,8 @@ if($settings == "valid")
if(!$dbconn = db_verbinden($mysql_server, $mysql_user, $mysql_pw, $mysql_db))
$err = error("Verbindung zur Datenbank fehlgeschlagen: ".htmlspecialchars(mysqli_connect_error()));
}
-if($_SESSION["login"] == "valid" && isset($_GET["id"])){
+// Wie sites/userkeys.php: nur Superadmins dürfen Passkeys vergeben
+if($_SESSION["login"] == "valid" && isset($_GET["id"]) && ((int)substr($_SESSION["rights"], RIGHTS_SUPERADMIN, 1) & RIGHTS_CHANGE)){
if(!mysqli_query($dbconn,"DELETE FROM addKey WHERE datetime < DATE_SUB(NOW(), INTERVAL 1 MINUTE);")){
echo mysqli_error($dbconn);
}
@@ -23,8 +24,8 @@ if($_SESSION["login"] == "valid" && isset($_GET["id"])){
if(!mysqli_query($dbconn,"INSERT INTO addKey SET accesskey=".$accessKey.", datetime=NOW();")){
echo mysqli_error($dbconn);
}
- header('Location: https://wm.el-wa.org/kunden?action=userkeys&id='.$_GET["id"].'&addKey='.$accessKey);
- echo 'https://wm.el-wa.org/kunden?action=userkeys&id='.$_GET["id"].'&addKey='.$accessKey;
+ header('Location: https://wm.el-wa.org/kunden?action=userkeys&id='.(int)$_GET["id"].'&addKey='.$accessKey);
+ echo 'https://wm.el-wa.org/kunden?action=userkeys&id='.(int)$_GET["id"].'&addKey='.$accessKey;
}else{
echo "Keine Berechtigung.";
}
diff --git a/authServer.php b/authServer.php
index 11fc2ad..4d240ca 100644
--- a/authServer.php
+++ b/authServer.php
@@ -105,6 +105,24 @@ try {
// request for create arguments
// ------------------------------------
+ // Passkeys anlegen darf nur ein angemeldeter Superadmin, der vorher in
+ // sites/userkeys.php eine gültige Einmal-Freigabe (addKey) eingelöst hat.
+ // Die Freigabe liegt in der Session und legt fest, für welchen Benutzer
+ // der Schlüssel gilt - die id aus der URL zählt nicht.
+ $passkeyFreigabe = null;
+ if (isset($_SESSION["passkey_freigabe"]) && $_SESSION["passkey_freigabe"]["bis"] >= time()
+ && ($_SESSION["login"] ?? "") == "valid"
+ && ((int)substr($_SESSION["rights"] ?? "", RIGHTS_SUPERADMIN, 1) & RIGHTS_CHANGE)) {
+ $passkeyFreigabe = $_SESSION["passkey_freigabe"];
+ }
+ if (($fn === 'getCreateArgs' || $fn === 'processCreate') && $passkeyFreigabe === null) {
+ throw new Exception('Keine Berechtigung, Passkeys anzulegen.');
+ }
+ if ($fn === 'queryFidoMetaDataService'
+ && !(($_SESSION["login"] ?? "") == "valid" && ((int)substr($_SESSION["rights"] ?? "", RIGHTS_SUPERADMIN, 1) & RIGHTS_CHANGE))) {
+ throw new Exception('Keine Berechtigung.');
+ }
+
if ($fn === 'getCreateArgs') {
$createArgs = $WebAuthn->getCreateArgs(\hex2bin($userId), $userName, $userDisplayName, 60*4, $requireResidentKey, $userVerification, $crossPlatformAttachment);
@@ -179,10 +197,12 @@ try {
if (!isset($_SESSION['registrations']) || !array_key_exists('registrations', $_SESSION) || !is_array($_SESSION['registrations'])) {
$_SESSION['registrations'] = [];
}*/
- if(!mysqli_query($dbconn,"INSERT INTO passkeys SET credentialId = '".base64_encode($data->credentialId)."', credentialPublicKey = '".base64_encode($data->credentialPublicKey)."', signatureCounter = '".base64_encode($data->signatureCounter)."', name = '".mysqli_real_escape_string($mysql,filter_input(INPUT_GET, 'name'))."', userId = '".mysqli_real_escape_string($mysql,filter_input(INPUT_GET, 'id'))."';")){
+ if(!mysqli_query($dbconn,"INSERT INTO passkeys SET credentialId = '".base64_encode($data->credentialId)."', credentialPublicKey = '".base64_encode($data->credentialPublicKey)."', signatureCounter = '".base64_encode($data->signatureCounter)."', name = '".mysqli_real_escape_string($mysql,filter_input(INPUT_GET, 'name'))."', userId = '".(int)$passkeyFreigabe["user"]."';")){
$msg = "Error:
".mysqli_error($dbconn)."
";
}
else{
+ // Freigabe gilt für genau einen Schlüssel
+ unset($_SESSION["passkey_freigabe"]);
if ($data->rootValid === false) {
$msg = 'registration ok, but certificate does not match any of the selected root ca. NO PROBLEM FOR THIS APP';
}
@@ -251,10 +271,16 @@ try {
$authKey = strval(random_int(0,99999999));
$result = mysqli_query($dbconn,"UPDATE passkeys SET authKey=".$authKey.", lastAuth=NOW() WHERE credentialId = '".base64_encode($id)."';");
- $qry= mysqli_query($dbconn, "SELECT * FROM user WHERE id = '".mysqli_real_escape_string($dbconn,$userId)."'");
- if(mysqli_num_rows($qry) == 1)
+ // Gesperrte Benutzer bleiben gesperrt, auch mit gültigem Passkey
+ $qry= mysqli_query($dbconn, "SELECT * FROM user WHERE id = '".mysqli_real_escape_string($dbconn,$userId)."' AND blocked = 0");
+ if(!$qry || mysqli_num_rows($qry) != 1)
+ {
+ throw new Exception('Benutzer nicht gefunden oder gesperrt.');
+ }
+ else
{
$udata = mysqli_fetch_assoc($qry);
+ session_regenerate_id(true);
$_SESSION["login"] = "valid";
$_SESSION["logedout"] = $udata["logedout"];
$_SESSION["user"] = $udata["id"];
diff --git a/sites/start.php b/sites/start.php
index afd3d03..eb43930 100644
--- a/sites/start.php
+++ b/sites/start.php
@@ -20,6 +20,8 @@ if(isset($_GET["formsent"]) && $_SESSION["login"] != "valid" && isLocal())
if(mysqli_num_rows($qry) == 1)
{
$udata = mysqli_fetch_assoc($qry);
+ // neue Session-ID nach dem Login, sonst ist Session-Fixation möglich
+ session_regenerate_id(true);
$_SESSION["login"] = "valid";
$_SESSION["logedout"] = $udata["logedout"];
$_SESSION["user"] = $udata["id"];
diff --git a/sites/userkeys.php b/sites/userkeys.php
index 64f3e94..fe0a60f 100644
--- a/sites/userkeys.php
+++ b/sites/userkeys.php
@@ -2,7 +2,12 @@
if(isset($_GET["id"]) && isset($_GET["addKey"])){
- if (checkAdduser($_GET["addUser"])) {
+ if (checkAdduser()) {
+ // Freigabe einlösen: gilt 5 Minuten, nur für diesen Benutzer und nur
+ // in dieser Session (geprüft in authServer.php). Der addKey ist damit
+ // verbraucht.
+ $_SESSION["passkey_freigabe"] = array("user" => (int)$_GET["id"], "bis" => time() + 300);
+ mysqli_query($mysql, "DELETE FROM addKey WHERE accesskey = '".mysqli_real_escape_string($mysql, $_GET["addKey"])."'");
echo <<
@@ -73,11 +78,11 @@ if(isset($_GET["id"]) && isset($_GET["addKey"])){
$smarty->assign("heading","Passkeys für externen Zugang verwalten");
$smarty->display("heading.tpl");
-$qry = mysqli_query($_SESSION["dbconn"],"SELECT id, vname, nname FROM user WHERE blocked = 0 AND user.id = ".mysqli_real_escape_string($_SESSION["dbconn"],$_GET["id"])) or die("Datenbank fehler: ".mysqli_error($_SESSION["dbconn"]));
+$qry = mysqli_query($_SESSION["dbconn"],"SELECT id, vname, nname FROM user WHERE blocked = 0 AND user.id = ".(int)$_GET["id"]) or die("Datenbank fehler: ".mysqli_error($_SESSION["dbconn"]));
$row=mysqli_fetch_array($qry);
$smarty->assign("user",$row);
-$qry = mysqli_query($_SESSION["dbconn"],"SELECT passkeys.id , passkeys.name FROM user JOIN passkeys ON user.id = passkeys.userId WHERE blocked = 0 AND user.id = ".mysqli_real_escape_string($_SESSION["dbconn"],$_GET["id"])) or die("Datenbank fehler: ".mysqli_error($_SESSION["dbconn"]));
+$qry = mysqli_query($_SESSION["dbconn"],"SELECT passkeys.id , passkeys.name FROM user JOIN passkeys ON user.id = passkeys.userId WHERE blocked = 0 AND user.id = ".(int)$_GET["id"]) or die("Datenbank fehler: ".mysqli_error($_SESSION["dbconn"]));
$keys = array();
while($row=mysqli_fetch_array($qry)){
$keys[] = $row;