summaryrefslogtreecommitdiffstats
path: root/shib/client_auth.php
diff options
context:
space:
mode:
authorSimon Rettberg2024-05-27 15:37:55 +0200
committerSimon Rettberg2024-05-27 15:37:55 +0200
commit43ddb14693e4a4830f471dd7c90f6257d95b7b29 (patch)
tree8c960b53e0f7ba1c660d16abf8bf044411b96080 /shib/client_auth.php
parentMerge branch 'master' of git.openslx.org:bwlp/bwlp-webadmin (diff)
downloadbwlp-webadmin-43ddb14693e4a4830f471dd7c90f6257d95b7b29.tar.gz
bwlp-webadmin-43ddb14693e4a4830f471dd7c90f6257d95b7b29.tar.xz
bwlp-webadmin-43ddb14693e4a4830f471dd7c90f6257d95b7b29.zip
Add support for client login via QRCodeHEADmaster
Diffstat (limited to 'shib/client_auth.php')
-rw-r--r--shib/client_auth.php142
1 files changed, 142 insertions, 0 deletions
diff --git a/shib/client_auth.php b/shib/client_auth.php
new file mode 100644
index 0000000..0af34de
--- /dev/null
+++ b/shib/client_auth.php
@@ -0,0 +1,142 @@
+<?php
+
+use JetBrains\PhpStorm\NoReturn;
+
+chdir('..');
+
+require_once 'config.php';
+
+/*
+Header('Content-Type: text/plain; charset=utf-8');
+die( json_encode($_SERVER, JSON_PRETTY_PRINT) );
+
+// */
+
+// Autoload classes from ./inc which adhere to naming scheme <lowercasename>.inc.php
+spl_autoload_register(function ($class) {
+ $file = 'inc/' . preg_replace('/[^a-z0-9]/', '', mb_strtolower($class)) . '.inc.php';
+ if (!file_exists($file))
+ return;
+ require_once $file;
+});
+
+#[NoReturn]
+function error(string $msg): void
+{
+ die('<!doctype html><html lang="en"><body><div id="bwlp-error">' . htmlspecialchars($msg) . '</div></body></html>');
+}
+
+
+
+Header('X-Frame-Options: DENY');
+Header("Content-Security-Policy: frame-ancestors 'none';");
+Header('Content-Type: text/html; charset=utf-8');
+
+$token = Request::get('token');
+$qrtoken = !empty(Request::get('qr'));
+if (strlen($token) <= 8) {
+ error('Unknown request');
+}
+
+// Got a token
+
+$user = '';
+// Get username from eppn is preferred
+if (isset($_SERVER[CONFIG_EPPN])) {
+ $user = preg_replace('/[^a-z0-9_@\-.]/', '', strtolower($_SERVER[CONFIG_EPPN]));
+ if (!empty($user) && is_numeric($user[0])) {
+ $user = 'x' . $user; // First character must not be a digit...
+ }
+}
+if (empty($user)) {
+ // No user - generate random username from persistent-id
+ $user = 'x' . substr(md5($_SERVER['persistent-id']), 0, 6);
+}
+if (isset($_SERVER[CONFIG_SCOPED_AFFILIATION]) && !str_contains($user, '@') && preg_match('/@[^@;\s]+/', $_SERVER[CONFIG_SCOPED_AFFILIATION], $out)) {
+ // We do not have an affiliation in the form of @something.com - try to extract from scoped affiliation
+ $user .= $out[0];
+}
+if (!str_contains($user, '@')) {
+ // *shrug*
+ $user .= '@unknown';
+}
+if (strlen($user) > 31) {
+ $user = substr($user, 0, 31);
+}
+/*
+Database::exec("CREATE TABLE IF NOT EXISTS client_token (
+ username varchar(128) not null,
+ token char(32) not null,
+ dateline int(10) unsigned not null,
+ KEY (username),
+ KEY (token),
+ KEY (dateline)
+) DEFAULT CHARSET=ascii COLLATE=ascii_general_ci");
+ */
+// Prevent too many attempts (max 20 in 5 mins)
+Database::exec("DELETE FROM client_token WHERE dateline < UNIX_TIMESTAMP() - 300");
+$num = Database::queryFirst("SELECT Count(*) AS num FROM client_token WHERE username = :user", ['user' => $user]);
+if ($num['num'] > 200) {
+ error('DoS detected');
+}
+
+$token2 = substr(md5(mt_rand() . ',' . microtime(true) . ',' . posix_getpid() . ','
+ . $_SERVER['REMOTE_ADDR'] . $_SERVER['REMOTE_PORT']), 0, 10);
+
+// For edit mode via CoW
+$dmsd = null;
+if (Util::getRole() === 'TUTOR') {
+ $shibSess = ShibAuth::login(null, 300);
+ if (!empty($shibSess['token'])) {
+ $dmsd = $shibSess['token'];
+ }
+}
+
+// See if valid QR code request
+if ($qrtoken) {
+ $f = Database::queryFirst("SELECT username FROM client_token WHERE qrtoken = :token LIMIT 1", ['token' => $token]);
+ if ($f === false) {
+ error('Unknown QR code login token');
+ }
+ if ($f['username'] !== '') {
+ error('Token already used');
+ }
+ $num = Database::exec("UPDATE client_token SET username = :user, token = :pass, dmsdsession = :dmsd
+ WHERE username = '' AND qrtoken = :token",
+ ['user' => $user, 'pass' => $token . $token2, 'token' => $token, 'dmsd' => $dmsd]);
+ if ($num !== 1) {
+ error('Token already used');
+ }
+ error('Login erfolgreich. Sie können diese Seite jetzt schließen.');
+}
+
+// Non-QRCode
+Database::exec("INSERT INTO client_token (username, token, dmsdsession, dateline)
+ VALUES (:user, :pass, :dmsd, UNIX_TIMESTAMP())",
+ ['user' => $user, 'pass' => $token . $token2, 'dmsd' => $dmsd]);
+$hash = md5($token);
+
+if (!empty($dmsd)) {
+ $dmsd = "<div id=\"bwlp-cow-token\">$dmsd</div>";
+}
+
+echo <<<BLUBB
+<!doctype html>
+<html lang="en">
+<body>
+ <div style="display:none">
+ <div id="bwlp-username">$user</div>
+ <div id="bwlp-password">$token2</div>
+ <div id="bwlp-hash">$hash</div>
+ $dmsd
+BLUBB;
+// For debugging
+/*
+foreach ($_SERVER as $k => $v) {
+ if (preg_match('/[a-z]/', $k)) {
+ echo '<div id="' . htmlspecialchars($k) . '">' . htmlspecialchars($v) . '</div>';
+ }
+}
+ */
+echo '</div>Please wait...</body></html>';
+exit;