-
Notifications
You must be signed in to change notification settings - Fork 2
/
shell
executable file
·156 lines (136 loc) · 3.58 KB
/
shell
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
#!/bin/sh
if [ -z "$GIT_USER" ]; then
echo "Need to have a GIT_USER name"
exit 1
fi
export GIT_SS_LOCAL_VERSION="1"
export FILE_PATH_LOG="$HOME/log.txt"
export FILE_NAME_MARKER=".ss-marker"
export FILE_NAME_ACCESS_READ=".ss-access_read"
export FILE_NAME_ACCESS_WRITE=".ss-access_write"
export FILE_PATH_AUTHORIZED_KEYS="$HOME/.ssh/authorized_keys"
export REPOS_PATH="$HOME/repos"
export REPO_USER_PATH="$REPOS_PATH/$GIT_USER"
CMD="$2"
_ACCESSED_REPO_NAME=${CMD#* } # remove first parameter
_ACCESSED_REPO_NAME=${_ACCESSED_REPO_NAME#"'"} # replace leading '
_ACCESSED_REPO_NAME=${_ACCESSED_REPO_NAME%"'"} # replace trailing '
export ACCESSED_REPO_PATH="$REPOS_PATH/$_ACCESSED_REPO_NAME"
set -euf #o pipefail
log() {
echo "$@" >> "$FILE_PATH_LOG"
}
if [ ! -d "$REPO_USER_PATH" ]; then
log "You don't have an users folder yet, $GIT_USER"
exit 1
fi
if [ $# -ne 2 ] || [ "$1" != "-c" ]; then
log "Interactive login not permitted"
echo "Interactive login not permitted"
exit 1
fi
require_admin_access() {
set +u
if [ "$GIT_ADMIN" != "true" ]; then
echo "You are not allowed to do that"
exit 1
fi
set -u
}
_require_access_mode() {
if [ ! -d "$ACCESSED_REPO_PATH" ]; then
log "Accessed repo does not exist: $ACCESSED_REPO_PATH"
exit 1
fi
local MODE="$1"
local ACCESS_FILE
case "$MODE" in
"read")
ACCESS_FILE="$FILE_NAME_ACCESS_READ"
;;
"write")
ACCESS_FILE="$FILE_NAME_ACCESS_WRITE"
;;
*)
echo "No such mode: '$MODE'"
exit 1
;;
esac
if [ ! -f "$ACCESSED_REPO_PATH/$ACCESS_FILE" ]; then
log "File '$ACCESSED_REPO_PATH/$ACCESS_FILE' does not exist"
exit 1
fi
if ! grep -xq "^$GIT_USER$" "$ACCESSED_REPO_PATH/$ACCESS_FILE"; then
log "User '$GIT_USER' has no $MODE access to '$ACCESSED_REPO_PATH'"
exit 1
fi
log "User '$GIT_USER' has $MODE access to '$ACCESSED_REPO_PATH'"
}
require_read_access() {
_require_access_mode "read"
}
require_write_access() {
_require_access_mode "write"
}
# Even if this might look vulnerable to a prefix / suffix attack to pass authentication
# (e.g. " git-receive-pack" or "user ; some-other-command"), it is safe :)
DO_REQUIRE_ADMIN=true
DO_REQUIRE_READ_ACCESS=true
DO_REQUIRE_WRITE_ACCESS=true
DO_REQUIRE_VERSION=true
case "$CMD" in
"git-receive-pack"*)
DO_REQUIRE_ADMIN=false
DO_REQUIRE_READ_ACCESS=false
DO_REQUIRE_VERSION=false
CMD="git-receive-pack '$ACCESSED_REPO_PATH'"
;;
"git-upload-pack"*)
DO_REQUIRE_ADMIN=false
DO_REQUIRE_WRITE_ACCESS=false
DO_REQUIRE_VERSION=false
CMD="git-upload-pack '$ACCESSED_REPO_PATH'"
;;
"git-upload-archive"*)
DO_REQUIRE_ADMIN=false
DO_REQUIRE_WRITE_ACCESS=false
DO_REQUIRE_VERSION=false
CMD="git-upload-archive '$ACCESSED_REPO_PATH'"
;;
"user"*)
DO_REQUIRE_READ_ACCESS=false
DO_REQUIRE_WRITE_ACCESS=false
;;
"repo"*)
DO_REQUIRE_ADMIN=false
DO_REQUIRE_READ_ACCESS=false
DO_REQUIRE_WRITE_ACCESS=false
;;
esac
if [ "$DO_REQUIRE_ADMIN" = true ]; then
require_admin_access
fi
if [ "$DO_REQUIRE_READ_ACCESS" = true ]; then
require_read_access
fi
if [ "$DO_REQUIRE_WRITE_ACCESS" = true ]; then
require_write_access
fi
if [ "$DO_REQUIRE_VERSION" = true ]; then
set +u
if [ -z "$GIT_SS_REMOTE_VERSION" ]; then
echo "Need to have a GIT_SS_REMOTE_VERSION env var"
exit 1
fi
set -u
if [ "$GIT_SS_REMOTE_VERSION" != "$GIT_SS_LOCAL_VERSION" ]; then
MSG="Your git-simpleserver client is outdated. Please update."
if [ "$GIT_SS_REMOTE_VERSION" -gt "$GIT_SS_LOCAL_VERSION" ]; then
MSG="The git-simpleserver server is outdated. Please update."
fi
echo "$MSG You: v$GIT_SS_REMOTE_VERSION, server: v$GIT_SS_LOCAL_VERSION"
exit 1
fi
fi
log "Executing '$CMD'"
git-shell -c "$CMD"