git-browser: pick up drawing drift fix
[girocco.git] / bin / git-shell-verify
blob490ac6ab15833d71713556a4eb1797681a3b9772
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_CONFIG_NOSYSTEM=1
12 GIT_ATTR_NOSYSTEM=1
13 GIT_NO_REPLACE_OBJECTS=1
14 GIT_TERMINAL_PROMPT=0
16 if ! [ -x /usr/bin/perl ]; then
17 # We are INSIDE the chroot
18 reporoot=/@jailreporoot@
19 XDG_CONFIG_HOME=/var/empty
20 HOME=/etc/girocco
21 GIT_ASKPASS=/bin/git-askpass-password
22 else
23 # We are NOT INSIDE the chroot
24 reporoot=@reporoot@
25 XDG_CONFIG_HOME=@chroot@/var/empty
26 HOME=@chroot@/etc/girocco
27 GIT_ASKPASS=@basedir@/bin/git-askpass-password
29 mob=@mob@
30 webadmurl=@webadmurl@
31 ua=@git_server_ua@
32 defined_ua=@defined_git_server_ua@
34 export XDG_CONFIG_HOME
35 export HOME
36 export GIT_CONFIG_NOSYSTEM
37 export GIT_ATTR_NOSYSTEM
38 export GIT_NO_REPLACE_OBJECTS
39 export GIT_TERMINAL_PROMPT
40 export GIT_ASKPASS
41 unset GIT_USER_AGENT
42 unset GIT_HTTP_USER_AGENT
43 if [ -n "$defined_ua" ]; then
44 GIT_USER_AGENT="$ua"
45 export GIT_USER_AGENT
46 GIT_HTTP_USER_AGENT="$ua"
47 export GIT_HTTP_USER_AGENT
50 # Only the following commands are allowed:
52 # git-shell -c "git-receive-pack 'dir'"
53 # git-shell -c "git receive-pack 'dir'"
54 # git-shell -c "git-upload-pack 'dir'"
55 # git-shell -c "git upload-pack 'dir'"
56 # git-shell -c "git-upload-archive 'dir'"
57 # git-shell -c "git upload-archive 'dir'"
59 # where dir must start with $reporoot/ but a leading/trailing '/' is optional
60 # as well as the final .git however if $dir does not start with $reporoot but
61 # adding a $reporoot prefix makes it work then the $reporoot prefix will be
62 # silently added.
64 if [ "$1" != "-c" ]; then
65 echo forbidden >&2
66 exit 1
69 dir="$2"
70 type=''
71 case "$2" in
72 "git-receive-pack "*) type='receive-pack'; dir="${dir#git-receive-pack }";;
73 "git receive-pack "*) type='receive-pack'; dir="${dir#git receive-pack }";;
74 "git-upload-pack "*) type='upload-pack'; dir="${dir#git-upload-pack }";;
75 "git upload-pack "*) type='upload-pack'; dir="${dir#git upload-pack }";;
76 "git-upload-archive "*) type='upload-archive'; dir="${dir#git-upload-archive }";;
77 "git upload-archive "*) type='upload-archive'; dir="${dir#git upload-archive }";;
79 echo forbidden >&2
80 exit 1
81 esac
83 # valid project names only allow 0-9A-Za-z._+- plus the / separator and they
84 # are always single quoted so the only valid directory names will always start
85 # with a single quote and end with a single quote and not contain any internal
86 # character that needs to be escaped.
88 case "$dir" in
89 "'"*) :;;
91 echo forbidden >&2
92 exit 1
93 esac
94 case "$dir" in
95 *"'") :;;
97 echo forbidden >&2
98 exit 1
99 esac
101 # Some shells do not properly handle quoting after # or % so we cannot
102 # put an explicit ' there in a way that works for all shells. Instead
103 # just remove a single character since we've already verified it's a '.
104 dir="${dir#?}"; dir="${dir%?}"
106 # add a missing leading /
107 case "$dir" in
108 /*) :;;
110 dir="/$dir"
111 esac
113 # remove a trailing /
114 case "$dir" in
115 *?/)
116 dir="${dir%/}"
117 esac
119 # add a missing trailing .git
120 case "$dir" in
121 *.git) :;;
123 dir="$dir.git"
124 esac
126 # do not allow any .. sequence
127 case "$dir" in *..*)
128 echo forbidden >&2
129 exit 1
130 esac
132 case "$dir" in
133 "$reporoot/"*) :;;
135 # Allow it if prefixing with $reporoot matches an existing directory
136 if [ -d "$reporoot$dir" ]; then
137 dir="$reporoot$dir"
138 else
139 echo forbidden >&2
140 exit 1
142 esac
144 # Valid project names never end in .git (we add that automagically), so a valid
145 # fork can never have .git at the end of any path component except the last.
146 # We check this to avoid a situation where a certain collection of pushed refs
147 # could be mistaken for a GIT_DIR. Git would ultimately complain, but some
148 # undesirable things could happen along the way.
150 # Remove the leading $reporoot and trailing .git to get a test string
151 testpath="${dir#$reporoot/}"
152 testpath="${testpath%.git}"
153 case "$testpath/" in *.[Gg][Ii][Tt]/*|_*)
154 echo forbidden >&2
155 exit 1
156 esac
158 if ! [ -d "$dir" ] || ! [ -f "$dir/HEAD" ] || ! [ -d "$dir/objects" ]; then
159 echo forbidden >&2
160 exit 1
163 proj="${dir#$reporoot/}"; projbare="${proj%.git}"
165 if [ "$type" = 'receive-pack' ] && ! [ -f "$dir/.nofetch" ]; then
166 echo "The $proj project is a mirror and may not be pushed to, sorry" >&2
167 exit 3
170 if ! [ -x /usr/bin/perl ] && [ "$type" = 'receive-pack' ]; then
171 # We are INSIDE the chroot trying to push
173 if ! can_user_push "$projbare"; then
174 # If mob is enabled and mob has push permissions and
175 # the current user is not the mob then it's a personal mob push
176 # presuming the special mob directory has been set up
177 if [ "$mob" = "mob" -a "$LOGNAME" != "mob" -a -d "$reporoot/$proj/mob" ] &&
178 can_user_push "$projbare" mob; then
180 umask 113
181 > "/etc/sshactive/${LOGNAME},"
182 mv -f "/etc/sshactive/${LOGNAME}," "/etc/sshactive/${LOGNAME}"
183 ! [ -e "$dir/.delaygc" ] || > "$dir/.allowgc" || :
185 exec git-shell -c "git-receive-pack '$reporoot/$proj/mob'"
186 exit 1
188 echo "The user '$LOGNAME' does not have push permissions for project '$proj'" >&2
189 echo "You may adjust push permissions at $webadmurl/editproj.cgi?name=$proj" >&2
190 exit 3
193 umask 113
194 > "/etc/sshactive/${LOGNAME},"
195 mv -f "/etc/sshactive/${LOGNAME}," "/etc/sshactive/${LOGNAME}"
196 ! [ -e "$dir/.delaygc" ] || > "$dir/.allowgc" || :
200 exec git-shell -c "git-$type '$dir'"
201 exit 1