peek_packet.c: do not use inet_ntop without HAVE_INET_NTOP
[girocco.git] / bin / git-daemon-verify
blob209757b790d21f3123ea566c4593548ca6fccac0
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 fromip=
25 logmsg()
27 [ "${cfg_suppress_git_ssh_logging:-0}" = "0" ] || return 0
28 _msg="$(LC_ALL=C tr -c '\040-\176' '[?*]' <<EOT
29 $fromip$*
30 EOT
31 )" && _msg="${_msg%[?]}" &&
32 logger -t "${0##*/}[$$]" <<EOT
33 $_msg
34 EOT
37 errormsg()
39 _l="$*"
40 printf '%04xERR %s' $(( 8 + ${#_l} )) "$_l"
43 invalbaderr()
45 errormsg "invalid or incomplete request"
48 invalerr()
50 errormsg "invalid or unsupported request"
53 denied()
55 errormsg "access denied or no such repository"
58 internalerr()
60 printf '%s\n' "git-daemon-verify: $*" >&2
61 errormsg "internal server error"
64 # A quick sanity check
65 if [ -z "$cfg_git_daemon_bin" ] || ! [ -x "$cfg_git_daemon_bin" ]; then
66 internalerr "bad cfg_git_daemon_bin: $cfg_git_daemon_bin"
67 exit 1
69 case "$cfg_reporoot" in /?*) :;; *)
70 internalerr "bad reporoot: $cfg_reporoot"
71 exit 1
72 esac
74 PATH="$(dirname "$cfg_git_daemon_bin"):$PATH"
75 export PATH
77 if ! request="$("$cfg_basedir/bin/peek_packet")" || [ -z "$request" ]; then
78 invalbaderr
79 exit 1
82 _IFS="$IFS"
83 IFS='
85 set -- $request
86 IFS="$_IFS"
87 [ $# -ge 1 ] || { invalidbaderr; exit 1; }
88 request="$1"
89 shift
91 # Extract host and port now
92 REMOTE_ADDR=
93 SERVER_ADDR=
94 SERVER_PORT=
95 [ "${hnam+set}" != "set" ] || unset hnam
96 [ "${pnum+set}" != "set" ] || unset pnum
97 [ "${hostport+set}" != "set" ] || unset hostport
98 for extra in "$@"; do
99 case "$extra" in
100 "host="*) hnam="${extra#host=}";;
101 "port="*) pnum="${extra#port=}";;
102 "server_addr="*) SERVER_ADDR="${extra#server_addr=}";;
103 "server_port="*) SERVER_PORT="${extra#server_port=}";;
104 "remote_addr="*) REMOTE_ADDR="${extra#remote_addr=}";;
105 esac
106 done
107 # Make nice hostport variable for later use
108 fromip="$REMOTE_ADDR"
109 fromip="${fromip:+$fromip }"
110 if [ "${hnam+set}" = "set" ]; then
111 case "$hnam" in
112 *":"*) hostport="[$hnam]";;
113 *) hostport="$hnam";;
114 esac
115 [ "${pnum+set}" != "set" ] || hostport="$hostport:$pnum"
118 # Validate the host name if requested
119 if [ -z "$cfg_git_daemon_any_host" ] && [ -n "$cfg_git_daemon_host_list" ]; then
120 case " $cfg_git_daemon_host_list " in *" $hnam "*);;*)
121 logmsg "denied ${request#git-}${hostport+ host=$hostport}"
122 denied
123 exit 1
124 esac
127 # The request should look like one of the following
129 # git-upload-pack /dir
130 # git-upload-pack ~name/dir
131 # git-upload-archive /dir
132 # git-upload-archive ~name/dir
133 # git-receive-pack /dir
134 # git-receive-pack ~name/dir
136 # Where the '~' forms are relative to a user's home directory.
137 # A trailing '/' is optional as well as a final '.git'.
138 # git-receive-pack and paths starting with '~' are rejected outright.
140 type=
141 dir=
142 case "$request" in
143 "git-upload-pack "*) type='upload-pack'; dir="${request#git-upload-pack }";;
144 "git-upload-archive "*) type='upload-archive'; dir="${request#git-upload-archive }";;
145 "git-receive-pack "*) type='receive-pack'; dir="${request#git-receive-pack }";;
147 invalerr
148 exit 1
149 esac
150 if [ "$type" = 'receive-pack' ]; then
151 logmsg "denied $type $dir${hostport+ host=$hostport}"
152 invalerr
153 exit 1
155 case "$dir" in /*) :;; *)
156 logmsg "denied $type $dir${hostport+ host=$hostport}"
157 invalerr
158 exit 1
159 esac
161 # remove extraneous '/' chars
162 proj="${dir#/}"
163 proj="${proj%/}"
164 # add a missing .git
165 case "$proj" in
166 *.git) :;;
168 proj="$proj.git"
169 esac
171 # Reject any project names that start with _ or contain ..
172 case "$proj" in _*|*..*)
173 logmsg "denied $type $dir${hostport+ host=$hostport}"
174 denied
175 exit 1
176 esac
178 odir="$dir"
179 reporoot="$cfg_reporoot"
180 dir="$reporoot/$proj"
182 # Valid project names never end in .git (we add that automagically), so a valid
183 # fork can never have .git at the end of any path component except the last.
184 # We check this to avoid a situation where a certain collection of pushed refs
185 # could be mistaken for a GIT_DIR. Git would ultimately complain, but some
186 # undesirable things could happen along the way.
188 # Remove the leading $reporoot and trailing .git to get a test string
189 testpath="${dir#$reporoot/}"
190 testpath="${testpath%.git}"
191 case "$testpath/" in *.[Gg][Ii][Tt]/*|_*)
192 logmsg "denied $type $odir${hostport+ host=$hostport}"
193 denied
194 exit 1
195 esac
197 if ! [ -d "$dir" ] || ! [ -f "$dir/HEAD" ] || ! [ -d "$dir/objects" ]; then
198 logmsg "denied $type $odir${hostport+ host=$hostport}"
199 denied
200 exit 1
203 [ -z "$var_upload_window" ] || [ "$type" != "upload-pack" ] ||
204 git_add_config "pack.window=$var_upload_window"
206 if [ "${cfg_fetch_stash_refs:-0}" = "0" ]; then
207 git_add_config "uploadpack.hiderefs=refs/stash"
208 git_add_config "uploadpack.hiderefs=refs/tgstash"
211 logmsg "accepted $type $odir${hostport+ host=$hostport}"
212 exec "$cfg_git_daemon_bin" --inetd --verbose --export-all --enable=upload-archive --base-path="$cfg_reporoot"
213 internalerr "exec failed: $cfg_git_daemon_bin"
214 exit 1