mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-24 00:00:05 +08:00
Squashed 'OpenVPN Adapter/Vendors/openvpn/' changes from e6d68831a..35bbca799
35bbca799 Merged in OVPN3-184-generate-warning (pull request #1) a73d2ce68 Merged in antonio/OVPN3-169-pure-ssl-transport (pull request #3) 8d7f5f3c1 Merged in feature/docker (pull request #2) d9b5055cd [OVPN3-169] cli.cpp: compile with -DOPENVPN_TLS_LINK when requested 2d99bbfea [OVPN3-169] cliopt.hpp: add support for TLS transport module 62c8461d2 [OVPN3-169] tcpcli.hpp: add runtime support for TLSLink e0e76bb28 [OVPN3-169] tcplink: introduce LinkBase abstract class a71014d40 [OVPN3-169] tcplink: create LinkCommon class and inherit from it cfd6df5bc build system: fix 'git apply' 3e49de7de [OVPN3-210] ovpncli: handle "allow-name-constraints" for OpenSSL 08d72bd76 [OVPN3-184] mbedtls: handle Name Constraints 40c70113d [OVPN3-184] Add mbedTLS patch ef8d11f34 [OVPN3-169] OpenSSL: implement write_ciphertext_unbuffered() function 37dc86378 [OVPN3-169] mbedTLS: implement write_ciphertext_unbuffered() function 5834ed401 [OVPN3-169] SSLAPI: add write_ciphertext_unbuffered() function 071050b5f vars-linux-dbg: update linux debug profile 5bbfe68c3 [OVPN3-169] Protocol: add support for TLS transport protocol type dc12d3189 [OVPN3-223] build: add docker images git-subtree-dir: OpenVPN Adapter/Vendors/openvpn git-subtree-split: 35bbca799dfa3fbe8e17f8d6e94c3946c397b593
This commit is contained in:
@@ -997,6 +997,15 @@ namespace openvpn {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_OPENSSL
|
||||||
|
if (state->options.exists("allow-name-constraints"))
|
||||||
|
{
|
||||||
|
ClientEvent::Base::Ptr ev = new ClientEvent::UnsupportedFeature("allow-name-constraints",
|
||||||
|
"Always verified correctly with OpenSSL", false);
|
||||||
|
state->events->add_event(std::move(ev));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// build client options object
|
// build client options object
|
||||||
ClientOptions::Ptr client_options = new ClientOptions(state->options, cc);
|
ClientOptions::Ptr client_options = new ClientOptions(state->options, cc);
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-5
@@ -36,11 +36,7 @@ else
|
|||||||
tar xfz $DL/$FNAME
|
tar xfz $DL/$FNAME
|
||||||
cd asio-$ASIO_VERSION
|
cd asio-$ASIO_VERSION
|
||||||
|
|
||||||
# apply pre-generated patches
|
apply_patches "asio"
|
||||||
for file in $O3/core/deps/asio/patches/*.patch; do
|
|
||||||
echo Applying patch: $file
|
|
||||||
git apply $file
|
|
||||||
done
|
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
|
|||||||
Vendored
+17
@@ -28,3 +28,20 @@ function download()
|
|||||||
|
|
||||||
check_download || return -1
|
check_download || return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function apply_patches()
|
||||||
|
{
|
||||||
|
DEP_NAME=$1
|
||||||
|
|
||||||
|
# change directory since git apply got confused when
|
||||||
|
# applying patches to files which are not found in index
|
||||||
|
DIR=$(pwd)
|
||||||
|
pushd ${DIR}
|
||||||
|
cd /tmp
|
||||||
|
# apply pre-generated patches
|
||||||
|
for file in $O3/core/deps/${DEP_NAME}/patches/*.patch; do
|
||||||
|
echo Applying patch: $file
|
||||||
|
git apply --directory ${DIR} --unsafe-path $file
|
||||||
|
done
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+1
-5
@@ -51,11 +51,7 @@ else
|
|||||||
# enable MD4 (needed for NTLM auth)
|
# enable MD4 (needed for NTLM auth)
|
||||||
perl -pi -e 's/^\/\/// if /#define MBEDTLS_MD4_C/' include/mbedtls/config.h
|
perl -pi -e 's/^\/\/// if /#define MBEDTLS_MD4_C/' include/mbedtls/config.h
|
||||||
|
|
||||||
# apply pre-generated patches
|
apply_patches "mbedtls"
|
||||||
for file in $O3/core/deps/mbedtls/patches/*.patch; do
|
|
||||||
echo Applying patch: $file
|
|
||||||
git apply $file
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "x$TARGET" == xlinux* || "x$TARGET" == xosx* ]]; then
|
if [[ "x$TARGET" == xlinux* || "x$TARGET" == xosx* ]]; then
|
||||||
|
|||||||
+361
@@ -0,0 +1,361 @@
|
|||||||
|
From 13dd5f71dfe345787c3c44ef177009530983bf20 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lev Stipakov <lev@openvpn.net>
|
||||||
|
Date: Fri, 23 Feb 2018 17:12:49 +0200
|
||||||
|
Subject: [PATCH] Enable allowing unsupported critical extensions in runtime
|
||||||
|
|
||||||
|
When compile time flag MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
|
||||||
|
is not set, certificate parsing fails if certificate contains unsupported critical extension.
|
||||||
|
|
||||||
|
This patch allows to modify this behavior in runtime.
|
||||||
|
|
||||||
|
Signed-off-by: Lev Stipakov <lev@openvpn.net>
|
||||||
|
---
|
||||||
|
include/mbedtls/oid.h | 13 ++++-
|
||||||
|
include/mbedtls/ssl.h | 22 ++++++++
|
||||||
|
include/mbedtls/x509_crt.h | 2 +
|
||||||
|
library/oid.c | 81 +++++++++++++++++++++++++-----
|
||||||
|
library/ssl_tls.c | 8 +++
|
||||||
|
library/x509_crt.c | 10 +++-
|
||||||
|
tests/data_files/test-ca-nc.crt | 20 ++++++++
|
||||||
|
tests/suites/test_suite_x509parse.data | 6 +++
|
||||||
|
tests/suites/test_suite_x509parse.function | 15 ++++++
|
||||||
|
9 files changed, 162 insertions(+), 15 deletions(-)
|
||||||
|
create mode 100644 tests/data_files/test-ca-nc.crt
|
||||||
|
|
||||||
|
diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
|
||||||
|
index fcecdafd..096b1b10 100644
|
||||||
|
--- a/include/mbedtls/oid.h
|
||||||
|
+++ b/include/mbedtls/oid.h
|
||||||
|
@@ -401,7 +401,7 @@ int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_b
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
|
||||||
|
/**
|
||||||
|
- * \brief Translate an X.509 extension OID into local values
|
||||||
|
+ * \brief Translate supported X.509 extension OID into local values
|
||||||
|
*
|
||||||
|
* \param oid OID to use
|
||||||
|
* \param ext_type place to store the extension type
|
||||||
|
@@ -409,6 +409,17 @@ int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_b
|
||||||
|
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
|
||||||
|
*/
|
||||||
|
int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type );
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * \brief Translate supported and unsupported X.509 extension OID into local values
|
||||||
|
+ *
|
||||||
|
+ * \param oid OID to use
|
||||||
|
+ * \param ext_type place to store the extension type
|
||||||
|
+ * \param is_supported place to store flag if extension is supported (1 - supported, 0 otherwise)
|
||||||
|
+ *
|
||||||
|
+ * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
|
||||||
|
+ */
|
||||||
|
+int mbedtls_oid_get_x509_ext_type_supported( const mbedtls_asn1_buf *oid, int *ext_type, int *is_supported );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
|
||||||
|
index cc000700..cb779f86 100644
|
||||||
|
--- a/include/mbedtls/ssl.h
|
||||||
|
+++ b/include/mbedtls/ssl.h
|
||||||
|
@@ -695,6 +695,10 @@ struct mbedtls_ssl_config
|
||||||
|
retransmission timeout (ms) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+ uint32_t allowed_unsupported_critical_exts; /*!< Bit flags which represent runtime-enabled
|
||||||
|
+ unsupported critical extensions, e.g.
|
||||||
|
+ MBEDTLS_X509_EXT_NAME_CONSTRAINTS */
|
||||||
|
+
|
||||||
|
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||||
|
int renego_max_records; /*!< grace period for renegotiation */
|
||||||
|
unsigned char renego_period[8]; /*!< value of the record counters
|
||||||
|
@@ -2234,6 +2238,24 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf,
|
||||||
|
const unsigned char period[8] );
|
||||||
|
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * \brief Allows unsupported critical extensions
|
||||||
|
+ *
|
||||||
|
+ * Without compile-time flag MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
|
||||||
|
+ * mbedTLS fails certificate verification if certificate contains
|
||||||
|
+ * unsupported critical extensions.
|
||||||
|
+ *
|
||||||
|
+ * This method allows to modify behavior in runtime by providing
|
||||||
|
+ * bit flags which represent unsupported extensions (for example MBEDTLS_X509_EXT_NAME_CONSTRAINTS)
|
||||||
|
+ * which should be allowed despite missing above mentioned compile-time flag.
|
||||||
|
+ *
|
||||||
|
+ * \param conf SSL configuration
|
||||||
|
+ * \param exts Bit flags which represent runtime-enabled unsupported critical extensions,
|
||||||
|
+ * e.g. MBEDTLS_X509_EXT_NAME_CONSTRAINTS
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+void mbedtls_ssl_conf_allow_unsupported_critical_exts( mbedtls_ssl_config *conf, uint32_t exts );
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* \brief Return the number of data bytes available to read
|
||||||
|
*
|
||||||
|
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
|
||||||
|
index 06166d8b..adc6474f 100644
|
||||||
|
--- a/include/mbedtls/x509_crt.h
|
||||||
|
+++ b/include/mbedtls/x509_crt.h
|
||||||
|
@@ -89,6 +89,8 @@ typedef struct mbedtls_x509_crt
|
||||||
|
mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */
|
||||||
|
void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */
|
||||||
|
|
||||||
|
+ uint32_t allowed_unsupported_critical_exts; /**< Optional Bit flags which represent runtime-enabled unsupported critical extensions, e.g. MBEDTLS_X509_EXT_NAME_CONSTRAINTS */
|
||||||
|
+
|
||||||
|
struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */
|
||||||
|
}
|
||||||
|
mbedtls_x509_crt;
|
||||||
|
diff --git a/library/oid.c b/library/oid.c
|
||||||
|
index f13826ed..7c50f24f 100644
|
||||||
|
--- a/library/oid.c
|
||||||
|
+++ b/library/oid.c
|
||||||
|
@@ -254,38 +254,95 @@ FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, co
|
||||||
|
typedef struct {
|
||||||
|
mbedtls_oid_descriptor_t descriptor;
|
||||||
|
int ext_type;
|
||||||
|
+ int is_supported;
|
||||||
|
} oid_x509_ext_t;
|
||||||
|
|
||||||
|
static const oid_x509_ext_t oid_x509_ext[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
- { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" },
|
||||||
|
- MBEDTLS_X509_EXT_BASIC_CONSTRAINTS,
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), "id-ce-authorityKeyIdentifier", "Authority Key Identifier" },
|
||||||
|
+ MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER, 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
- { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" },
|
||||||
|
- MBEDTLS_X509_EXT_KEY_USAGE,
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), "id-ce-subjectKeyIdentifier", "Subject Key Identifier" },
|
||||||
|
+ MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER, 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
- { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" },
|
||||||
|
- MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE,
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" },
|
||||||
|
+ MBEDTLS_X509_EXT_KEY_USAGE, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
- { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" },
|
||||||
|
- MBEDTLS_X509_EXT_SUBJECT_ALT_NAME,
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" },
|
||||||
|
+ MBEDTLS_X509_EXT_CERTIFICATE_POLICIES, 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
- { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" },
|
||||||
|
- MBEDTLS_X509_EXT_NS_CERT_TYPE,
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_POLICY_MAPPINGS ), "id-ce-policyMappings", "Policy Mapping" },
|
||||||
|
+ MBEDTLS_X509_EXT_POLICY_MAPPINGS, 0,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_ISSUER_ALT_NAME ), "id-ce-issuerAltName", "Issuer Alt Name" },
|
||||||
|
+ MBEDTLS_X509_EXT_ISSUER_ALT_NAME, 0,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS ), "id-ce-subjectDirectoryAttributes", "Subject Directory Attributes" },
|
||||||
|
+ MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS, 0,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" },
|
||||||
|
+ MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, 1,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_NAME_CONSTRAINTS ), "id-ce-nameConstraints", "Name Constraints" },
|
||||||
|
+ MBEDTLS_X509_EXT_NAME_CONSTRAINTS, 0,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_POLICY_CONSTRAINTS ), "id-ce-policyConstraints", "Policy Constraints" },
|
||||||
|
+ MBEDTLS_X509_EXT_POLICY_CONSTRAINTS, 0,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" },
|
||||||
|
+ MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, 1
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_CRL_DISTRIBUTION_POINTS ), "id-ce-cRLDistributionPoints", "CRL Distribution Points" },
|
||||||
|
+ MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS, 0,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_INIHIBIT_ANYPOLICY ), "id-ce-inhibitAnyPolicy", "Inhibit Any Policy" },
|
||||||
|
+ MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY, 0,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_FRESHEST_CRL ), "id-ce-freshestCRL", "Freshest CRL" },
|
||||||
|
+ MBEDTLS_X509_EXT_FRESHEST_CRL, 0,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" },
|
||||||
|
+ MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, 1
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" },
|
||||||
|
+ MBEDTLS_X509_EXT_NS_CERT_TYPE, 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ NULL, 0, NULL, NULL },
|
||||||
|
- 0,
|
||||||
|
+ 0, 0
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)
|
||||||
|
-FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type)
|
||||||
|
+FN_OID_GET_ATTR2(mbedtls_oid_get_x509_ext_type_supported, oid_x509_ext_t, x509_ext, int, ext_type, int, is_supported)
|
||||||
|
+
|
||||||
|
+int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type )
|
||||||
|
+{
|
||||||
|
+ int ret = 0;
|
||||||
|
+ int is_supported = 0;
|
||||||
|
+
|
||||||
|
+ ret = mbedtls_oid_get_x509_ext_type_supported(oid, ext_type, &is_supported);
|
||||||
|
+ if( is_supported == 0 )
|
||||||
|
+ ret = MBEDTLS_ERR_OID_NOT_FOUND;
|
||||||
|
+
|
||||||
|
+ return( ret );
|
||||||
|
+}
|
||||||
|
|
||||||
|
static const mbedtls_oid_descriptor_t oid_ext_key_usage[] =
|
||||||
|
{
|
||||||
|
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
|
||||||
|
index 661ae706..ed1f7b67 100644
|
||||||
|
--- a/library/ssl_tls.c
|
||||||
|
+++ b/library/ssl_tls.c
|
||||||
|
@@ -4468,6 +4468,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
|
||||||
|
|
||||||
|
mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert );
|
||||||
|
|
||||||
|
+ ssl->session_negotiate->peer_cert->allowed_unsupported_critical_exts =
|
||||||
|
+ ssl->conf->allowed_unsupported_critical_exts;
|
||||||
|
+
|
||||||
|
i += 3;
|
||||||
|
|
||||||
|
while( i < ssl->in_hslen )
|
||||||
|
@@ -6344,6 +6347,11 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf,
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
||||||
|
|
||||||
|
+void mbedtls_ssl_conf_allow_unsupported_critical_exts( mbedtls_ssl_config *conf, uint32_t exts )
|
||||||
|
+{
|
||||||
|
+ conf->allowed_unsupported_critical_exts = exts;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||||
|
#if defined(MBEDTLS_SSL_CLI_C)
|
||||||
|
void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets )
|
||||||
|
diff --git a/library/x509_crt.c b/library/x509_crt.c
|
||||||
|
index c6209fb4..1a61e5e9 100644
|
||||||
|
--- a/library/x509_crt.c
|
||||||
|
+++ b/library/x509_crt.c
|
||||||
|
@@ -526,6 +526,7 @@ static int x509_get_crt_ext( unsigned char **p,
|
||||||
|
int ret;
|
||||||
|
size_t len;
|
||||||
|
unsigned char *end_ext_data, *end_ext_octet;
|
||||||
|
+ int is_supported;
|
||||||
|
|
||||||
|
if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
|
||||||
|
{
|
||||||
|
@@ -585,9 +586,9 @@ static int x509_get_crt_ext( unsigned char **p,
|
||||||
|
/*
|
||||||
|
* Detect supported extensions
|
||||||
|
*/
|
||||||
|
- ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
|
||||||
|
+ ret = mbedtls_oid_get_x509_ext_type_supported( &extn_oid, &ext_type, &is_supported );
|
||||||
|
|
||||||
|
- if( ret != 0 )
|
||||||
|
+ if( ( ret != 0 ) || ( is_supported == 0 ) )
|
||||||
|
{
|
||||||
|
/* No parser found, skip extension */
|
||||||
|
*p = end_ext_octet;
|
||||||
|
@@ -595,6 +596,10 @@ static int x509_get_crt_ext( unsigned char **p,
|
||||||
|
#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
|
||||||
|
if( is_critical )
|
||||||
|
{
|
||||||
|
+ /* Do not fail if extension is found, but unsupported and allowed in runtime */
|
||||||
|
+ if( ( ret == 0 ) && ( ext_type & crt->allowed_unsupported_critical_exts ) )
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
/* Data is marked as critical: fail */
|
||||||
|
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
|
||||||
|
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
|
||||||
|
@@ -948,6 +953,7 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu
|
||||||
|
|
||||||
|
prev = crt;
|
||||||
|
mbedtls_x509_crt_init( crt->next );
|
||||||
|
+ crt->next->allowed_unsupported_critical_exts = crt->allowed_unsupported_critical_exts;
|
||||||
|
crt = crt->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/tests/data_files/test-ca-nc.crt b/tests/data_files/test-ca-nc.crt
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..7e0c5613
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/data_files/test-ca-nc.crt
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+-----BEGIN CERTIFICATE-----
|
||||||
|
+MIIDSzCCAjOgAwIBAgIJAJx/NjT4C4viMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNV
|
||||||
|
+BAMMCExlZXZpQ0E0MB4XDTE4MDEyNzE1MDczMloXDTI4MDEyNTE1MDczMlowEzER
|
||||||
|
+MA8GA1UEAwwITGVldmlDQTQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||||
|
+AQDWN79RTlyFm5o0LVMSVjc68W0+gtl95xpaaD7IS6gDYjcbGnCwSefiq7y9rtck
|
||||||
|
+OM1A5Bzhj5+iWbmZStUmeJUhSGgxP/FxuUaAV0fsBGJ5jDrzmbhzDkHsNxDMB2ks
|
||||||
|
+XFyy4LfODcBs9TXxY43KUKuq/0meiT3WAaZWHMYle9vkQJM2l0RyH4IXHCHiIRwd
|
||||||
|
+2wntin6T9QOFJOc2ietNb7KsXVne81wb7h9BVMsjCIAsbPpHa+PZQs1xFuxmRxCs
|
||||||
|
+kpavnMy+SqevHhvqtvbHppcXYtZspTnkVoXWUdx3HHXgZMQKlAWlwyx57xpZBU2g
|
||||||
|
+qksO+KCLVYOQMN9usmuMOpHHAgMBAAGjgaEwgZ4wHQYDVR0eAQH/BBMwEaAPMA2C
|
||||||
|
+C2V4YW1wbGUuY29tMB0GA1UdDgQWBBR3T9IilPeRAFfLO8ocg216OBo+6DBDBgNV
|
||||||
|
+HSMEPDA6gBR3T9IilPeRAFfLO8ocg216OBo+6KEXpBUwEzERMA8GA1UEAwwITGVl
|
||||||
|
+dmlDQTSCCQCcfzY0+AuL4jAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkq
|
||||||
|
+hkiG9w0BAQsFAAOCAQEAR086ciNM3ujSQNhhguqFHYGfDRRuAgOk4l7GXIfFa9te
|
||||||
|
+B2KMLSwP367QaMwFxRrOoDvixIjzbpiiKB3cv+IXqGyfsRJw47XLwGK4FtSsXjst
|
||||||
|
+m2M8W5iXBQ94XoLj9OKb4ZJWKI930S/PF7uuxICtWttYSoylfyMkiR45+1SLj2eF
|
||||||
|
+X4EnXK3Q0H42v8LCDFqj9iNQ2WMLwA7kFPB+oOZxkFi2G0F3VuW+JZeBPQCpYdRO
|
||||||
|
+0kQQ/gIZE6KEdscKHi9y6OfGSeRlDBMADky9NiZy7I3AcspLcmMQh/191/DnooNe
|
||||||
|
+OwQ6w1HweApjB46bGyILpGUi9MZhvCnoLWg+cN3/wQ==
|
||||||
|
+-----END CERTIFICATE-----
|
||||||
|
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
|
||||||
|
index b8c902e2..e7dcb61f 100644
|
||||||
|
--- a/tests/suites/test_suite_x509parse.data
|
||||||
|
+++ b/tests/suites/test_suite_x509parse.data
|
||||||
|
@@ -1574,6 +1574,12 @@ X509 File parse (trailing spaces, OK)
|
||||||
|
depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
|
||||||
|
x509parse_crt_file:"data_files/server7_trailing_space.crt":0
|
||||||
|
|
||||||
|
+X509 File parse (unsupported critical ext Name Constraints, fail)
|
||||||
|
+x509parse_crt_file:"data_files/test-ca-nc.crt":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
|
||||||
|
+
|
||||||
|
+X509 File parse (allowed unsupported critical ext Name Constraints, ok)
|
||||||
|
+x509parse_crt_file_allow_exts:"data_files/test-ca-nc.crt":MBEDTLS_X509_EXT_NAME_CONSTRAINTS:0
|
||||||
|
+
|
||||||
|
X509 Get time (UTC no issues)
|
||||||
|
depends_on:MBEDTLS_X509_USE_C
|
||||||
|
x509_get_time:MBEDTLS_ASN1_UTC_TIME:"500101000000Z":0:1950:1:1:0:0:0
|
||||||
|
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
|
||||||
|
index 0dfdd61c..2be1defd 100644
|
||||||
|
--- a/tests/suites/test_suite_x509parse.function
|
||||||
|
+++ b/tests/suites/test_suite_x509parse.function
|
||||||
|
@@ -395,6 +395,21 @@ exit:
|
||||||
|
}
|
||||||
|
/* END_CASE */
|
||||||
|
|
||||||
|
+/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_FS_IO */
|
||||||
|
+void x509parse_crt_file_allow_exts( char *crt_file, int exts, int result )
|
||||||
|
+{
|
||||||
|
+ mbedtls_x509_crt crt;
|
||||||
|
+
|
||||||
|
+ mbedtls_x509_crt_init( &crt );
|
||||||
|
+ crt.allowed_unsupported_critical_exts = exts;
|
||||||
|
+
|
||||||
|
+ TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == result );
|
||||||
|
+
|
||||||
|
+exit:
|
||||||
|
+ mbedtls_x509_crt_free( &crt );
|
||||||
|
+}
|
||||||
|
+/* END_CASE */
|
||||||
|
+
|
||||||
|
/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C */
|
||||||
|
void x509parse_crt( char *crt_data, char *result_str, int result )
|
||||||
|
{
|
||||||
|
--
|
||||||
|
2.14.3 (Apple Git-98)
|
||||||
|
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# build ovpn3-core with system-provided mbedtls and lz4 on various linux distros
|
||||||
|
|
||||||
|
docker build -f dockerfiles/Dockerfile.debian -t deb .
|
||||||
|
docker run -it deb
|
||||||
|
|
||||||
|
docker build -f dockerfiles/Dockerfile.ubu -t ubu .
|
||||||
|
docker run -it ubu
|
||||||
|
|
||||||
|
docker build -f dockerfiles/Dockerfile.centos -t cnt .
|
||||||
|
docker run -it cnt
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
FROM centos/devtoolset-7-toolchain-centos7
|
||||||
|
|
||||||
|
USER 0
|
||||||
|
RUN yum -y update && yum -y install epel-release && \
|
||||||
|
yum -y install -y mbedtls-devel lz4-devel git wget perl-Digest-SHA make
|
||||||
|
|
||||||
|
ADD . /ovpn3/core
|
||||||
|
|
||||||
|
ENV O3 /ovpn3/
|
||||||
|
ENV DEP_DIR /ovpn3/deps
|
||||||
|
ENV DL /ovpn3/dl
|
||||||
|
|
||||||
|
CMD mkdir $DEP_DIR && mkdir $DL && \
|
||||||
|
/ovpn3/core/scripts/linux/build-all && \
|
||||||
|
cd $O3/core/test/ovpncli && \
|
||||||
|
ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli && \
|
||||||
|
cd $O3/core/test/ssl && \
|
||||||
|
ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build proto && \
|
||||||
|
./proto
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
FROM debian:9
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y autoconf build-essential wget git liblz4-dev libmbedtls-dev
|
||||||
|
|
||||||
|
ADD . /ovpn3/core
|
||||||
|
|
||||||
|
ENV O3 /ovpn3/
|
||||||
|
ENV DEP_DIR /ovpn3/deps
|
||||||
|
ENV DL /ovpn3/dl
|
||||||
|
|
||||||
|
CMD mkdir $DEP_DIR && mkdir $DL && \
|
||||||
|
/ovpn3/core/scripts/linux/build-all && \
|
||||||
|
cd $O3/core/test/ovpncli && \
|
||||||
|
ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli && \
|
||||||
|
cd $O3/core/test/ssl && \
|
||||||
|
ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build proto && \
|
||||||
|
./proto
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
FROM ubuntu:16.04
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y autoconf build-essential wget git liblz4-dev libmbedtls-dev
|
||||||
|
|
||||||
|
ADD . /ovpn3/core
|
||||||
|
|
||||||
|
ENV O3 /ovpn3/
|
||||||
|
ENV DEP_DIR /ovpn3/deps
|
||||||
|
ENV DL /ovpn3/dl
|
||||||
|
|
||||||
|
CMD mkdir $DEP_DIR && mkdir $DL && \
|
||||||
|
/ovpn3/core/scripts/linux/build-all && \
|
||||||
|
cd $O3/core/test/ovpncli && \
|
||||||
|
ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli && \
|
||||||
|
cd $O3/core/test/ssl && \
|
||||||
|
ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build proto && \
|
||||||
|
./proto
|
||||||
@@ -54,6 +54,7 @@ namespace openvpn {
|
|||||||
PAUSE,
|
PAUSE,
|
||||||
RESUME,
|
RESUME,
|
||||||
RELAY,
|
RELAY,
|
||||||
|
UNSUPPORTED_FEATURE,
|
||||||
|
|
||||||
// start of nonfatal errors, must be marked by NONFATAL_ERROR_START below
|
// start of nonfatal errors, must be marked by NONFATAL_ERROR_START below
|
||||||
TRANSPORT_ERROR,
|
TRANSPORT_ERROR,
|
||||||
@@ -105,6 +106,7 @@ namespace openvpn {
|
|||||||
"PAUSE",
|
"PAUSE",
|
||||||
"RESUME",
|
"RESUME",
|
||||||
"RELAY",
|
"RELAY",
|
||||||
|
"UNSUPPORTED_FEATURE",
|
||||||
|
|
||||||
// nonfatal errors
|
// nonfatal errors
|
||||||
"TRANSPORT_ERROR",
|
"TRANSPORT_ERROR",
|
||||||
@@ -253,6 +255,28 @@ namespace openvpn {
|
|||||||
TLSVersionMinFail() : Base(TLS_VERSION_MIN) {}
|
TLSVersionMinFail() : Base(TLS_VERSION_MIN) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UnsupportedFeature : public Base
|
||||||
|
{
|
||||||
|
typedef RCPtr<UnsupportedFeature> Ptr;
|
||||||
|
|
||||||
|
UnsupportedFeature(const std::string& name_arg, const std::string& reason_arg, bool critical_arg)
|
||||||
|
: Base(UNSUPPORTED_FEATURE),
|
||||||
|
name(name_arg),
|
||||||
|
reason(reason_arg),
|
||||||
|
critical(critical_arg) {}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string reason;
|
||||||
|
bool critical;
|
||||||
|
|
||||||
|
virtual std::string render() const
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
out << "name: " << name << ", reason: " << reason << ", critical: " << critical;
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Connected : public Base
|
struct Connected : public Base
|
||||||
{
|
{
|
||||||
typedef RCPtr<Connected> Ptr;
|
typedef RCPtr<Connected> Ptr;
|
||||||
|
|||||||
@@ -667,6 +667,9 @@ namespace openvpn {
|
|||||||
if (relay_mode)
|
if (relay_mode)
|
||||||
lflags |= SSLConfigAPI::LF_RELAY_MODE;
|
lflags |= SSLConfigAPI::LF_RELAY_MODE;
|
||||||
|
|
||||||
|
if (opt.exists("allow-name-constraints"))
|
||||||
|
lflags |= SSLConfigAPI::LF_ALLOW_NAME_CONSTRAINTS;
|
||||||
|
|
||||||
// client SSL config
|
// client SSL config
|
||||||
SSLLib::SSLAPI::Config::Ptr cc(new SSLLib::SSLAPI::Config());
|
SSLLib::SSLAPI::Config::Ptr cc(new SSLLib::SSLAPI::Config());
|
||||||
cc->set_external_pki_callback(config.external_pki);
|
cc->set_external_pki_callback(config.external_pki);
|
||||||
@@ -730,7 +733,6 @@ namespace openvpn {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (dco)
|
if (dco)
|
||||||
{
|
{
|
||||||
DCO::TransportConfig transconf;
|
DCO::TransportConfig transconf;
|
||||||
@@ -789,7 +791,11 @@ namespace openvpn {
|
|||||||
#endif
|
#endif
|
||||||
transport_factory = udpconf;
|
transport_factory = udpconf;
|
||||||
}
|
}
|
||||||
else if (transport_protocol.is_tcp())
|
else if (transport_protocol.is_tcp()
|
||||||
|
#ifdef OPENVPN_TLS_LINK
|
||||||
|
|| transport_protocol.is_tls()
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// TCP transport
|
// TCP transport
|
||||||
TCPTransport::ClientConfig::Ptr tcpconf = TCPTransport::ClientConfig::new_obj();
|
TCPTransport::ClientConfig::Ptr tcpconf = TCPTransport::ClientConfig::new_obj();
|
||||||
@@ -797,6 +803,10 @@ namespace openvpn {
|
|||||||
tcpconf->frame = frame;
|
tcpconf->frame = frame;
|
||||||
tcpconf->stats = cli_stats;
|
tcpconf->stats = cli_stats;
|
||||||
tcpconf->socket_protect = socket_protect;
|
tcpconf->socket_protect = socket_protect;
|
||||||
|
#ifdef OPENVPN_TLS_LINK
|
||||||
|
if (transport_protocol.is_tls())
|
||||||
|
tcpconf->use_tls = true;
|
||||||
|
#endif
|
||||||
#ifdef OPENVPN_GREMLIN
|
#ifdef OPENVPN_GREMLIN
|
||||||
tcpconf->gremlin_config = gremlin_config;
|
tcpconf->gremlin_config = gremlin_config;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -291,10 +291,15 @@ namespace openvpn {
|
|||||||
protoConfig->load(options, ProtoContextOptions(), -1, false);
|
protoConfig->load(options, ProtoContextOptions(), -1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int lflags = SSLConfigAPI::LF_PARSE_MODE;
|
||||||
|
|
||||||
|
if (options.exists("allow-name-constraints"))
|
||||||
|
lflags |= SSLConfigAPI::LF_ALLOW_NAME_CONSTRAINTS;
|
||||||
|
|
||||||
// ssl lib configuration
|
// ssl lib configuration
|
||||||
try {
|
try {
|
||||||
sslConfig.reset(new SSLLib::SSLAPI::Config());
|
sslConfig.reset(new SSLLib::SSLAPI::Config());
|
||||||
sslConfig->load(options, SSLConfigAPI::LF_PARSE_MODE);
|
sslConfig->load(options, lflags);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
sslConfig.reset();
|
sslConfig.reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -795,6 +795,12 @@ namespace openvpn {
|
|||||||
ClientEvent::Base::Ptr ev = new ClientEvent::Warn("TLS: received certificate signed with MD5. Please inform your admin to upgrade to a stronger algorithm. Support for MD5 will be dropped at end of Apr 2018");
|
ClientEvent::Base::Ptr ev = new ClientEvent::Warn("TLS: received certificate signed with MD5. Please inform your admin to upgrade to a stronger algorithm. Support for MD5 will be dropped at end of Apr 2018");
|
||||||
cli_events->add_event(std::move(ev));
|
cli_events->add_event(std::move(ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tls_warnings & SSLAPI::TLS_WARN_NAME_CONSTRAINTS)
|
||||||
|
{
|
||||||
|
ClientEvent::Base::Ptr ev = new ClientEvent::Warn("TLS: Your CA contains a 'x509v3 Name Constraints' extension, but its validation is not supported. This might be a security breach, please contact your administrator.");
|
||||||
|
cli_events->add_event(std::move(ev));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// base class calls here when primary session transitions to ACTIVE state
|
// base class calls here when primary session transitions to ACTIVE state
|
||||||
|
|||||||
@@ -130,12 +130,12 @@ namespace openvpn {
|
|||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
~X509Cert()
|
virtual ~X509Cert()
|
||||||
{
|
{
|
||||||
dealloc();
|
dealloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void alloc()
|
void alloc()
|
||||||
{
|
{
|
||||||
if (!chain)
|
if (!chain)
|
||||||
@@ -145,6 +145,9 @@ namespace openvpn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mbedtls_x509_crt *chain;
|
||||||
|
|
||||||
|
private:
|
||||||
void dealloc()
|
void dealloc()
|
||||||
{
|
{
|
||||||
if (chain)
|
if (chain)
|
||||||
@@ -155,8 +158,6 @@ namespace openvpn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_x509_crt *chain;
|
|
||||||
|
|
||||||
static const std::string begin_cert;
|
static const std::string begin_cert;
|
||||||
static const std::string end_cert;
|
static const std::string end_cert;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include <mbedtls/oid.h>
|
#include <mbedtls/oid.h>
|
||||||
#include <mbedtls/sha1.h>
|
#include <mbedtls/sha1.h>
|
||||||
#include <mbedtls/debug.h>
|
#include <mbedtls/debug.h>
|
||||||
|
#include <mbedtls/asn1.h>
|
||||||
|
|
||||||
#include <openvpn/common/size.hpp>
|
#include <openvpn/common/size.hpp>
|
||||||
#include <openvpn/common/exception.hpp>
|
#include <openvpn/common/exception.hpp>
|
||||||
@@ -211,7 +212,8 @@ namespace openvpn {
|
|||||||
tls_cert_profile(TLSCertProfile::UNDEF),
|
tls_cert_profile(TLSCertProfile::UNDEF),
|
||||||
local_cert_enabled(true),
|
local_cert_enabled(true),
|
||||||
enable_renegotiation(false),
|
enable_renegotiation(false),
|
||||||
force_aes_cbc_ciphersuites(false) {}
|
force_aes_cbc_ciphersuites(false),
|
||||||
|
allow_name_constraints(false) {}
|
||||||
|
|
||||||
virtual SSLFactoryAPI::Ptr new_factory()
|
virtual SSLFactoryAPI::Ptr new_factory()
|
||||||
{
|
{
|
||||||
@@ -456,6 +458,8 @@ namespace openvpn {
|
|||||||
&& opt.exists("client-cert-not-required"))
|
&& opt.exists("client-cert-not-required"))
|
||||||
flags |= SSLConst::NO_VERIFY_PEER;
|
flags |= SSLConst::NO_VERIFY_PEER;
|
||||||
|
|
||||||
|
allow_name_constraints = lflags & LF_ALLOW_NAME_CONSTRAINTS;
|
||||||
|
|
||||||
// ca
|
// ca
|
||||||
{
|
{
|
||||||
std::string ca_txt = opt.cat("ca");
|
std::string ca_txt = opt.cat("ca");
|
||||||
@@ -532,6 +536,16 @@ namespace openvpn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool name_constraints_allowed() const
|
||||||
|
{
|
||||||
|
return allow_name_constraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_server() const
|
||||||
|
{
|
||||||
|
return mode.is_server();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const mbedtls_x509_crt_profile *select_crt_profile() const
|
const mbedtls_x509_crt_profile *select_crt_profile() const
|
||||||
{
|
{
|
||||||
@@ -553,8 +567,12 @@ namespace openvpn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Mode mode;
|
Mode mode;
|
||||||
|
|
||||||
|
protected:
|
||||||
MbedTLSPKI::X509Cert::Ptr crt_chain; // local cert chain (including client cert + extra certs)
|
MbedTLSPKI::X509Cert::Ptr crt_chain; // local cert chain (including client cert + extra certs)
|
||||||
MbedTLSPKI::X509Cert::Ptr ca_chain; // CA chain for remote verification
|
MbedTLSPKI::X509Cert::Ptr ca_chain; // CA chain for remote verification
|
||||||
|
|
||||||
|
private:
|
||||||
MbedTLSPKI::X509CRL::Ptr crl_chain; // CRL chain for remote verification
|
MbedTLSPKI::X509CRL::Ptr crl_chain; // CRL chain for remote verification
|
||||||
MbedTLSPKI::PKContext::Ptr priv_key; // private key
|
MbedTLSPKI::PKContext::Ptr priv_key; // private key
|
||||||
std::string priv_key_pwd; // private key password
|
std::string priv_key_pwd; // private key password
|
||||||
@@ -573,6 +591,7 @@ namespace openvpn {
|
|||||||
bool local_cert_enabled;
|
bool local_cert_enabled;
|
||||||
bool enable_renegotiation;
|
bool enable_renegotiation;
|
||||||
bool force_aes_cbc_ciphersuites;
|
bool force_aes_cbc_ciphersuites;
|
||||||
|
bool allow_name_constraints;
|
||||||
RandomAPI::Ptr rng; // random data source
|
RandomAPI::Ptr rng; // random data source
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -649,6 +668,14 @@ namespace openvpn {
|
|||||||
overflow = true;
|
overflow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void write_ciphertext_unbuffered(const unsigned char *data, const size_t size)
|
||||||
|
{
|
||||||
|
if (ct_in.size() < MAX_CIPHERTEXT_IN)
|
||||||
|
ct_in.write(data, size);
|
||||||
|
else
|
||||||
|
overflow = true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool read_ciphertext_ready() const
|
virtual bool read_ciphertext_ready() const
|
||||||
{
|
{
|
||||||
return !ct_out.empty();
|
return !ct_out.empty();
|
||||||
@@ -676,12 +703,12 @@ namespace openvpn {
|
|||||||
return authcert;
|
return authcert;
|
||||||
}
|
}
|
||||||
|
|
||||||
~SSL()
|
virtual ~SSL()
|
||||||
{
|
{
|
||||||
erase();
|
erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
SSL(MbedTLSContext* ctx, const char *hostname)
|
SSL(MbedTLSContext* ctx, const char *hostname)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
@@ -863,6 +890,10 @@ namespace openvpn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_config *sslconf; // SSL configuration parameters for SSL connection object
|
||||||
|
MbedTLSContext *parent;
|
||||||
|
|
||||||
|
private:
|
||||||
// cleartext read callback
|
// cleartext read callback
|
||||||
static int ct_read_func(void *arg, unsigned char *data, size_t length)
|
static int ct_read_func(void *arg, unsigned char *data, size_t length)
|
||||||
{
|
{
|
||||||
@@ -925,9 +956,7 @@ namespace openvpn {
|
|||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
MbedTLSContext *parent;
|
|
||||||
mbedtls_ssl_context *ssl; // underlying SSL connection object
|
mbedtls_ssl_context *ssl; // underlying SSL connection object
|
||||||
mbedtls_ssl_config *sslconf; // SSL configuration parameters for SSL connection object
|
|
||||||
MbedTLSPKI::PKContext epki_ctx; // external PKI context
|
MbedTLSPKI::PKContext epki_ctx; // external PKI context
|
||||||
RandomAPI::Ptr rng; // random data source
|
RandomAPI::Ptr rng; // random data source
|
||||||
MemQStream ct_in; // write ciphertext to here
|
MemQStream ct_in; // write ciphertext to here
|
||||||
@@ -955,12 +984,12 @@ namespace openvpn {
|
|||||||
return config->mode;
|
return config->mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
~MbedTLSContext()
|
virtual ~MbedTLSContext()
|
||||||
{
|
{
|
||||||
erase();
|
erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
MbedTLSContext(Config* config_arg)
|
MbedTLSContext(Config* config_arg)
|
||||||
: config(config_arg)
|
: config(config_arg)
|
||||||
{
|
{
|
||||||
@@ -972,6 +1001,7 @@ namespace openvpn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
size_t key_len() const
|
size_t key_len() const
|
||||||
{
|
{
|
||||||
return mbedtls_pk_get_bitlen(&config->crt_chain->get()->pk) / 8;
|
return mbedtls_pk_get_bitlen(&config->crt_chain->get()->pk) / 8;
|
||||||
@@ -1114,6 +1144,7 @@ namespace openvpn {
|
|||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
static int verify_callback_client(void *arg, mbedtls_x509_crt *cert, int depth, uint32_t *flags)
|
static int verify_callback_client(void *arg, mbedtls_x509_crt *cert, int depth, uint32_t *flags)
|
||||||
{
|
{
|
||||||
MbedTLSContext::SSL *ssl = (MbedTLSContext::SSL *)arg;
|
MbedTLSContext::SSL *ssl = (MbedTLSContext::SSL *)arg;
|
||||||
@@ -1231,6 +1262,9 @@ namespace openvpn {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Config::Ptr config;
|
||||||
|
|
||||||
|
private:
|
||||||
static std::string cert_info(const mbedtls_x509_crt *cert, const char *prefix = nullptr)
|
static std::string cert_info(const mbedtls_x509_crt *cert, const char *prefix = nullptr)
|
||||||
{
|
{
|
||||||
const size_t buf_size = 4096;
|
const size_t buf_size = 4096;
|
||||||
@@ -1354,8 +1388,6 @@ namespace openvpn {
|
|||||||
MbedTLSContext *self = (MbedTLSContext *) arg;
|
MbedTLSContext *self = (MbedTLSContext *) arg;
|
||||||
return self->key_len();
|
return self->key_len();
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::Ptr config;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace openvpn
|
} // namespace openvpn
|
||||||
|
|||||||
@@ -469,6 +469,15 @@ namespace openvpn {
|
|||||||
overflow = true;
|
overflow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void write_ciphertext_unbuffered(const unsigned char *data, const size_t size)
|
||||||
|
{
|
||||||
|
bmq_stream::MemQ* in = bmq_stream::memq_from_bio(ct_in);
|
||||||
|
if (in->size() < MAX_CIPHERTEXT_IN)
|
||||||
|
in->write(data, size);
|
||||||
|
else
|
||||||
|
overflow = true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool read_ciphertext_ready() const
|
virtual bool read_ciphertext_ready() const
|
||||||
{
|
{
|
||||||
return !bmq_stream::memq_from_bio(ct_out)->empty();
|
return !bmq_stream::memq_from_bio(ct_out)->empty();
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ namespace openvpn {
|
|||||||
|
|
||||||
enum TLSWarnings {
|
enum TLSWarnings {
|
||||||
TLS_WARN_SIG_MD5 = (1 << 0),
|
TLS_WARN_SIG_MD5 = (1 << 0),
|
||||||
|
TLS_WARN_NAME_CONSTRAINTS = (1 << 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef RCPtr<SSLAPI> Ptr;
|
typedef RCPtr<SSLAPI> Ptr;
|
||||||
@@ -60,6 +61,7 @@ namespace openvpn {
|
|||||||
virtual ssize_t read_cleartext(void *data, const size_t capacity) = 0;
|
virtual ssize_t read_cleartext(void *data, const size_t capacity) = 0;
|
||||||
virtual bool read_cleartext_ready() const = 0;
|
virtual bool read_cleartext_ready() const = 0;
|
||||||
virtual void write_ciphertext(const BufferPtr& buf) = 0;
|
virtual void write_ciphertext(const BufferPtr& buf) = 0;
|
||||||
|
virtual void write_ciphertext_unbuffered(const unsigned char *data, const size_t size) = 0;
|
||||||
virtual bool read_ciphertext_ready() const = 0;
|
virtual bool read_ciphertext_ready() const = 0;
|
||||||
virtual BufferPtr read_ciphertext() = 0;
|
virtual BufferPtr read_ciphertext() = 0;
|
||||||
virtual std::string ssl_handshake_details() const = 0;
|
virtual std::string ssl_handshake_details() const = 0;
|
||||||
@@ -112,6 +114,7 @@ namespace openvpn {
|
|||||||
LF_PARSE_MODE = (1<<0),
|
LF_PARSE_MODE = (1<<0),
|
||||||
LF_ALLOW_CLIENT_CERT_NOT_REQUIRED = (1<<1),
|
LF_ALLOW_CLIENT_CERT_NOT_REQUIRED = (1<<1),
|
||||||
LF_RELAY_MODE = (1<<2), // look for "relay-ca" instead of "ca" directive
|
LF_RELAY_MODE = (1<<2), // look for "relay-ca" instead of "ca" directive
|
||||||
|
LF_ALLOW_NAME_CONSTRAINTS = (1<<3) // do not fail on Name Constraints ext and drop a warning to UI
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string private_key_type_string() const
|
std::string private_key_type_string() const
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
#include <openvpn/mbedtls/crypto/api.hpp>
|
#include <openvpn/mbedtls/crypto/api.hpp>
|
||||||
#include <openvpn/mbedtls/ssl/sslctx.hpp>
|
#include <openvpn/mbedtls/ssl/sslctx.hpp>
|
||||||
#include <openvpn/mbedtls/util/rand.hpp>
|
#include <openvpn/mbedtls/util/rand.hpp>
|
||||||
|
#ifdef HAVE_OPENVPN_COMMON
|
||||||
|
#include <openvpn/mbedtls/ssl/sslctxnc.hpp>
|
||||||
|
#endif
|
||||||
#ifdef OPENVPN_PLATFORM_UWP
|
#ifdef OPENVPN_PLATFORM_UWP
|
||||||
#include <openvpn/mbedtls/util/uwprand.hpp>
|
#include <openvpn/mbedtls/util/uwprand.hpp>
|
||||||
#endif
|
#endif
|
||||||
@@ -56,7 +59,11 @@ namespace openvpn {
|
|||||||
#if defined(USE_MBEDTLS)
|
#if defined(USE_MBEDTLS)
|
||||||
#define SSL_LIB_NAME "MbedTLS"
|
#define SSL_LIB_NAME "MbedTLS"
|
||||||
typedef MbedTLSCryptoAPI CryptoAPI;
|
typedef MbedTLSCryptoAPI CryptoAPI;
|
||||||
|
#ifdef HAVE_OPENVPN_COMMON
|
||||||
|
typedef MbedTLSContextNameConstraints SSLAPI;
|
||||||
|
#else
|
||||||
typedef MbedTLSContext SSLAPI;
|
typedef MbedTLSContext SSLAPI;
|
||||||
|
#endif
|
||||||
#if defined OPENVPN_PLATFORM_UWP
|
#if defined OPENVPN_PLATFORM_UWP
|
||||||
typedef MbedTLSRandomWithUWPEntropy RandomAPI;
|
typedef MbedTLSRandomWithUWPEntropy RandomAPI;
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ namespace openvpn {
|
|||||||
typedef TCPTransport::Link<openvpn_io::ip::tcp, Client*, false> LinkImpl;
|
typedef TCPTransport::Link<openvpn_io::ip::tcp, Client*, false> LinkImpl;
|
||||||
|
|
||||||
friend class ClientConfig; // calls constructor
|
friend class ClientConfig; // calls constructor
|
||||||
friend LinkImpl; // calls tcp_read_handler
|
friend LinkImpl::Base; // calls tcp_read_handler
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void transport_start()
|
virtual void transport_start()
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
#include <openvpn/io/io.hpp>
|
#include <openvpn/io/io.hpp>
|
||||||
|
|
||||||
#include <openvpn/transport/tcplink.hpp>
|
#include <openvpn/transport/tcplink.hpp>
|
||||||
|
#ifdef OPENVPN_TLS_LINK
|
||||||
|
#include <openvpn/transport/tlslink.hpp>
|
||||||
|
#endif
|
||||||
#include <openvpn/transport/client/transbase.hpp>
|
#include <openvpn/transport/client/transbase.hpp>
|
||||||
#include <openvpn/transport/socket_protect.hpp>
|
#include <openvpn/transport/socket_protect.hpp>
|
||||||
#include <openvpn/client/remotelist.hpp>
|
#include <openvpn/client/remotelist.hpp>
|
||||||
@@ -48,6 +51,10 @@ namespace openvpn {
|
|||||||
|
|
||||||
SocketProtect* socket_protect;
|
SocketProtect* socket_protect;
|
||||||
|
|
||||||
|
#ifdef OPENVPN_TLS_LINK
|
||||||
|
bool use_tls = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
#ifdef OPENVPN_GREMLIN
|
||||||
Gremlin::Config::Ptr gremlin_config;
|
Gremlin::Config::Ptr gremlin_config;
|
||||||
#endif
|
#endif
|
||||||
@@ -72,9 +79,12 @@ namespace openvpn {
|
|||||||
typedef RCPtr<Client> Ptr;
|
typedef RCPtr<Client> Ptr;
|
||||||
|
|
||||||
typedef Link<openvpn_io::ip::tcp, Client*, false> LinkImpl;
|
typedef Link<openvpn_io::ip::tcp, Client*, false> LinkImpl;
|
||||||
|
#ifdef OPENVPN_TLS_LINK
|
||||||
|
typedef TLSLink<openvpn_io::ip::tcp, Client*, false> LinkImplTLS;
|
||||||
|
#endif
|
||||||
|
|
||||||
friend class ClientConfig; // calls constructor
|
friend class ClientConfig; // calls constructor
|
||||||
friend LinkImpl; // calls tcp_read_handler
|
friend LinkImpl::Base; // calls tcp_read_handler
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void transport_start()
|
virtual void transport_start()
|
||||||
@@ -207,24 +217,24 @@ namespace openvpn {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_eof_handler() // called by LinkImpl
|
void tcp_eof_handler() // called by LinkImpl::Base
|
||||||
{
|
{
|
||||||
config->stats->error(Error::NETWORK_EOF_ERROR);
|
config->stats->error(Error::NETWORK_EOF_ERROR);
|
||||||
tcp_error_handler("NETWORK_EOF_ERROR");
|
tcp_error_handler("NETWORK_EOF_ERROR");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tcp_read_handler(BufferAllocated& buf) // called by LinkImpl
|
bool tcp_read_handler(BufferAllocated& buf) // called by LinkImpl::Base
|
||||||
{
|
{
|
||||||
parent->transport_recv(buf);
|
parent->transport_recv(buf);
|
||||||
return !stop_requeueing;
|
return !stop_requeueing;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_write_queue_needs_send() // called by LinkImpl
|
void tcp_write_queue_needs_send() // called by LinkImpl::Base
|
||||||
{
|
{
|
||||||
parent->transport_needs_send();
|
parent->transport_needs_send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_error_handler(const char *error) // called by LinkImpl
|
void tcp_error_handler(const char *error) // called by LinkImpl::Base
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "Transport error on '" << server_host << ": " << error;
|
os << "Transport error on '" << server_host << ": " << error;
|
||||||
@@ -302,12 +312,35 @@ namespace openvpn {
|
|||||||
{
|
{
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
|
#ifdef OPENVPN_TLS_LINK
|
||||||
|
if (config->use_tls)
|
||||||
|
{
|
||||||
|
SSLLib::SSLAPI::Config::Ptr ssl_conf;
|
||||||
|
ssl_conf.reset(new SSLLib::SSLAPI::Config());
|
||||||
|
ssl_conf->set_mode(Mode(Mode::CLIENT));
|
||||||
|
ssl_conf->set_flags(SSLConst::LOG_VERIFY_STATUS|SSLConst::NO_VERIFY_PEER);
|
||||||
|
ssl_conf->set_local_cert_enabled(false);
|
||||||
|
ssl_conf->set_frame(config->frame);
|
||||||
|
ssl_conf->set_rng(new SSLLib::RandomAPI(false));
|
||||||
|
|
||||||
|
impl.reset(new LinkImplTLS(this,
|
||||||
|
io_context,
|
||||||
|
socket,
|
||||||
|
0,
|
||||||
|
config->free_list_max_size,
|
||||||
|
config->frame,
|
||||||
|
config->stats,
|
||||||
|
ssl_conf->new_factory()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
impl.reset(new LinkImpl(this,
|
impl.reset(new LinkImpl(this,
|
||||||
socket,
|
socket,
|
||||||
0, // // send_queue_max_size is unlimited because we regulate size in cliproto.hpp
|
0, // send_queue_max_size is unlimited because we regulate size in cliproto.hpp
|
||||||
config->free_list_max_size,
|
config->free_list_max_size,
|
||||||
(*config->frame)[Frame::READ_LINK_TCP],
|
(*config->frame)[Frame::READ_LINK_TCP],
|
||||||
config->stats));
|
config->stats));
|
||||||
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
#ifdef OPENVPN_GREMLIN
|
||||||
impl->gremlin_config(config->gremlin_config);
|
impl->gremlin_config(config->gremlin_config);
|
||||||
#endif
|
#endif
|
||||||
@@ -334,9 +367,9 @@ namespace openvpn {
|
|||||||
openvpn_io::ip::tcp::socket socket;
|
openvpn_io::ip::tcp::socket socket;
|
||||||
ClientConfig::Ptr config;
|
ClientConfig::Ptr config;
|
||||||
TransportClientParent* parent;
|
TransportClientParent* parent;
|
||||||
LinkImpl::Ptr impl;
|
LinkBase::Ptr impl;
|
||||||
openvpn_io::ip::tcp::resolver resolver;
|
openvpn_io::ip::tcp::resolver resolver;
|
||||||
LinkImpl::protocol::endpoint server_endpoint;
|
LinkImpl::Base::protocol::endpoint server_endpoint;
|
||||||
bool halt;
|
bool halt;
|
||||||
bool stop_requeueing;
|
bool stop_requeueing;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,11 +41,14 @@ namespace openvpn {
|
|||||||
TCPv4,
|
TCPv4,
|
||||||
UDPv6,
|
UDPv6,
|
||||||
TCPv6,
|
TCPv6,
|
||||||
|
TLSv4, // TLS over IPv4
|
||||||
|
TLSv6, // TLS over IPv6
|
||||||
UnixStream, // unix domain socket (stream)
|
UnixStream, // unix domain socket (stream)
|
||||||
UnixDGram, // unix domain socket (datagram)
|
UnixDGram, // unix domain socket (datagram)
|
||||||
NamedPipe, // named pipe (Windows only)
|
NamedPipe, // named pipe (Windows only)
|
||||||
UDP=UDPv4,
|
UDP=UDPv4,
|
||||||
TCP=TCPv4,
|
TCP=TCPv4,
|
||||||
|
TLS=TLSv4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AllowSuffix {
|
enum AllowSuffix {
|
||||||
@@ -64,8 +67,9 @@ namespace openvpn {
|
|||||||
|
|
||||||
bool is_udp() const { return type_ == UDPv4 || type_ == UDPv6; }
|
bool is_udp() const { return type_ == UDPv4 || type_ == UDPv6; }
|
||||||
bool is_tcp() const { return type_ == TCPv4 || type_ == TCPv6; }
|
bool is_tcp() const { return type_ == TCPv4 || type_ == TCPv6; }
|
||||||
bool is_reliable() const { return is_tcp(); }
|
bool is_tls() const { return type_ == TLSv4 || type_ == TLSv6; }
|
||||||
bool is_ipv6() const { return type_ == UDPv6 || type_ == TCPv6; }
|
bool is_reliable() const { return is_tcp() || is_tls(); }
|
||||||
|
bool is_ipv6() const { return type_ == UDPv6 || type_ == TCPv6 || type_ == TLSv6; }
|
||||||
bool is_unix() const { return type_ == UnixStream || type_ == UnixDGram; }
|
bool is_unix() const { return type_ == UnixStream || type_ == UnixDGram; }
|
||||||
bool is_named_pipe() const { return type_ == NamedPipe; }
|
bool is_named_pipe() const { return type_ == NamedPipe; }
|
||||||
bool is_local() const { return is_unix() || is_named_pipe(); }
|
bool is_local() const { return is_unix() || is_named_pipe(); }
|
||||||
@@ -87,7 +91,7 @@ namespace openvpn {
|
|||||||
|
|
||||||
unsigned int extra_transport_bytes() const
|
unsigned int extra_transport_bytes() const
|
||||||
{
|
{
|
||||||
return is_tcp() ? sizeof(std::uint16_t) : 0;
|
return (is_tcp() || is_tls()) ? sizeof(std::uint16_t) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mod_addr_version(const IP::Addr& addr)
|
void mod_addr_version(const IP::Addr& addr)
|
||||||
@@ -101,12 +105,16 @@ namespace openvpn {
|
|||||||
type_ = UDPv4;
|
type_ = UDPv4;
|
||||||
else if (is_tcp())
|
else if (is_tcp())
|
||||||
type_ = TCPv4;
|
type_ = TCPv4;
|
||||||
|
else if (is_tls())
|
||||||
|
type_ = TLSv4;
|
||||||
break;
|
break;
|
||||||
case IP::Addr::V6:
|
case IP::Addr::V6:
|
||||||
if (is_udp())
|
if (is_udp())
|
||||||
type_ = UDPv6;
|
type_ = UDPv6;
|
||||||
else if (is_tcp())
|
else if (is_tcp())
|
||||||
type_ = TCPv6;
|
type_ = TCPv6;
|
||||||
|
else if (is_tls())
|
||||||
|
type_ = TLSv6;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,6 +165,9 @@ namespace openvpn {
|
|||||||
return 3;
|
return 3;
|
||||||
case NamedPipe:
|
case NamedPipe:
|
||||||
return 4;
|
return 4;
|
||||||
|
case TLSv4:
|
||||||
|
case TLSv6:
|
||||||
|
return 5;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -174,6 +185,10 @@ namespace openvpn {
|
|||||||
return "UDPv6";
|
return "UDPv6";
|
||||||
case TCPv6:
|
case TCPv6:
|
||||||
return "TCPv6";
|
return "TCPv6";
|
||||||
|
case TLSv4:
|
||||||
|
return "TLSv4";
|
||||||
|
case TLSv6:
|
||||||
|
return "TLSv6";
|
||||||
case UnixStream:
|
case UnixStream:
|
||||||
return "UnixStream";
|
return "UnixStream";
|
||||||
case UnixDGram:
|
case UnixDGram:
|
||||||
@@ -199,6 +214,10 @@ namespace openvpn {
|
|||||||
return "udp6";
|
return "udp6";
|
||||||
case TCPv6:
|
case TCPv6:
|
||||||
return "tcp6";
|
return "tcp6";
|
||||||
|
case TLSv4:
|
||||||
|
return "tls4";
|
||||||
|
case TLSv6:
|
||||||
|
return "tls6";
|
||||||
case UnixStream:
|
case UnixStream:
|
||||||
return "unix-stream";
|
return "unix-stream";
|
||||||
case UnixDGram:
|
case UnixDGram:
|
||||||
@@ -224,6 +243,10 @@ namespace openvpn {
|
|||||||
return force_ipv4 ? "UDPv4" : "UDPv6";
|
return force_ipv4 ? "UDPv4" : "UDPv6";
|
||||||
case TCPv6:
|
case TCPv6:
|
||||||
return force_ipv4 ? "TCPv4_CLIENT" : "TCPv6_CLIENT";
|
return force_ipv4 ? "TCPv4_CLIENT" : "TCPv6_CLIENT";
|
||||||
|
case TLSv4:
|
||||||
|
return "TLSv4";
|
||||||
|
case TLSv6:
|
||||||
|
return force_ipv4 ? "TLSv4" : "TLSv6";
|
||||||
default:
|
default:
|
||||||
return "UNDEF_PROTO";
|
return "UNDEF_PROTO";
|
||||||
}
|
}
|
||||||
@@ -268,6 +291,8 @@ namespace openvpn {
|
|||||||
ret = UDPv4;
|
ret = UDPv4;
|
||||||
else if (s1 == "tcp")
|
else if (s1 == "tcp")
|
||||||
ret = TCPv4;
|
ret = TCPv4;
|
||||||
|
else if (s1 == "tls")
|
||||||
|
ret = TLSv4;
|
||||||
}
|
}
|
||||||
else if (s2 == "6" || s2 == "v6")
|
else if (s2 == "6" || s2 == "v6")
|
||||||
{
|
{
|
||||||
@@ -275,6 +300,8 @@ namespace openvpn {
|
|||||||
ret = UDPv6;
|
ret = UDPv6;
|
||||||
else if (s1 == "tcp")
|
else if (s1 == "tcp")
|
||||||
ret = TCPv6;
|
ret = TCPv6;
|
||||||
|
else if (s1 == "tls")
|
||||||
|
ret = TLSv6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
+23
-355
@@ -37,401 +37,69 @@
|
|||||||
#include <openvpn/log/sessionstats.hpp>
|
#include <openvpn/log/sessionstats.hpp>
|
||||||
#include <openvpn/transport/pktstream.hpp>
|
#include <openvpn/transport/pktstream.hpp>
|
||||||
#include <openvpn/transport/mutate.hpp>
|
#include <openvpn/transport/mutate.hpp>
|
||||||
|
#include <openvpn/transport/tcplinkcommon.hpp>
|
||||||
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
#ifdef OPENVPN_GREMLIN
|
||||||
#include <openvpn/transport/gremlin.hpp>
|
#include <openvpn/transport/gremlin.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OPENVPN_DEBUG_TCPLINK) && OPENVPN_DEBUG_TCPLINK >= 1
|
|
||||||
#define OPENVPN_LOG_TCPLINK_ERROR(x) OPENVPN_LOG(x)
|
|
||||||
#else
|
|
||||||
#define OPENVPN_LOG_TCPLINK_ERROR(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(OPENVPN_DEBUG_TCPLINK) && OPENVPN_DEBUG_TCPLINK >= 3
|
|
||||||
#define OPENVPN_LOG_TCPLINK_VERBOSE(x) OPENVPN_LOG(x)
|
|
||||||
#else
|
|
||||||
#define OPENVPN_LOG_TCPLINK_VERBOSE(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace openvpn {
|
namespace openvpn {
|
||||||
namespace TCPTransport {
|
namespace TCPTransport {
|
||||||
|
|
||||||
struct PacketFrom
|
|
||||||
{
|
|
||||||
typedef std::unique_ptr<PacketFrom> SPtr;
|
|
||||||
BufferAllocated buf;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Protocol, typename ReadHandler, bool RAW_MODE_ONLY>
|
template <typename Protocol, typename ReadHandler, bool RAW_MODE_ONLY>
|
||||||
class Link : public RC<thread_unsafe_refcount>
|
class Link : public LinkCommon<Protocol,
|
||||||
|
ReadHandler,
|
||||||
|
RAW_MODE_ONLY>
|
||||||
{
|
{
|
||||||
typedef std::deque<BufferPtr> Queue;
|
typedef std::deque<BufferPtr> Queue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef LinkCommon<Protocol,
|
||||||
|
ReadHandler,
|
||||||
|
RAW_MODE_ONLY> Base;
|
||||||
typedef RCPtr<Link> Ptr;
|
typedef RCPtr<Link> Ptr;
|
||||||
|
|
||||||
typedef Protocol protocol;
|
typedef Protocol protocol;
|
||||||
|
|
||||||
|
friend Base;
|
||||||
|
|
||||||
Link(ReadHandler read_handler_arg,
|
Link(ReadHandler read_handler_arg,
|
||||||
typename Protocol::socket& socket_arg,
|
typename Protocol::socket& socket_arg,
|
||||||
const size_t send_queue_max_size_arg, // 0 to disable
|
const size_t send_queue_max_size_arg, // 0 to disable
|
||||||
const size_t free_list_max_size_arg,
|
const size_t free_list_max_size_arg,
|
||||||
const Frame::Context& frame_context_arg,
|
const Frame::Context& frame_context_arg,
|
||||||
const SessionStats::Ptr& stats_arg)
|
const SessionStats::Ptr& stats_arg)
|
||||||
: socket(socket_arg),
|
: Base(read_handler_arg, socket_arg, send_queue_max_size_arg,
|
||||||
halt(false),
|
free_list_max_size_arg, frame_context_arg, stats_arg)
|
||||||
read_handler(read_handler_arg),
|
{ }
|
||||||
frame_context(frame_context_arg),
|
|
||||||
stats(stats_arg),
|
|
||||||
send_queue_max_size(send_queue_max_size_arg),
|
|
||||||
free_list_max_size(free_list_max_size_arg)
|
|
||||||
{
|
|
||||||
set_raw_mode(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
|
||||||
void gremlin_config(const Gremlin::Config::Ptr& config)
|
|
||||||
{
|
|
||||||
if (config)
|
|
||||||
gremlin.reset(new Gremlin::SendRecvQueue(socket.get_executor().context(), config, true));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// In raw mode, data is sent and received without any special encapsulation.
|
|
||||||
// In non-raw mode, data is packetized by prepending a 16-bit length word
|
|
||||||
// onto each packet. The OpenVPN protocol runs in non-raw mode, while other
|
|
||||||
// TCP protocols such as HTTP or HTTPS would run in raw mode.
|
|
||||||
// This method is a no-op if RAW_MODE_ONLY is true.
|
|
||||||
void set_raw_mode(const bool mode)
|
|
||||||
{
|
|
||||||
set_raw_mode_read(mode);
|
|
||||||
set_raw_mode_write(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_raw_mode_read(const bool mode)
|
|
||||||
{
|
|
||||||
if (RAW_MODE_ONLY)
|
|
||||||
raw_mode_read = true;
|
|
||||||
else
|
|
||||||
raw_mode_read = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_raw_mode_write(const bool mode)
|
|
||||||
{
|
|
||||||
if (RAW_MODE_ONLY)
|
|
||||||
raw_mode_write = true;
|
|
||||||
else
|
|
||||||
raw_mode_write = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_raw_mode() const {
|
|
||||||
return is_raw_mode_read() && is_raw_mode_write();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_raw_mode_read() const {
|
|
||||||
if (RAW_MODE_ONLY)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return raw_mode_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_raw_mode_write() const {
|
|
||||||
if (RAW_MODE_ONLY)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return raw_mode_write;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_mutate(const TransportMutateStream::Ptr& mutate_arg)
|
|
||||||
{
|
|
||||||
mutate = mutate_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool send_queue_empty() const
|
|
||||||
{
|
|
||||||
return send_queue_size() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Called by LinkCommon and TCPTransport Client class
|
||||||
unsigned int send_queue_size() const
|
unsigned int send_queue_size() const
|
||||||
{
|
{
|
||||||
return queue.size()
|
return Base::queue.size()
|
||||||
#ifdef OPENVPN_GREMLIN
|
#ifdef OPENVPN_GREMLIN
|
||||||
+ (gremlin ? gremlin->send_size() : 0)
|
+ (gremlin ? gremlin->send_size() : 0)
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool send(BufferAllocated& b)
|
|
||||||
{
|
|
||||||
if (halt)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (send_queue_max_size && queue.size() >= send_queue_max_size)
|
|
||||||
{
|
|
||||||
stats->error(Error::TCP_OVERFLOW);
|
|
||||||
read_handler->tcp_error_handler("TCP_OVERFLOW");
|
|
||||||
stop();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferPtr buf;
|
|
||||||
if (!free_list.empty())
|
|
||||||
{
|
|
||||||
buf = free_list.front();
|
|
||||||
free_list.pop_front();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buf.reset(new BufferAllocated());
|
|
||||||
buf->swap(b);
|
|
||||||
if (!is_raw_mode_write())
|
|
||||||
PacketStream::prepend_size(*buf);
|
|
||||||
if (mutate)
|
|
||||||
mutate->pre_send(*buf);
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
|
||||||
if (gremlin)
|
|
||||||
gremlin_queue_send_buffer(buf);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
queue_send_buffer(buf);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void inject(const Buffer& src)
|
|
||||||
{
|
|
||||||
const size_t size = src.size();
|
|
||||||
OPENVPN_LOG_TCPLINK_VERBOSE("TCP inject size=" << size);
|
|
||||||
if (size && !RAW_MODE_ONLY)
|
|
||||||
{
|
|
||||||
BufferAllocated buf;
|
|
||||||
frame_context.prepare(buf);
|
|
||||||
buf.write(src.c_data(), size);
|
|
||||||
BufferAllocated pkt;
|
|
||||||
put_pktstream(buf, pkt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void start()
|
|
||||||
{
|
|
||||||
if (!halt)
|
|
||||||
queue_recv(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop()
|
|
||||||
{
|
|
||||||
halt = true;
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
|
||||||
if (gremlin)
|
|
||||||
gremlin->stop();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset_align_adjust(const size_t align_adjust)
|
|
||||||
{
|
|
||||||
frame_context.reset_align_adjust(align_adjust + (is_raw_mode() ? 0 : 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
~Link() { stop(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void queue_send_buffer(BufferPtr& buf)
|
// Called by LinkCommon
|
||||||
|
virtual void from_app_send_buffer(BufferPtr& buf) override
|
||||||
{
|
{
|
||||||
queue.push_back(std::move(buf));
|
Base::queue_send_buffer(buf);
|
||||||
if (queue.size() == 1) // send operation not currently active?
|
|
||||||
queue_send();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void queue_send()
|
virtual void recv_buffer(PacketFrom::SPtr& pfp, const size_t bytes_recvd) override
|
||||||
{
|
|
||||||
BufferAllocated& buf = *queue.front();
|
|
||||||
socket.async_send(buf.const_buffer_clamp(),
|
|
||||||
[self=Ptr(this)](const openvpn_io::error_code& error, const size_t bytes_sent)
|
|
||||||
{
|
|
||||||
self->handle_send(error, bytes_sent);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_send(const openvpn_io::error_code& error, const size_t bytes_sent)
|
|
||||||
{
|
|
||||||
if (!halt)
|
|
||||||
{
|
|
||||||
if (!error)
|
|
||||||
{
|
|
||||||
OPENVPN_LOG_TCPLINK_VERBOSE("TCP send raw=" << raw_mode_write << " size=" << bytes_sent);
|
|
||||||
stats->inc_stat(SessionStats::BYTES_OUT, bytes_sent);
|
|
||||||
stats->inc_stat(SessionStats::PACKETS_OUT, 1);
|
|
||||||
|
|
||||||
BufferPtr buf = queue.front();
|
|
||||||
if (bytes_sent == buf->size())
|
|
||||||
{
|
|
||||||
queue.pop_front();
|
|
||||||
if (free_list.size() < free_list_max_size)
|
|
||||||
{
|
|
||||||
buf->reset_content();
|
|
||||||
free_list.push_back(std::move(buf)); // recycle the buffer for later use
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (bytes_sent < buf->size())
|
|
||||||
buf->advance(bytes_sent);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stats->error(Error::TCP_OVERFLOW);
|
|
||||||
read_handler->tcp_error_handler("TCP_INTERNAL_ERROR"); // error sent more bytes than we asked for
|
|
||||||
stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OPENVPN_LOG_TCPLINK_ERROR("TCP send error: " << error.message());
|
|
||||||
stats->error(Error::NETWORK_SEND_ERROR);
|
|
||||||
read_handler->tcp_error_handler("NETWORK_SEND_ERROR");
|
|
||||||
stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!queue.empty())
|
|
||||||
queue_send();
|
|
||||||
else
|
|
||||||
read_handler->tcp_write_queue_needs_send();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void queue_recv(PacketFrom *tcpfrom)
|
|
||||||
{
|
|
||||||
OPENVPN_LOG_TCPLINK_VERBOSE("TCPLink::queue_recv");
|
|
||||||
if (!tcpfrom)
|
|
||||||
tcpfrom = new PacketFrom();
|
|
||||||
frame_context.prepare(tcpfrom->buf);
|
|
||||||
|
|
||||||
socket.async_receive(frame_context.mutable_buffer_clamp(tcpfrom->buf),
|
|
||||||
[self=Ptr(this), tcpfrom=PacketFrom::SPtr(tcpfrom)](const openvpn_io::error_code& error, const size_t bytes_recvd) mutable
|
|
||||||
{
|
|
||||||
self->handle_recv(std::move(tcpfrom), error, bytes_recvd);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_recv(PacketFrom::SPtr pfp, const openvpn_io::error_code& error, const size_t bytes_recvd)
|
|
||||||
{
|
|
||||||
OPENVPN_LOG_TCPLINK_VERBOSE("TCPLink::handle_recv: " << error.message());
|
|
||||||
if (!halt)
|
|
||||||
{
|
|
||||||
if (!error)
|
|
||||||
{
|
{
|
||||||
bool requeue = true;
|
bool requeue = true;
|
||||||
OPENVPN_LOG_TCPLINK_VERBOSE("TCP recv raw=" << raw_mode_read << " size=" << bytes_recvd);
|
OPENVPN_LOG_TCPLINK_VERBOSE("TCP recv raw=" << Base::raw_mode_read << " size=" << bytes_recvd);
|
||||||
|
|
||||||
pfp->buf.set_size(bytes_recvd);
|
pfp->buf.set_size(bytes_recvd);
|
||||||
if (!is_raw_mode_read())
|
requeue = Base::process_recv_buffer(pfp->buf);
|
||||||
{
|
if (!Base::halt && requeue)
|
||||||
try {
|
Base::queue_recv(pfp.release()); // reuse PacketFrom object
|
||||||
BufferAllocated pkt;
|
|
||||||
requeue = put_pktstream(pfp->buf, pkt);
|
|
||||||
if (!pfp->buf.allocated() && pkt.allocated()) // recycle pkt allocated buffer
|
|
||||||
pfp->buf.move(pkt);
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
OPENVPN_LOG_TCPLINK_ERROR("TCP packet extract exception: " << e.what());
|
|
||||||
stats->error(Error::TCP_SIZE_ERROR);
|
|
||||||
read_handler->tcp_error_handler("TCP_SIZE_ERROR");
|
|
||||||
stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mutate)
|
|
||||||
mutate->post_recv(pfp->buf);
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
|
||||||
if (gremlin)
|
|
||||||
requeue = gremlin_recv(pfp->buf);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
requeue = read_handler->tcp_read_handler(pfp->buf);
|
|
||||||
}
|
|
||||||
if (!halt && requeue)
|
|
||||||
queue_recv(pfp.release()); // reuse PacketFrom object
|
|
||||||
}
|
|
||||||
else if (error == openvpn_io::error::eof)
|
|
||||||
{
|
|
||||||
OPENVPN_LOG_TCPLINK_ERROR("TCP recv EOF");
|
|
||||||
read_handler->tcp_eof_handler();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OPENVPN_LOG_TCPLINK_ERROR("TCP recv error: " << error.message());
|
|
||||||
stats->error(Error::NETWORK_RECV_ERROR);
|
|
||||||
read_handler->tcp_error_handler("NETWORK_RECV_ERROR");
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool put_pktstream(BufferAllocated& buf, BufferAllocated& pkt)
|
|
||||||
{
|
|
||||||
bool requeue = true;
|
|
||||||
stats->inc_stat(SessionStats::BYTES_IN, buf.size());
|
|
||||||
stats->inc_stat(SessionStats::PACKETS_IN, 1);
|
|
||||||
if (mutate)
|
|
||||||
mutate->post_recv(buf);
|
|
||||||
while (buf.size())
|
|
||||||
{
|
|
||||||
pktstream.put(buf, frame_context);
|
|
||||||
if (pktstream.ready())
|
|
||||||
{
|
|
||||||
pktstream.get(pkt);
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
|
||||||
if (gremlin)
|
|
||||||
requeue = gremlin_recv(pkt);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
requeue = read_handler->tcp_read_handler(pkt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return requeue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
|
||||||
void gremlin_queue_send_buffer(BufferPtr& buf)
|
|
||||||
{
|
|
||||||
gremlin->send_queue([self=Ptr(this), buf=std::move(buf)]() mutable {
|
|
||||||
if (!self->halt)
|
|
||||||
{
|
|
||||||
self->queue_send_buffer(buf);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool gremlin_recv(BufferAllocated& buf)
|
|
||||||
{
|
|
||||||
gremlin->recv_queue([self=Ptr(this), buf=std::move(buf)]() mutable {
|
|
||||||
if (!self->halt)
|
|
||||||
{
|
|
||||||
const bool requeue = self->read_handler->tcp_read_handler(buf);
|
|
||||||
if (requeue)
|
|
||||||
self->queue_recv(nullptr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typename Protocol::socket& socket;
|
|
||||||
bool halt;
|
|
||||||
bool raw_mode_read;
|
|
||||||
bool raw_mode_write;
|
|
||||||
ReadHandler read_handler;
|
|
||||||
Frame::Context frame_context;
|
|
||||||
SessionStats::Ptr stats;
|
|
||||||
const size_t send_queue_max_size;
|
|
||||||
const size_t free_list_max_size;
|
|
||||||
Queue queue; // send queue
|
|
||||||
Queue free_list; // recycled free buffers for send queue
|
|
||||||
PacketStream pktstream;
|
|
||||||
TransportMutateStream::Ptr mutate;
|
|
||||||
|
|
||||||
#ifdef OPENVPN_GREMLIN
|
|
||||||
std::unique_ptr<Gremlin::SendRecvQueue> gremlin;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // namespace openvpn
|
} // namespace openvpn
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright (C) 2012-2018 OpenVPN Inc.
|
||||||
|
|
||||||
|
// Base class for generic link objects.
|
||||||
|
|
||||||
|
#include <openvpn/buffer/buffer.hpp>
|
||||||
|
#include <openvpn/common/rc.hpp>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace openvpn
|
||||||
|
{
|
||||||
|
namespace TCPTransport
|
||||||
|
{
|
||||||
|
struct PacketFrom
|
||||||
|
{
|
||||||
|
typedef std::unique_ptr<PacketFrom> SPtr;
|
||||||
|
BufferAllocated buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LinkBase : public RC<thread_unsafe_refcount>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
virtual void recv_buffer(PacketFrom::SPtr& pfp,
|
||||||
|
const size_t bytes_recvd) = 0;
|
||||||
|
virtual void from_app_send_buffer(BufferPtr& buf) = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef RCPtr<LinkBase> Ptr;
|
||||||
|
|
||||||
|
virtual bool send_queue_empty() const = 0;
|
||||||
|
virtual unsigned int send_queue_size() const = 0;
|
||||||
|
virtual void reset_align_adjust(const size_t align_adjust) = 0;
|
||||||
|
virtual bool send(BufferAllocated& b) = 0;
|
||||||
|
virtual void set_raw_mode(const bool mode) = 0;
|
||||||
|
virtual void start() = 0;
|
||||||
|
virtual void stop() = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,441 @@
|
|||||||
|
// Copyright (C) 2012-2018 OpenVPN Inc.
|
||||||
|
|
||||||
|
// Base class for TCP link objects.
|
||||||
|
|
||||||
|
#ifndef OPENVPN_TRANSPORT_COMMONLINK_H
|
||||||
|
#define OPENVPN_TRANSPORT_COMMONLINK_H
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <utility> // for std::move
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <openvpn/io/io.hpp>
|
||||||
|
|
||||||
|
#include <openvpn/common/size.hpp>
|
||||||
|
#include <openvpn/common/rc.hpp>
|
||||||
|
#include <openvpn/common/socktypes.hpp>
|
||||||
|
#include <openvpn/frame/frame.hpp>
|
||||||
|
#include <openvpn/log/sessionstats.hpp>
|
||||||
|
#include <openvpn/transport/tcplinkbase.hpp>
|
||||||
|
#include <openvpn/transport/pktstream.hpp>
|
||||||
|
#include <openvpn/transport/mutate.hpp>
|
||||||
|
|
||||||
|
#ifdef OPENVPN_GREMLIN
|
||||||
|
#include <openvpn/transport/gremlin.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OPENVPN_DEBUG_TCPLINK) && OPENVPN_DEBUG_TCPLINK >= 1
|
||||||
|
#define OPENVPN_LOG_TCPLINK_ERROR(x) OPENVPN_LOG(x)
|
||||||
|
#else
|
||||||
|
#define OPENVPN_LOG_TCPLINK_ERROR(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OPENVPN_DEBUG_TCPLINK) && OPENVPN_DEBUG_TCPLINK >= 3
|
||||||
|
#define OPENVPN_LOG_TCPLINK_VERBOSE(x) OPENVPN_LOG(x)
|
||||||
|
#else
|
||||||
|
#define OPENVPN_LOG_TCPLINK_VERBOSE(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace openvpn {
|
||||||
|
namespace TCPTransport {
|
||||||
|
|
||||||
|
template <typename Protocol,
|
||||||
|
typename ReadHandler,
|
||||||
|
bool RAW_MODE_ONLY>
|
||||||
|
class LinkCommon : public LinkBase
|
||||||
|
{
|
||||||
|
typedef std::deque<BufferPtr> Queue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef RCPtr<LinkCommon<Protocol, ReadHandler, RAW_MODE_ONLY>> Ptr;
|
||||||
|
typedef Protocol protocol;
|
||||||
|
|
||||||
|
// In raw mode, data is sent and received without any special encapsulation.
|
||||||
|
// In non-raw mode, data is packetized by prepending a 16-bit length word
|
||||||
|
// onto each packet. The OpenVPN protocol runs in non-raw mode, while other
|
||||||
|
// TCP protocols such as HTTP or HTTPS would run in raw mode.
|
||||||
|
// This method is a no-op if RAW_MODE_ONLY is true.
|
||||||
|
void set_raw_mode(const bool mode)
|
||||||
|
{
|
||||||
|
set_raw_mode_read(mode);
|
||||||
|
set_raw_mode_write(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_raw_mode_read(const bool mode)
|
||||||
|
{
|
||||||
|
if (RAW_MODE_ONLY)
|
||||||
|
raw_mode_read = true;
|
||||||
|
else
|
||||||
|
raw_mode_read = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_raw_mode_write(const bool mode)
|
||||||
|
{
|
||||||
|
if (RAW_MODE_ONLY)
|
||||||
|
raw_mode_write = true;
|
||||||
|
else
|
||||||
|
raw_mode_write = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_mutate(const TransportMutateStream::Ptr& mutate_arg)
|
||||||
|
{
|
||||||
|
mutate = mutate_arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool send_queue_empty() const
|
||||||
|
{
|
||||||
|
return send_queue_size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inject(const Buffer& src)
|
||||||
|
{
|
||||||
|
const size_t size = src.size();
|
||||||
|
OPENVPN_LOG_TCPLINK_VERBOSE("TCP inject size=" << size);
|
||||||
|
if (size && !RAW_MODE_ONLY)
|
||||||
|
{
|
||||||
|
BufferAllocated buf;
|
||||||
|
frame_context.prepare(buf);
|
||||||
|
buf.write(src.c_data(), size);
|
||||||
|
BufferAllocated pkt;
|
||||||
|
put_pktstream(buf, pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
if (!halt)
|
||||||
|
queue_recv(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop()
|
||||||
|
{
|
||||||
|
halt = true;
|
||||||
|
#ifdef OPENVPN_GREMLIN
|
||||||
|
if (gremlin)
|
||||||
|
gremlin->stop();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_align_adjust(const size_t align_adjust)
|
||||||
|
{
|
||||||
|
frame_context.reset_align_adjust(align_adjust + (is_raw_mode() ? 0 : 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int send_queue_size() const
|
||||||
|
{
|
||||||
|
return queue.size()
|
||||||
|
#ifdef OPENVPN_GREMLIN
|
||||||
|
+ (gremlin ? gremlin->send_size() : 0)
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool send(BufferAllocated& b)
|
||||||
|
{
|
||||||
|
if (halt)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (send_queue_max_size && send_queue_size() >= send_queue_max_size)
|
||||||
|
{
|
||||||
|
stats->error(Error::TCP_OVERFLOW);
|
||||||
|
read_handler->tcp_error_handler("TCP_OVERFLOW");
|
||||||
|
stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferPtr buf;
|
||||||
|
if (!free_list.empty())
|
||||||
|
{
|
||||||
|
buf = free_list.front();
|
||||||
|
free_list.pop_front();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buf.reset(new BufferAllocated());
|
||||||
|
buf->swap(b);
|
||||||
|
if (!is_raw_mode_write())
|
||||||
|
PacketStream::prepend_size(*buf);
|
||||||
|
if (mutate)
|
||||||
|
mutate->pre_send(*buf);
|
||||||
|
#ifdef OPENVPN_GREMLIN
|
||||||
|
if (gremlin)
|
||||||
|
gremlin_queue_send_buffer(buf);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
from_app_send_buffer(buf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_recv(PacketFrom *tcpfrom)
|
||||||
|
{
|
||||||
|
OPENVPN_LOG_TCPLINK_VERBOSE("TLSLink::queue_recv");
|
||||||
|
if (!tcpfrom)
|
||||||
|
tcpfrom = new PacketFrom();
|
||||||
|
frame_context.prepare(tcpfrom->buf);
|
||||||
|
|
||||||
|
socket.async_receive(frame_context.mutable_buffer_clamp(tcpfrom->buf),
|
||||||
|
[self=Ptr(this), tcpfrom=PacketFrom::SPtr(tcpfrom)](const openvpn_io::error_code& error, const size_t bytes_recvd) mutable
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self->handle_recv(std::move(tcpfrom), error, bytes_recvd);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
OPENVPN_LOG_TCPLINK_ERROR("TCP packet extract exception: " << e.what());
|
||||||
|
self->stats->error(Error::TCP_SIZE_ERROR);
|
||||||
|
self->read_handler->tcp_error_handler("TCP_SIZE_ERROR");
|
||||||
|
self->stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
LinkCommon(ReadHandler read_handler_arg,
|
||||||
|
typename Protocol::socket& socket_arg,
|
||||||
|
const size_t send_queue_max_size_arg, // 0 to disable
|
||||||
|
const size_t free_list_max_size_arg,
|
||||||
|
const Frame::Context& frame_context_arg,
|
||||||
|
const SessionStats::Ptr& stats_arg)
|
||||||
|
: socket(socket_arg),
|
||||||
|
halt(false),
|
||||||
|
read_handler(read_handler_arg),
|
||||||
|
frame_context(frame_context_arg),
|
||||||
|
stats(stats_arg),
|
||||||
|
send_queue_max_size(send_queue_max_size_arg),
|
||||||
|
free_list_max_size(free_list_max_size_arg)
|
||||||
|
{
|
||||||
|
set_raw_mode(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef OPENVPN_GREMLIN
|
||||||
|
void gremlin_config(const Gremlin::Config::Ptr& config)
|
||||||
|
{
|
||||||
|
if (config)
|
||||||
|
gremlin.reset(new Gremlin::SendRecvQueue(socket.get_executor().context(), config, true));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool is_raw_mode() const {
|
||||||
|
return is_raw_mode_read() && is_raw_mode_write();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_raw_mode_read() const {
|
||||||
|
if (RAW_MODE_ONLY)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return raw_mode_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_raw_mode_write() const {
|
||||||
|
if (RAW_MODE_ONLY)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return raw_mode_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkCommon() { stop(); }
|
||||||
|
|
||||||
|
void queue_send_buffer(BufferPtr& buf)
|
||||||
|
{
|
||||||
|
queue.push_back(std::move(buf));
|
||||||
|
if (queue.size() == 1) // send operation not currently active?
|
||||||
|
queue_send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_send()
|
||||||
|
{
|
||||||
|
BufferAllocated& buf = *queue.front();
|
||||||
|
socket.async_send(buf.const_buffer_clamp(),
|
||||||
|
[self=Ptr(this)](const openvpn_io::error_code& error, const size_t bytes_sent)
|
||||||
|
{
|
||||||
|
self->handle_send(error, bytes_sent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_send(const openvpn_io::error_code& error, const size_t bytes_sent)
|
||||||
|
{
|
||||||
|
if (!halt)
|
||||||
|
{
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
OPENVPN_LOG_TCPLINK_VERBOSE("TLS-TCP send raw=" << raw_mode_write << " size=" << bytes_sent);
|
||||||
|
stats->inc_stat(SessionStats::BYTES_OUT, bytes_sent);
|
||||||
|
stats->inc_stat(SessionStats::PACKETS_OUT, 1);
|
||||||
|
|
||||||
|
BufferPtr buf = queue.front();
|
||||||
|
if (bytes_sent == buf->size())
|
||||||
|
{
|
||||||
|
queue.pop_front();
|
||||||
|
if (free_list.size() < free_list_max_size)
|
||||||
|
{
|
||||||
|
buf->reset_content();
|
||||||
|
free_list.push_back(std::move(buf)); // recycle the buffer for later use
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bytes_sent < buf->size())
|
||||||
|
buf->advance(bytes_sent);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stats->error(Error::TCP_OVERFLOW);
|
||||||
|
read_handler->tcp_error_handler("TCP_INTERNAL_ERROR"); // error sent more bytes than we asked for
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OPENVPN_LOG_TCPLINK_ERROR("TLS-TCP send error: " << error.message());
|
||||||
|
stats->error(Error::NETWORK_SEND_ERROR);
|
||||||
|
read_handler->tcp_error_handler("NETWORK_SEND_ERROR");
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!queue.empty())
|
||||||
|
queue_send();
|
||||||
|
else
|
||||||
|
tcp_write_queue_needs_send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_recv_buffer(BufferAllocated& buf)
|
||||||
|
{
|
||||||
|
bool requeue = true;
|
||||||
|
|
||||||
|
OPENVPN_LOG_TCPLINK_VERBOSE("TLSLink::process_recv_buffer: size=" << buf.size());
|
||||||
|
|
||||||
|
if (!is_raw_mode_read())
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
BufferAllocated pkt;
|
||||||
|
requeue = put_pktstream(buf, pkt);
|
||||||
|
if (!buf.allocated() && pkt.allocated()) // recycle pkt allocated buffer
|
||||||
|
buf.move(pkt);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
OPENVPN_LOG_TCPLINK_ERROR("TLS-TCP packet extract error: " << e.what());
|
||||||
|
stats->error(Error::TCP_SIZE_ERROR);
|
||||||
|
read_handler->tcp_error_handler("TCP_SIZE_ERROR");
|
||||||
|
stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mutate)
|
||||||
|
mutate->post_recv(buf);
|
||||||
|
#ifdef OPENVPN_GREMLIN
|
||||||
|
if (gremlin)
|
||||||
|
requeue = gremlin_recv(buf);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
requeue = read_handler->tcp_read_handler(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return requeue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_recv(PacketFrom::SPtr pfp, const openvpn_io::error_code& error, const size_t bytes_recvd)
|
||||||
|
{
|
||||||
|
OPENVPN_LOG_TCPLINK_VERBOSE("Link::handle_recv: " << error.message());
|
||||||
|
if (!halt)
|
||||||
|
{
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
recv_buffer(pfp, bytes_recvd);
|
||||||
|
}
|
||||||
|
else if (error == openvpn_io::error::eof)
|
||||||
|
{
|
||||||
|
OPENVPN_LOG_TCPLINK_ERROR("TCP recv EOF");
|
||||||
|
read_handler->tcp_eof_handler();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OPENVPN_LOG_TCPLINK_ERROR("TCP recv error: " << error.message());
|
||||||
|
stats->error(Error::NETWORK_RECV_ERROR);
|
||||||
|
read_handler->tcp_error_handler("NETWORK_RECV_ERROR");
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool put_pktstream(BufferAllocated& buf, BufferAllocated& pkt)
|
||||||
|
{
|
||||||
|
bool requeue = true;
|
||||||
|
stats->inc_stat(SessionStats::BYTES_IN, buf.size());
|
||||||
|
stats->inc_stat(SessionStats::PACKETS_IN, 1);
|
||||||
|
if (mutate)
|
||||||
|
mutate->post_recv(buf);
|
||||||
|
while (buf.size())
|
||||||
|
{
|
||||||
|
pktstream.put(buf, frame_context);
|
||||||
|
if (pktstream.ready())
|
||||||
|
{
|
||||||
|
pktstream.get(pkt);
|
||||||
|
#ifdef OPENVPN_GREMLIN
|
||||||
|
if (gremlin)
|
||||||
|
requeue = gremlin_recv(pkt);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
requeue = read_handler->tcp_read_handler(pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return requeue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef OPENVPN_GREMLIN
|
||||||
|
void gremlin_queue_send_buffer(BufferPtr& buf)
|
||||||
|
{
|
||||||
|
gremlin->send_queue([self=Ptr(this), buf=std::move(buf)]() mutable {
|
||||||
|
if (!self->halt)
|
||||||
|
{
|
||||||
|
self->queue_send_buffer(buf);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gremlin_recv(BufferAllocated& buf)
|
||||||
|
{
|
||||||
|
gremlin->recv_queue([self=Ptr(this), buf=std::move(buf)]() mutable {
|
||||||
|
if (!self->halt)
|
||||||
|
{
|
||||||
|
const bool requeue = self->read_handler->tcp_read_handler(buf);
|
||||||
|
if (requeue)
|
||||||
|
self->queue_recv(nullptr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void tcp_write_queue_needs_send()
|
||||||
|
{
|
||||||
|
read_handler->tcp_write_queue_needs_send();
|
||||||
|
}
|
||||||
|
|
||||||
|
typename Protocol::socket& socket;
|
||||||
|
bool halt;
|
||||||
|
ReadHandler read_handler;
|
||||||
|
Frame::Context frame_context;
|
||||||
|
SessionStats::Ptr stats;
|
||||||
|
const size_t send_queue_max_size;
|
||||||
|
const size_t free_list_max_size;
|
||||||
|
Queue queue; // send queue
|
||||||
|
Queue free_list; // recycled free buffers for send queue
|
||||||
|
PacketStream pktstream;
|
||||||
|
TransportMutateStream::Ptr mutate;
|
||||||
|
bool raw_mode_read;
|
||||||
|
bool raw_mode_write;
|
||||||
|
|
||||||
|
#ifdef OPENVPN_GREMLIN
|
||||||
|
std::unique_ptr<Gremlin::SendRecvQueue> gremlin;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void recv_buffer(PacketFrom::SPtr& pfp, const size_t bytes_recvd) = 0;
|
||||||
|
virtual void from_app_send_buffer(BufferPtr& buf) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} // namespace openvpn
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -7,6 +7,7 @@ GCC_EXTRA="$GCC_EXTRA -DOPENVPN_SHOW_SESSION_TOKEN"
|
|||||||
[ "$DEX" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_DISABLE_EXPLICIT_EXIT"
|
[ "$DEX" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_DISABLE_EXPLICIT_EXIT"
|
||||||
[ "$BS64" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_BS64_DATA_LIMIT=2500000"
|
[ "$BS64" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_BS64_DATA_LIMIT=2500000"
|
||||||
[ "$ROVER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_REMOTE_OVERRIDE"
|
[ "$ROVER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_REMOTE_OVERRIDE"
|
||||||
|
[ "$TLS" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_TLS_LINK"
|
||||||
if [ "$AGENT" = "1" ]; then
|
if [ "$AGENT" = "1" ]; then
|
||||||
GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT"
|
GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT"
|
||||||
fi
|
fi
|
||||||
|
|||||||
+5
-5
@@ -2,11 +2,11 @@ export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64
|
|||||||
[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux
|
[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux
|
||||||
export PLATFORM=linux
|
export PLATFORM=linux
|
||||||
export DEBUG_BUILD=1
|
export DEBUG_BUILD=1
|
||||||
export OTHER_COMPILER_FLAGS="-g -Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread"
|
export OTHER_COMPILER_FLAGS="-ggdb -Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread"
|
||||||
export CXX_COMPILER_FLAGS="-std=c++14"
|
export CXX_COMPILER_FLAGS="-std=c++14"
|
||||||
export LIB_OPT_LEVEL="-O0"
|
export LIB_OPT_LEVEL="-O0"
|
||||||
export LIB_FPIC="-fPIC"
|
export LIB_FPIC="-fPIC"
|
||||||
export GPP_CMD=g++-5
|
export GPP_CMD=g++
|
||||||
export GCC_CMD=gcc-5
|
export GCC_CMD=gcc
|
||||||
export AR_CMD=gcc-ar-5
|
export AR_CMD=gcc-ar
|
||||||
export RANLIB_CMD=gcc-ranlib-5
|
export RANLIB_CMD=gcc-ranlib
|
||||||
|
|||||||
Reference in New Issue
Block a user