User.pm: bump up maximum key list length
[girocco.git] / bin / git-shell-verify
blob49b7a7b55beeebbeaec3c2615bd88bd76c36bd5d
1 #!/bin/sh
3 # Abort any push early if the pushing user doesn't have any push permissions
4 # at all. This avoids unnecessary traffic and unpacked object pollution.
6 # This script is intended for use from within the chroot jail and may or may
7 # not work properly outside it.
9 set -e
11 # git_add_config "some.var=value"
12 # every ' in value must be replaced with the 4-character sequence '\'' before
13 # calling this function or Git will barf. Will not be effective unless running
14 # Git version 1.7.3 or later.
15 git_add_config() {
16 GIT_CONFIG_PARAMETERS="${GIT_CONFIG_PARAMETERS:+$GIT_CONFIG_PARAMETERS }'$1'"
17 export GIT_CONFIG_PARAMETERS
20 TMPDIR="/tmp"
21 GIT_CONFIG_NOSYSTEM=1
22 GIT_ATTR_NOSYSTEM=1
23 GIT_NO_REPLACE_OBJECTS=1
24 GIT_TERMINAL_PROMPT=0
25 GIT_PAGER="cat"
26 PAGER="cat"
27 GIROCCO_SUPPRESS_AUTO_GC_UPDATE=1
29 if ! [ -x @perlbin@ ]; then
30 # We are INSIDE the chroot
31 reporoot=/@jailreporoot@
32 XDG_CONFIG_HOME=/var/empty
33 HOME=/etc/girocco
34 GIT_ASKPASS=/bin/git-askpass-password
35 else
36 # We are NOT INSIDE the chroot
37 reporoot=@reporoot@
38 XDG_CONFIG_HOME=@chroot@/var/empty
39 HOME=@chroot@/etc/girocco
40 GIT_ASKPASS=@basedir@/bin/git-askpass-password
42 mob=@mob@
43 webadmurl=@webadmurl@
44 ua=@git_server_ua@
45 defined_ua=@defined_git_server_ua@
46 cfg_git_no_mmap=@git_no_mmap@
47 var_big_file_threshold=@big_file_threshold@
48 var_upload_window=@upload_pack_window@
49 cfg_fetch_stash_refs=@fetch_stash_refs@
51 export XDG_CONFIG_HOME
52 export HOME
53 export TMPDIR
54 export GIT_CONFIG_NOSYSTEM
55 export GIT_ATTR_NOSYSTEM
56 export GIT_NO_REPLACE_OBJECTS
57 export GIT_TERMINAL_PROMPT
58 export GIT_PAGER
59 export PAGER
60 export GIT_ASKPASS
61 export GIROCCO_SUPPRESS_AUTO_GC_UPDATE
62 unset GIT_USER_AGENT
63 unset GIT_HTTP_USER_AGENT
64 if [ -n "$defined_ua" ]; then
65 GIT_USER_AGENT="$ua"
66 export GIT_USER_AGENT
68 unset GIT_CONFIG_PARAMETERS
69 git_add_config "core.ignoreCase=false"
70 git_add_config "core.pager=cat"
71 if [ -n "$cfg_git_no_mmap" ]; then
72 # Just like compiling with NO_MMAP
73 git_add_config "core.packedGitWindowSize=1m"
74 else
75 # Always use the 32-bit default (32m) even on 64-bit to avoid memory blowout
76 git_add_config "core.packedGitWindowSize=32m"
78 [ -z "$var_big_file_threshold" ] ||
79 git_add_config "core.bigFileThreshold=$var_big_file_threshold"
80 git_add_config "gc.auto=0"
82 if [ "${cfg_fetch_stash_refs:-0}" = "0" ]; then
83 git_add_config "uploadpack.hiderefs=refs/stash"
84 git_add_config "uploadpack.hiderefs=refs/tgstash"
87 # When accessing Git via ssh, there should never be a terminal on 0, 1 or 2
88 # The "no-pty" flag should be set in all the ssh keys files to prevent this
89 # However, just in case, check for it here and die as a safety fallback
90 if [ -t 0 ] || [ -t 1 ] || [ -t 2 ]; then
91 echo forbidden >&2
92 exit 1
95 # Only the following commands are allowed:
97 # git-shell -c "git-receive-pack 'dir'"
98 # git-shell -c "git receive-pack 'dir'"
99 # git-shell -c "git-upload-pack 'dir'"
100 # git-shell -c "git upload-pack 'dir'"
101 # git-shell -c "git-upload-archive 'dir'"
102 # git-shell -c "git upload-archive 'dir'"
104 # where dir must start with $reporoot/ but a leading/trailing '/' is optional
105 # as well as the final .git however if $dir does not start with $reporoot but
106 # adding a $reporoot prefix makes it work then the $reporoot prefix will be
107 # silently added.
109 if [ "$1" != "-c" ]; then
110 echo forbidden >&2
111 exit 1
114 dir="$2"
115 type=''
116 case "$2" in
117 "git-receive-pack "*) type='receive-pack'; dir="${dir#git-receive-pack }";;
118 "git receive-pack "*) type='receive-pack'; dir="${dir#git receive-pack }";;
119 "git-upload-pack "*) type='upload-pack'; dir="${dir#git-upload-pack }";;
120 "git upload-pack "*) type='upload-pack'; dir="${dir#git upload-pack }";;
121 "git-upload-archive "*) type='upload-archive'; dir="${dir#git-upload-archive }";;
122 "git upload-archive "*) type='upload-archive'; dir="${dir#git upload-archive }";;
124 echo forbidden >&2
125 exit 1
126 esac
128 # valid project names only allow 0-9A-Za-z._+- plus the / separator and they
129 # are always single quoted so the only valid directory names will always start
130 # with a single quote and end with a single quote and not contain any internal
131 # character that needs to be escaped.
133 case "$dir" in
134 "'"*) :;;
136 echo forbidden >&2
137 exit 1
138 esac
139 case "$dir" in
140 *"'") :;;
142 echo forbidden >&2
143 exit 1
144 esac
146 # Some shells do not properly handle quoting after # or % so we cannot
147 # put an explicit ' there in a way that works for all shells. Instead
148 # just remove a single character since we've already verified it's a '.
149 dir="${dir#?}"; dir="${dir%?}"
151 # add a missing leading /
152 case "$dir" in
153 /*) :;;
155 dir="/$dir"
156 esac
158 # remove a trailing /
159 case "$dir" in
160 *?/)
161 dir="${dir%/}"
162 esac
164 # add a missing trailing .git
165 case "$dir" in
166 *.git) :;;
168 dir="$dir.git"
169 esac
171 # do not allow any .. sequence
172 case "$dir" in *..*)
173 echo forbidden >&2
174 exit 1
175 esac
177 case "$dir" in
178 "$reporoot/"*) :;;
180 # Allow it if prefixing with $reporoot matches an existing directory
181 if [ -d "$reporoot$dir" ]; then
182 dir="$reporoot$dir"
183 else
184 echo forbidden >&2
185 exit 1
187 esac
189 # Valid project names never end in .git (we add that automagically), so a valid
190 # fork can never have .git at the end of any path component except the last.
191 # We check this to avoid a situation where a certain collection of pushed refs
192 # could be mistaken for a GIT_DIR. Git would ultimately complain, but some
193 # undesirable things could happen along the way.
195 # Remove the leading $reporoot and trailing .git to get a test string
196 testpath="${dir#$reporoot/}"
197 testpath="${testpath%.git}"
198 case "$testpath/" in *.[Gg][Ii][Tt]/*|_*)
199 echo forbidden >&2
200 exit 1
201 esac
203 if ! [ -d "$dir" ] || ! [ -f "$dir/HEAD" ] || ! [ -d "$dir/objects" ]; then
204 echo forbidden >&2
205 exit 1
208 proj="${dir#$reporoot/}"; projbare="${proj%.git}"
210 if [ "$type" = 'receive-pack' ] && [ "$LOGNAME" = 'git' ]; then
211 echo "The user '$LOGNAME' may only be used for fetches, sorry" >&2
212 exit 3
215 if [ "$type" = 'receive-pack' ] && ! [ -f "$dir/.nofetch" ]; then
216 echo "The $proj project is a mirror and may not be pushed to, sorry" >&2
217 exit 3
220 if [ "$type" = 'receive-pack' ]; then
221 git_add_config 'receive.unpackLimit=1'
222 # Note the git config documentation is wrong
223 # transfer.unpackLimit, if set, overrides receive.unpackLimit
224 git_add_config 'transfer.unpackLimit=1'
227 if ! [ -x @perlbin@ ] && [ "$type" = 'receive-pack' ]; then
228 # We are INSIDE the chroot trying to push
230 if ! can_user_push "$projbare"; then
231 # If mob is enabled and mob has push permissions and
232 # the current user is not the mob then it's a personal mob push
233 # presuming the special mob directory has been set up
234 if [ "$mob" = "mob" ] && [ "$LOGNAME" != "mob" ] && [ -d "$reporoot/$proj/mob" ] &&
235 can_user_push "$projbare" mob; then
237 umask 113
238 >"/etc/sshactive/$LOGNAME,"
239 mv -f "/etc/sshactive/$LOGNAME," "/etc/sshactive/$LOGNAME"
240 ! [ -e "$dir/.delaygc" ] || >"$dir/.allowgc" || :
242 exec git-shell -c "git-receive-pack '$reporoot/$proj/mob'"
243 exit 1
245 echo "The user '$LOGNAME' does not have push permissions for project '$proj'" >&2
246 echo "You may adjust push permissions at $webadmurl/editproj.cgi?name=$proj" >&2
247 exit 3
250 umask 113
251 >"/etc/sshactive/$LOGNAME,"
252 mv -f "/etc/sshactive/$LOGNAME," "/etc/sshactive/$LOGNAME"
253 ! [ -e "$dir/.delaygc" ] || >"$dir/.allowgc" || :
257 [ -z "$var_upload_window" ] || [ "$type" != "upload-pack" ] ||
258 git_add_config "pack.window=$var_upload_window"
260 exec git-shell -c "git-$type '$dir'"
261 exit 1