setup: make sure Git never runs a pager
[girocco.git] / bin / git-shell-verify
blob27307c0cd5271cea404113dc32cfff819d299519
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 GIT_CONFIG_NOSYSTEM=1
21 GIT_ATTR_NOSYSTEM=1
22 GIT_NO_REPLACE_OBJECTS=1
23 GIT_TERMINAL_PROMPT=0
24 GIT_PAGER="cat"
25 PAGER="cat"
27 if ! [ -x @perlbin@ ]; then
28 # We are INSIDE the chroot
29 reporoot=/@jailreporoot@
30 XDG_CONFIG_HOME=/var/empty
31 HOME=/etc/girocco
32 GIT_ASKPASS=/bin/git-askpass-password
33 else
34 # We are NOT INSIDE the chroot
35 reporoot=@reporoot@
36 XDG_CONFIG_HOME=@chroot@/var/empty
37 HOME=@chroot@/etc/girocco
38 GIT_ASKPASS=@basedir@/bin/git-askpass-password
40 mob=@mob@
41 webadmurl=@webadmurl@
42 ua=@git_server_ua@
43 defined_ua=@defined_git_server_ua@
44 cfg_git_no_mmap=@git_no_mmap@
45 var_big_file_threshold=@big_file_threshold@
46 var_upload_window=@upload_pack_window@
48 export XDG_CONFIG_HOME
49 export HOME
50 export GIT_CONFIG_NOSYSTEM
51 export GIT_ATTR_NOSYSTEM
52 export GIT_NO_REPLACE_OBJECTS
53 export GIT_TERMINAL_PROMPT
54 export GIT_PAGER
55 export PAGER
56 export GIT_ASKPASS
57 unset GIT_USER_AGENT
58 unset GIT_HTTP_USER_AGENT
59 if [ -n "$defined_ua" ]; then
60 GIT_USER_AGENT="$ua"
61 export GIT_USER_AGENT
62 GIT_HTTP_USER_AGENT="$ua"
63 export GIT_HTTP_USER_AGENT
65 unset GIT_CONFIG_PARAMETERS
66 git_add_config "core.ignoreCase=false"
67 git_add_config "core.pager=cat"
68 if [ -n "$cfg_git_no_mmap" ]; then
69 # Just like compiling with NO_MMAP
70 git_add_config "core.packedGitWindowSize=1m"
71 else
72 # Always use the 32-bit default (32m) even on 64-bit to avoid memory blowout
73 git_add_config "core.packedGitWindowSize=32m"
75 [ -z "$var_big_file_threshold" ] ||
76 git_add_config "core.bigFileThreshold=$var_big_file_threshold"
78 # When accessing Git via ssh, there should never be a terminal on 0, 1 or 2
79 # The "no-pty" flag should be set in all the ssh keys files to prevent this
80 # However, just in case, check for it here and die as a safety fallback
81 if [ -t 0 ] || [ -t 1 ] || [ -t 2 ]; then
82 echo forbidden >&2
83 exit 1
86 # Only the following commands are allowed:
88 # git-shell -c "git-receive-pack 'dir'"
89 # git-shell -c "git receive-pack 'dir'"
90 # git-shell -c "git-upload-pack 'dir'"
91 # git-shell -c "git upload-pack 'dir'"
92 # git-shell -c "git-upload-archive 'dir'"
93 # git-shell -c "git upload-archive 'dir'"
95 # where dir must start with $reporoot/ but a leading/trailing '/' is optional
96 # as well as the final .git however if $dir does not start with $reporoot but
97 # adding a $reporoot prefix makes it work then the $reporoot prefix will be
98 # silently added.
100 if [ "$1" != "-c" ]; then
101 echo forbidden >&2
102 exit 1
105 dir="$2"
106 type=''
107 case "$2" in
108 "git-receive-pack "*) type='receive-pack'; dir="${dir#git-receive-pack }";;
109 "git receive-pack "*) type='receive-pack'; dir="${dir#git receive-pack }";;
110 "git-upload-pack "*) type='upload-pack'; dir="${dir#git-upload-pack }";;
111 "git upload-pack "*) type='upload-pack'; dir="${dir#git upload-pack }";;
112 "git-upload-archive "*) type='upload-archive'; dir="${dir#git-upload-archive }";;
113 "git upload-archive "*) type='upload-archive'; dir="${dir#git upload-archive }";;
115 echo forbidden >&2
116 exit 1
117 esac
119 # valid project names only allow 0-9A-Za-z._+- plus the / separator and they
120 # are always single quoted so the only valid directory names will always start
121 # with a single quote and end with a single quote and not contain any internal
122 # character that needs to be escaped.
124 case "$dir" in
125 "'"*) :;;
127 echo forbidden >&2
128 exit 1
129 esac
130 case "$dir" in
131 *"'") :;;
133 echo forbidden >&2
134 exit 1
135 esac
137 # Some shells do not properly handle quoting after # or % so we cannot
138 # put an explicit ' there in a way that works for all shells. Instead
139 # just remove a single character since we've already verified it's a '.
140 dir="${dir#?}"; dir="${dir%?}"
142 # add a missing leading /
143 case "$dir" in
144 /*) :;;
146 dir="/$dir"
147 esac
149 # remove a trailing /
150 case "$dir" in
151 *?/)
152 dir="${dir%/}"
153 esac
155 # add a missing trailing .git
156 case "$dir" in
157 *.git) :;;
159 dir="$dir.git"
160 esac
162 # do not allow any .. sequence
163 case "$dir" in *..*)
164 echo forbidden >&2
165 exit 1
166 esac
168 case "$dir" in
169 "$reporoot/"*) :;;
171 # Allow it if prefixing with $reporoot matches an existing directory
172 if [ -d "$reporoot$dir" ]; then
173 dir="$reporoot$dir"
174 else
175 echo forbidden >&2
176 exit 1
178 esac
180 # Valid project names never end in .git (we add that automagically), so a valid
181 # fork can never have .git at the end of any path component except the last.
182 # We check this to avoid a situation where a certain collection of pushed refs
183 # could be mistaken for a GIT_DIR. Git would ultimately complain, but some
184 # undesirable things could happen along the way.
186 # Remove the leading $reporoot and trailing .git to get a test string
187 testpath="${dir#$reporoot/}"
188 testpath="${testpath%.git}"
189 case "$testpath/" in *.[Gg][Ii][Tt]/*|_*)
190 echo forbidden >&2
191 exit 1
192 esac
194 if ! [ -d "$dir" ] || ! [ -f "$dir/HEAD" ] || ! [ -d "$dir/objects" ]; then
195 echo forbidden >&2
196 exit 1
199 proj="${dir#$reporoot/}"; projbare="${proj%.git}"
201 if [ "$type" = 'receive-pack' ] && [ "$LOGNAME" = 'git' ]; then
202 echo "The user '$LOGNAME' may only be used for fetches, sorry" >&2
203 exit 3
206 if [ "$type" = 'receive-pack' ] && ! [ -f "$dir/.nofetch" ]; then
207 echo "The $proj project is a mirror and may not be pushed to, sorry" >&2
208 exit 3
211 if [ "$type" = 'receive-pack' ]; then
212 git_add_config 'receive.unpackLimit=1'
213 # Note the git config documentation is wrong
214 # transfer.unpackLimit, if set, overrides receive.unpackLimit
215 git_add_config 'transfer.unpackLimit=1'
218 if ! [ -x @perlbin@ ] && [ "$type" = 'receive-pack' ]; then
219 # We are INSIDE the chroot trying to push
221 if ! can_user_push "$projbare"; then
222 # If mob is enabled and mob has push permissions and
223 # the current user is not the mob then it's a personal mob push
224 # presuming the special mob directory has been set up
225 if [ "$mob" = "mob" ] && [ "$LOGNAME" != "mob" ] && [ -d "$reporoot/$proj/mob" ] &&
226 can_user_push "$projbare" mob; then
228 umask 113
229 >"/etc/sshactive/$LOGNAME,"
230 mv -f "/etc/sshactive/$LOGNAME," "/etc/sshactive/$LOGNAME"
231 ! [ -e "$dir/.delaygc" ] || >"$dir/.allowgc" || :
233 exec git-shell -c "git-receive-pack '$reporoot/$proj/mob'"
234 exit 1
236 echo "The user '$LOGNAME' does not have push permissions for project '$proj'" >&2
237 echo "You may adjust push permissions at $webadmurl/editproj.cgi?name=$proj" >&2
238 exit 3
241 umask 113
242 >"/etc/sshactive/$LOGNAME,"
243 mv -f "/etc/sshactive/$LOGNAME," "/etc/sshactive/$LOGNAME"
244 ! [ -e "$dir/.delaygc" ] || >"$dir/.allowgc" || :
248 [ -z "$var_upload_window" ] || [ "$type" != "upload-pack" ] ||
249 git_add_config "pack.window=$var_upload_window"
251 exec git-shell -c "git-$type '$dir'"
252 exit 1