http transport: reset error message on cert failure Store the error message from the underlying TLS library before calling the certificate callback. If it refuses to act (demonstrated by returning GIT_PASSTHROUGH) then restore the error message. Otherwise, if the callback does not set an error message, set a sensible default that implicates the callback itself.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
diff --git a/src/transports/http.c b/src/transports/http.c
index 82ae77d..65b5f5f 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -692,25 +692,25 @@ static int check_certificate(
void *cert_cb_payload)
{
git_cert *cert;
+ git_error_state last_error = {0};
int error;
if ((error = git_stream_certificate(&cert, stream)) < 0)
return error;
- giterr_clear();
- error = cert_cb(cert, is_valid, url->host, cert_cb_payload);
+ giterr_state_capture(&last_error, GIT_ECERTIFICATE);
- if (error == GIT_PASSTHROUGH)
- error = is_valid ? 0 : GIT_ECERTIFICATE;
+ error = cert_cb(cert, is_valid, url->host, cert_cb_payload);
- if (error) {
- if (!giterr_last())
- giterr_set(GITERR_NET, "user cancelled certificate check");
+ if (error == GIT_PASSTHROUGH && !is_valid)
+ return giterr_state_restore(&last_error);
+ else if (error == GIT_PASSTHROUGH)
+ error = 0;
+ else if (error && !giterr_last())
+ giterr_set(GITERR_NET, "user rejected certificate for %s", url->host);
- return error;
- }
-
- return 0;
+ giterr_state_free(&last_error);
+ return error;
}
static int http_connect(http_subtransport *t)