project-disk-use: included binned use
[girocco.git] / bin / git-shell-verify
blobd93c0f263958f5ef3bf5a1719dde3beaf2a9c84f
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
14 if ! [ -x /usr/bin/perl ]; then
15 # We are INSIDE the chroot
16 reporoot=/@jailreporoot@
17 XDG_CONFIG_HOME=/var/empty
18 HOME=/etc/girocco
19 else
20 # We are NOT INSIDE the chroot
21 reporoot=@reporoot@
22 XDG_CONFIG_HOME=@chroot@/var/empty
23 HOME=@chroot@/etc/girocco
25 mob=@mob@
26 webadmurl=@webadmurl@
28 export GIT_CONFIG_NOSYSTEM
29 export GIT_ATTR_NOSYSTEM
30 export XDG_CONFIG_HOME
31 export HOME
33 # Only the following commands are allowed:
35 # git-shell -c "git-receive-pack 'dir'"
36 # git-shell -c "git receive-pack 'dir'"
37 # git-shell -c "git-upload-pack 'dir'"
38 # git-shell -c "git upload-pack 'dir'"
39 # git-shell -c "git-upload-archive 'dir'"
40 # git-shell -c "git upload-archive 'dir'"
42 # where dir must start with $reporoot/ but a leading/trailing '/' is optional
43 # as well as the final .git however if $dir does not start with $reporoot but
44 # adding a $reporoot prefix makes it work then the $reporoot prefix will be
45 # silently added.
47 if [ "$1" != "-c" ]; then
48 echo forbidden >&2
49 exit 1
52 dir="$2"
53 type=''
54 case "$2" in
55 "git-receive-pack "*) type='receive-pack'; dir="${dir#git-receive-pack }";;
56 "git receive-pack "*) type='receive-pack'; dir="${dir#git receive-pack }";;
57 "git-upload-pack "*) type='upload-pack'; dir="${dir#git-upload-pack }";;
58 "git upload-pack "*) type='upload-pack'; dir="${dir#git upload-pack }";;
59 "git-upload-archive "*) type='upload-archive'; dir="${dir#git-upload-archive }";;
60 "git upload-archive "*) type='upload-archive'; dir="${dir#git upload-archive }";;
62 echo forbidden >&2
63 exit 1
64 esac
66 # valid project names only allow 0-9A-Za-z._+- plus the / separator and they
67 # are always single quoted so the only valid directory names will always start
68 # with a single quote and end with a single quote and not contain any internal
69 # character that needs to be escaped.
71 case "$dir" in
72 "'"*) :;;
74 echo forbidden >&2
75 exit 1
76 esac
77 case "$dir" in
78 *"'") :;;
80 echo forbidden >&2
81 exit 1
82 esac
84 # Some shells do not properly handle quoting after # or % so we cannot
85 # put an explicit ' there in a way that works for all shells. Instead
86 # just remove a single character since we've already verified it's a '.
87 dir="${dir#?}"; dir="${dir%?}"
89 # add a missing leading /
90 case "$dir" in
91 /*) :;;
93 dir="/$dir"
94 esac
96 # remove a trailing /
97 case "$dir" in
98 *?/)
99 dir="${dir%/}"
100 esac
102 # add a missing trailing .git
103 case "$dir" in
104 *.git) :;;
106 dir="$dir.git"
107 esac
109 case "$dir" in
110 "$reporoot/"*) :;;
112 # Allow it if prefixing with $reporoot matches an existing directory
113 if [ -d "$reporoot$dir" ]; then
114 dir="$reporoot$dir"
115 else
116 echo forbidden >&2
117 exit 1
119 esac
121 # Valid project names never end in .git (we add that automagically), so a valid
122 # fork can never have .git at the end of any path component except the last.
123 # We check this to avoid a situation where a certain collection of pushed refs
124 # could be mistaken for a GIT_DIR. Git would ultimately complain, but some
125 # undesirable things could happen along the way.
127 # Remove the leading $reporoot and trailing .git to get a test string
128 testpath="${dir#$reporoot/}"
129 testpath="${testpath%.git}"
130 case "$testpath/" in *.[Gg][Ii][Tt]/*)
131 echo forbidden >&2
132 exit 1
133 esac
135 if ! [ -d "$dir" ] || ! [ -f "$dir/HEAD" ] || ! [ -d "$dir/objects" ]; then
136 echo forbidden >&2
137 exit 1
140 proj="${dir#$reporoot/}"; projbare="${proj%.git}"
142 if [ "$type" = 'receive-pack' ] && ! [ -f "$dir/.nofetch" ]; then
143 echo "The $proj project is a mirror and may not be pushed to, sorry" >&2
144 exit 3
147 if ! [ -x /usr/bin/perl ] && [ "$type" = 'receive-pack' ]; then
148 # We are INSIDE the chroot trying to push
150 if ! can_user_push "$projbare"; then
151 # If mob is enabled and mob has push permissions and
152 # the current user is not the mob then it's a personal mob push
153 # presuming the special mob directory has been set up
154 if [ "$mob" = "mob" -a "$LOGNAME" != "mob" -a -d "$reporoot/$proj/mob" ] &&
155 can_user_push "$projbare" mob; then
157 umask 113
158 > "/etc/sshactive/${LOGNAME},"
159 mv -f "/etc/sshactive/${LOGNAME}," "/etc/sshactive/${LOGNAME}"
161 exec git-shell -c "git-receive-pack '$reporoot/$proj/mob'"
162 exit 1
164 echo "The user '$LOGNAME' does not have push permissions for project '$proj'" >&2
165 echo "You may adjust push permissions at $webadmurl/editproj.cgi?name=$proj" >&2
166 exit 3
169 umask 113
170 > "/etc/sshactive/${LOGNAME},"
171 mv -f "/etc/sshactive/${LOGNAME}," "/etc/sshactive/${LOGNAME}"
175 exec git-shell -c "git-$type '$dir'"
176 exit 1