This commit is contained in:
Ludwig Behm 2024-04-19 18:26:59 +02:00
commit 01910e3f75
18 changed files with 6676 additions and 0 deletions

22
Makefile Normal file
View file

@ -0,0 +1,22 @@
install:
@echo create directories
install -o0 -g0 -d /var/www/tuer.kraut.space /etc/tuer3.0 /etc/nsd/zones
@echo setup network
install -o0 -g0 -m644 hostapd.conf /etc/hostapd/hostapd.conf
install -o0 -g0 -m644 networkd/* /etc/systemd/network/
systemctl restart systemd-networkd.service hostapd.service
@echo setup nsd dns server
install -o0 -g0 nsd/nsd.conf.d/* /etc/nsd/nsd.conf.d/
install -o0 -g0 nsd/zones/* /etc/nsd/zones/
@echo install nginx
rm -f /etc/nginx/sites-enabled/default
install -o0 -g0 nginx.site.conf /etc/nginx/sites-available/tuer.kraut.space
rm -f /etc/nginx/sites-enabled/tuer.kraut.space
ln -s ../sites-available/tuer.kraut.space /etc/nginx/sites-enabled/tuer.kraut.space
systemctl restart nginx.service
@echo deploy web directory
cp -r src/* /var/www/tuer.kraut.space/

1749
hostapd.conf Normal file

File diff suppressed because it is too large Load diff

5
networkd/10-lan.network Normal file
View file

@ -0,0 +1,5 @@
[Match]
Name=enx*
[Network]
Address=192.168.254.250/24

13
networkd/10-wlan0.network Normal file
View file

@ -0,0 +1,13 @@
[Match]
Name=wlan0
[Network]
Address=192.168.1.1/24
LLMNR=no
DNSSEC=no
MulticastDNS=yes
IPForward=no
DHCPServer=yes
[DHCPServer]
DNS=192.168.1.1

57
nginx.site.conf Normal file
View file

@ -0,0 +1,57 @@
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
location / {
return 301 https://tuer.kraut.space/$request_uri?;
}
}
server {
# SSL configuration
#
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
ssl_certificate /etc/ssl/private/tuer.kraut.space/fullchain.pem;
ssl_certificate_key /etc/ssl/private/tuer.kraut.space/privkey.pem;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name tuer.kraut.space;
error_page 404 /404.html;
location ~ /(404.html|style.css|doc/|media/) {
root /var/www/tuer.kraut.space/html;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location /cgi-bin/kraut.space {
return 301 /;
}
location / {
try_files $uri $uri/ /index.html;
default_type text/html;
gzip off;
include fastcgi_params;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME /var/www/tuer.kraut.space/cgi-bin/kraut.space;
# According to RFC3875 (https://tools.ietf.org/html/rfc3875#section-4.1.14) in SERVER_NAME
# we should put actual hostname user came to. For nginx it is in $host
# This will allow to run multihost instances
fastcgi_param SERVER_NAME $host;
}
}

View file

@ -0,0 +1,11 @@
server:
ip-address: 192.168.1.1
port: 53
server-count: 1
hide-version: yes
identity: "doorito.tuer.kraut.space"
zonesdir: "/etc/nsd/zones"
zone:
name: kraut.space
zonefile: kraut.space

15
nsd/zones/kraut.space Normal file
View file

@ -0,0 +1,15 @@
$ORIGIN kraut.space. ; default zone domain
$TTL 60 ; default time to live
@ IN SOA doorito.tuer.kraut.space. office.kraut.space. (
2404182124 ; serial number <yymmddHHMM>
60 ; Refresh
7200 ; Retry
60 ; Expire
60 ; Min TTL
)
IN NS doorito.tuer.kraut.space.
doorito.tuer IN A 192.168.1.1
tuer IN A 192.168.1.1

64
src/cgi-bin/kraut.space Executable file
View file

@ -0,0 +1,64 @@
#!/bin/sh -e
header() {
printf 'Content-type: text/html\nStrict-Transport-Security: max-age=86400000\n\n'
}
# extract parameters
# tr -cd removes all characters, this prevents things like xss
getp() {
echo "$REQUEST_URI" | sed 's/.*?//' | sed 's/%20/ /g' \
| tr '?&' '\n' | tr --complement --delete '0-9a-z_= \n' \
| grep --extended-regexp "^$1=" | sed "s/^$1=//"
}
ACCESS_LIST=/etc/tuer3.0/door_access_list
secret="$(getp secret)"
secret_length="$(echo "$secret" | wc --chars)"
hashed_secret="$(echo "$secret" | sha512sum | cut -f1 -d\ )"
cmd=$(getp cmd)
# check secret
# the secrets file has to contain the hashes on a single line, comments are allowed on seperate lines
# secrets can only contain the characters that are allowed in getp() with tr -cd
if [ -z "$secret" ] \
|| [ "$secret_length" -lt 30 ] \
|| ! grep -v -e '^[ \t]*#' "$ACCESS_LIST" | grep -q ";$hashed_secret$"
then
header
CABBAGE=""
[ -z "$secret" ] || CABBAGE="Ich bin mir nicht sicher. Mir scheint, du bist doch ein Kohlkopf oder Anderes!"
# shellcheck disable=SC2002
cat ../tpl/secret.html | sed 's/<!--XCABBAGEX-->/'"$CABBAGE"'/'
exit
fi
# control relais card
if [ -n "$cmd" ]; then
case "$cmd" in
indoor_lock) keyble-sendcommand --address 00:1a:22:18:43:ed --user_id 3 --user_key 0e49fe15cffa15ed6520a224110f23e9 -c lock;;
indoor_open) keyble-sendcommand --address 00:1a:22:18:43:ed --user_id 3 --user_key 0e49fe15cffa15ed6520a224110f23e9 -c open;;
#outdoor_buzz) pin=22; delay1=15; delay2=5;;
*) header; echo 'Do not hack the hackerspace!'"$cmd"; exit;;
esac
# execute long-running ppio job in background shell
#( sleep $delay1
# /usr/local/bin/gpio -g write $pin on
# sleep $delay2
# /usr/local/bin/gpio -g write $pin off
#) </dev/null >/dev/null 2>/dev/null &
header
sed 's/XTIMEOUTX/'"$((delay1 + delay2))"'/' ../tpl/wait.html | sed 's/XSECRETX/'"$secret"/
exit
fi
# show feature page
header
sed 's/XSECRET_HEREX/'"$secret"'/' ../tpl/features.html
exit

21
src/html/404.html Normal file

File diff suppressed because one or more lines are too long

6
src/html/media/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
BC546_48-CDIL.pdf
en-g6d.pdf
HM-RC-4-2_UM_GE_EQ-3_130906.pdf
HM_SECKEYS_ANL.pdf
mXtwxrt.pdf

49
src/html/media/genpw.sh Executable file
View file

@ -0,0 +1,49 @@
#!/bin/bash
QUESTTEXT='Wie ist dein Name/Nick?'
HELPTEXT="Nickname"
DLG=`which zenity`
if [[ $? -ne 0 ]] ; then
if [[ "$1" == "" ]] ; then
echo "Passphrasengenerierung abgebrochen. Bitte einen Nutzernamen als Kommandoparameter angeben."
exit 1
else
USER=$1
DIALOG=cmd
fi
else
if [[ "$1" == "" ]] ; then
USER=`zenity --entry --text="$QUESTTEXT" --entry-text=$HELPTEXT`
else
USER=`zenity --entry --text="$QUESTTEXT" --entry-text="$1"`
fi
if [[ $? -ne 0 || "$USER" == "$HELPTEXT" ]] ; then
echo "Passphrasengenerierung abgebrochen."
exit 1
fi
DIALOG=zenity
fi
STAMP=`date +%Y-%m-%dT%T`
FILE="$PWD/$USER.$STAMP.keyhash"
PASSPHRASE=`tr -dc _a-z0-9 </dev/urandom | head -c 31`
PPHASH=`echo "$PASSPHRASE" | sha512sum | tr --delete " -"`
echo "$USER;$STAMP;$PPHASH">>$FILE
# Ausgabe
TEXT="Hallo $USER,\ndeine neue Passphrase ist:\n\n\t$PASSPHRASE\n
Hinweis:\tDie Passphrase erscheint nur in diesem Dialog und im Terminal\n\t\tund wird sonst nirgendwo gespeichert. Sichere sie dir bitte!\n\n
Es wurde eine Datei mit deinen Schlüsseldaten generiert. Ihr Name lautet:
\n\t$FILE\n\nÜbergib sie bitte vertrauensvoll an einen Schließsystemverantwortlichen.\n"
case "$DIALOG" in
zenity)
zenity --info --text="$TEXT" --window-icon=warning
;;
*)
;;
esac
echo -e "$TEXT"

1675
src/html/media/tuer1.3.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 100 KiB

1633
src/html/media/tuer3.0.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 94 KiB

1249
src/html/media/tuer3.1.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 67 KiB

42
src/html/style.css Normal file
View file

@ -0,0 +1,42 @@
@-o-viewport { width:device-width }
@-moz-viewport { width:device-width }
@-webkit-viewport { width:device-width }
@-ms-viewport { width:device-width }
@-viewport { width:device-width }
body {
margin:0px;
padding: 5%;
background-color: #242943;
color: white;
font-family: sans-serif;
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIGJ5IGp0ZiAtLT4KCjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICBpZD0ic3ZnMiIKICAgd2lkdGg9IjE2IgogICBoZWlnaHQ9IjE2IgogICB2aWV3Qm94PSIwIDAgMTYgMTYiCiAgIHNvZGlwb2RpOmRvY25hbWU9InR1ZXIuc3ZnIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjkyLjEgcjE1MzcxIj4KICA8cGF0aAogICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlOm5vbmU7c3Ryb2tlLXdpZHRoOjFweDtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxO2ZpbGwtb3BhY2l0eTowLjEzNzI1NDkxIgogICAgIGQ9Ik0gNiAxIEwgNiA2LjQwMDM5MDYgTCA0IDUgTCA0IDcgTCAxIDcgTCAxIDEwIEwgNCAxMCBMIDQgMTIgTCA2IDEwLjU5OTYwOSBMIDYgMTUgTCA3IDE1IEwgNyA5LjkwMDM5MDYgTCA5IDguNSBMIDcgNy4wOTk2MDk0IEwgNyAyIEwgOSAyIEwgOSA4LjUgTCA5IDEzIEwgMTQgMTUgTCAxNSAxNSBMIDE1IDEgTCA2IDEgeiAiCiAgICAgaWQ9InBhdGgzNiIgLz4KPC9zdmc+Cg==");
background-attachment: fixed;
background-repeat: no-repeat;
background-size: auto 100%;
}
h2 {font-size: 17px; color: white}
input, button { width: 45%; height:3em; margin-bottom: 1em; }
input { width: 95%; opacity: 0.95;}
.main_button { height: 7em;}
.main_open { background-color: #006600}
.main_close { background-color: #660000}
button {
border: 0px solid lightgrey;
background-color: #314159;
color: white;
font-size: 15px;
font-weight: bold;
border-radius: 11px;
opacity: 0.9;
}
@media screen and (max-width: 640px) {
body { margin:0 }
button { width:100%; height:3em;}
input { width:95%; height:3em;}
}
a{color: #a5b7e0}
.footnote { font-size: 75%;}

21
src/tpl/features.html Normal file
View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Tür 3.1: Schließfunktionswahl</title>
<meta name="viewport" content="width=device-width, target-densitydpi=device-dpi">
<link rel="stylesheet" href="/style.css">
<link rel="favicon icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEUAAAAAAAD///+D3c/SAAAAAXRSTlMAQObYZgAAADpJREFUCFtjYNBatYqBQTU0jIFBbSqUYFoGItKAxKowIDE1FEyEQllgMbAsWB2D2koQwTWNgUGLYRUAd4kWEUPUxjwAAAAASUVORK5CYII=">
</head>
<body>
<form method="GET" action="">
<input type=hidden name=secret value="XSECRET_HEREX">
<h2>Schließfunktionen</h2>
<button class="main_button main_open" type="submit" name="cmd" value="indoor_open">Tür öffnen</button><br/>
<!--<button class="main_button" type="submit" name="cmd" value="outdoor_buzz">Haustüröffner</button><br/>-->
<button class="main_close" type="submit" name="cmd" value="indoor_lock">Tür abschließen</button>
</form>
</body>
</html>

26
src/tpl/secret.html Normal file
View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Tür 3.1: Tokenabfrage</title>
<meta name="viewport" content="width=device-width, target-densitydpi=device-dpi">
<link rel="stylesheet" href="/style.css">
<link rel="favicon icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEUAAAAAAAD///+D3c/SAAAAAXRSTlMAQObYZgAAADpJREFUCFtjYNBatYqBQTU0jIFBbSqUYFoGItKAxKowIDE1FEyEQllgMbAsWB2D2koQwTWNgUGLYRUAd4kWEUPUxjwAAAAASUVORK5CYII=">
</head>
<body>
<form method="GET" action=""> <!--/cgi-bin/kraut.space"-->
<h2>Sprich Sterblicher!</h2>
<p><!--XCABBAGEX--></p>
<p>Bist du ein menschliches Wesen und kein Kohlkopf oder Anderes?</p>
<input id="secret" class="textfield" name="secret" accesskey="t" required autofocus placeholder=" Wie ist dein Token? ">
<br>
<button type="submit" accesskey="E"><span class="accesskey">E</span>rleuchte mich!</button>
</form>
<p>Dies ist ein Service des Hackspace Jena e.&#8239;V. und aufschließlich für Mitglieder des Krautspace™.</p>
<p>Dieses Netzwerk liefert keinen Zugang zum Internet.</p>
<p>Für Interessierte gibt es eine <a href="../doc/index.html">Systemdokumentation</a>.</p>
<p class="footnote">©20172019 Hackspace Jena e.&#8239;V. https://kraut.space<p>
</body>
</html>

18
src/tpl/wait.html Normal file
View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="XTIMEOUTX; URL=?secret=XSECRETX">
<title>Tür 3.1: Anfrage in Arbeit</title>
<meta name="viewport" content="width=device-width, target-densitydpi=device-dpi">
<link rel="stylesheet" href="/style.css">
<link rel="favicon icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEUAAAAAAAD///+D3c/SAAAAAXRSTlMAQObYZgAAADpJREFUCFtjYNBatYqBQTU0jIFBbSqUYFoGItKAxKowIDE1FEyEQllgMbAsWB2D2koQwTWNgUGLYRUAd4kWEUPUxjwAAAAASUVORK5CYII=">
</head>
<body>
Anforderung wird ausgeführt Bitte warten. (XTIMEOUTXs)
<p><b>Für die Hauseingangstür ab jetzt bitte mindestens einmal klingeln!</b></p>
<p> Die Türanlage wurde umgestellt. Unser KTA kann jetzt nur noch aufschließen wenn vorher unten jemand geklingelt hatte.</p>
</body>
</html>