@@ -111,7 +111,8 @@ typedef struct {
111111 DWORD post_body_len ;
112112 unsigned sent_request : 1 ,
113113 received_response : 1 ,
114- chunked : 1 ;
114+ chunked : 1 ,
115+ status_sending_request_reached : 1 ;
115116} winhttp_stream ;
116117
117118typedef struct {
@@ -713,30 +714,36 @@ static void CALLBACK winhttp_status(
713714 DWORD status ;
714715
715716 GIT_UNUSED (connection );
716- GIT_UNUSED (ctx );
717717 GIT_UNUSED (info_len );
718718
719- if (code != WINHTTP_CALLBACK_STATUS_SECURE_FAILURE )
720- return ;
721-
722- status = * ((DWORD * )info );
723-
724- if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID ))
725- git_error_set (GIT_ERROR_HTTP , "SSL certificate issued for different common name" );
726- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID ))
727- git_error_set (GIT_ERROR_HTTP , "SSL certificate has expired" );
728- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA ))
729- git_error_set (GIT_ERROR_HTTP , "SSL certificate signed by unknown CA" );
730- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT ))
731- git_error_set (GIT_ERROR_HTTP , "SSL certificate is invalid" );
732- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED ))
733- git_error_set (GIT_ERROR_HTTP , "certificate revocation check failed" );
734- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED ))
735- git_error_set (GIT_ERROR_HTTP , "SSL certificate was revoked" );
736- else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR ))
737- git_error_set (GIT_ERROR_HTTP , "security libraries could not be loaded" );
738- else
739- git_error_set (GIT_ERROR_HTTP , "unknown security error %lu" , status );
719+ switch (code ) {
720+ case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE :
721+ status = * ((DWORD * )info );
722+
723+ if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID ))
724+ git_error_set (GIT_ERROR_HTTP , "SSL certificate issued for different common name" );
725+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID ))
726+ git_error_set (GIT_ERROR_HTTP , "SSL certificate has expired" );
727+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA ))
728+ git_error_set (GIT_ERROR_HTTP , "SSL certificate signed by unknown CA" );
729+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT ))
730+ git_error_set (GIT_ERROR_HTTP , "SSL certificate is invalid" );
731+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED ))
732+ git_error_set (GIT_ERROR_HTTP , "certificate revocation check failed" );
733+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED ))
734+ git_error_set (GIT_ERROR_HTTP , "SSL certificate was revoked" );
735+ else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR ))
736+ git_error_set (GIT_ERROR_HTTP , "security libraries could not be loaded" );
737+ else
738+ git_error_set (GIT_ERROR_HTTP , "unknown security error %lu" , status );
739+
740+ break ;
741+
742+ case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST :
743+ ((winhttp_stream * ) ctx )-> status_sending_request_reached = 1 ;
744+
745+ break ;
746+ }
740747}
741748
742749static int winhttp_connect (
@@ -836,7 +843,12 @@ static int winhttp_connect(
836843 goto on_error ;
837844 }
838845
839- if (WinHttpSetStatusCallback (t -> connection , winhttp_status , WINHTTP_CALLBACK_FLAG_SECURE_FAILURE , 0 ) == WINHTTP_INVALID_STATUS_CALLBACK ) {
846+ if (WinHttpSetStatusCallback (
847+ t -> connection ,
848+ winhttp_status ,
849+ WINHTTP_CALLBACK_FLAG_SECURE_FAILURE | WINHTTP_CALLBACK_FLAG_SEND_REQUEST ,
850+ 0
851+ ) == WINHTTP_INVALID_STATUS_CALLBACK ) {
840852 git_error_set (GIT_ERROR_OS , "failed to set status callback" );
841853 goto on_error ;
842854 }
@@ -869,12 +881,12 @@ static int do_send_request(winhttp_stream *s, size_t len, bool chunked)
869881 success = WinHttpSendRequest (s -> request ,
870882 WINHTTP_NO_ADDITIONAL_HEADERS , 0 ,
871883 WINHTTP_NO_REQUEST_DATA , 0 ,
872- WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH , 0 );
884+ WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH , ( DWORD_PTR ) s );
873885 } else {
874886 success = WinHttpSendRequest (s -> request ,
875887 WINHTTP_NO_ADDITIONAL_HEADERS , 0 ,
876888 WINHTTP_NO_REQUEST_DATA , 0 ,
877- (DWORD )len , 0 );
889+ (DWORD )len , ( DWORD_PTR ) s );
878890 }
879891
880892 if (success || GetLastError () != (DWORD )SEC_E_BUFFER_TOO_SMALL )
@@ -911,7 +923,13 @@ static int send_request(winhttp_stream *s, size_t len, bool chunked)
911923 }
912924 }
913925
914- if (!request_failed || !cert_valid ) {
926+ /*
927+ * Only check the certificate if we were able to reach the sending request phase, or
928+ * received a secure failure error. Otherwise, the server certificate won't be available
929+ * since the request wasn't able to complete (e.g. proxy auth required)
930+ */
931+ if (!cert_valid ||
932+ (!request_failed && s -> status_sending_request_reached )) {
915933 git_error_clear ();
916934 if ((error = certificate_check (s , cert_valid )) < 0 ) {
917935 if (!git_error_last ())
0 commit comments