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.
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.
16 GIT_CONFIG_PARAMETERS
="${GIT_CONFIG_PARAMETERS:+$GIT_CONFIG_PARAMETERS }'$1'"
17 export GIT_CONFIG_PARAMETERS
23 GIT_NO_REPLACE_OBJECTS
=1
27 GIROCCO_SUPPRESS_AUTO_GC_UPDATE
=1
29 if ! [ -x @perlbin@
]; then
30 # We are INSIDE the chroot
31 PATH
=/bin
&& export PATH
32 reporoot
=/@jailreporoot@
33 XDG_CONFIG_HOME
=/var
/empty
35 GIT_ASKPASS
=/bin
/git-askpass-password
37 # We are NOT INSIDE the chroot
39 XDG_CONFIG_HOME
=@chroot@
/var
/empty
40 HOME
=@chroot@
/etc
/girocco
41 GIT_ASKPASS
=@basedir@
/bin
/git-askpass-password
46 defined_ua
=@defined_git_server_ua@
47 cfg_git_no_mmap
=@git_no_mmap@
48 var_big_file_threshold
=@big_file_threshold@
49 var_upload_window
=@upload_pack_window@
50 cfg_fetch_stash_refs
=@fetch_stash_refs@
51 cfg_suppress_git_ssh_logging
=@suppress_git_ssh_logging@
52 cfg_max_file_size512
=@max_file_size512@
54 export XDG_CONFIG_HOME
57 export GIT_CONFIG_NOSYSTEM
58 export GIT_ATTR_NOSYSTEM
59 export GIT_NO_REPLACE_OBJECTS
60 export GIT_TERMINAL_PROMPT
64 export GIROCCO_SUPPRESS_AUTO_GC_UPDATE
66 unset GIT_HTTP_USER_AGENT
67 if [ -n "$defined_ua" ]; then
71 unset GIT_CONFIG_PARAMETERS
72 git_add_config
"core.ignoreCase=false"
73 git_add_config
"core.pager=cat"
74 if [ -n "$cfg_git_no_mmap" ]; then
75 # Just like compiling with NO_MMAP
76 git_add_config
"core.packedGitWindowSize=1m"
78 # Always use the 32-bit default (32m) even on 64-bit to avoid memory blowout
79 git_add_config
"core.packedGitWindowSize=32m"
81 # Always use the 32-bit default (256m) even on 64-bit to avoid memory blowout
82 git_add_config
"core.packedGitLimit=256m"
83 [ -z "$var_big_file_threshold" ] ||
84 git_add_config
"core.bigFileThreshold=$var_big_file_threshold"
85 git_add_config
"gc.auto=0"
87 if [ "${cfg_fetch_stash_refs:-0}" = "0" ]; then
88 git_add_config
"uploadpack.hiderefs=refs/stash"
89 git_add_config
"uploadpack.hiderefs=refs/tgstash"
92 fromip
="${SSH_CLIENT%% *}"
93 fromip
="${fromip:+$fromip }"
97 [ "${cfg_suppress_git_ssh_logging:-0}" = "0" ] ||
return 0
98 _msg
="$(LC_ALL=C tr -c '\040-\176' '[?*]' <<EOT
101 )" && _msg
="${_msg%[?]}" &&
102 logger
-t "${0##*/}[$$]" <<EOT
107 # When accessing Git via ssh, there should never be a terminal on 0, 1 or 2
108 # The "no-pty" flag should be set in all the ssh keys files to prevent this
109 # However, just in case, check for it here and die as a safety fallback
110 if [ -t 0 ] ||
[ -t 1 ] ||
[ -t 2 ]; then
116 # Only the following commands are allowed:
118 # git-shell -c "git-receive-pack 'dir'"
119 # git-shell -c "git receive-pack 'dir'"
120 # git-shell -c "git-upload-pack 'dir'"
121 # git-shell -c "git upload-pack 'dir'"
122 # git-shell -c "git-upload-archive 'dir'"
123 # git-shell -c "git upload-archive 'dir'"
125 # where dir must start with $reporoot/ but a leading/trailing '/' is optional
126 # as well as the final .git however if $dir does not start with $reporoot but
127 # adding a $reporoot prefix makes it work then the $reporoot prefix will be
130 if [ "$1" != "-c" ]; then
138 "git-receive-pack "*) type='receive-pack'; dir
="${dir#git-receive-pack }";;
139 "git receive-pack "*) type='receive-pack'; dir
="${dir#git receive-pack }";;
140 "git-upload-pack "*) type='upload-pack'; dir
="${dir#git-upload-pack }";;
141 "git upload-pack "*) type='upload-pack'; dir
="${dir#git upload-pack }";;
142 "git-upload-archive "*) type='upload-archive'; dir
="${dir#git-upload-archive }";;
143 "git upload-archive "*) type='upload-archive'; dir
="${dir#git upload-archive }";;
149 # valid project names only allow 0-9A-Za-z._+- plus the / separator and they
150 # are always single quoted so the only valid directory names will always start
151 # with a single quote and end with a single quote and not contain any internal
152 # character that needs to be escaped.
157 logmsg
"denied $type $dir"
164 logmsg
"denied $type $dir"
169 # Some shells do not properly handle quoting after # or % so we cannot
170 # put an explicit ' there in a way that works for all shells. Instead
171 # just remove a single character since we've already verified it's a '.
172 dir
="${dir#?}"; dir
="${dir%?}"
174 # add a missing leading /
181 # remove a trailing /
187 # add a missing trailing .git
194 # do not allow any .. sequence
196 logmsg
"denied $type $dir"
205 # Allow it if prefixing with $reporoot matches an existing directory
206 if [ -d "$reporoot$dir" ]; then
209 logmsg
"denied $type $dir"
215 # Valid project names never end in .git (we add that automagically), so a valid
216 # fork can never have .git at the end of any path component except the last.
217 # We check this to avoid a situation where a certain collection of pushed refs
218 # could be mistaken for a GIT_DIR. Git would ultimately complain, but some
219 # undesirable things could happen along the way.
221 # Remove the leading $reporoot and trailing .git to get a test string
222 testpath
="${dir#$reporoot/}"
223 testpath
="${testpath%.git}"
224 case "$testpath/" in *.
[Gg
][Ii
][Tt
]/*|_
*)
225 logmsg
"denied $type $odir"
230 if ! [ -d "$dir" ] ||
! [ -f "$dir/HEAD" ] ||
! [ -d "$dir/objects" ]; then
231 logmsg
"denied $type $odir"
236 proj
="${dir#$reporoot/}"; projbare
="${proj%.git}"
238 if [ "$type" = 'receive-pack' ] && [ "$LOGNAME" = 'git' ]; then
239 logmsg
"denied $type $odir"
240 echo "The user '$LOGNAME' may only be used for fetches, sorry" >&2
244 if [ "$type" = 'receive-pack' ] && ! [ -f "$dir/.nofetch" ]; then
245 logmsg
"denied $type $odir"
246 echo "The $proj project is a mirror and may not be pushed to, sorry" >&2
250 GIT_SHELL
='git-shell'
251 if [ "$type" = 'receive-pack' ]; then
252 git_add_config
'receive.unpackLimit=1'
253 # Note the git config documentation is wrong
254 # transfer.unpackLimit, if set, overrides receive.unpackLimit
255 git_add_config
'transfer.unpackLimit=1'
256 # set up the correct git-shell command if cfg_max_file_size512 > 0
257 if [ "${cfg_max_file_size512:-0}" != "0" ]; then
258 GIT_SHELL
='ulimit512 -i -f "$cfg_max_file_size512" -- git-shell'
262 if ! [ -x @perlbin@
] && [ "$type" = 'receive-pack' ]; then
263 # We are INSIDE the chroot trying to push
265 if ! can_user_push
"$projbare"; then
266 # If mob is enabled and mob has push permissions and
267 # the current user is not the mob then it's a personal mob push
268 # presuming the special mob directory has been set up
269 if [ "$mob" = "mob" ] && [ "$LOGNAME" != "mob" ] && [ -d "$reporoot/$proj/mob" ] &&
270 can_user_push
"$projbare" mob
; then
273 >"/etc/sshactive/$LOGNAME,"
274 mv -f "/etc/sshactive/$LOGNAME," "/etc/sshactive/$LOGNAME"
275 ! [ -e "$dir/.delaygc" ] ||
>"$dir/.allowgc" ||
:
277 logmsg
"accepted $type $odir mob"
278 eval 'exec '"$GIT_SHELL"' -c "git-receive-pack '\''$reporoot/$proj/mob'\''"'
281 logmsg
"denied $type $odir noperms"
282 echo "The user '$LOGNAME' does not have push permissions for project '$proj'" >&2
283 echo "You may adjust push permissions at $webadmurl/editproj.cgi?name=$proj" >&2
288 >"/etc/sshactive/$LOGNAME,"
289 mv -f "/etc/sshactive/$LOGNAME," "/etc/sshactive/$LOGNAME"
290 ! [ -e "$dir/.delaygc" ] ||
>"$dir/.allowgc" ||
:
294 [ -z "$var_upload_window" ] ||
[ "$type" != "upload-pack" ] ||
295 git_add_config
"pack.window=$var_upload_window"
297 logmsg
"accepted $type $odir"
298 eval 'exec '"$GIT_SHELL"' -c "git-$type '\''$dir'\''"'