3 # Copyright 2018 - 2022 Paul Hänsch
5 # Permission to use, copy, modify, and/or distribute this software for any
6 # purpose with or without fee is hereby granted, provided that the above
7 # copyright notice and this permission notice appear in all copies.
9 # THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 [ -n "$include_session" ] && return 0
20 export _DATE="$(date +%s)"
21 SESSION_TIMEOUT="${SESSION_TIMEOUT:-7200}"
23 if ! which uuencode >/dev/null; then
24 uuencode() { busybox uuencode "$@"; }
26 if ! which sha256sum >/dev/null; then
27 sha256sum() { busybox sha256sum "$@"; }
30 if which openssl >/dev/null; then
31 session_mac(){ { [ $# -gt 0 ] && printf %s "$*" || cat; } | openssl dgst -sha1 -hmac "$(server_key)" -binary |slopecode; }
33 # Gonzo MAC if openssl is unavailable
35 { server_key | dd status=none bs=256 count=1 skip=1
36 { server_key | dd status=none bs=256 count=1
37 [ $# -gt 0 ] && printf %s "$*" || cat
41 | sha256sum | cut -d\ -f1
46 IDFILE="${IDFILE:-${_DATA:-.}/serverkey}"
47 if [ "$(stat -c %s "$IDFILE")" -ne 512 ] || ! cat "$IDFILE"; then
48 dd count=1 bs=512 if=/dev/urandom \
54 # 6-Bit Code that retains sort order of input data, while beeing safe to use
55 # in ascii transmissions, unix file names, HTTP URLs, and HTML attributes
57 { [ $# -gt 0 ] && printf %s "$*" || cat; } \
58 | uuencode -m - | sed '
60 y;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/;0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;
65 dd bs=12 count=1 if=/dev/urandom 2>&- \
70 d=$(($_DATE % 4294967296))
73 $((d / 16777216 % 256)) \
74 $((d / 65536 % 256)) \
78 dd bs=8 count=1 if=/dev/urandom 2>&-
83 # transaction ID to modify a given file
85 session_mac "$(stat -c %F%i%n%N%s%Y "$file" 2>&-)" "$SESSION_ID"
88 checkid(){ { [ $# -gt 0 ] && printf %s "$*" || cat; } | grep -m 1 -xE '[0-9a-zA-Z:=]{16}'; }
91 local session sid time sig checksig
92 unset SESSION_KEY SESSION_ID
94 read -r sid time sig <<-END
95 $(POST session_key || COOKIE session)
98 checksig="$(session_mac "$sid" "$time")"
100 if [ "$checksig" = "$sig" \
101 -a "$time" -ge "$_DATE" \
102 -a "$(checkid "$sid")" ] 2>&-
104 time=$(( $_DATE + $SESSION_TIMEOUT ))
105 sig="$(session_mac "$sid" "$time")"
107 SESSION_KEY="${sid} ${time} ${sig}"
119 debug "Setting up new session"
121 time=$(( $_DATE + $SESSION_TIMEOUT ))
122 sig="$(session_mac "$sid" "$time")"
124 SESSION_KEY="${sid} ${time} ${sig}"
129 # Set tamper-proof authenticated cookie
130 local key="$1" value="$2"
131 SET_COOKIE session "$key"="${value} $(session_mac "$value" "$SESSION_ID")" Path="/${_BASE#/}" SameSite=Strict HttpOnly
135 # read authenticated cookie
136 # fail if value has been tampered with
137 local key="$1" value sig
138 value="$(COOKIE "$key")"
139 sig="${value##* }" value="${value% *}"
140 if [ "$sig" = "$(session_mac "$value" "$SESSION_ID")" ]; then
141 printf %s\\n "$value"
148 [ "$1" = new ] && new_session
149 SET_COOKIE 0 session="$SESSION_KEY" Path="/${_BASE#/}" SameSite=Strict HttpOnly
152 update_session || new_session