Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
added git_mbedtls_stream_new
  • Loading branch information
wildart committed Oct 9, 2015
commit f7bb614f873bfd3d9d25b66a79540ddf59e09d68
55 changes: 34 additions & 21 deletions src/global.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,36 +137,45 @@ static void init_ssl(void)

#ifdef GIT_MBEDTLS
int ret = 0;
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
mbedtls_x509_crt *cacert = NULL;
mbedtls_ctr_drbg_context *ctr_drbg;
mbedtls_x509_crt *cacert;

// Seeding the random number generator
mbedtls_entropy = git__malloc(sizeof(mbedtls_entropy_context));
mbedtls_entropy_init(mbedtls_entropy);
mbedtls_ctr_drbg_init(ctr_drbg);

// Seeding the random number generator
ctr_drbg = git__malloc(sizeof(mbedtls_ctr_drbg_context));
mbedtls_ctr_drbg_init(ctr_drbg);
if (!ret && ( ret = mbedtls_ctr_drbg_seed(ctr_drbg,
mbedtls_entropy_func,
mbedtls_entropy, NULL, 0) ) != 0) {
mbedtls_ctr_drbg_free(ctr_drbg);
mbedtls_ctr_drbg_free(ctr_drbg);
git__free(ctr_drbg);
}

// Configure TLSv1
if (!ret) {
git__ssl_conf = git__malloc(sizeof(mbedtls_ssl_config));
mbedtls_ssl_config_init(git__ssl_conf);
if ( (ret = mbedtls_ssl_config_defaults(git__ssl_conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0) {
mbedtls_ssl_config_free(git__ssl_conf);
git__ssl_conf = NULL;
} else {
mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_rng(git__ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg);

// Do not load certificates, initialize later through settings
mbedtls_x509_crt_init(cacert);
mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
}
}
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0) {
mbedtls_ctr_drbg_free(ctr_drbg);
git__free(ctr_drbg);
mbedtls_ssl_config_free(git__ssl_conf);
git__free(git__ssl_conf);
git__ssl_conf = NULL;
} else {
mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_rng(git__ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg);

// Do not load certificates, initialize later through settings
cacert = git__malloc(sizeof(mbedtls_x509_crt));
mbedtls_x509_crt_init(cacert);
mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
}
}
#endif
}

Expand All @@ -184,13 +193,17 @@ static void uninit_ssl(void)
#endif
#ifdef GIT_MBEDTLS
if (git__ssl_conf) {
mbedtls_x509_crt_free(git__ssl_conf->ca_chain);
mbedtls_ctr_drbg_free(git__ssl_conf->p_rng);
mbedtls_x509_crt_free(git__ssl_conf->ca_chain);
git__free(git__ssl_conf->ca_chain);
mbedtls_ctr_drbg_free(git__ssl_conf->p_rng);
git__free(git__ssl_conf->p_rng);
mbedtls_ssl_config_free(git__ssl_conf);
git__free(git__ssl_conf);
git__ssl_conf = NULL;
}
if (mbedtls_entropy) {
mbedtls_entropy_free(mbedtls_entropy);
git__free(mbedtls_entropy);
mbedtls_entropy = NULL;
}
#endif
Expand Down
303 changes: 303 additions & 0 deletions src/mbedtls_stream.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/

#ifdef GIT_MBEDTLS

#include <ctype.h>

#include "global.h"
#include "posix.h"
#include "stream.h"
#include "socket_stream.h"
#include "netops.h"
#include "git2/transport.h"

#ifdef GIT_CURL
# include "curl_stream.h"
#endif

#ifndef GIT_WIN32
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
#endif

#include <mbedtls/ssl.h>
#include <mbedtls/x509.h>
#include <mbedtls/error.h>

static int bio_read(void *b, unsigned char *buf, size_t len)
{
git_stream *io = (git_stream *) b;
return (int) git_stream_read(io, buf, len);
}

static int bio_write(void *b, const unsigned char *buf, size_t len)
{
git_stream *io = (git_stream *) b;
return (int) git_stream_write(io, (const char *)buf, len, 0);
}

static int ssl_set_error(int error)
{
char errbuf[512];

assert(error != MBEDTLS_ERR_SSL_WANT_READ);
assert(error != MBEDTLS_ERR_SSL_WANT_WRITE);

if (error == 0) {
giterr_set(GITERR_NET, "SSL error: unknown error");
} else {
mbedtls_strerror( error, errbuf, 512 );
giterr_set(GITERR_NET, "SSL error: %d - %s", error, errbuf);
}

return -1;
}

static int ssl_teardown(mbedtls_ssl_context *ssl)
{
int ret = 0;

ret = mbedtls_ssl_close_notify(ssl);
if (ret < 0)
ret = ssl_set_error(ret);

mbedtls_ssl_free(ssl);
return ret;
}

static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host)
{
const mbedtls_x509_crt *cert;
int flags;
struct in6_addr addr6;
struct in_addr addr4;
void *addr;

if( ( flags = mbedtls_ssl_get_verify_result(ssl) ) != 0 )
{
char vrfy_buf[512];
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf);
return GIT_ECERTIFICATE;
}

/* Try to parse the host as an IP address to see if it is */
if (p_inet_pton(AF_INET, host, &addr4)) {
addr = &addr4;
} else {
if(p_inet_pton(AF_INET6, host, &addr6)) {
addr = &addr6;
}
}

cert = mbedtls_ssl_get_peer_cert(ssl);
if (!cert) {
giterr_set(GITERR_SSL, "the server did not provide a certificate");
return -1;
}

/* Check the alternative names */
//TODO: cert->subject_alt_names

/* If no alternative names are available, check the common name */
/*TODO
mbedtls_x509_name peer_name = cert->subject;
if (peer_name == NULL)
goto on_error;
*/

return 0;

on_error:
return ssl_set_error(0);

cert_fail_name:
giterr_set(GITERR_SSL, "hostname does not match certificate");
return GIT_ECERTIFICATE;
}

typedef struct {
git_stream parent;
git_stream *io;
bool connected;
char *host;
mbedtls_ssl_context *ssl;
git_cert_x509 cert_info;
} mbedtls_stream;


int mbedtls_connect(git_stream *stream)
{
int ret;
mbedtls_stream *st = (mbedtls_stream *) stream;

if ((ret = git_stream_connect(st->io)) < 0)
return ret;

st->connected = true;

mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL);

/* specify the host in case SNI is needed */
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
mbedtls_ssl_set_hostname(st->ssl, st->host);
#endif

if ((ret = mbedtls_ssl_handshake(st->ssl)) != 0)
return ssl_set_error(ret);

return verify_server_cert(st->ssl, st->host);
}

int mbedtls_certificate(git_cert **out, git_stream *stream)
{
unsigned char *encoded_cert;
mbedtls_stream *st = (mbedtls_stream *) stream;

const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(st->ssl);
if (!cert) {
giterr_set(GITERR_SSL, "the server did not provide a certificate");
return -1;
}

/* Retrieve the length of the certificate first */
if (cert->raw.len == 0) {
giterr_set(GITERR_NET, "failed to retrieve certificate information");
return -1;
}

encoded_cert = git__malloc(cert->raw.len);
GITERR_CHECK_ALLOC(encoded_cert);
memcpy(encoded_cert, cert->raw.p, cert->raw.len);

st->cert_info.parent.cert_type = GIT_CERT_X509;
st->cert_info.data = encoded_cert;
st->cert_info.len = cert->raw.len;

*out = &st->cert_info.parent;

return 0;
}

static int mbedtls_set_proxy(git_stream *stream, const char *proxy_url)
{
mbedtls_stream *st = (mbedtls_stream *) stream;

return git_stream_set_proxy(st->io, proxy_url);
}

ssize_t mbedtls_write(git_stream *stream, const char *data, size_t len, int flags)
{
mbedtls_stream *st = (mbedtls_stream *) stream;
int ret;

GIT_UNUSED(flags);

if ((ret = mbedtls_ssl_write(st->ssl, (const unsigned char *)data, len)) <= 0) {
return ssl_set_error(ret);
}

return ret;
}

ssize_t mbedtls_read(git_stream *stream, void *data, size_t len)
{
mbedtls_stream *st = (mbedtls_stream *) stream;
int ret;

if ((ret = mbedtls_ssl_read(st->ssl, (unsigned char *)data, len)) <= 0)
ssl_set_error(ret);

return ret;
}

int mbedtls_close(git_stream *stream)
{
mbedtls_stream *st = (mbedtls_stream *) stream;
int ret = 0;

if (st->connected && (ret = ssl_teardown(st->ssl)) != 0)
return -1;

st->connected = false;

return git_stream_close(st->io);
}

void mbedtls_free(git_stream *stream)
{
mbedtls_stream *st = (mbedtls_stream *) stream;

git__free(st->host);
git__free(st->cert_info.data);
git_stream_free(st->io);
git__free(st->ssl);
git__free(st);
}

int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
{
int error;
mbedtls_stream *st;

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)
return error;

st->ssl = git__malloc(sizeof(mbedtls_ssl_context));
GITERR_CHECK_ALLOC(st->ssl);
mbedtls_ssl_init(st->ssl);
if( (error = mbedtls_ssl_setup(st->ssl, git__ssl_conf)) != 0 ) {
mbedtls_ssl_free(st->ssl);
giterr_set(GITERR_SSL, "failed to create ssl object");
return -1;
}

st->host = git__strdup(host);
GITERR_CHECK_ALLOC(st->host);

st->parent.version = GIT_STREAM_VERSION;
st->parent.encrypted = 1;
st->parent.proxy_support = git_stream_supports_proxy(st->io);
st->parent.connect = mbedtls_connect;
st->parent.certificate = mbedtls_certificate;
st->parent.set_proxy = mbedtls_set_proxy;
st->parent.read = mbedtls_read;
st->parent.write = mbedtls_write;
st->parent.close = mbedtls_close;
st->parent.free = mbedtls_free;

*out = (git_stream *) st;
return 0;
}

#else

#include "stream.h"

int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
{
GIT_UNUSED(out);
GIT_UNUSED(host);
GIT_UNUSED(port);

giterr_set(GITERR_SSL, "openssl is not supported in this version");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"mbedtls is not supported in this version" ?

return -1;
}

#endif

Loading