git-shell-verify: make leading/trailing '/' optional
[girocco.git] / bin / git-shell-verify
blob246359342e08cf8ad519a5ac986eda8d1cf558a5
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 if ! [ -x /usr/bin/perl ]; then
12 # We are INSIDE the chroot
13 reporoot=/@jailreporoot@
14 else
15 # We are NOT INSIDE the chroot
16 reporoot=@reporoot@
18 webadmurl=@webadmurl@
20 # Only the following commands are allowed:
22 # git-shell -c 'git-receive-pack dir'
23 # git-shell -c 'git receive-pack dir'
24 # git-shell -c 'git-upload-pack dir'
25 # git-shell -c 'git upload-pack dir'
26 # git-shell -c 'git-upload-archive dir'
27 # git-shell -c 'git upload-archive dir'
29 # where dir must start with $reporoot/ but a leading/trailing '/' is optional
31 if [ "$1" != "-c" ]; then
32 echo 403 forbidden >&2
33 exit 1
36 dir="$2"
37 type=''
38 case "$2" in
39 "git-receive-pack "*) type='receive-pack'; dir="${dir#git-receive-pack }";;
40 "git receive-pack "*) type='receive-pack'; dir="${dir#git receive-pack }";;
41 "git-upload-pack "*) type='upload-pack'; dir="${dir#git-upload-pack }";;
42 "git upload-pack "*) type='upload-pack'; dir="${dir#git upload-pack }";;
43 "git-upload-archive "*) type='upload-archive'; dir="${dir#git-upload-archive }";;
44 "git upload-archive "*) type='upload-archive'; dir="${dir#git upload-archive }";;
46 echo 403 forbidden >&2
47 exit 1
48 esac
50 # valid project names only allow 0-9A-Za-z._+- plus the / separator and they
51 # are always single quoted so the only valid directory names will always start
52 # with a single quote and end with a single quote and not contain any internal
53 # character that needs to be escaped.
55 case "$dir" in
56 "'"*) :;;
58 echo 403 forbidden >&2
59 exit 1
60 esac
61 case "$dir" in
62 *"'") :;;
64 echo 403 forbidden >&2
65 exit 1
66 esac
68 dir="${dir#\'}"; dir="${dir%\'}"
70 # add a missing leading /
71 case "$dir" in
72 /*) :;;
74 dir="/$dir"
75 esac
77 # remove a trailing /
78 case "$dir" in
79 *?/)
80 dir="${dir%/}"
81 esac
83 case "$dir" in
84 "$reporoot/"*) :;;
86 echo 403 forbidden >&2
87 exit 1
88 esac
90 if ! [ -d "$dir" ] || ! [ -f "$dir/HEAD" ] || ! [ -d "$dir/objects" ]; then
91 echo 403 forbidden >&2
92 exit 1
95 proj="${dir#$reporoot/}"; projbare="${proj%.git}"
97 if [ "$type" = 'receive-pack' ] && ! [ -f "$dir/.nofetch" ]; then
98 echo "The $proj project is a mirror and may not be pushed to, sorry" >&2
99 exit 3
102 if ! [ -x /usr/bin/perl ] && [ "$type" = 'receive-pack' ]; then
103 # We are INSIDE the chroot trying to push
105 if ! can_user_push "$projbare"; then
106 echo "The user '$LOGNAME' does not have push permissions for project '$proj'" >&2
107 echo "You may adjust push permissions at $webadmurl/editproj.cgi?name=$proj" >&2
108 exit 3
112 exec git-shell "$@"
113 exit 1