-
Notifications
You must be signed in to change notification settings - Fork 2.5k
add support of mbedTLS #3462
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
add support of mbedTLS #3462
Changes from 1 commit
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
30ff088
mbedtls cmake config
wildart ccbd58b
define mbedtls global configuration
wildart 322f06d
added certificate location setup
wildart b79ecc4
introduced GIT_MBEDTLS symbol
wildart f7bb614
added git_mbedtls_stream_new
wildart f160f49
fixed typos in cmake module
wildart 87411f7
added certificates loading
wildart c5f5a25
proper certificate verification & cleanup of `git_mbedtls_stream_new`
wildart 00e5422
use libmbedcrypto for SHA1
wildart 14f537f
added new CI configuration for mbedtls
wildart File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
added git_mbedtls_stream_new
- Loading branch information
commit f7bb614f873bfd3d9d25b66a79540ddf59e09d68
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | ||
return -1; | ||
} | ||
|
||
#endif | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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" ?