Skip to content

Commit 9b51cc8

Browse files
authored
Merge pull request libgit2#4050 from ethomson/ethomson/winhttp_errmsgs
WinHTTP: set proper error messages when SSL fails
2 parents 1196807 + 1910a04 commit 9b51cc8

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

src/transports/winhttp.c

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,12 @@ static int certificate_check(winhttp_stream *s, int valid)
242242
git_cert_x509 cert;
243243

244244
/* If there is no override, we should fail if WinHTTP doesn't think it's fine */
245-
if (t->owner->certificate_check_cb == NULL && !valid)
245+
if (t->owner->certificate_check_cb == NULL && !valid) {
246+
if (!giterr_last())
247+
giterr_set(GITERR_NET, "unknown certificate check failure");
248+
246249
return GIT_ECERTIFICATE;
250+
}
247251

248252
if (t->owner->certificate_check_cb == NULL || !t->connection_data.use_ssl)
249253
return 0;
@@ -691,6 +695,38 @@ static int user_agent(git_buf *ua)
691695
return git_buf_putc(ua, ')');
692696
}
693697

698+
static void CALLBACK winhttp_status(
699+
HINTERNET connection,
700+
DWORD_PTR ctx,
701+
DWORD code,
702+
LPVOID info,
703+
DWORD info_len)
704+
{
705+
DWORD status;
706+
707+
if (code != WINHTTP_CALLBACK_STATUS_SECURE_FAILURE)
708+
return;
709+
710+
status = *((DWORD *)info);
711+
712+
if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID))
713+
giterr_set(GITERR_NET, "SSL certificate issued for different common name");
714+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID))
715+
giterr_set(GITERR_NET, "SSL certificate has expired");
716+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA))
717+
giterr_set(GITERR_NET, "SSL certificate signed by unknown CA");
718+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT))
719+
giterr_set(GITERR_NET, "SSL certificate is invalid");
720+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED))
721+
giterr_set(GITERR_NET, "certificate revocation check failed");
722+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED))
723+
giterr_set(GITERR_NET, "SSL certificate was revoked");
724+
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR))
725+
giterr_set(GITERR_NET, "security libraries could not be loaded");
726+
else
727+
giterr_set(GITERR_NET, "unknown security error %d", status);
728+
}
729+
694730
static int winhttp_connect(
695731
winhttp_subtransport *t)
696732
{
@@ -760,6 +796,11 @@ static int winhttp_connect(
760796
goto on_error;
761797
}
762798

799+
if (WinHttpSetStatusCallback(t->connection, winhttp_status, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0) == WINHTTP_INVALID_STATUS_CALLBACK) {
800+
giterr_set(GITERR_OS, "failed to set status callback");
801+
goto on_error;
802+
}
803+
763804
error = 0;
764805

765806
on_error:
@@ -798,16 +839,15 @@ static int send_request(winhttp_stream *s, size_t len, int ignore_length)
798839
int request_failed = 0, cert_valid = 1, error = 0;
799840
DWORD ignore_flags;
800841

801-
if ((error = do_send_request(s, len, ignore_length)) < 0)
802-
request_failed = 1;
803-
804-
if (request_failed) {
842+
giterr_clear();
843+
if ((error = do_send_request(s, len, ignore_length)) < 0) {
805844
if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) {
806845
giterr_set(GITERR_OS, "failed to send request");
807846
return -1;
808-
} else {
809-
cert_valid = 0;
810847
}
848+
849+
request_failed = 1;
850+
cert_valid = 0;
811851
}
812852

813853
giterr_clear();

0 commit comments

Comments
 (0)