]> git.plutz.net Git - cgilite/blob - session.sh
enable pipe/argument choice for more functions
[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 if ! which uuencode >/dev/null; then
10   uuencode() { busybox uuencode "$@"; }
11 fi
12 if ! which sha256sum >/dev/null; then
13   sha256sum() { busybox sha256sum "$@"; }
14 fi
15
16 if which openssl >/dev/null; then
17   session_mac(){ { [ $# -gt 0 ] && printf %s "$*" || cat; } | openssl dgst -sha1 -hmac "$(server_key)" -binary |slopecode; }
18 else
19   # sham hmac if openssl is unavailable
20   session_mac(){ { [ $# -gt 0 ] && printf %s "$*" || cat; server_key; } | sha256sum |cut -d\  -f1; }
21 fi
22
23 server_key(){
24   IDFILE="${IDFILE:-${_DATA:-.}/serverkey}"
25   if [ "$(stat -c %s "$IDFILE")" -ne 512 ] || ! cat "$IDFILE"; then
26     dd count=1 bs=512 if=/dev/urandom \
27     | tee "$IDFILE"
28   fi 2>&-
29 }
30
31 slopecode(){
32   # 6-Bit Code that retains sort order of input data, while beeing safe to use
33   # in ascii transmissions, unix file names, HTTP URLs, and HTML attributes
34
35   { [ $# -gt 0 ] && printf %s "$*" || cat; } \
36   | uuencode -m - | sed '
37     1d;$d; 
38     y;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/;0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;
39   '
40 }
41
42 randomid(){
43   dd bs=12 count=1 if=/dev/urandom 2>&- \
44   | slopecode
45 }
46
47 timeid(){
48   d=$(($_DATE % 4294967296))
49   { printf "$(
50       printf \\%o \
51         $((d / 16777216 % 256)) \
52         $((d / 65536 % 256)) \
53         $((d / 256 % 256)) \
54         $((d % 256))
55     )"
56     dd bs=8 count=1 if=/dev/urandom 2>&-
57   } | slopecode
58 }
59
60 transid(){
61   # transaction ID to modify a given file
62   local file="$1"
63   session_mac "$(stat -c %F%i%n%N%s%Y "$file" 2>&-)" "$SESSION_ID"
64 }
65
66 checkid(){ { [ $# -gt 0 ] && printf %s "$*" || cat; } | grep -m 1 -xE '[0-9a-zA-Z:=]{16}'; }
67
68 update_session(){
69   local session sid time sig checksig
70
71   read -r sid time sig <<-END
72         $(POST session_key || COOKIE session)
73         END
74   
75   checksig="$(session_mac "$sid" "$time")"
76   
77   if ! [ "$checksig" = "$sig" \
78     -a "$time" -ge "$_DATE" \
79     -a "$(printf %s "$sid" |checkid)" ] 2>&-
80   then
81     debug "Setting up new session"
82     sid="$(randomid)"
83   fi
84
85   time=$(( $_DATE + $SESSION_TIMEOUT ))
86   sig="$(session_mac "$sid" "$time")"
87   printf %s\\n "${sid} ${time} ${sig}"
88 }
89
90 SESSION_BIND() {
91   # Set tamper-proof authenticated cookie
92   local key="$1" value="$2"
93   SET_COOKIE session "$key"="${value} $(session_mac "$value" "$SESSION_ID")"
94 }
95
96 SESSION_VAR() {
97   # read authenticated cookie
98   # fail if value has been tampered with
99   local key="$1" value sig
100   value="$(COOKIE "$key")"
101   sig="${value##* }" value="${value% *}"
102   if [ "$sig" = "$(session_mac "$value" "$SESSION_ID")" ]; then
103     printf %s\\n "$value"
104   else
105     return 1
106   fi
107 }
108
109 SESSION_KEY="$(update_session)"
110 SET_COOKIE 0 session="$SESSION_KEY" Path=/ SameSite=Strict HttpOnly
111 SESSION_ID="${SESSION_KEY%% *}"