Merge branch 'master' into rorcz
[girocco.git] / bin / git-daemon-verify
blob06ecbb79577e79a1608b32f12b2a6f2e395de0d0
1 #!/bin/sh
3 # Abort any fetch early if the fetch is invalid or times out.
4 # This avoids unnecessary traffic and unpacked object pollution.
6 # This script is called for fetch, archive and push.
7 # Push requests are outright rejected and so are paths starting with ~.
9 set -e
11 . @basedir@/shlib.sh
13 unset GIT_USER_AGENT
14 unset GIT_HTTP_USER_AGENT
15 if [ -n "$defined_cfg_git_server_ua" ]; then
16 GIT_USER_AGENT="$cfg_git_server_ua"
17 export GIT_USER_AGENT
20 [ -z "$GIT_DAEMON_BIN" ] || cfg_git_daemon_bin="$GIT_DAEMON_BIN"
21 [ -n "$cfg_git_daemon_bin" ] ||
22 cfg_git_daemon_bin="$var_git_exec_path/git-daemon"
24 logmsg()
26 [ "${cfg_suppress_git_ssh_logging:-0}" = "0" ] || return 0
27 _msg="$(LC_ALL=C tr -c '\040-\176' '[?*]' <<EOT
29 EOT
30 )" && _msg="${_msg%[?]}" &&
31 logger -t "${0##*/}[$$]" <<EOT
32 $_msg
33 EOT
36 errormsg()
38 _l="$*"
39 printf '%04xERR %s' $(( 8 + ${#_l} )) "$_l"
42 invalbaderr()
44 errormsg "invalid or incomplete request"
47 invalerr()
49 errormsg "invalid or unsupported request"
52 denied()
54 errormsg "access denied or no such repository"
57 internalerr()
59 printf '%s\n' "git-daemon-verify: $*" >&2
60 errormsg "internal server error"
63 # A quick sanity check
64 if [ -z "$cfg_git_daemon_bin" ] || ! [ -x "$cfg_git_daemon_bin" ]; then
65 internalerr "bad cfg_git_daemon_bin: $cfg_git_daemon_bin"
66 exit 1
68 case "$cfg_reporoot" in /?*) :;; *)
69 internalerr "bad reporoot: $cfg_reporoot"
70 exit 1
71 esac
73 PATH="$(dirname "$cfg_git_daemon_bin"):$PATH"
74 export PATH
76 if ! request="$("$cfg_basedir/bin/peek_packet")" || [ -z "$request" ]; then
77 invalbaderr
78 exit 1
81 _IFS="$IFS"
82 IFS='
84 set -- $request
85 IFS="$_IFS"
86 [ $# -ge 1 ] || { invalidbaderr; exit 1; }
87 request="$1"
88 shift
90 # Extract host and port now
91 [ "${hnam+set}" != "set" ] || unset hnam
92 [ "${pnum+set}" != "set" ] || unset pnum
93 [ "${hostport+set}" != "set" ] || unset hostport
94 for extra in "$@"; do
95 case "$extra" in
96 "host="*) hnam="${extra#host=}";;
97 "port="*) pnum="${extra#port=}";;
98 esac
99 done
100 # Make nice hostport variable for later use
101 if [ "${hnam+set}" = "set" ]; then
102 case "$hnam" in
103 *":"*) hostport="[$hnam]";;
104 *) hostport="$hnam";;
105 esac
106 [ "${pnum+set}" != "set" ] || hostport="$hostport:$pnum"
109 # Validate the host name if requested
110 if [ -z "$cfg_git_daemon_any_host" ] && [ -n "$cfg_git_daemon_host_list" ]; then
111 case " $cfg_git_daemon_host_list " in *" $hnam "*);;*)
112 logmsg "denied ${request#git-}${hostport+ host=$hostport}"
113 denied
114 exit 1
115 esac
118 # The request should look like one of the following
120 # git-upload-pack /dir
121 # git-upload-pack ~name/dir
122 # git-upload-archive /dir
123 # git-upload-archive ~name/dir
124 # git-receive-pack /dir
125 # git-receive-pack ~name/dir
127 # Where the '~' forms are relative to a user's home directory.
128 # A trailing '/' is optional as well as a final '.git'.
129 # git-receive-pack and paths starting with '~' are rejected outright.
131 type=
132 dir=
133 case "$request" in
134 "git-upload-pack "*) type='upload-pack'; dir="${request#git-upload-pack }";;
135 "git-upload-archive "*) type='upload-archive'; dir="${request#git-upload-archive }";;
136 "git-receive-pack "*) type='receive-pack'; dir="${request#git-receive-pack }";;
138 invalerr
139 exit 1
140 esac
141 if [ "$type" = 'receive-pack' ]; then
142 logmsg "denied $type $dir${hostport+ host=$hostport}"
143 invalerr
144 exit 1
146 case "$dir" in /*) :;; *)
147 logmsg "denied $type $dir${hostport+ host=$hostport}"
148 invalerr
149 exit 1
150 esac
152 # remove extraneous '/' chars
153 proj="${dir#/}"
154 proj="${proj%/}"
155 # add a missing .git
156 case "$proj" in
157 *.git) :;;
159 proj="$proj.git"
160 esac
162 # Reject any project names that start with _ or contain ..
163 case "$proj" in _*|*..*)
164 logmsg "denied $type $dir${hostport+ host=$hostport}"
165 denied
166 exit 1
167 esac
169 odir="$dir"
170 reporoot="$cfg_reporoot"
171 dir="$reporoot/$proj"
173 # Valid project names never end in .git (we add that automagically), so a valid
174 # fork can never have .git at the end of any path component except the last.
175 # We check this to avoid a situation where a certain collection of pushed refs
176 # could be mistaken for a GIT_DIR. Git would ultimately complain, but some
177 # undesirable things could happen along the way.
179 # Remove the leading $reporoot and trailing .git to get a test string
180 testpath="${dir#$reporoot/}"
181 testpath="${testpath%.git}"
182 case "$testpath/" in *.[Gg][Ii][Tt]/*|_*)
183 logmsg "denied $type $odir${hostport+ host=$hostport}"
184 denied
185 exit 1
186 esac
188 if ! [ -d "$dir" ] || ! [ -f "$dir/HEAD" ] || ! [ -d "$dir/objects" ]; then
189 logmsg "denied $type $odir${hostport+ host=$hostport}"
190 denied
191 exit 1
194 [ -z "$var_upload_window" ] || [ "$type" != "upload-pack" ] ||
195 git_add_config "pack.window=$var_upload_window"
197 if [ "${cfg_fetch_stash_refs:-0}" = "0" ]; then
198 git_add_config "uploadpack.hiderefs=refs/stash"
199 git_add_config "uploadpack.hiderefs=refs/tgstash"
202 logmsg "accepted $type $odir${hostport+ host=$hostport}"
203 exec "$cfg_git_daemon_bin" --inetd --verbose --export-all --enable=upload-archive --base-path="$cfg_reporoot"
204 internalerr "exec failed: $cfg_git_daemon_bin"
205 exit 1