mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-22 06:26:26 +00:00
tls: introduce a wrap function
Introduce `git_tls_stream_wrap` which will take an existing `stream` with an already connected socket and begin speaking TLS on top of it. This is useful if you've built a connection to a proxy server and you wish to begin CONNECT over it to tunnel a TLS connection. Also update the pluggable TLS stream layer so that it can accept a registration structure that provides an `init` and `wrap` function, instead of a single initialization function.
This commit is contained in:
@@ -40,18 +40,48 @@ typedef struct git_stream {
|
||||
void (*free)(struct git_stream *);
|
||||
} git_stream;
|
||||
|
||||
typedef int (*git_stream_cb)(git_stream **out, const char *host, const char *port);
|
||||
typedef struct {
|
||||
/** The `version` field should be set to `GIT_STREAM_VERSION`. */
|
||||
int version;
|
||||
|
||||
/**
|
||||
* Called to create a new TLS connection to a given host.
|
||||
*
|
||||
* @param out The created TLS stream
|
||||
* @param host The hostname to connect to; may be a hostname or
|
||||
* IP address
|
||||
* @param port The port to connect to; may be a port number or
|
||||
* service name
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
int (*init)(git_stream **out, const char *host, const char *port);
|
||||
|
||||
/**
|
||||
* Called to create a new TLS connection on top of the given
|
||||
* stream. May be used to proxy a TLS stream over a CONNECT
|
||||
* session.
|
||||
*
|
||||
* @param out The created TLS stream
|
||||
* @param in An existing stream to add TLS to
|
||||
* @param host The hostname that the stream is connected to,
|
||||
* for certificate validation
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
int (*wrap)(git_stream **out, git_stream *in, const char *host);
|
||||
} git_stream_registration;
|
||||
|
||||
/**
|
||||
* Register a TLS stream constructor for the library to use
|
||||
* Register TLS stream constructors for the library to use
|
||||
*
|
||||
* If a constructor is already set, it will be overwritten. Pass
|
||||
* `NULL` in order to deregister the current constructor.
|
||||
* If a registration structure is already set, it will be overwritten.
|
||||
* Pass `NULL` in order to deregister the current constructor and return
|
||||
* to the system defaults.
|
||||
*
|
||||
* @param ctor the constructor to use
|
||||
* @param registration the registration data
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_stream_register_tls(git_stream_cb ctor);
|
||||
GIT_EXTERN(int) git_stream_register_tls(
|
||||
git_stream_registration *registration);
|
||||
|
||||
GIT_END_DECL
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "sysdir.h"
|
||||
#include "filter.h"
|
||||
#include "merge_driver.h"
|
||||
#include "streams/tls.h"
|
||||
#include "streams/curl.h"
|
||||
#include "streams/mbedtls.h"
|
||||
#include "streams/openssl.h"
|
||||
@@ -67,6 +68,7 @@ static int init_common(void)
|
||||
(ret = git_filter_global_init()) == 0 &&
|
||||
(ret = git_merge_driver_global_init()) == 0 &&
|
||||
(ret = git_transport_ssh_global_init()) == 0 &&
|
||||
(ret = git_tls_stream_global_init()) == 0 &&
|
||||
(ret = git_openssl_stream_global_init()) == 0 &&
|
||||
(ret = git_curl_stream_global_init()) == 0 &&
|
||||
(ret = git_mbedtls_stream_global_init()) == 0)
|
||||
|
||||
@@ -242,6 +242,7 @@ static int verify_server_cert(mbedtls_ssl_context *ssl)
|
||||
typedef struct {
|
||||
git_stream parent;
|
||||
git_stream *io;
|
||||
int owned;
|
||||
bool connected;
|
||||
char *host;
|
||||
mbedtls_ssl_context *ssl;
|
||||
@@ -254,7 +255,7 @@ int mbedtls_connect(git_stream *stream)
|
||||
int ret;
|
||||
mbedtls_stream *st = (mbedtls_stream *) stream;
|
||||
|
||||
if ((ret = git_stream_connect(st->io)) < 0)
|
||||
if (st->owned && (ret = git_stream_connect(st->io)) < 0)
|
||||
return ret;
|
||||
|
||||
st->connected = true;
|
||||
@@ -345,37 +346,37 @@ int mbedtls_stream_close(git_stream *stream)
|
||||
|
||||
st->connected = false;
|
||||
|
||||
return git_stream_close(st->io);
|
||||
return st->owned ? git_stream_close(st->io) : 0;
|
||||
}
|
||||
|
||||
void mbedtls_stream_free(git_stream *stream)
|
||||
{
|
||||
mbedtls_stream *st = (mbedtls_stream *) stream;
|
||||
|
||||
if (st->owned)
|
||||
git_stream_free(st->io);
|
||||
|
||||
git__free(st->host);
|
||||
git__free(st->cert_info.data);
|
||||
git_stream_free(st->io);
|
||||
mbedtls_ssl_free(st->ssl);
|
||||
git__free(st->ssl);
|
||||
git__free(st);
|
||||
}
|
||||
|
||||
int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
|
||||
static int mbedtls_stream_wrap(
|
||||
git_stream **out,
|
||||
git_stream *in,
|
||||
const char *host,
|
||||
int owned)
|
||||
{
|
||||
int error;
|
||||
mbedtls_stream *st;
|
||||
int error;
|
||||
|
||||
st = git__calloc(1, sizeof(mbedtls_stream));
|
||||
GITERR_CHECK_ALLOC(st);
|
||||
|
||||
#ifdef GIT_CURL
|
||||
error = git_curl_stream_new(&st->io, host, port);
|
||||
#else
|
||||
error = git_socket_stream_new(&st->io, host, port);
|
||||
#endif
|
||||
|
||||
if (error < 0)
|
||||
goto out_err;
|
||||
st->io = in;
|
||||
st->owned = owned;
|
||||
|
||||
st->ssl = git__malloc(sizeof(mbedtls_ssl_context));
|
||||
GITERR_CHECK_ALLOC(st->ssl);
|
||||
@@ -405,12 +406,48 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
|
||||
|
||||
out_err:
|
||||
mbedtls_ssl_free(st->ssl);
|
||||
git_stream_close(st->io);
|
||||
git_stream_free(st->io);
|
||||
git__free(st);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_mbedtls_stream_wrap(
|
||||
git_stream **out,
|
||||
git_stream *in,
|
||||
const char *host)
|
||||
{
|
||||
return mbedtls_stream_wrap(out, in, host, 0);
|
||||
}
|
||||
|
||||
int git_mbedtls_stream_new(
|
||||
git_stream **out,
|
||||
const char *host,
|
||||
const char *port)
|
||||
{
|
||||
git_stream *stream;
|
||||
int error;
|
||||
|
||||
assert(out && host && port);
|
||||
|
||||
#ifdef GIT_CURL
|
||||
error = git_curl_stream_new(&stream, host, port);
|
||||
#else
|
||||
error = git_socket_stream_new(&stream, host, port);
|
||||
#endif
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if ((error = mbedtls_stream_wrap(out, stream, host, 1)) < 0) {
|
||||
git_stream_close(stream);
|
||||
git_stream_free(stream);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_mbedtls__set_cert_location(const char *path, int is_dir)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
extern int git_mbedtls_stream_global_init(void);
|
||||
|
||||
extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port);
|
||||
extern int git_mbedtls_stream_wrap(git_stream **out, git_stream *in, const char *host);
|
||||
|
||||
extern int git_mbedtls__set_cert_location(const char *path, int is_dir);
|
||||
|
||||
|
||||
@@ -569,6 +569,7 @@ cleanup:
|
||||
typedef struct {
|
||||
git_stream parent;
|
||||
git_stream *io;
|
||||
int owned;
|
||||
bool connected;
|
||||
char *host;
|
||||
SSL *ssl;
|
||||
@@ -583,7 +584,7 @@ int openssl_connect(git_stream *stream)
|
||||
BIO *bio;
|
||||
openssl_stream *st = (openssl_stream *) stream;
|
||||
|
||||
if ((ret = git_stream_connect(st->io)) < 0)
|
||||
if (st->owned && (ret = git_stream_connect(st->io)) < 0)
|
||||
return ret;
|
||||
|
||||
bio = BIO_new(git_stream_bio_method);
|
||||
@@ -682,43 +683,43 @@ int openssl_close(git_stream *stream)
|
||||
|
||||
st->connected = false;
|
||||
|
||||
return git_stream_close(st->io);
|
||||
return st->owned ? git_stream_close(st->io) : 0;
|
||||
}
|
||||
|
||||
void openssl_free(git_stream *stream)
|
||||
{
|
||||
openssl_stream *st = (openssl_stream *) stream;
|
||||
|
||||
if (st->owned)
|
||||
git_stream_free(st->io);
|
||||
|
||||
SSL_free(st->ssl);
|
||||
git__free(st->host);
|
||||
git__free(st->cert_info.data);
|
||||
git_stream_free(st->io);
|
||||
git__free(st);
|
||||
}
|
||||
|
||||
int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
|
||||
static int openssl_stream_wrap(
|
||||
git_stream **out,
|
||||
git_stream *in,
|
||||
const char *host,
|
||||
int owned)
|
||||
{
|
||||
int error;
|
||||
openssl_stream *st;
|
||||
|
||||
assert(out && in && host);
|
||||
|
||||
st = git__calloc(1, sizeof(openssl_stream));
|
||||
GITERR_CHECK_ALLOC(st);
|
||||
|
||||
st->io = NULL;
|
||||
#ifdef GIT_CURL
|
||||
error = git_curl_stream_new(&st->io, host, port);
|
||||
#else
|
||||
error = git_socket_stream_new(&st->io, host, port);
|
||||
#endif
|
||||
|
||||
if (error < 0)
|
||||
goto out_err;
|
||||
st->io = in;
|
||||
st->owned = owned;
|
||||
|
||||
st->ssl = SSL_new(git__ssl_ctx);
|
||||
if (st->ssl == NULL) {
|
||||
giterr_set(GITERR_SSL, "failed to create ssl object");
|
||||
error = -1;
|
||||
goto out_err;
|
||||
git__free(st);
|
||||
return -1;
|
||||
}
|
||||
|
||||
st->host = git__strdup(host);
|
||||
@@ -737,10 +738,33 @@ int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
|
||||
|
||||
*out = (git_stream *) st;
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_err:
|
||||
git_stream_free(st->io);
|
||||
git__free(st);
|
||||
int git_openssl_stream_wrap(git_stream **out, git_stream *in, const char *host)
|
||||
{
|
||||
return openssl_stream_wrap(out, in, host, 0);
|
||||
}
|
||||
|
||||
int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
|
||||
{
|
||||
git_stream *stream = NULL;
|
||||
int error;
|
||||
|
||||
assert(out && host && port);
|
||||
|
||||
#ifdef GIT_CURL
|
||||
error = git_curl_stream_new(&stream, host, port);
|
||||
#else
|
||||
error = git_socket_stream_new(&stream, host, port);
|
||||
#endif
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if ((error = openssl_stream_wrap(out, stream, host, 1)) < 0) {
|
||||
git_stream_close(stream);
|
||||
git_stream_free(stream);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
extern int git_openssl_stream_global_init(void);
|
||||
|
||||
extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port);
|
||||
extern int git_openssl_stream_wrap(git_stream **out, git_stream *in, const char *host);
|
||||
|
||||
extern int git_openssl__set_cert_location(const char *file, const char *path);
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ static int stransport_error(OSStatus ret)
|
||||
giterr_set(GITERR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8));
|
||||
CFRelease(message);
|
||||
#else
|
||||
giterr_set(GITERR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
|
||||
GIT_UNUSED(message);
|
||||
giterr_set(GITERR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
|
||||
GIT_UNUSED(message);
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
@@ -44,6 +44,7 @@ static int stransport_error(OSStatus ret)
|
||||
typedef struct {
|
||||
git_stream parent;
|
||||
git_stream *io;
|
||||
int owned;
|
||||
SSLContextRef ctx;
|
||||
CFDataRef der_data;
|
||||
git_cert_x509 cert_info;
|
||||
@@ -57,7 +58,7 @@ static int stransport_connect(git_stream *stream)
|
||||
SecTrustResultType sec_res;
|
||||
OSStatus ret;
|
||||
|
||||
if ((error = git_stream_connect(st->io)) < 0)
|
||||
if (st->owned && (error = git_stream_connect(st->io)) < 0)
|
||||
return error;
|
||||
|
||||
ret = SSLHandshake(st->ctx);
|
||||
@@ -226,41 +227,38 @@ static int stransport_close(git_stream *stream)
|
||||
if (ret != noErr && ret != errSSLClosedGraceful)
|
||||
return stransport_error(ret);
|
||||
|
||||
return git_stream_close(st->io);
|
||||
return st->owned ? git_stream_close(st->io) : 0;
|
||||
}
|
||||
|
||||
static void stransport_free(git_stream *stream)
|
||||
{
|
||||
stransport_stream *st = (stransport_stream *) stream;
|
||||
|
||||
git_stream_free(st->io);
|
||||
if (st->owned)
|
||||
git_stream_free(st->io);
|
||||
|
||||
CFRelease(st->ctx);
|
||||
if (st->der_data)
|
||||
CFRelease(st->der_data);
|
||||
git__free(st);
|
||||
}
|
||||
|
||||
int git_stransport_stream_new(git_stream **out, const char *host, const char *port)
|
||||
static int stransport_wrap(
|
||||
git_stream **out,
|
||||
git_stream *in,
|
||||
const char *host,
|
||||
int owned)
|
||||
{
|
||||
stransport_stream *st;
|
||||
int error;
|
||||
OSStatus ret;
|
||||
|
||||
assert(out && host);
|
||||
assert(out && in && host);
|
||||
|
||||
st = git__calloc(1, sizeof(stransport_stream));
|
||||
GITERR_CHECK_ALLOC(st);
|
||||
|
||||
#ifdef GIT_CURL
|
||||
error = git_curl_stream_new(&st->io, host, port);
|
||||
#else
|
||||
error = git_socket_stream_new(&st->io, host, port);
|
||||
#endif
|
||||
|
||||
if (error < 0){
|
||||
git__free(st);
|
||||
return error;
|
||||
}
|
||||
st->io = in;
|
||||
st->owned = owned;
|
||||
|
||||
st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
|
||||
if (!st->ctx) {
|
||||
@@ -295,4 +293,36 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_stransport_stream_wrap(
|
||||
git_stream **out,
|
||||
git_stream *in,
|
||||
const char *host)
|
||||
{
|
||||
return stransport_wrap(out, in, host, 0);
|
||||
}
|
||||
|
||||
int git_stransport_stream_new(git_stream **out, const char *host, const char *port)
|
||||
{
|
||||
git_stream *stream = NULL;
|
||||
int error;
|
||||
|
||||
assert(out && host);
|
||||
|
||||
#ifdef GIT_CURL
|
||||
error = git_curl_stream_new(&stream, host, port);
|
||||
#else
|
||||
error = git_socket_stream_new(&stream, host, port);
|
||||
#endif
|
||||
|
||||
if (!error)
|
||||
error = stransport_wrap(out, stream, host, 1);
|
||||
|
||||
if (error < 0 && stream) {
|
||||
git_stream_close(stream);
|
||||
git_stream_free(stream);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,5 +12,6 @@
|
||||
#include "git2/sys/stream.h"
|
||||
|
||||
extern int git_stransport_stream_new(git_stream **out, const char *host, const char *port);
|
||||
extern int git_stransport_stream_wrap(git_stream **out, git_stream *in, const char *host);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,41 +5,124 @@
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#include "streams/tls.h"
|
||||
|
||||
#include "git2/errors.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "global.h"
|
||||
#include "streams/tls.h"
|
||||
#include "streams/mbedtls.h"
|
||||
#include "streams/openssl.h"
|
||||
#include "streams/stransport.h"
|
||||
|
||||
static git_stream_cb tls_ctor;
|
||||
struct git_tls_stream_registration {
|
||||
git_rwlock lock;
|
||||
git_stream_registration callbacks;
|
||||
};
|
||||
|
||||
int git_stream_register_tls(git_stream_cb ctor)
|
||||
static struct git_tls_stream_registration stream_registration;
|
||||
|
||||
static void shutdown_ssl(void)
|
||||
{
|
||||
tls_ctor = ctor;
|
||||
git_rwlock_free(&stream_registration.lock);
|
||||
}
|
||||
|
||||
int git_tls_stream_global_init(void)
|
||||
{
|
||||
if (git_rwlock_init(&stream_registration.lock) < 0)
|
||||
return -1;
|
||||
|
||||
git__on_shutdown(shutdown_ssl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_stream_register_tls(git_stream_registration *registration)
|
||||
{
|
||||
assert(!registration || registration->init);
|
||||
|
||||
if (git_rwlock_wrlock(&stream_registration.lock) < 0) {
|
||||
giterr_set(GITERR_OS, "failed to lock stream registration");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (registration)
|
||||
memcpy(&stream_registration.callbacks, registration,
|
||||
sizeof(git_stream_registration));
|
||||
else
|
||||
memset(&stream_registration.callbacks, 0,
|
||||
sizeof(git_stream_registration));
|
||||
|
||||
git_rwlock_wrunlock(&stream_registration.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_tls_stream_new(git_stream **out, const char *host, const char *port)
|
||||
{
|
||||
int (*init)(git_stream **, const char *, const char *) = NULL;
|
||||
|
||||
if (tls_ctor)
|
||||
return tls_ctor(out, host, port);
|
||||
assert(out && host && port);
|
||||
|
||||
if (git_rwlock_rdlock(&stream_registration.lock) < 0) {
|
||||
giterr_set(GITERR_OS, "failed to lock stream registration");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stream_registration.callbacks.init) {
|
||||
init = stream_registration.callbacks.init;
|
||||
} else {
|
||||
#ifdef GIT_SECURE_TRANSPORT
|
||||
return git_stransport_stream_new(out, host, port);
|
||||
init = git_stransport_stream_new;
|
||||
#elif defined(GIT_OPENSSL)
|
||||
return git_openssl_stream_new(out, host, port);
|
||||
init = git_openssl_stream_new;
|
||||
#elif defined(GIT_MBEDTLS)
|
||||
return git_mbedtls_stream_new(out, host, port);
|
||||
#else
|
||||
GIT_UNUSED(out);
|
||||
GIT_UNUSED(host);
|
||||
GIT_UNUSED(port);
|
||||
|
||||
giterr_set(GITERR_SSL, "there is no TLS stream available");
|
||||
return -1;
|
||||
init = git_mbedtls_stream_new;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (git_rwlock_rdunlock(&stream_registration.lock) < 0) {
|
||||
giterr_set(GITERR_OS, "failed to unlock stream registration");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!init) {
|
||||
giterr_set(GITERR_SSL, "there is no TLS stream available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return init(out, host, port);
|
||||
}
|
||||
|
||||
int git_tls_stream_wrap(git_stream **out, git_stream *in, const char *host)
|
||||
{
|
||||
int (*wrap)(git_stream **, git_stream *, const char *) = NULL;
|
||||
|
||||
assert(out && in);
|
||||
|
||||
if (git_rwlock_rdlock(&stream_registration.lock) < 0) {
|
||||
giterr_set(GITERR_OS, "failed to lock stream registration");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stream_registration.callbacks.wrap) {
|
||||
wrap = stream_registration.callbacks.wrap;
|
||||
} else {
|
||||
#ifdef GIT_SECURE_TRANSPORT
|
||||
wrap = git_stransport_stream_wrap;
|
||||
#elif defined(GIT_OPENSSL)
|
||||
wrap = git_openssl_stream_wrap;
|
||||
#elif defined(GIT_MBEDTLS)
|
||||
wrap = git_mbedtls_stream_wrap;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (git_rwlock_rdunlock(&stream_registration.lock) < 0) {
|
||||
giterr_set(GITERR_OS, "failed to unlock stream registration");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!wrap) {
|
||||
giterr_set(GITERR_SSL, "there is no TLS stream available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return wrap(out, in, host);
|
||||
}
|
||||
|
||||
@@ -11,13 +11,24 @@
|
||||
|
||||
#include "git2/sys/stream.h"
|
||||
|
||||
/** Configure TLS stream functions. */
|
||||
int git_tls_stream_global_init(void);
|
||||
|
||||
/**
|
||||
* Create a TLS stream with the most appropriate backend available for
|
||||
* the current platform.
|
||||
*
|
||||
* This allows us to ask for a SecureTransport or OpenSSL stream
|
||||
* according to being on general Unix vs OS X.
|
||||
* the current platform, whether that's SecureTransport on macOS,
|
||||
* OpenSSL or mbedTLS on other Unixes, or something else entirely.
|
||||
*/
|
||||
extern int git_tls_stream_new(git_stream **out, const char *host, const char *port);
|
||||
|
||||
/**
|
||||
* Create a TLS stream on top of an existing insecure stream, using
|
||||
* the most appropriate backend available for the current platform.
|
||||
*
|
||||
* This allows us to create a CONNECT stream on top of a proxy;
|
||||
* using SecureTransport on macOS, OpenSSL or mbedTLS on other
|
||||
* Unixes, or something else entirely.
|
||||
*/
|
||||
extern int git_tls_stream_wrap(git_stream **out, git_stream *in, const char *host);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -713,10 +713,31 @@ static int check_certificate(
|
||||
return error;
|
||||
}
|
||||
|
||||
static int stream_connect(
|
||||
git_stream *stream,
|
||||
gitno_connection_data *url,
|
||||
git_transport_certificate_check_cb cert_cb,
|
||||
void *cb_payload)
|
||||
{
|
||||
int error;
|
||||
|
||||
GITERR_CHECK_VERSION(stream, GIT_STREAM_VERSION, "git_stream");
|
||||
|
||||
error = git_stream_connect(stream);
|
||||
|
||||
if (error && error != GIT_ECERTIFICATE)
|
||||
return error;
|
||||
|
||||
if (git_stream_is_encrypted(stream) && cert_cb != NULL)
|
||||
error = check_certificate(stream, url, !error, cert_cb, cb_payload);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int http_connect(http_subtransport *t)
|
||||
{
|
||||
gitno_connection_data *url;
|
||||
git_stream *stream = NULL;
|
||||
git_stream *proxy_stream = NULL, *stream = NULL;
|
||||
git_transport_certificate_check_cb cert_cb;
|
||||
void *cb_payload;
|
||||
int error;
|
||||
@@ -744,8 +765,14 @@ static int http_connect(http_subtransport *t)
|
||||
}
|
||||
|
||||
#ifdef GIT_CURL
|
||||
error = git_curl_stream_new(&stream,
|
||||
t->server.url.host, t->server.url.port);
|
||||
if ((error = git_curl_stream_new(&stream,
|
||||
t->server.url.host, t->server.url.port)) < 0)
|
||||
goto on_error;
|
||||
|
||||
GITERR_CHECK_VERSION(stream, GIT_STREAM_VERSION, "git_stream");
|
||||
|
||||
if ((error = apply_proxy_config_to_stream(stream, &t->proxy_opts)) < 0)
|
||||
goto on_error;
|
||||
#else
|
||||
if (url->use_ssl)
|
||||
error = git_tls_stream_new(&stream, url->host, url->port);
|
||||
@@ -756,20 +783,7 @@ static int http_connect(http_subtransport *t)
|
||||
if (error < 0)
|
||||
goto on_error;
|
||||
|
||||
GITERR_CHECK_VERSION(stream, GIT_STREAM_VERSION, "git_stream");
|
||||
|
||||
if ((error = apply_proxy_config_to_stream(stream, &t->proxy_opts)) < 0)
|
||||
goto on_error;
|
||||
|
||||
error = git_stream_connect(stream);
|
||||
|
||||
if (error && error != GIT_ECERTIFICATE)
|
||||
goto on_error;
|
||||
|
||||
if (git_stream_is_encrypted(stream) && cert_cb != NULL)
|
||||
error = check_certificate(stream, url, !error, cert_cb, cb_payload);
|
||||
|
||||
if (error)
|
||||
if ((error = stream_connect(stream, url, cert_cb, cb_payload)) < 0)
|
||||
goto on_error;
|
||||
|
||||
t->server.stream = stream;
|
||||
@@ -782,6 +796,11 @@ on_error:
|
||||
git_stream_free(stream);
|
||||
}
|
||||
|
||||
if (proxy_stream) {
|
||||
git_stream_close(proxy_stream);
|
||||
git_stream_free(proxy_stream);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
static git_stream test_stream;
|
||||
static int ctor_called;
|
||||
|
||||
static int test_ctor(git_stream **out, const char *host, const char *port)
|
||||
static int test_stream_init(git_stream **out, const char *host, const char *port)
|
||||
{
|
||||
GIT_UNUSED(host);
|
||||
GIT_UNUSED(port);
|
||||
@@ -17,13 +17,29 @@ static int test_ctor(git_stream **out, const char *host, const char *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_stream_wrap(git_stream **out, git_stream *in, const char *host)
|
||||
{
|
||||
GIT_UNUSED(in);
|
||||
GIT_UNUSED(host);
|
||||
|
||||
ctor_called = 1;
|
||||
*out = &test_stream;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_core_stream__register_tls(void)
|
||||
{
|
||||
git_stream *stream;
|
||||
git_stream_registration registration = {0};
|
||||
int error;
|
||||
|
||||
registration.version = 1;
|
||||
registration.init = test_stream_init;
|
||||
registration.wrap = test_stream_wrap;
|
||||
|
||||
ctor_called = 0;
|
||||
cl_git_pass(git_stream_register_tls(test_ctor));
|
||||
cl_git_pass(git_stream_register_tls(®istration));
|
||||
cl_git_pass(git_tls_stream_new(&stream, "localhost", "443"));
|
||||
cl_assert_equal_i(1, ctor_called);
|
||||
cl_assert_equal_p(&test_stream, stream);
|
||||
|
||||
Reference in New Issue
Block a user