Merge commit '01b13a65484a01f314d6d97c74b48216ead2bc24'
[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   local info
29   [ $# -eq 0 ] && info="$(cat)" || info="$*"
30
31   if which openssl >/dev/null; then
32     printf %s "$info" |openssl dgst -sha1 -hmac "$(server_key)" -binary |slopecode
33   else
34     { printf %s "$info"; server_key; } |sha256sum |cut -d\  -f1
35   fi
36 }
37
38 randomid(){
39   dd bs=12 count=1 if=/dev/urandom 2>&- \
40   | slopecode
41 }
42
43 timeid(){
44   d=$(($_DATE % 4294967296))
45   { printf "$(
46       printf \\%o \
47         $((d / 16777216 % 256)) \
48         $((d / 65536 % 256)) \
49         $((d / 256 % 256)) \
50         $((d % 256))
51     )"
52     dd bs=8 count=1 if=/dev/urandom 2>&-
53   } | slopecode
54 }
55
56 checkid(){ grep -m 1 -xE '[0-9a-zA-Z:=]{16}'; }
57
58 transid(){
59   # transaction ID to modify a given file
60   local file="$1"
61   session_mac "$(stat -c %F%i%n%N%s%Y "$file" 2>&-)" "$SESSION_ID"
62 }
63
64 update_session(){
65   local session sid time sig checksig
66
67   read -r sid time sig <<-END
68         $(POST session_key || COOKIE session)
69         END
70   
71   checksig="$(session_mac "$sid" "$time")"
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="$(session_mac "$sid" "$time")"
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%% *}"