-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathadmins.sh
166 lines (144 loc) · 3.92 KB
/
admins.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/bin/bash
# This "module" provides functions for managing and accessing admin and
# moderator accounts as well as their login sessions.
. ./config
. ./param.sh
. ./html.sh
# The admin list. This is a three-column file where each line contains a
# username, that user's access level (either "admin" or "mod"), and then the
# user's hashed password.
ADMIN_FILE=$DATA_DIR/admins
# File to store session information.
SESS_FILE=$DATA_DIR/sess
# Exits successfully if the current session is logged in as an admin.
# shellcheck disable=SC2155
is_admin() {
if whoami; then
local level=$(user_level "$SESS_USER")
if [ "$level" = "admin" ]; then
return 0
else
return 1
fi
else
return 1
fi
}
# shellcheck disable=SC2155
is_mod() {
if whoami; then
local level=$(user_level "$SESS_USER")
if [ "$level" = "mod" ] || [ "$level" = "admin" ]; then
return 0
else
return 1
fi
else
return 1
fi
}
# Requires that the user is a moderator. If not, responds with status 403 and
# prints an error. This should be done before the page prints anything.
require_mod() {
if ! is_mod; then
echo "Status: 403 Forbidden"
echo "Content-Type: text/html"
echo
html_page "Access Denied" <<EOF
<h1>Access Denied</h1>
<p>You don't have access to this.</p>
EOF
exit 0
fi
}
require_admin() {
if ! is_admin; then
echo "Status: 403 Forbidden"
echo "Content-Type: text/plain"
echo
html_page "Access Denied" <<EOF
<h1>Access Denied</h1>
<p>You don't have access to this.</p>
EOF
exit 0
fi
}
# Sends a web response that logs in as the given user. This terminates the
# script. This prints an entire CGI response and should be done before the
# script has printed anything.
login_as() {
sessid=$(gen_sessid)
# Set our new session
echo "$1 $(date +%s) $sessid" >> "$SESS_FILE"
echo "Content-Type: text/html"
echo "Set-Cookie: sessid=$sessid; HtmlOnly; Path=/"
echo
html_page <<EOF
<h1>Logged in as $1</h1>
<a href="$INDEX_URL">Home</a>
<a href="$URL_ROOT/admin/index.cgi">Admin panel</a>
EOF
exit 0
}
# NOTE: Some functions here contain code that handles plaintext passwords. It
# is critical that any variables storing sensitive user info, such as
# passwords, are declared as local variables. That is, use "local pass=$2"
# instead of "pass=$2".
# Exits success if the given username and password authenticate successfully.
# shellcheck disable=SC2155
auth_check() {
local user="$1"
local pass="$2"
local inhash=$(hash_passwd "$pass")
local uhash=$(user_hash "$user")
if [ "$inhash" = "$uhash" ]; then
# Authentication succeeded.
return 0
else
return 1
fi
}
# Prints the user level for the given user.
user_level() {
local user="$1"
grep "$user" "$ADMIN_FILE" | awk '{ print $2; }'
}
# Prints the hashed password for the given user.
user_hash() {
local user="$1"
grep "$user" "$ADMIN_FILE" | awk '{ print $3; }'
}
# TODO: Salt passwords too
hash_passwd() {
echo -n "$1" | sha512sum | awk '{ print $1; }'
}
# Checks who the current session ID is logged in as. Stores the result in
# "$SESS_USER" if there is a user. If the session ID is invalid or expired,
# returns nonzero.
# shellcheck disable=SC2155
whoami() {
local sessid=$(get_cookie sessid)
if [ -z "$sessid" ]; then
return 1
fi
if whois_sessid "$sessid"; then
return 0
else
return 1
fi
}
# Checks who the given session is logged in as. Stores the result in
# "$SESS_USER" if there is a user. If the session ID is invalid or expired,
# returns nonzero.
whois_sessid() {
local sess_info
if sess_info=$(grep "$1" "$SESS_FILE"); then
SESS_USER=$(echo "$sess_info" | awk '{ print $1; }')
return 0
else
return 1
fi
}
gen_sessid() {
uuidgen
}