Skip to content

Commit 2ce2315

Browse files
committed
http transport: support cert check for proxies
Refactor certificate checking so that it can easily be called for proxies or the remote server.
1 parent 74c6e08 commit 2ce2315

File tree

1 file changed

+70
-39
lines changed

1 file changed

+70
-39
lines changed

src/transports/http.c

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -636,14 +636,15 @@ static int write_chunk(git_stream *io, const char *buffer, size_t len)
636636
return 0;
637637
}
638638

639-
static int apply_proxy_config_to_stream(http_subtransport *t)
639+
static int apply_proxy_config_to_stream(
640+
git_stream *stream, git_proxy_options *proxy_opts)
640641
{
641642
/* Only set the proxy configuration on the curl stream. */
642-
if (!git_stream_supports_proxy(t->server.stream) ||
643-
t->proxy_opts.type == GIT_PROXY_NONE)
643+
if (!git_stream_supports_proxy(stream) ||
644+
proxy_opts->type == GIT_PROXY_NONE)
644645
return 0;
645646

646-
return git_stream_set_proxy(t->server.stream, &t->proxy_opts);
647+
return git_stream_set_proxy(stream, proxy_opts);
647648
}
648649

649650
static int load_proxy_config(http_subtransport *t)
@@ -683,9 +684,41 @@ static int load_proxy_config(http_subtransport *t)
683684
return gitno_connection_data_from_url(&t->proxy.url, t->proxy_opts.url, NULL);
684685
}
685686

687+
static int check_certificate(
688+
git_stream *stream,
689+
gitno_connection_data *url,
690+
int is_valid,
691+
git_transport_certificate_check_cb cert_cb,
692+
void *cert_cb_payload)
693+
{
694+
git_cert *cert;
695+
int error;
696+
697+
if ((error = git_stream_certificate(&cert, stream)) < 0)
698+
return error;
699+
700+
giterr_clear();
701+
error = cert_cb(cert, is_valid, url->host, cert_cb_payload);
702+
703+
if (error == GIT_PASSTHROUGH)
704+
error = is_valid ? 0 : GIT_ECERTIFICATE;
705+
706+
if (error) {
707+
if (!giterr_last())
708+
giterr_set(GITERR_NET, "user cancelled certificate check");
709+
710+
return error;
711+
}
712+
713+
return 0;
714+
}
715+
686716
static int http_connect(http_subtransport *t)
687717
{
688-
gitno_connection_data *connection_url;
718+
gitno_connection_data *url;
719+
git_stream *stream = NULL;
720+
git_transport_certificate_check_cb cert_cb;
721+
void *cb_payload;
689722
int error;
690723

691724
if (t->connected &&
@@ -700,58 +733,56 @@ static int http_connect(http_subtransport *t)
700733
t->connected = 0;
701734
}
702735

703-
connection_url = (t->proxy_opts.type == GIT_PROXY_SPECIFIED) ?
704-
&t->proxy.url : &t->server.url;
736+
if (t->proxy_opts.type == GIT_PROXY_SPECIFIED) {
737+
url = &t->proxy.url;
738+
cert_cb = t->proxy_opts.certificate_check;
739+
cb_payload = t->proxy_opts.payload;
740+
} else {
741+
url = &t->server.url;
742+
cert_cb = t->owner->certificate_check_cb;
743+
cb_payload = t->owner->message_cb_payload;
744+
}
705745

706746
#ifdef GIT_CURL
707-
error = git_curl_stream_new(&t->server.stream,
747+
error = git_curl_stream_new(&stream,
708748
t->server.url.host, t->server.url.port);
709749
#else
710-
if (connection_url->use_ssl)
711-
error = git_tls_stream_new(&t->server.stream,
712-
connection_url->host, connection_url->port);
750+
if (url->use_ssl)
751+
error = git_tls_stream_new(&stream, url->host, url->port);
713752
else
714-
error = git_socket_stream_new(&t->server.stream,
715-
connection_url->host, connection_url->port);
753+
error = git_socket_stream_new(&stream, url->host, url->port);
716754
#endif
717755

718756
if (error < 0)
719-
return error;
720-
721-
GITERR_CHECK_VERSION(t->server.stream, GIT_STREAM_VERSION, "git_stream");
757+
goto on_error;
722758

723-
if ((error = apply_proxy_config_to_stream(t)) < 0)
724-
return error;
759+
GITERR_CHECK_VERSION(stream, GIT_STREAM_VERSION, "git_stream");
725760

726-
error = git_stream_connect(t->server.stream);
761+
if ((error = apply_proxy_config_to_stream(stream, &t->proxy_opts)) < 0)
762+
goto on_error;
727763

728-
if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL &&
729-
git_stream_is_encrypted(t->server.stream)) {
730-
git_cert *cert;
731-
int is_valid = (error == GIT_OK);
764+
error = git_stream_connect(stream);
732765

733-
if ((error = git_stream_certificate(&cert, t->server.stream)) < 0)
734-
return error;
766+
if (error && error != GIT_ECERTIFICATE)
767+
goto on_error;
735768

736-
giterr_clear();
737-
error = t->owner->certificate_check_cb(cert, is_valid, t->server.url.host, t->owner->message_cb_payload);
769+
if (git_stream_is_encrypted(stream) && cert_cb != NULL)
770+
error = check_certificate(stream, url, !error, cert_cb, cb_payload);
738771

739-
if (error == GIT_PASSTHROUGH)
740-
error = is_valid ? 0 : GIT_ECERTIFICATE;
772+
if (error)
773+
goto on_error;
741774

742-
if (error < 0) {
743-
if (!giterr_last())
744-
giterr_set(GITERR_NET, "user cancelled certificate check");
775+
t->server.stream = stream;
776+
t->connected = 1;
777+
return 0;
745778

746-
return error;
747-
}
779+
on_error:
780+
if (stream) {
781+
git_stream_close(stream);
782+
git_stream_free(stream);
748783
}
749784

750-
if (error < 0)
751-
return error;
752-
753-
t->connected = 1;
754-
return 0;
785+
return error;
755786
}
756787

757788
static int http_stream_read(

0 commit comments

Comments
 (0)