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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
|
test_description='Check the shipped auth extensions'
CGIT_TEST_NO_CREATE_REPOS=YesPlease
. ./setup.sh
. "$TEST_OUTPUT_DIRECTORY/extensions/lib.sh"
auth_hash=$(openssl passwd -6 -salt testsalt "open sesame" 2>/dev/null) ||
auth_hash=
test -z "$interpreters" || test_set_prereq STANDALONE_LUA
for lua in ${interpreters:-lua}
do
for variant in inline file
do
test_expect_success STANDALONE_LUA "auth-$variant checks under $lua" '
mkdir "unit-$lua-$variant" &&
"$lua" "$EXT_TEST_DIRECTORY/test-auth.lua" \
"$EXTENSIONS_DIRECTORY/auth-$variant.lua" $variant "$PWD/unit-$lua-$variant"
'
done
auth_libs=AUTH_LIBS_$(echo "$lua" | tr a-z. A-Z_)
if test -n "$auth_hash" &&
"$lua" -e "
require('openssl.hmac') require('openssl.rand') require('posix.sys.stat')
assert(require('posix.unistd').crypt('open sesame', '$auth_hash') == '$auth_hash')
" >/dev/null 2>&1
then
test_set_prereq $auth_libs
fi
for variant in inline file
do
test_expect_success "STANDALONE_LUA,$auth_libs" "auth-$variant checks against the real libraries under $lua" '
mkdir "real-$lua-$variant" &&
"$lua" "$EXT_TEST_DIRECTORY/test-auth.lua" \
"$EXTENSIONS_DIRECTORY/auth-$variant.lua" $variant "$PWD/real-$lua-$variant" "$auth_hash"
'
done
done
test_expect_success 'the two auth filters share their code word for word' '
sed -n "/^-- The url helpers below/,\$p" "$EXTENSIONS_DIRECTORY/auth-file.lua" >file-tail &&
sed -n "/^-- The url helpers below/,\$p" "$EXTENSIONS_DIRECTORY/auth-inline.lua" >inline-whole &&
sed "/^-- Lua patterns backtrack/,/^\$/d" inline-whole >inline-tail &&
test_line_count -gt 300 file-tail &&
test_cmp file-tail inline-tail &&
sed -n "/^-- Lua patterns backtrack/,/^end\$/p" "$EXTENSIONS_DIRECTORY/auth-file.lua" >file-trim &&
sed -n "/^-- Lua patterns backtrack/,/^end\$/p" "$EXTENSIONS_DIRECTORY/auth-inline.lua" >inline-trim &&
test_line_count = 14 file-trim &&
test_cmp file-trim inline-trim
'
test_expect_success 'create a repository with one commit' '
test_create_repo repos/authy &&
(
cd repos/authy &&
echo content >file &&
git add file &&
git commit -m "guarded commit"
)
'
if test "$CGIT_HAS_LUA" -eq 1 &&
! cgit_lua_probe "$PWD/repos/authy/.git" openssl.rand openssl.hmac posix.sys.stat posix.unistd
then
test_set_prereq CGIT_LUA_NOAUTH
say 'cgit lua lacks luaossl or luaposix, expecting protected pages refused'
elif test "$CGIT_HAS_LUA" -eq 1 && test -n "$auth_hash"
then
cat >crypt-probe.lua <<-EOF
function filter_open(...) end
function filter_write(str) end
function filter_close()
if require("posix.unistd").crypt("open sesame", "$auth_hash") == "$auth_hash" then
html("CRYPT_PROBE_YES")
end
return 0
end
EOF
cgitrc_repo crypt-probe-rc authy "repo.commit-filter=lua:$PWD/crypt-probe.lua"
if cgit_rc crypt-probe-rc "url=authy/commit/" | grep CRYPT_PROBE_YES >/dev/null
then
test_set_prereq CGIT_LUA_AUTH
fi
fi
test_expect_success CGIT_LUA 'point cgit at the unedited auth filter' '
cgitrc_repo cgitrc authy "auth-filter=lua:$EXTENSIONS_DIRECTORY/auth-inline.lua"
'
test_expect_success CGIT_LUA 'an unedited copy protects nothing' '
cgit_ok cgitrc "url=authy/log/" >tmp &&
test_grep ">guarded commit</a>" tmp
'
test_expect_success CGIT_LUA_NOAUTH 'without the modules a protected repository stays closed' '
cat >protect.awk <<-\EOF &&
/^local secret_filename = / { print "local secret_filename = \"" secret "\""; next }
{ print }
/^local protected_repos = [{]$/ { print "\t[\"authy\"] = { alice = true }," }
EOF
awk -v secret="$PWD/guarded-secret" -f protect.awk "$EXTENSIONS_DIRECTORY/auth-inline.lua" >guarded.lua &&
grep "\"authy\"" guarded.lua &&
grep "guarded-secret" guarded.lua &&
cgitrc_repo guardedrc authy "auth-filter=lua:$PWD/guarded.lua" &&
cgit_rc guardedrc "url=authy/log/" >tmp 2>err &&
! grep "guarded commit" tmp &&
grep "<p class=.login-error. role=.alert.>Logins are unavailable" tmp &&
grep -E "^\[cgit\] .*module .(openssl\.rand|openssl\.hmac|posix\.sys\.stat|posix\.unistd). not found" err
'
test_expect_success CGIT_LUA_AUTH 'a login through cgit opens a protected repository' '
cat >grant.awk <<-EOF &&
/^local secret_filename = / { print "local secret_filename = \"$PWD/login-secret\""; next }
{ print }
/^local protected_repos = [{]\$/ { print "\t[\"authy\"] = { alice = true }," }
/^local users = [{]\$/ { print "\talice = \"$auth_hash\"," }
EOF
awk -f grant.awk "$EXTENSIONS_DIRECTORY/auth-inline.lua" >granted.lua &&
grep "login-secret" granted.lua &&
grep "testsalt" granted.lua &&
grep "\"authy\"" granted.lua &&
cgitrc_repo grantrc authy "auth-filter=lua:$PWD/granted.lua" &&
(export HTTPS=on && cgit_ok grantrc "url=authy/log/") >form &&
grep "<form class=.login." form &&
! grep "guarded commit" form &&
token=$(sed -n "s/.*value=.\(redirect|[^|]*|0|[0-9a-f]*|[0-9a-f]*\).*/\1/p" form) &&
test -n "$token" &&
body="username=alice&password=open+sesame&redirect=$(printf "%s\n" "$token" |
sed "s/%/%25/g; s/+/%2B/g; s/|/%7C/g")" &&
printf "%s" "$body" >post &&
(
export CGIT_CONFIG="$PWD/grantrc" QUERY_STRING=p=login REQUEST_METHOD=POST \
HTTPS=on CONTENT_LENGTH=${#body} CONTENT_TYPE=application/x-www-form-urlencoded &&
cgit <post >answer 2>err
) &&
test_must_be_empty err &&
grep "^Status: 302" answer &&
grep "^Location: /authy/log/\$" answer &&
cookie=$(sed -n "s/^Set-Cookie: \(__Host-cgitauth=[^;]*\);.*/\1/p" answer) &&
test -n "$cookie" &&
(export HTTPS=on HTTP_COOKIE="$cookie" && cgit_ok grantrc "url=authy/log/") >tmp &&
grep ">guarded commit</a>" tmp &&
(export HTTPS=on && cgit_ok grantrc "url=authy/log/") >tmp &&
grep "<form class=.login." tmp &&
! grep "guarded commit" tmp
'
test_expect_success 'an auth filter is handed the repository url' '
write_script seen.sh <<-\EOF &&
test "$1" = authenticate-cookie && printf "%s\n" "$9" >seen
exit 1
EOF
cgitrc_repo seenrc team/tools.git "auth-filter=exec:$PWD/seen.sh" \
"repo.path=$PWD/repos/authy/.git" "repo.name=tools.git" &&
echo team/tools.git >expect &&
cgit_ok seenrc "url=team/tools.git/log/" >tmp &&
grep ">guarded commit</a>" tmp &&
test_cmp expect seen &&
rm seen &&
cgit_ok seenrc "r=team/tools.git&p=log" >tmp &&
grep ">guarded commit</a>" tmp &&
test_cmp expect seen &&
mkdir -p scan/team &&
git clone -q --bare repos/authy scan/team/tools.git &&
cat >scanrc <<-EOF &&
virtual-root=/
cache-size=0
auth-filter=exec:$PWD/seen.sh
section-from-path=1
scan-path=$PWD/scan
EOF
cgit_ok scanrc "" >tmp &&
grep ">tools.git</a>" tmp &&
rm seen &&
cgit_ok scanrc "url=team/tools.git/log/" >tmp &&
grep ">guarded commit</a>" tmp &&
test_cmp expect seen
'
test_expect_success 'the login page keeps the repository to itself' '
write_script deny.sh <<-\EOF &&
test "$1" = body && echo "<p>sign in</p>"
exit 0
EOF
cgitrc_repo denyrc authy "root-desc=the whole site" "auth-filter=exec:$PWD/deny.sh" \
"repo.desc=the secret plan" "repo.owner=Mallory Owner" "repo.hide=1" &&
cgit_ok denyrc "url=authy/log/" >tmp &&
test_grep "<p>sign in</p>" tmp &&
test_grep "<p class=.sub desc.>the whole site</p>" tmp &&
test_grep "<meta name=.description. content=.the whole site.>" tmp &&
test_grep ! "secret plan" tmp &&
test_grep ! "Mallory" tmp &&
write_script letin.sh <<-\EOF &&
exit 1
EOF
sed "s|deny.sh|letin.sh|" denyrc >letinrc &&
cgit_ok letinrc "url=authy/log/" >tmp &&
test_grep "secret plan" tmp &&
test_grep "Mallory Owner" tmp
'
test_expect_success 'the login page asks not to be indexed' '
cgit_ok denyrc "url=authy/log/" >tmp &&
test_grep "<meta name=.robots. content=.noindex, nofollow.>" tmp &&
{
echo "robots=" &&
cat denyrc
} >norobotsrc &&
cgit_ok norobotsrc "url=authy/log/" >tmp &&
test_grep "<meta name=.robots. content=.noindex, nofollow.>" tmp
'
test_done
|