Git fork

t5563: refactor for multi-stage authentication

Some HTTP authentication schemes, such as NTLM- and Kerberos-based
options, require more than one round trip to authenticate. Currently,
these can only be supported in libcurl, since Git does not have support
for this in the credential helper protocol.

However, in a future commit, we'll add support for this functionality
into the credential helper protocol and Git itself. Because we don't
really want to implement either NTLM or Kerberos, both of which are
complex protocols, we'll want to test this using a fake credential
authentication scheme. In order to do so, update t5563 and its backend
to allow us to accept multiple sets of credentials and respond with
different behavior in each case.

Since we can now provide any number of possible status codes, provide a
non-specific reason phrase so we don't have to generate a more specific
one based on the response. The reason phrase is mandatory according to
the status-line production in RFC 7230, but clients SHOULD ignore it,
and curl does (except to print it).

Each entry in the authorization and challenge fields contains an ID,
which indicates a corresponding credential and response. If the
response is a 200 status, then we continue to execute git-http-backend.
Otherwise, we print the corresponding status and response. If no ID is
matched, we use the default response with a status of 401.

Note that there is an implicit order to the parameters. The ID is
always first and the creds or response value is always last, and
therefore may contain spaces, equals signs, or other arbitrary data.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

brian m. carlson and committed by
Junio C Hamano
37417b77 bd590bde

+66 -47
+13 -4
t/lib-httpd/nph-custom-auth.sh
··· 19 19 # 20 20 21 21 if test -n "$HTTP_AUTHORIZATION" && \ 22 - grep -Fqsx "${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE" 22 + grep -Fqs "creds=${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE" 23 23 then 24 + idno=$(grep -F "creds=${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE" | sed -e 's/^id=\([a-z0-9-][a-z0-9-]*\) .*$/\1/') 25 + status=$(sed -ne "s/^id=$idno.*status=\\([0-9][0-9][0-9]\\).*\$/\\1/p" "$CHALLENGE_FILE" | head -n1) 24 26 # Note that although git-http-backend returns a status line, it 25 27 # does so using a CGI 'Status' header. Because this script is an 26 28 # No Parsed Headers (NPH) script, we must return a real HTTP 27 29 # status line. 28 30 # This is only a test script, so we don't bother to check for 29 31 # the actual status from git-http-backend and always return 200. 30 - echo 'HTTP/1.1 200 OK' 31 - exec "$GIT_EXEC_PATH"/git-http-backend 32 + echo "HTTP/1.1 $status Nonspecific Reason Phrase" 33 + if test "$status" -eq 200 34 + then 35 + exec "$GIT_EXEC_PATH"/git-http-backend 36 + else 37 + sed -ne "s/^id=$idno.*response=//p" "$CHALLENGE_FILE" 38 + echo 39 + exit 40 + fi 32 41 fi 33 42 34 43 echo 'HTTP/1.1 401 Authorization Required' 35 44 if test -f "$CHALLENGE_FILE" 36 45 then 37 - cat "$CHALLENGE_FILE" 46 + sed -ne 's/^id=default.*response=//p' "$CHALLENGE_FILE" 38 47 fi 39 48 echo
+53 -43
t/t5563-simple-http-auth.sh
··· 63 63 64 64 # Basic base64(alice:secret-passwd) 65 65 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 66 - Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 66 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 67 67 EOF 68 68 69 69 cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && 70 - WWW-Authenticate: Basic realm="example.com" 70 + id=1 status=200 71 + id=default response=WWW-Authenticate: Basic realm="example.com" 71 72 EOF 72 73 73 74 test_config_global credential.helper test-helper && ··· 100 101 101 102 # Basic base64(alice:secret-passwd) 102 103 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 103 - Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 104 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 104 105 EOF 105 106 106 107 cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && 107 - WWW-Authenticate: Basic realm="example.com" 108 + id=1 status=200 109 + id=default response=WWW-Authenticate: Basic realm="example.com" 108 110 EOF 109 111 110 112 test_config_global credential.helper test-helper && ··· 137 139 138 140 # Basic base64(alice:secret-passwd) 139 141 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 140 - Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 142 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 141 143 EOF 142 144 143 145 cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && 144 - WWW-Authenticate: Basic realm="example.com" 146 + id=1 status=200 147 + id=default response=WWW-Authenticate: Basic realm="example.com" 145 148 EOF 146 149 147 150 test_config_global credential.helper test-helper && ··· 174 177 175 178 # Basic base64(alice:secret-passwd) 176 179 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 177 - Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 180 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 178 181 EOF 179 182 180 183 cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && 181 - WWW-Authenticate: FooBar param1="value1" param2="value2" 182 - WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0 183 - WWW-Authenticate: Basic realm="example.com" 184 + id=1 status=200 185 + id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2" 186 + id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0 187 + id=default response=WWW-Authenticate: Basic realm="example.com" 184 188 EOF 185 189 186 190 test_config_global credential.helper test-helper && ··· 214 218 215 219 # Basic base64(alice:secret-passwd) 216 220 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 217 - Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 221 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 218 222 EOF 219 223 220 224 cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && 221 - www-authenticate: foobar param1="value1" param2="value2" 222 - WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0 223 - WwW-aUtHeNtIcAtE: baSiC realm="example.com" 225 + id=1 status=200 226 + id=default response=www-authenticate: foobar param1="value1" param2="value2" 227 + id=default response=WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0 228 + id=default response=WwW-aUtHeNtIcAtE: baSiC realm="example.com" 224 229 EOF 225 230 226 231 test_config_global credential.helper test-helper && ··· 254 259 255 260 # Basic base64(alice:secret-passwd) 256 261 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 257 - Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 262 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 258 263 EOF 259 264 260 265 # Note that leading and trailing whitespace is important to correctly 261 266 # simulate a continuation/folded header. 262 267 cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && 263 - WWW-Authenticate: FooBar param1="value1" 264 - param2="value2" 265 - WWW-Authenticate: Bearer authorize_uri="id.example.com" 266 - p=1 267 - q=0 268 - WWW-Authenticate: Basic realm="example.com" 268 + id=1 status=200 269 + id=default response=WWW-Authenticate: FooBar param1="value1" 270 + id=default response= param2="value2" 271 + id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" 272 + id=default response= p=1 273 + id=default response= q=0 274 + id=default response=WWW-Authenticate: Basic realm="example.com" 269 275 EOF 270 276 271 277 test_config_global credential.helper test-helper && ··· 299 305 300 306 # Basic base64(alice:secret-passwd) 301 307 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 302 - Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 308 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 303 309 EOF 304 310 305 311 CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" && 306 312 307 313 # Note that leading and trailing whitespace is important to correctly 308 314 # simulate a continuation/folded header. 309 - printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" && 310 - printf " \r\n" >>"$CHALLENGE" && 311 - printf " param2=\"value2\"\r\n" >>"$CHALLENGE" && 312 - printf "WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>"$CHALLENGE" && 313 - printf " p=1\r\n" >>"$CHALLENGE" && 314 - printf " \r\n" >>"$CHALLENGE" && 315 - printf " q=0\r\n" >>"$CHALLENGE" && 316 - printf "WWW-Authenticate: Basic realm=\"example.com\"\r\n" >>"$CHALLENGE" && 315 + printf "id=1 status=200\n" >"$CHALLENGE" && 316 + printf "id=default response=WWW-Authenticate: FooBar param1=\"value1\"\r\n" >>"$CHALLENGE" && 317 + printf "id=default response= \r\n" >>"$CHALLENGE" && 318 + printf "id=default response= param2=\"value2\"\r\n" >>"$CHALLENGE" && 319 + printf "id=default response=WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>"$CHALLENGE" && 320 + printf "id=default response= p=1\r\n" >>"$CHALLENGE" && 321 + printf "id=default response= \r\n" >>"$CHALLENGE" && 322 + printf "id=default response= q=0\r\n" >>"$CHALLENGE" && 323 + printf "id=default response=WWW-Authenticate: Basic realm=\"example.com\"\r\n" >>"$CHALLENGE" && 317 324 318 325 test_config_global credential.helper test-helper && 319 326 git ls-remote "$HTTPD_URL/custom_auth/repo.git" && ··· 346 353 347 354 # Basic base64(alice:secret-passwd) 348 355 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 349 - Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 356 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== 350 357 EOF 351 358 352 359 CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" && 353 360 354 361 # Note that leading and trailing whitespace is important to correctly 355 362 # simulate a continuation/folded header. 356 - printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" && 357 - printf " \r\n" >>"$CHALLENGE" && 358 - printf "\tparam2=\"value2\"\r\n" >>"$CHALLENGE" && 359 - printf "WWW-Authenticate: Basic realm=\"example.com\"" >>"$CHALLENGE" && 363 + printf "id=1 status=200\n" >"$CHALLENGE" && 364 + printf "id=default response=WWW-Authenticate: FooBar param1=\"value1\"\r\n" >>"$CHALLENGE" && 365 + printf "id=default response= \r\n" >>"$CHALLENGE" && 366 + printf "id=default response=\tparam2=\"value2\"\r\n" >>"$CHALLENGE" && 367 + printf "id=default response=WWW-Authenticate: Basic realm=\"example.com\"" >>"$CHALLENGE" && 360 368 361 369 test_config_global credential.helper test-helper && 362 370 git ls-remote "$HTTPD_URL/custom_auth/repo.git" && ··· 389 397 390 398 # Basic base64(a-git-token) 391 399 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 392 - Bearer YS1naXQtdG9rZW4= 400 + id=1 creds=Bearer YS1naXQtdG9rZW4= 393 401 EOF 394 402 395 403 CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" && 396 404 397 405 cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && 398 - WWW-Authenticate: FooBar param1="value1" param2="value2" 399 - WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0 400 - WWW-Authenticate: Basic realm="example.com" 406 + id=1 status=200 407 + id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2" 408 + id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0 409 + id=default response=WWW-Authenticate: Basic realm="example.com" 401 410 EOF 402 411 403 412 test_config_global credential.helper test-helper && ··· 433 442 434 443 # Basic base64(a-git-token) 435 444 cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && 436 - Bearer YS1naXQtdG9rZW4= 445 + id=1 creds=Bearer YS1naXQtdG9rZW4= 437 446 EOF 438 447 439 448 CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" && 440 449 441 450 cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && 442 - WWW-Authenticate: FooBar param1="value1" param2="value2" 443 - WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0 444 - WWW-Authenticate: Basic realm="example.com" 451 + id=1 status=200 452 + id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2" 453 + id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0 454 + id=default response=WWW-Authenticate: Basic realm="example.com" 445 455 EOF 446 456 447 457 test_config_global credential.helper test-helper &&