Commit 2ce2315c by Edward Thomson

http transport: support cert check for proxies

Refactor certificate checking so that it can easily be called for
proxies or the remote server.
parent 74c6e08e
...@@ -636,14 +636,15 @@ static int write_chunk(git_stream *io, const char *buffer, size_t len) ...@@ -636,14 +636,15 @@ static int write_chunk(git_stream *io, const char *buffer, size_t len)
return 0; return 0;
} }
static int apply_proxy_config_to_stream(http_subtransport *t) static int apply_proxy_config_to_stream(
git_stream *stream, git_proxy_options *proxy_opts)
{ {
/* Only set the proxy configuration on the curl stream. */ /* Only set the proxy configuration on the curl stream. */
if (!git_stream_supports_proxy(t->server.stream) || if (!git_stream_supports_proxy(stream) ||
t->proxy_opts.type == GIT_PROXY_NONE) proxy_opts->type == GIT_PROXY_NONE)
return 0; return 0;
return git_stream_set_proxy(t->server.stream, &t->proxy_opts); return git_stream_set_proxy(stream, proxy_opts);
} }
static int load_proxy_config(http_subtransport *t) static int load_proxy_config(http_subtransport *t)
...@@ -683,9 +684,41 @@ static int load_proxy_config(http_subtransport *t) ...@@ -683,9 +684,41 @@ static int load_proxy_config(http_subtransport *t)
return gitno_connection_data_from_url(&t->proxy.url, t->proxy_opts.url, NULL); return gitno_connection_data_from_url(&t->proxy.url, t->proxy_opts.url, NULL);
} }
static int check_certificate(
git_stream *stream,
gitno_connection_data *url,
int is_valid,
git_transport_certificate_check_cb cert_cb,
void *cert_cb_payload)
{
git_cert *cert;
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);
if (error == GIT_PASSTHROUGH)
error = is_valid ? 0 : GIT_ECERTIFICATE;
if (error) {
if (!giterr_last())
giterr_set(GITERR_NET, "user cancelled certificate check");
return error;
}
return 0;
}
static int http_connect(http_subtransport *t) static int http_connect(http_subtransport *t)
{ {
gitno_connection_data *connection_url; gitno_connection_data *url;
git_stream *stream = NULL;
git_transport_certificate_check_cb cert_cb;
void *cb_payload;
int error; int error;
if (t->connected && if (t->connected &&
...@@ -700,58 +733,56 @@ static int http_connect(http_subtransport *t) ...@@ -700,58 +733,56 @@ static int http_connect(http_subtransport *t)
t->connected = 0; t->connected = 0;
} }
connection_url = (t->proxy_opts.type == GIT_PROXY_SPECIFIED) ? if (t->proxy_opts.type == GIT_PROXY_SPECIFIED) {
&t->proxy.url : &t->server.url; url = &t->proxy.url;
cert_cb = t->proxy_opts.certificate_check;
cb_payload = t->proxy_opts.payload;
} else {
url = &t->server.url;
cert_cb = t->owner->certificate_check_cb;
cb_payload = t->owner->message_cb_payload;
}
#ifdef GIT_CURL #ifdef GIT_CURL
error = git_curl_stream_new(&t->server.stream, error = git_curl_stream_new(&stream,
t->server.url.host, t->server.url.port); t->server.url.host, t->server.url.port);
#else #else
if (connection_url->use_ssl) if (url->use_ssl)
error = git_tls_stream_new(&t->server.stream, error = git_tls_stream_new(&stream, url->host, url->port);
connection_url->host, connection_url->port);
else else
error = git_socket_stream_new(&t->server.stream, error = git_socket_stream_new(&stream, url->host, url->port);
connection_url->host, connection_url->port);
#endif #endif
if (error < 0) if (error < 0)
return error; goto on_error;
GITERR_CHECK_VERSION(t->server.stream, GIT_STREAM_VERSION, "git_stream");
if ((error = apply_proxy_config_to_stream(t)) < 0) GITERR_CHECK_VERSION(stream, GIT_STREAM_VERSION, "git_stream");
return error;
error = git_stream_connect(t->server.stream); if ((error = apply_proxy_config_to_stream(stream, &t->proxy_opts)) < 0)
goto on_error;
if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL && error = git_stream_connect(stream);
git_stream_is_encrypted(t->server.stream)) {
git_cert *cert;
int is_valid = (error == GIT_OK);
if ((error = git_stream_certificate(&cert, t->server.stream)) < 0) if (error && error != GIT_ECERTIFICATE)
return error; goto on_error;
giterr_clear(); if (git_stream_is_encrypted(stream) && cert_cb != NULL)
error = t->owner->certificate_check_cb(cert, is_valid, t->server.url.host, t->owner->message_cb_payload); error = check_certificate(stream, url, !error, cert_cb, cb_payload);
if (error == GIT_PASSTHROUGH) if (error)
error = is_valid ? 0 : GIT_ECERTIFICATE; goto on_error;
if (error < 0) { t->server.stream = stream;
if (!giterr_last()) t->connected = 1;
giterr_set(GITERR_NET, "user cancelled certificate check"); return 0;
return error; on_error:
} if (stream) {
git_stream_close(stream);
git_stream_free(stream);
} }
if (error < 0) return error;
return error;
t->connected = 1;
return 0;
} }
static int http_stream_read( static int http_stream_read(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment