t5563: add tests for http.emptyAuth with Negotiate

Add tests exercising the interaction between http.emptyAuth and servers that advertise Negotiate (SPNEGO) authentication. Verify that auto mode gives Negotiate a chance via empty auth (resulting in two 401 responses before falling through to credential_fill with Basic credentials), and that false mode strips Negotiate immediately (only one 401 response). Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Matthew John Cheetham committed Apr 16, 2026 at 09:20 UTC 9b1630b97273beceb64ea8f740c5820317aaa8b3
1 file changed +74
t/t5563-simple-http-auth.sh
+74
@@ -719,4 +719,78 @@ test_expect_success 'access using three-legged auth' '
719 EOF
720 '
721
722 +test_lazy_prereq SPNEGO 'curl --version | grep -qi "SPNEGO\|GSS-API\|Kerberos\|negotiate"'
723 +
724 +test_expect_success SPNEGO 'http.emptyAuth=auto attempts Negotiate before credential_fill' '
725 + test_when_finished "per_test_cleanup" &&
726 +
727 + set_credential_reply get <<-EOF &&
728 + username=alice
729 + password=secret-passwd
730 + EOF
731 +
732 + # Basic base64(alice:secret-passwd)
733 + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
734 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
735 + EOF
736 +
737 + cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
738 + id=1 status=200
739 + id=default response=WWW-Authenticate: Negotiate
740 + id=default response=WWW-Authenticate: Basic realm="example.com"
741 + EOF
742 +
743 + test_config_global credential.helper test-helper &&
744 + GIT_TRACE_CURL="$TRASH_DIRECTORY/trace-auto" \
745 + git -c http.emptyAuth=auto \
746 + ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
747 +
748 + # In auto mode with a Negotiate+Basic server, there should be
749 + # three 401 responses: (1) initial no-auth request, (2) empty-auth
750 + # retry where Negotiate fails (no Kerberos ticket), (3) libcurl
751 + # internal Negotiate retry. The fourth attempt uses Basic
752 + # credentials from credential_fill and succeeds.
753 + grep "HTTP/[0-9.]* 401" "$TRASH_DIRECTORY/trace-auto" >actual_401s &&
754 + test_line_count = 3 actual_401s &&
755 +
756 + expect_credential_query get <<-EOF
757 + capability[]=authtype
758 + capability[]=state
759 + protocol=http
760 + host=$HTTPD_DEST
761 + wwwauth[]=Negotiate
762 + wwwauth[]=Basic realm="example.com"
763 + EOF
764 +'
765 +
766 +test_expect_success SPNEGO 'http.emptyAuth=false skips Negotiate' '
767 + test_when_finished "per_test_cleanup" &&
768 +
769 + set_credential_reply get <<-EOF &&
770 + username=alice
771 + password=secret-passwd
772 + EOF
773 +
774 + # Basic base64(alice:secret-passwd)
775 + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
776 + id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
777 + EOF
778 +
779 + cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
780 + id=1 status=200
781 + id=default response=WWW-Authenticate: Negotiate
782 + id=default response=WWW-Authenticate: Basic realm="example.com"
783 + EOF
784 +
785 + test_config_global credential.helper test-helper &&
786 + GIT_TRACE_CURL="$TRASH_DIRECTORY/trace-false" \
787 + git -c http.emptyAuth=false \
788 + ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
789 +
790 + # With emptyAuth=false, Negotiate is stripped immediately and
791 + # credential_fill is called right away. Only one 401 response.
792 + grep "HTTP/[0-9.]* 401" "$TRASH_DIRECTORY/trace-false" >actual_401s &&
793 + test_line_count = 1 actual_401s
794 +'
795 +
796 test_done