toymaker.git

commit 5d41ddd87d5d656c1ca36a6bb746475600f62230

Author: Adam <git@apiote.xyz>

check POST authorization

 password.sh | 23 +++++++++++++++++++++++
 server2.sh | 39 ++++++++++++++++++++++++++++++++++++---


diff --git a/password.sh b/password.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f7f5420d6d1cae05b8b17341848d1907ad6808c6
--- /dev/null
+++ b/password.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+encode() {
+	if [ -z "$1" ]
+	then
+		salt=$(dd if=/dev/urandom count=7 bs=1 2>/dev/null | base32 | tr -d '=')
+	else
+		salt=$1
+	fi
+	cat - | argon2 "$salt" -id -t 3 -m 12 -p 1 -l 32 -e
+}
+
+verify() {
+	stored=$1
+	salt=$(echo "$stored" | cut -d '$' -f 5 | base64 -d)
+	tested=$(cat - | encode "$salt")
+	test "$stored" = "$tested"
+}
+
+if [ "$(basename "$0")" = 'password.sh' ]
+then
+	cat - | encode "$1"
+fi




diff --git a/server2.sh b/server2.sh
index 876f32b7a1402a6c600756af8852f1972a9b4e0a..1d64f38d22ecb3f09e152f4d45b3007a10cee45f 100755
--- a/server2.sh
+++ b/server2.sh
@@ -4,6 +4,7 @@ # Based on server by Upper Stream (c) 2017, MIT license
 
 . start.sh
 . get.sh
+. password.sh
 
 set -e
 
@@ -65,6 +66,18 @@ 	printf "HTTP/1.1 202 Accepted\r\nContent-Length: %s\r\nLocation: /toys/%s/%s\r\n\r\n%s\r\n" "${#message}" "$name" "$item" "$message" > "$fifo1"
 	printf "202 -"
 }
 
+respond401() {
+	message=""
+	printf "HTTP/1.1 401 Unauthorized\r\nContent-Length: %s\r\n\r\n%s\r\n" "${#message}" "$message" > "$fifo1"
+	printf "401 -"
+}
+
+respond403() {
+	message=""
+	printf "HTTP/1.1 403 Forbidden\r\nContent-Length: %s\r\n\r\n%s\r\n" "${#message}" "$message" > "$fifo1"
+	printf "403 -"
+}
+
 respond404() {
 	path=$1
 	# todo template
@@ -86,9 +99,25 @@ 	printf "HTTP/1.1 500 Internal Server Error\r\nContent-Length: %s\r\n\r\n%s\r\n" "${#message}" "$message" > "$fifo1"
 	printf "500 -"
 }
 
+check_auth() {
+	authorization=$1
+	stored=$(cat password)
+	if [ -z "$stored" ] || [ -z "$authorization" ]
+	then
+		respond401
+		return 1
+	fi
+	if ! printf '%s' "$authorization" | verify "$stored"
+	then
+		respond403
+		return 1
+	fi
+}
+
 execute() {
 	method="$1"
 	path="$2"
+	authorization="$3"
 	toys=$(field "$path" 2)
 	if [ "$toys" != 'toys' ]
 	then
@@ -134,6 +163,8 @@ 			respond404 "$path"
 		fi
 		;;
 	POST)
+		check_auth "$authorization" || return
+
 		toy=$(field "$path" 3)
 		if [ "$(slashes "$path")" -ne 3 ] || [ -n "$(field "$path" 4)" ]
 		then
@@ -177,12 +208,14 @@ 			;;
 		Host:*)
 			host=${line#Host: }
 			;;
-		# Authorization
+		Authorization:*)
+			authorization=${line#Authorization: }
+			;;
 		*:*)
 			;;
 		"")
 			date=$(date +'%d/%m/%Y:%H:%M:%S %z')
-			status_length=$(execute "$method" "$path")
+			status_length=$(execute "$method" "$path" "$authorization")
 			printf "%s %s \"http://%s%s\" %s\n" "$date" "$method" "$host" "$path" "$status_length"
 			trap - INT
 			exit
@@ -194,7 +227,7 @@ 	done
 }
 
 # dependency verification
-for cmd in nc; do
+for cmd in nc argon2 podman; do
   command -v $cmd >/dev/null || { echo "$0: \`$cmd\` not found"; exit 2; }
 done