Merge commit 'c0dcd45c3ecac33376e06b7ca470ae56f2ed5e19' into cgilite
[confetti] / cgilite / session.sh
1 #!/bin/sh
2
3 [ -n "$include_session" ] && return 0
4 include_session="$0"
5
6 _DATE="$(date +%s)"
7 SESSION_TIMEOUT="${SESSION_TIMEOUT:-7200}"
8
9 server_key(){
10   IDFILE="${IDFILE:-${_DATA:-.}/serverkey}"
11   if [ "$(stat -c %s "$IDFILE")" -ne 512 ] || ! cat "$IDFILE"; then
12     dd count=1 bs=512 if=/dev/urandom \
13     | tee "$IDFILE"
14   fi 2>&-
15 }
16
17 slopecode(){
18   # 6-Bit Code that retains sort order of input data, while beeing safe to use
19   # in ascii transmissions, unix file names, HTTP URLs, and HTML attributes
20
21   uuencode -m - | sed '
22     1d;$d; 
23     y;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/;0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;
24   '
25 }
26
27 session_mac(){
28   if which openssl >/dev/null; then
29     openssl dgst -sha1 -hmac "$(server_key)" -binary |slopecode
30   else
31     { cat; server_key; } |sha256sum |cut -d\  -f1
32   fi
33 }
34
35 randomid(){
36   dd bs=12 count=1 if=/dev/urandom 2>&- \
37   | slopecode
38 }
39
40 timeid(){
41   d=$(($_DATE % 4294967296))
42   { printf "$(
43       printf \\%o \
44         $((d / 16777216 % 256)) \
45         $((d / 65536 % 256)) \
46         $((d / 256 % 256)) \
47         $((d % 256))
48     )"
49     dd bs=8 count=1 if=/dev/urandom 2>&-
50   } | slopecode
51 }
52
53 checkid(){ grep -m 1 -xE '[0-9a-zA-Z:=]{16}'; }
54
55 transid(){
56   # transaction ID to modify a given file
57   local file="$1"
58   { stat -c %F%i%n%N%s%Y "$file" 2>&-
59     printf %s "$SESSION_ID"
60   } | session_mac
61 }
62
63 update_session(){
64   local session sid time sig serverkey checksig
65
66   IFS=- read -r sid time sig <<-END
67         $(POST session_key || COOKIE session)
68         END
69   serverkey="$(server_key)"
70   
71   checksig="$(printf %s "$sid" "$time" |session_mac)"
72   
73   if ! [ "$checksig" = "$sig" \
74     -a "$time" -ge "$_DATE" \
75     -a "$(printf %s "$sid" |checkid)" ] 2>&-
76   then
77     debug "Setting up new session"
78     sid="$(randomid)"
79   fi
80
81   time=$(( $_DATE + $SESSION_TIMEOUT ))
82   sig="$(printf %s "$sid" "$time" |session_mac)"
83   printf %s\\n "${sid}-${time}-${sig}"
84 }
85
86 SESSION_KEY="$(update_session)"
87 SET_COOKIE 0 session="$SESSION_KEY" Path=/ SameSite=Strict HttpOnly
88 SESSION_ID="${SESSION_KEY%%-*}"