 5f2117b24f
			
		
	
	5f2117b24f
	
	
	
		
			
			Add the value of the WWW-Authenticate response header to credential requests. Credential helpers that understand and support HTTP authentication and authorization can use this standard header (RFC 2616 Section 14.47 [1]) to generate valid credentials. WWW-Authenticate headers can contain information pertaining to the authority, authentication mechanism, or extra parameters/scopes that are required. The current I/O format for credential helpers only allows for unique names for properties/attributes, so in order to transmit multiple header values (with a specific order) we introduce a new convention whereby a C-style array syntax is used in the property name to denote multiple ordered values for the same property. In this case we send multiple `wwwauth[]` properties where the order that the repeated attributes appear in the conversation reflects the order that the WWW-Authenticate headers appeared in the HTTP response. Add a set of tests to exercise the HTTP authentication header parsing and the interop with credential helpers. Credential helpers will receive WWW-Authenticate information in credential requests. [1] https://datatracker.ietf.org/doc/html/rfc2616#section-14.47 Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
		
			
				
	
	
		
			326 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			326 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/sh
 | |
| 
 | |
| test_description='test http auth header and credential helper interop'
 | |
| 
 | |
| . ./test-lib.sh
 | |
| . "$TEST_DIRECTORY"/lib-httpd.sh
 | |
| 
 | |
| start_httpd
 | |
| 
 | |
| test_expect_success 'setup_credential_helper' '
 | |
| 	mkdir "$TRASH_DIRECTORY/bin" &&
 | |
| 	PATH=$PATH:"$TRASH_DIRECTORY/bin" &&
 | |
| 	export PATH &&
 | |
| 
 | |
| 	CREDENTIAL_HELPER="$TRASH_DIRECTORY/bin/git-credential-test-helper" &&
 | |
| 	write_script "$CREDENTIAL_HELPER" <<-\EOF
 | |
| 	cmd=$1
 | |
| 	teefile=$cmd-query.cred
 | |
| 	catfile=$cmd-reply.cred
 | |
| 	sed -n -e "/^$/q" -e "p" >>$teefile
 | |
| 	if test "$cmd" = "get"
 | |
| 	then
 | |
| 		cat $catfile
 | |
| 	fi
 | |
| 	EOF
 | |
| '
 | |
| 
 | |
| set_credential_reply () {
 | |
| 	cat >"$TRASH_DIRECTORY/$1-reply.cred"
 | |
| }
 | |
| 
 | |
| expect_credential_query () {
 | |
| 	cat >"$TRASH_DIRECTORY/$1-expect.cred" &&
 | |
| 	test_cmp "$TRASH_DIRECTORY/$1-expect.cred" \
 | |
| 		 "$TRASH_DIRECTORY/$1-query.cred"
 | |
| }
 | |
| 
 | |
| per_test_cleanup () {
 | |
| 	rm -f *.cred &&
 | |
| 	rm -f "$HTTPD_ROOT_PATH"/custom-auth.valid \
 | |
| 	      "$HTTPD_ROOT_PATH"/custom-auth.challenge
 | |
| }
 | |
| 
 | |
| test_expect_success 'setup repository' '
 | |
| 	test_commit foo &&
 | |
| 	git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
 | |
| 	git push --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git"
 | |
| '
 | |
| 
 | |
| test_expect_success 'access using basic auth' '
 | |
| 	test_when_finished "per_test_cleanup" &&
 | |
| 
 | |
| 	set_credential_reply get <<-EOF &&
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| 
 | |
| 	# Basic base64(alice:secret-passwd)
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
 | |
| 	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
 | |
| 	EOF
 | |
| 
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
 | |
| 	WWW-Authenticate: Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	test_config_global credential.helper test-helper &&
 | |
| 	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
 | |
| 
 | |
| 	expect_credential_query get <<-EOF &&
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	wwwauth[]=Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	expect_credential_query store <<-EOF
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| '
 | |
| 
 | |
| test_expect_success 'access using basic auth invalid credentials' '
 | |
| 	test_when_finished "per_test_cleanup" &&
 | |
| 
 | |
| 	set_credential_reply get <<-EOF &&
 | |
| 	username=baduser
 | |
| 	password=wrong-passwd
 | |
| 	EOF
 | |
| 
 | |
| 	# Basic base64(alice:secret-passwd)
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
 | |
| 	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
 | |
| 	EOF
 | |
| 
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
 | |
| 	WWW-Authenticate: Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	test_config_global credential.helper test-helper &&
 | |
| 	test_must_fail git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
 | |
| 
 | |
| 	expect_credential_query get <<-EOF &&
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	wwwauth[]=Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	expect_credential_query erase <<-EOF
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	username=baduser
 | |
| 	password=wrong-passwd
 | |
| 	wwwauth[]=Basic realm="example.com"
 | |
| 	EOF
 | |
| '
 | |
| 
 | |
| test_expect_success 'access using basic auth with extra challenges' '
 | |
| 	test_when_finished "per_test_cleanup" &&
 | |
| 
 | |
| 	set_credential_reply get <<-EOF &&
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| 
 | |
| 	# Basic base64(alice:secret-passwd)
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
 | |
| 	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
 | |
| 	EOF
 | |
| 
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
 | |
| 	WWW-Authenticate: FooBar param1="value1" param2="value2"
 | |
| 	WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
 | |
| 	WWW-Authenticate: Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	test_config_global credential.helper test-helper &&
 | |
| 	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
 | |
| 
 | |
| 	expect_credential_query get <<-EOF &&
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	wwwauth[]=FooBar param1="value1" param2="value2"
 | |
| 	wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
 | |
| 	wwwauth[]=Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	expect_credential_query store <<-EOF
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| '
 | |
| 
 | |
| test_expect_success 'access using basic auth mixed-case wwwauth header name' '
 | |
| 	test_when_finished "per_test_cleanup" &&
 | |
| 
 | |
| 	set_credential_reply get <<-EOF &&
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| 
 | |
| 	# Basic base64(alice:secret-passwd)
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
 | |
| 	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
 | |
| 	EOF
 | |
| 
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
 | |
| 	www-authenticate: foobar param1="value1" param2="value2"
 | |
| 	WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0
 | |
| 	WwW-aUtHeNtIcAtE: baSiC realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	test_config_global credential.helper test-helper &&
 | |
| 	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
 | |
| 
 | |
| 	expect_credential_query get <<-EOF &&
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	wwwauth[]=foobar param1="value1" param2="value2"
 | |
| 	wwwauth[]=BEARER authorize_uri="id.example.com" p=1 q=0
 | |
| 	wwwauth[]=baSiC realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	expect_credential_query store <<-EOF
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| '
 | |
| 
 | |
| test_expect_success 'access using basic auth with wwwauth header continuations' '
 | |
| 	test_when_finished "per_test_cleanup" &&
 | |
| 
 | |
| 	set_credential_reply get <<-EOF &&
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| 
 | |
| 	# Basic base64(alice:secret-passwd)
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
 | |
| 	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
 | |
| 	EOF
 | |
| 
 | |
| 	# Note that leading and trailing whitespace is important to correctly
 | |
| 	# simulate a continuation/folded header.
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
 | |
| 	WWW-Authenticate: FooBar param1="value1"
 | |
| 	 param2="value2"
 | |
| 	WWW-Authenticate: Bearer authorize_uri="id.example.com"
 | |
| 	 p=1
 | |
| 	 q=0
 | |
| 	WWW-Authenticate: Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	test_config_global credential.helper test-helper &&
 | |
| 	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
 | |
| 
 | |
| 	expect_credential_query get <<-EOF &&
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	wwwauth[]=FooBar param1="value1" param2="value2"
 | |
| 	wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
 | |
| 	wwwauth[]=Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	expect_credential_query store <<-EOF
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| '
 | |
| 
 | |
| test_expect_success 'access using basic auth with wwwauth header empty continuations' '
 | |
| 	test_when_finished "per_test_cleanup" &&
 | |
| 
 | |
| 	set_credential_reply get <<-EOF &&
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| 
 | |
| 	# Basic base64(alice:secret-passwd)
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
 | |
| 	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
 | |
| 	EOF
 | |
| 
 | |
| 	CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
 | |
| 
 | |
| 	# Note that leading and trailing whitespace is important to correctly
 | |
| 	# simulate a continuation/folded header.
 | |
| 	printf "">$CHALLENGE &&
 | |
| 	printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >$CHALLENGE &&
 | |
| 	printf " \r\n" >>$CHALLENGE &&
 | |
| 	printf " param2=\"value2\"\r\n" >>$CHALLENGE &&
 | |
| 	printf "WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>$CHALLENGE &&
 | |
| 	printf " p=1\r\n" >>$CHALLENGE &&
 | |
| 	printf " \r\n" >>$CHALLENGE &&
 | |
| 	printf " q=0\r\n" >>$CHALLENGE &&
 | |
| 	printf "WWW-Authenticate: Basic realm=\"example.com\"\r\n" >>$CHALLENGE &&
 | |
| 
 | |
| 	test_config_global credential.helper test-helper &&
 | |
| 	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
 | |
| 
 | |
| 	expect_credential_query get <<-EOF &&
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	wwwauth[]=FooBar param1="value1" param2="value2"
 | |
| 	wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
 | |
| 	wwwauth[]=Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	expect_credential_query store <<-EOF
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| '
 | |
| 
 | |
| test_expect_success 'access using basic auth with wwwauth header mixed line-endings' '
 | |
| 	test_when_finished "per_test_cleanup" &&
 | |
| 
 | |
| 	set_credential_reply get <<-EOF &&
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| 
 | |
| 	# Basic base64(alice:secret-passwd)
 | |
| 	cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
 | |
| 	Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
 | |
| 	EOF
 | |
| 
 | |
| 	CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
 | |
| 
 | |
| 	# Note that leading and trailing whitespace is important to correctly
 | |
| 	# simulate a continuation/folded header.
 | |
| 	printf "">$CHALLENGE &&
 | |
| 	printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >$CHALLENGE &&
 | |
| 	printf " \r\n" >>$CHALLENGE &&
 | |
| 	printf "\tparam2=\"value2\"\r\n" >>$CHALLENGE &&
 | |
| 	printf "WWW-Authenticate: Basic realm=\"example.com\"" >>$CHALLENGE &&
 | |
| 
 | |
| 	test_config_global credential.helper test-helper &&
 | |
| 	git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
 | |
| 
 | |
| 	expect_credential_query get <<-EOF &&
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	wwwauth[]=FooBar param1="value1" param2="value2"
 | |
| 	wwwauth[]=Basic realm="example.com"
 | |
| 	EOF
 | |
| 
 | |
| 	expect_credential_query store <<-EOF
 | |
| 	protocol=http
 | |
| 	host=$HTTPD_DEST
 | |
| 	username=alice
 | |
| 	password=secret-passwd
 | |
| 	EOF
 | |
| '
 | |
| 
 | |
| test_done
 |