mirror of
https://github.com/libgit2/libgit2.git
synced 2026-01-25 02:56:17 +00:00
checkpoint
This commit is contained in:
@@ -36,6 +36,14 @@ typedef struct {
|
||||
#define GIT_STREAM_CONNECT_OPTIONS_INIT \
|
||||
{ GIT_STREAM_CONNECT_OPTIONS_VERSION }
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
typedef SOCKET git_socket_t;
|
||||
# define GIT_SOCKET_INVALID INVALID_SOCKET
|
||||
#else
|
||||
typedef int git_socket_t;
|
||||
# define GIT_SOCKET_INVALID -1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Every stream must have this struct as its first element, so the
|
||||
* API can talk to it. You'd define your stream as
|
||||
@@ -64,6 +72,7 @@ typedef struct git_stream {
|
||||
struct git_stream *,
|
||||
struct git_stream *in,
|
||||
const char *host);
|
||||
git_socket_t GIT_CALLBACK(get_socket)(struct git_stream *);
|
||||
int GIT_CALLBACK(certificate)(git_cert **, struct git_stream *);
|
||||
ssize_t GIT_CALLBACK(read)(struct git_stream *, void *, size_t);
|
||||
ssize_t GIT_CALLBACK(write)(struct git_stream *, const char *, size_t, int);
|
||||
@@ -82,20 +91,6 @@ typedef struct {
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
int GIT_CALLBACK(init)(git_stream **out);
|
||||
|
||||
/**
|
||||
* Called to create a new connection on top of the given stream. If
|
||||
* this is a TLS stream, then this function may be used to proxy a
|
||||
* TLS stream over an HTTP CONNECT session. If this is unset, then
|
||||
* HTTP CONNECT proxies will not be supported.
|
||||
*
|
||||
* @param out The created 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 GIT_CALLBACK(wrap)(git_stream **out, git_stream *in, const char *host);
|
||||
} git_stream_registration;
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "smart.h"
|
||||
#include "http.h"
|
||||
#include "trace.h"
|
||||
#include "transport.h"
|
||||
#include "streams/tls.h"
|
||||
#include "streams/socket.h"
|
||||
#include "net/auth.h"
|
||||
@@ -25,6 +26,9 @@
|
||||
|
||||
bool git_http__expect_continue = false;
|
||||
|
||||
extern int git_transport__timeout;
|
||||
extern int git_transport__connect_timeout;
|
||||
|
||||
typedef enum {
|
||||
HTTP_STATE_NONE = 0,
|
||||
HTTP_STATE_SENDING_REQUEST,
|
||||
@@ -97,9 +101,6 @@ static const http_service receive_pack_service = {
|
||||
1
|
||||
};
|
||||
|
||||
extern int git_transport__connect_timeout;
|
||||
extern int git_transport__timeout;
|
||||
|
||||
#define SERVER_TYPE_REMOTE "remote"
|
||||
#define SERVER_TYPE_PROXY "proxy"
|
||||
|
||||
@@ -695,8 +696,9 @@ static int http_action(
|
||||
GIT_ERROR_CHECK_ALLOC(stream);
|
||||
|
||||
opts.user_agent = transport->user_agent.ptr;
|
||||
opts.connect_timeout = git_transport__connect_timeout;
|
||||
|
||||
opts.timeout = git_transport__timeout;
|
||||
opts.connect_timeout = git_transport__connect_timeout;
|
||||
|
||||
opts.server_certificate_check_cb = connect_opts->callbacks.certificate_check;
|
||||
opts.server_certificate_check_payload = connect_opts->callbacks.payload;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "runtime.h"
|
||||
#include "smart.h"
|
||||
#include "transport.h"
|
||||
#include "streams/socket.h"
|
||||
#include "sysdir.h"
|
||||
#include "net/url.h"
|
||||
@@ -523,16 +524,22 @@ static int _git_ssh_session_create(
|
||||
LIBSSH2_KNOWNHOSTS **hosts,
|
||||
const char *hostname,
|
||||
int port,
|
||||
git_stream *io)
|
||||
git_stream *stream)
|
||||
{
|
||||
git_stream_socket *socket = GIT_CONTAINER_OF(io, git_stream_socket, parent);
|
||||
LIBSSH2_SESSION *s;
|
||||
LIBSSH2_KNOWNHOSTS *known_hosts;
|
||||
git_socket_t socket;
|
||||
git_str prefs = GIT_STR_INIT;
|
||||
int rc = 0;
|
||||
|
||||
GIT_ASSERT_ARG(session);
|
||||
GIT_ASSERT_ARG(hosts);
|
||||
GIT_ASSERT_ARG(stream);
|
||||
|
||||
if ((socket = git_stream_get_socket(stream)) == GIT_SOCKET_INVALID) {
|
||||
git_error_set(GIT_ERROR_NET, "could not get socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = libssh2_session_init();
|
||||
if (!s) {
|
||||
@@ -559,7 +566,7 @@ static int _git_ssh_session_create(
|
||||
git_str_dispose(&prefs);
|
||||
|
||||
do {
|
||||
rc = libssh2_session_handshake(s, socket->s);
|
||||
rc = libssh2_session_handshake(s, socket);
|
||||
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
|
||||
|
||||
if (rc != LIBSSH2_ERROR_NONE) {
|
||||
@@ -768,9 +775,10 @@ static int _git_ssh_setup_conn(
|
||||
int auth_methods, error = 0, port;
|
||||
ssh_stream *s;
|
||||
git_credential *cred = NULL;
|
||||
LIBSSH2_SESSION *session=NULL;
|
||||
LIBSSH2_CHANNEL *channel=NULL;
|
||||
LIBSSH2_SESSION *session = NULL;
|
||||
LIBSSH2_CHANNEL *channel = NULL;
|
||||
LIBSSH2_KNOWNHOSTS *known_hosts = NULL;
|
||||
git_stream_connect_options opts = GIT_STREAM_CONNECT_OPTIONS_INIT;
|
||||
|
||||
t->current_stream = NULL;
|
||||
|
||||
@@ -782,9 +790,11 @@ static int _git_ssh_setup_conn(
|
||||
s->session = NULL;
|
||||
s->channel = NULL;
|
||||
|
||||
git_transport__set_connect_opts(&opts);
|
||||
|
||||
if ((error = git_net_url_parse_standard_or_scp(&s->url, url)) < 0 ||
|
||||
(error = git_stream_socket_new(&s->io, s->url.host, s->url.port)) < 0 ||
|
||||
(error = git_stream_connect(s->io)) < 0)
|
||||
(error = git_stream_socket_new(&s->io)) < 0 ||
|
||||
(error = git_stream_connect(s->io, s->url.host, s->url.port, &opts)) < 0)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
|
||||
@@ -32,6 +32,11 @@ GIT_INLINE(int) git_stream_is_encrypted(git_stream *st)
|
||||
return st->encrypted;
|
||||
}
|
||||
|
||||
GIT_INLINE(GIT_SOCKET) git_stream_get_socket(git_stream *st)
|
||||
{
|
||||
return st->get_socket(st);
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_stream_certificate(git_cert **out, git_stream *st)
|
||||
{
|
||||
if (!st->encrypted) {
|
||||
|
||||
@@ -15,10 +15,9 @@
|
||||
|
||||
#include "git2_util.h"
|
||||
#include "runtime.h"
|
||||
#include "settings.h"
|
||||
#include "posix.h"
|
||||
#include "stream.h"
|
||||
#include "net.h"
|
||||
#include "net/url.h"
|
||||
#include "streams/socket.h"
|
||||
#include "git2/transport.h"
|
||||
#include "git2/sys/openssl.h"
|
||||
@@ -36,7 +35,7 @@
|
||||
# include <openssl/bio.h>
|
||||
#endif
|
||||
|
||||
SSL_CTX *git__ssl_ctx;
|
||||
SSL_CTX *openssl_ctx;
|
||||
|
||||
#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
|
||||
|
||||
@@ -55,9 +54,9 @@ static void shutdown_ssl(void)
|
||||
git_stream_bio_method = NULL;
|
||||
}
|
||||
|
||||
if (git__ssl_ctx) {
|
||||
SSL_CTX_free(git__ssl_ctx);
|
||||
git__ssl_ctx = NULL;
|
||||
if (openssl_ctx) {
|
||||
SSL_CTX_free(openssl_ctx);
|
||||
openssl_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +104,6 @@ static void git_openssl_free(void *mem)
|
||||
static int openssl_init(void)
|
||||
{
|
||||
long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
|
||||
const char *ciphers = git_libgit2__ssl_ciphers();
|
||||
#ifdef VALGRIND
|
||||
static bool allocators_initialized = false;
|
||||
#endif
|
||||
@@ -138,19 +136,14 @@ static int openssl_init(void)
|
||||
* compatibility. We then disable SSL so we only allow OpenSSL
|
||||
* to speak TLSv1 to perform the encryption itself.
|
||||
*/
|
||||
if (!(git__ssl_ctx = SSL_CTX_new(SSLv23_method())))
|
||||
if (!(openssl_ctx = SSL_CTX_new(SSLv23_method())))
|
||||
goto error;
|
||||
|
||||
SSL_CTX_set_options(git__ssl_ctx, ssl_opts);
|
||||
SSL_CTX_set_mode(git__ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_verify(git__ssl_ctx, SSL_VERIFY_NONE, NULL);
|
||||
if (!SSL_CTX_set_default_verify_paths(git__ssl_ctx))
|
||||
goto error;
|
||||
SSL_CTX_set_options(openssl_ctx, ssl_opts);
|
||||
SSL_CTX_set_mode(openssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_verify(openssl_ctx, SSL_VERIFY_NONE, NULL);
|
||||
|
||||
if (!ciphers)
|
||||
ciphers = GIT_SSL_DEFAULT_CIPHERS;
|
||||
|
||||
if(!SSL_CTX_set_cipher_list(git__ssl_ctx, ciphers))
|
||||
if (!SSL_CTX_set_default_verify_paths(openssl_ctx))
|
||||
goto error;
|
||||
|
||||
if (init_bio_method() < 0)
|
||||
@@ -161,8 +154,8 @@ static int openssl_init(void)
|
||||
error:
|
||||
git_error_set(GIT_ERROR_NET, "could not initialize openssl: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
SSL_CTX_free(git__ssl_ctx);
|
||||
git__ssl_ctx = NULL;
|
||||
SSL_CTX_free(openssl_ctx);
|
||||
openssl_ctx = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -503,14 +496,20 @@ typedef struct {
|
||||
git_cert_x509 cert_info;
|
||||
} openssl_stream;
|
||||
|
||||
static int openssl_connect(git_stream *stream)
|
||||
static int openssl_create_session(openssl_stream *st, const char *host)
|
||||
{
|
||||
int ret;
|
||||
BIO *bio;
|
||||
openssl_stream *st = (openssl_stream *) stream;
|
||||
int ret;
|
||||
|
||||
if (st->owned && (ret = git_stream_connect(st->io)) < 0)
|
||||
return ret;
|
||||
st->ssl = SSL_new(openssl_ctx);
|
||||
|
||||
if (st->ssl == NULL) {
|
||||
git_error_set(GIT_ERROR_SSL, "failed to create ssl object");
|
||||
return -1;
|
||||
}
|
||||
|
||||
st->host = git__strdup(host);
|
||||
GIT_ERROR_CHECK_ALLOC(st->host);
|
||||
|
||||
bio = BIO_new(git_stream_bio_method);
|
||||
GIT_ERROR_CHECK_ALLOC(bio);
|
||||
@@ -531,6 +530,33 @@ static int openssl_connect(git_stream *stream)
|
||||
return verify_server_cert(st->ssl, st->host);
|
||||
}
|
||||
|
||||
static int openssl_connect(
|
||||
git_stream *stream,
|
||||
const char *host,
|
||||
const char *port,
|
||||
const git_stream_connect_options *opts)
|
||||
{
|
||||
openssl_stream *st = (openssl_stream *)stream;
|
||||
|
||||
if (git_stream_socket_new(&st->io) < 0 ||
|
||||
git_stream_connect(st->io, host, port, opts) < 0)
|
||||
return -1;
|
||||
|
||||
st->owned = 1;
|
||||
|
||||
return openssl_create_session(st, host);
|
||||
}
|
||||
|
||||
static int openssl_wrap(git_stream *stream, git_stream *in, const char *host)
|
||||
{
|
||||
openssl_stream *st = (openssl_stream *)stream;
|
||||
|
||||
st->io = in;
|
||||
st->owned = 0;
|
||||
|
||||
return openssl_create_session(st, host);
|
||||
}
|
||||
|
||||
static int openssl_certificate(git_cert **out, git_stream *stream)
|
||||
{
|
||||
openssl_stream *st = (openssl_stream *) stream;
|
||||
@@ -622,37 +648,28 @@ static void openssl_free(git_stream *stream)
|
||||
git__free(st);
|
||||
}
|
||||
|
||||
static int openssl_stream_wrap(
|
||||
git_stream **out,
|
||||
git_stream *in,
|
||||
const char *host,
|
||||
int owned)
|
||||
int git_stream_openssl_new(git_stream **out)
|
||||
{
|
||||
openssl_stream *st;
|
||||
|
||||
GIT_ASSERT_ARG(out);
|
||||
GIT_ASSERT_ARG(in);
|
||||
GIT_ASSERT_ARG(host);
|
||||
|
||||
if (openssl_ensure_initialized() < 0)
|
||||
return -1;
|
||||
|
||||
st = git__calloc(1, sizeof(openssl_stream));
|
||||
GIT_ERROR_CHECK_ALLOC(st);
|
||||
|
||||
st->io = in;
|
||||
st->owned = owned;
|
||||
|
||||
st->ssl = SSL_new(git__ssl_ctx);
|
||||
if (st->ssl == NULL) {
|
||||
if ((st->ssl = SSL_new(openssl_ctx)) == NULL) {
|
||||
git_error_set(GIT_ERROR_SSL, "failed to create ssl object");
|
||||
git__free(st);
|
||||
return -1;
|
||||
}
|
||||
|
||||
st->host = git__strdup(host);
|
||||
GIT_ERROR_CHECK_ALLOC(st->host);
|
||||
|
||||
st->parent.version = GIT_STREAM_VERSION;
|
||||
st->parent.encrypted = 1;
|
||||
st->parent.connect = openssl_connect;
|
||||
st->parent.wrap = openssl_wrap;
|
||||
st->parent.certificate = openssl_certificate;
|
||||
st->parent.read = openssl_read;
|
||||
st->parent.write = openssl_write;
|
||||
@@ -663,43 +680,12 @@ static int openssl_stream_wrap(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_stream_openssl_wrap(git_stream **out, git_stream *in, const char *host)
|
||||
{
|
||||
if (openssl_ensure_initialized() < 0)
|
||||
return -1;
|
||||
|
||||
return openssl_stream_wrap(out, in, host, 0);
|
||||
}
|
||||
|
||||
int git_stream_openssl_new(git_stream **out, const char *host, const char *port)
|
||||
{
|
||||
git_stream *stream = NULL;
|
||||
int error;
|
||||
|
||||
GIT_ASSERT_ARG(out);
|
||||
GIT_ASSERT_ARG(host);
|
||||
GIT_ASSERT_ARG(port);
|
||||
|
||||
if (openssl_ensure_initialized() < 0)
|
||||
return -1;
|
||||
|
||||
if ((error = git_stream_socket_new(&stream, host, port)) < 0)
|
||||
return error;
|
||||
|
||||
if ((error = openssl_stream_wrap(out, stream, host, 1)) < 0) {
|
||||
git_stream_close(stream);
|
||||
git_stream_free(stream);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_openssl__set_cert_location(const char *file, const char *path)
|
||||
{
|
||||
if (openssl_ensure_initialized() < 0)
|
||||
return -1;
|
||||
|
||||
if (SSL_CTX_load_verify_locations(git__ssl_ctx, file, path) == 0) {
|
||||
if (SSL_CTX_load_verify_locations(openssl_ctx, file, path) == 0) {
|
||||
char errmsg[256];
|
||||
|
||||
ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg));
|
||||
@@ -711,6 +697,20 @@ int git_openssl__set_cert_location(const char *file, const char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_openssl__set_ciphers(const char *ciphers)
|
||||
{
|
||||
if (!ciphers)
|
||||
ciphers = GIT_SSL_DEFAULT_CIPHERS;
|
||||
|
||||
if (openssl_ensure_initialized() < 0)
|
||||
return -1;
|
||||
|
||||
if(!SSL_CTX_set_cipher_list(openssl_ctx, GIT_SSL_DEFAULT_CIPHERS))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "stream.h"
|
||||
|
||||
@@ -23,9 +23,9 @@ extern int git_stream_openssl_global_init(void);
|
||||
# endif
|
||||
|
||||
#ifdef GIT_HTTPS_OPENSSL
|
||||
extern int git_openssl__set_ciphers(const char *ciphers);
|
||||
extern int git_openssl__set_cert_location(const char *file, const char *path);
|
||||
extern int git_stream_openssl_new(git_stream **out, const char *host, const char *port);
|
||||
extern int git_stream_openssl_wrap(git_stream **out, git_stream *in, const char *host);
|
||||
extern int git_stream_openssl_new(git_stream **out);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -108,7 +108,6 @@ int git_stream_register_tls(
|
||||
if (ctor) {
|
||||
registration.version = GIT_STREAM_VERSION;
|
||||
registration.init = ctor;
|
||||
registration.wrap = NULL;
|
||||
|
||||
return git_stream_register(GIT_STREAM_TLS, ®istration);
|
||||
} else {
|
||||
|
||||
@@ -243,6 +243,22 @@ done:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int socket_wrap(git_stream *stream, git_stream *in, const char *host)
|
||||
{
|
||||
GIT_UNUSED(stream);
|
||||
GIT_UNUSED(in);
|
||||
GIT_UNUSED(host);
|
||||
|
||||
git_error_set(GIT_ERROR_NET, "cannot wrap a plaintext socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static git_socket_t socket_get(git_stream *stream)
|
||||
{
|
||||
git_stream_socket *st = (git_stream_socket *) stream;
|
||||
return st->s;
|
||||
}
|
||||
|
||||
static ssize_t socket_write(
|
||||
git_stream *stream,
|
||||
const char *data,
|
||||
@@ -350,6 +366,8 @@ static int default_socket_stream_new(git_stream **out)
|
||||
|
||||
st->parent.version = GIT_STREAM_VERSION;
|
||||
st->parent.connect = socket_connect;
|
||||
st->parent.wrap = socket_wrap;
|
||||
st->parent.get_socket = socket_get;
|
||||
st->parent.write = socket_write;
|
||||
st->parent.read = socket_read;
|
||||
st->parent.close = socket_close;
|
||||
|
||||
Reference in New Issue
Block a user