various: add read-only mode support
[girocco.git] / cgi / authrequired.cgi
blob413b62a80bea2892599b431fe5c95f077ca02fa0
1 #!/bin/sh
3 # authrequired.cgi -- show certification authorization instructions on 401
4 # Copyright (C) 2014,2016,2017 Kyle J. McKay. All rights reserved.
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 # Version 1.3.1
22 # We pretend like we don't exist. Unless this was an attempt to access a push
23 # URL over HTTP/HTTPS in which case we return a suitable error message.
25 # Some of this detection requires REQUEST_URI to be set which is an Apache
26 # extension. If REQUEST_URI is not set that portion of the smart detection
27 # will be disabled.
29 # Also note that we return a 403 error instead of a 401 error because we require
30 # a user push certificate. Returning a 401 error and having the client then
31 # provide a user name and password is completely pointless since we now are
32 # providing copious amounts of help text.
34 # If the client appears to be an older version of Git that will probably not
35 # display a text/plain error response to the user then the error message is
36 # sent as an 'ERR ' packet in smart protocol format instead. Git versions
37 # older than 1.8.3 as well as JGit and libgit require the 'ERR ' packet format.
38 # This 'ERR ' packet format support requires that REQUEST_URI be set to the
39 # original URI that was fetched or it will never trigger.
41 set -e
43 headers() {
44 printf '%s\r\n' "Status: $1"
45 printf '%s\r\n' "Expires: Fri, 01 Jan 1980 00:00:00 GMT"
46 printf '%s\r\n' "Pragma: no-cache"
47 printf '%s\r\n' "Cache-Control: no-cache, max-age=0, must-revalidate"
48 printf '%s\r\n' "Content-Type: $2"
49 [ -z "$3" ] || printf "%s\r\n" "$3"
50 printf '\r\n'
53 notfound() {
54 # Simulate a 404 error as though we do not exist
55 headers 404 "text/html; charset=utf-8"
56 SPACE=
57 [ -z "$REQUEST_URI" ] || SPACE=" "
58 cat <<EOF
59 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
60 <html><head>
61 <title>404 Not Found</title>
62 </head><body>
63 <h1>Not Found</h1>
64 <p>The requested URL $REQUEST_URI${SPACE}was not found on this server.</p>
65 <hr />
66 $SERVER_SIGNATURE
67 </body></html>
68 EOF
69 exit 0
72 # Set isoldgit if we've detected an old Git client that needs an 'ERR ' packet
73 isoldgit=
74 case "$HTTP_USER_AGENT" in *[Gg]it/*)
75 case "$HTTP_USER_AGENT" in
76 *[Jj][Gg]it/*)
77 isoldgit=1
80 suffix="${HTTP_USER_AGENT##*[Gg]it/}"
81 gitvers="${suffix%%[!0-9.]*}"
82 gitvers="${gitvers%.}"
83 case "$gitvers" in
84 [1-9][0-9]*|[2-9]|[2-9].*|1.[1-9][0-9]*|1.9*| \
85 1.8.[1-9][0-9]*|1.8.[3-9]|1.8.[3-9].*) :;;
87 isoldgit=1
88 esac
89 esac
90 esac
92 needsauth=1
93 service=
94 if [ -n "$REQUEST_URI" ]; then
95 # Try to detect whether or not it was something that needs auth
96 needsauth=
97 BASE="${REQUEST_URI%%[?]*}"
98 QS="${REQUEST_URI#$BASE}"
99 QS="${QS#[?]}"
100 case "$BASE" in
101 */info/refs)
102 case "&$QS&" in *"&service=git-receive-pack&"*)
103 service=git-receive-pack
104 needsauth=1
105 esac
107 */git-receive-pack)
108 service=git-receive-pack
109 needsauth=1
110 esac
112 [ -n "$needsauth" ] || notfound
114 # Return a text/plain response WITHOUT any additional parameters (such as
115 # charset=) so that the Git client will display the result.
117 # If AUTHREQUIRED_MESSAGE is set, that's inserted as an extra line
118 xmsg=
119 nl='
121 if [ -n "$AUTHREQUIRED_MESSAGE" ]; then
122 xmsg="$AUTHREQUIRED_MESSAGE$nl$nl"
125 # We need some config variables
126 . @basedir@/shlib.sh
128 message="\
129 ======================================================================
130 Authentication Required
131 ======================================================================
133 ${xmsg}In order to push using https, you must first
134 configure a user push certificate.
136 You may download a user push certificate from
137 the edit user page that may be accessed at:
139 $cfg_webadmurl/edituser.cgi
141 Instructions for configuring Git to use the
142 downloaded push certificate can be found at:
144 $cfg_htmlurl/httpspush.html
146 Do not forget to also configure the location
147 of your private key (see the above page).
149 ======================================================================
151 if [ -n "$isoldgit" ] && [ -n "$service" ]; then
152 l1=$(( 15 + ${#service} ))
153 l2=$(( 9 + ${#message} ))
154 headers 200 "application/x-$service-advertisement" \
155 "Content-Length: $(( $l1 + 4 + $l2 ))"
156 printf '%04x# service=%s\n0000%04xERR \n%s' $l1 "$service" \
157 $l2 "$message"
158 else
159 # IMPORTANT: Do NOT add any extra parameters here!
160 # Older Git clients cannot handle anything other than
161 # EXACTLY "text/plain"!
162 headers 403 "text/plain"
163 printf '%s' "$message"
165 exit 0