AWS: move from MbedTLS to OpenSSL for the connection
There seems to be a crash in Amazon's MbedTLS code, let's see if openssl behaves better
This commit is contained in:
parent
fb1353292c
commit
167ac6f3c3
1
debian/control
vendored
1
debian/control
vendored
@ -23,7 +23,6 @@ Build-Depends: debhelper (>= 9.0.0),
|
||||
libavahi-client-dev,
|
||||
libavahi-common-dev,
|
||||
libssl-dev,
|
||||
libmbedtls-dev,
|
||||
libaws-iot-device-sdk-cpp,
|
||||
dbus-test-runner,
|
||||
|
||||
|
||||
@ -1,348 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
* express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file MbedTLSConnection.hpp
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <util/memory/stl/Vector.hpp>
|
||||
|
||||
#include "MbedTLSConnection.hpp"
|
||||
#include "util/logging/LogMacros.hpp"
|
||||
|
||||
#define MBEDTLS_WRAPPER_LOG_TAG "[MbedTLS Wrapper]"
|
||||
#define MAX_CHARS_IN_PORT_NUMBER 6
|
||||
|
||||
namespace awsiotsdk {
|
||||
namespace network {
|
||||
MbedTLSConnection::MbedTLSConnection(util::String endpoint,
|
||||
uint16_t endpoint_port,
|
||||
util::String root_ca_location,
|
||||
util::String device_cert_location,
|
||||
util::String device_private_key_location,
|
||||
std::chrono::milliseconds tls_handshake_timeout,
|
||||
std::chrono::milliseconds tls_read_timeout,
|
||||
std::chrono::milliseconds tls_write_timeout,
|
||||
bool server_verification_flag) {
|
||||
endpoint_ = endpoint;
|
||||
endpoint_port_ = endpoint_port;
|
||||
root_ca_location_ = root_ca_location;
|
||||
device_cert_location_ = device_cert_location;
|
||||
device_private_key_location_ = device_private_key_location;
|
||||
server_verification_flag_ = server_verification_flag;
|
||||
tls_handshake_timeout_ = tls_handshake_timeout;
|
||||
tls_read_timeout_ = tls_read_timeout;
|
||||
tls_write_timeout_ = tls_write_timeout;
|
||||
flags_ = 0;
|
||||
|
||||
is_connected_ = false;
|
||||
requires_free_ = false;
|
||||
}
|
||||
|
||||
bool MbedTLSConnection::IsPhysicalLayerConnected() {
|
||||
// Use this to add implementation which can check for physical layer disconnect
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MbedTLSConnection::IsConnected() {
|
||||
return is_connected_;
|
||||
}
|
||||
|
||||
int MbedTLSConnection::VerifyCertificate(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
|
||||
char buf[1024];
|
||||
((void) data);
|
||||
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "Verify requested for (Depth %d):", depth);
|
||||
mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "%s", buf);
|
||||
|
||||
if ((*flags) == 0) {
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "This certificate has no flags");
|
||||
} else {
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, buf, sizeof(buf), " ! ", *flags);
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "%s\n", buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ResponseCode MbedTLSConnection::ConnectInternal() {
|
||||
ResponseCode rc = ResponseCode::SUCCESS;
|
||||
|
||||
int ret = 0;
|
||||
const util::String pers = "aws_iot_tls_wrapper";
|
||||
char port_buf[6];
|
||||
char vrfy_buf[512];
|
||||
|
||||
mbedtls_net_init(&server_fd_);
|
||||
mbedtls_ssl_init(&ssl_);
|
||||
mbedtls_ssl_config_init(&conf_);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg_);
|
||||
mbedtls_x509_crt_init(&cacert_);
|
||||
mbedtls_x509_crt_init(&clicert_);
|
||||
mbedtls_pk_init(&pkey_);
|
||||
|
||||
requires_free_ = true;
|
||||
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "...............................%d", MBEDTLS_SSL_MAX_CONTENT_LEN);
|
||||
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Seeding the random number generator...");
|
||||
mbedtls_entropy_init(&entropy_);
|
||||
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg_, mbedtls_entropy_func, &entropy_,
|
||||
(const unsigned char *) (pers.c_str()), pers.length())) != 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, " Connect Failed!!! mbedtls_ctr_drbg_seed returned -0x%x", -ret);
|
||||
return ResponseCode::NETWORK_SSL_INIT_ERROR;
|
||||
}
|
||||
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Loading the CA root certificate... %s", root_ca_location_.c_str());
|
||||
ret = mbedtls_x509_crt_parse_file(&cacert_, root_ca_location_.c_str());
|
||||
if (ret < 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG,
|
||||
"Failed!!! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n",
|
||||
-ret);
|
||||
return ResponseCode::NETWORK_SSL_ROOT_CRT_PARSE_ERROR;
|
||||
}
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "ok (%d skipped)\n", ret);
|
||||
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Loading the client cert. and key...");
|
||||
ret = mbedtls_x509_crt_parse_file(&clicert_, device_cert_location_.c_str());
|
||||
if (ret != 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG,
|
||||
"Failed!!! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n",
|
||||
-ret);
|
||||
return ResponseCode::NETWORK_SSL_DEVICE_CRT_PARSE_ERROR;
|
||||
}
|
||||
|
||||
ret = mbedtls_pk_parse_keyfile(&pkey_, device_private_key_location_.c_str(), "");
|
||||
if (ret != 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG,
|
||||
"Failed!!! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n",
|
||||
-ret);
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " path : %s ", device_private_key_location_.c_str());
|
||||
return ResponseCode::NETWORK_SSL_KEY_PARSE_ERROR;
|
||||
}
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " ok\n");
|
||||
snprintf(port_buf, MAX_CHARS_IN_PORT_NUMBER, "%d", endpoint_port_);
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Connecting to %s/%s...", endpoint_.c_str(), port_buf);
|
||||
if ((ret = mbedtls_net_connect(&server_fd_, endpoint_.c_str(), port_buf, MBEDTLS_NET_PROTO_TCP)) != 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_net_connect returned -0x%x\n\n", -ret);
|
||||
switch (ret) {
|
||||
case MBEDTLS_ERR_NET_SOCKET_FAILED:
|
||||
return ResponseCode::NETWORK_TCP_SETUP_ERROR;
|
||||
case MBEDTLS_ERR_NET_UNKNOWN_HOST:
|
||||
return ResponseCode::NETWORK_TCP_UNKNOWN_HOST;
|
||||
case MBEDTLS_ERR_NET_CONNECT_FAILED:
|
||||
default:
|
||||
return ResponseCode::NETWORK_TCP_CONNECT_ERROR;
|
||||
};
|
||||
}
|
||||
|
||||
ret = mbedtls_net_set_block(&server_fd_);
|
||||
if (ret != 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! net_set_(non)block() returned -0x%x\n\n", -ret);
|
||||
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
|
||||
}
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "Ok!");
|
||||
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Setting up the SSL/TLS structure...");
|
||||
if ((ret = mbedtls_ssl_config_defaults(&conf_, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG,
|
||||
"Failed!!! mbedtls_ssl_config_defaults returned -0x%x\n\n",
|
||||
-ret);
|
||||
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_verify(&conf_, &MbedTLSConnection::VerifyCertificate, NULL);
|
||||
if (server_verification_flag_) {
|
||||
mbedtls_ssl_conf_authmode(&conf_, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
} else {
|
||||
mbedtls_ssl_conf_authmode(&conf_, MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||||
}
|
||||
mbedtls_ssl_conf_rng(&conf_, mbedtls_ctr_drbg_random, &ctr_drbg_);
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(&conf_, &cacert_, NULL);
|
||||
if ((ret = mbedtls_ssl_conf_own_cert(&conf_, &clicert_, &pkey_)) !=
|
||||
0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_ssl_conf_own_cert returned %d\n\n", ret);
|
||||
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_read_timeout(&conf_, static_cast<uint32_t>(tls_handshake_timeout_.count()));
|
||||
if ((ret = mbedtls_ssl_set_hostname(&ssl_, endpoint_.c_str())) != 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_ssl_set_hostname returned %d\n\n", ret);
|
||||
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
|
||||
}
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "\n\nSSL state connect : %d ", ssl_.state);
|
||||
mbedtls_ssl_set_bio(&ssl_, &server_fd_, mbedtls_net_send, NULL, mbedtls_net_recv_timeout);
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "Ok!");
|
||||
|
||||
if ((ret = mbedtls_ssl_setup(&ssl_, &conf_)) != 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_ssl_setup returned -0x%x\n\n", -ret);
|
||||
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "\n\nSSL state connect : %d ", ssl_.state);
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Performing the SSL/TLS handshake...");
|
||||
while ((ret = mbedtls_ssl_handshake(&ssl_)) != 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_ssl_handshake returned -0x%x\n", -ret);
|
||||
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, " Unable to verify the server's certificate. "
|
||||
"Either it is invalid,\n"
|
||||
" or you didn't set ca_file or ca_path "
|
||||
"to an appropriate value.\n"
|
||||
" Alternatively, you may want to use "
|
||||
"auth_mode=optional for testing purposes.\n");
|
||||
}
|
||||
return ResponseCode::NETWORK_SSL_TLS_HANDSHAKE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG,
|
||||
" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n",
|
||||
mbedtls_ssl_get_version(&ssl_),
|
||||
mbedtls_ssl_get_ciphersuite(&ssl_));
|
||||
if ((ret = mbedtls_ssl_get_record_expansion(&ssl_)) >= 0) {
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " [ Record expansion is %d ]\n", ret);
|
||||
} else {
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " [ Record expansion is unknown (compression) ]\n");
|
||||
}
|
||||
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Verifying peer X.509 certificate...");
|
||||
|
||||
if (server_verification_flag_) {
|
||||
if ((flags_ = mbedtls_ssl_get_verify_result(&ssl_)) != 0) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, " failed\n");
|
||||
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags_);
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "%s\n", vrfy_buf);
|
||||
rc = ResponseCode::NETWORK_SSL_SERVER_VERIFICATION_ERROR;
|
||||
} else {
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " ok\n");
|
||||
rc = ResponseCode::SUCCESS;
|
||||
}
|
||||
} else {
|
||||
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " Server Verification skipped\n");
|
||||
rc = ResponseCode::SUCCESS;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_read_timeout(&conf_, static_cast<uint32_t>(tls_read_timeout_.count()));
|
||||
is_connected_ = true;
|
||||
return rc;
|
||||
}
|
||||
|
||||
ResponseCode MbedTLSConnection::WriteInternal(const util::String &buf, size_t &size_written_bytes_out) {
|
||||
size_t total_written_length = 0;
|
||||
ResponseCode rc = ResponseCode::SUCCESS;
|
||||
size_t bytes_to_write = buf.length();
|
||||
const unsigned char *buf_cstr = (const unsigned char *) (buf.c_str());
|
||||
bool isErrorFlag = false;
|
||||
int ret;
|
||||
|
||||
auto timeout = std::chrono::system_clock::now() + tls_write_timeout_;
|
||||
auto now = std::chrono::system_clock::now();
|
||||
|
||||
do {
|
||||
ret = mbedtls_ssl_write(&ssl_, buf_cstr + total_written_length, bytes_to_write - total_written_length);
|
||||
if (ret > 0) {
|
||||
total_written_length += ret;
|
||||
} else if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_ssl_write returned -0x%x\n\n", -ret);
|
||||
/* All other negative return values indicate connection needs to be reset.
|
||||
* Will be caught in ping request so ignored here */
|
||||
isErrorFlag = true;
|
||||
break;
|
||||
}
|
||||
now = std::chrono::system_clock::now();
|
||||
} while (now < timeout && total_written_length < bytes_to_write);
|
||||
|
||||
size_written_bytes_out = total_written_length;
|
||||
|
||||
if (isErrorFlag) {
|
||||
rc = ResponseCode::NETWORK_SSL_WRITE_ERROR;
|
||||
} else if (now < timeout && total_written_length != bytes_to_write) {
|
||||
return ResponseCode::NETWORK_SSL_WRITE_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
ResponseCode MbedTLSConnection::ReadInternal(util::Vector<unsigned char> &buf, size_t buf_read_offset,
|
||||
size_t size_bytes_to_read, size_t &size_read_bytes_out) {
|
||||
int ret;
|
||||
size_t total_read_length = 0;
|
||||
size_t remaining_bytes_to_read = size_bytes_to_read;
|
||||
auto timeout = std::chrono::system_clock::now() + tls_read_timeout_;
|
||||
do {
|
||||
// This read will timeout after IOT_SSL_READ_TIMEOUT if there's no data to be read
|
||||
ret = mbedtls_ssl_read(&ssl_, &buf[buf_read_offset], remaining_bytes_to_read);
|
||||
if (ret > 0) {
|
||||
buf_read_offset += ret;
|
||||
total_read_length += ret;
|
||||
remaining_bytes_to_read -= ret;
|
||||
size_read_bytes_out = total_read_length;
|
||||
} else if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE
|
||||
&& ret != MBEDTLS_ERR_SSL_TIMEOUT) {
|
||||
return ResponseCode::NETWORK_SSL_READ_ERROR;
|
||||
}
|
||||
} while (remaining_bytes_to_read > 0 && timeout < std::chrono::system_clock::now());
|
||||
|
||||
if (0 == total_read_length) {
|
||||
return ResponseCode::NETWORK_SSL_NOTHING_TO_READ;
|
||||
} else if (size_read_bytes_out == size_bytes_to_read) {
|
||||
return ResponseCode::SUCCESS;
|
||||
} else if (0 < total_read_length) {
|
||||
return ResponseCode::NETWORK_SSL_READ_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
return ResponseCode::NETWORK_SSL_READ_ERROR;
|
||||
}
|
||||
|
||||
ResponseCode MbedTLSConnection::DisconnectInternal() {
|
||||
if (is_connected_) {
|
||||
int ret = 0;
|
||||
do {
|
||||
ret = mbedtls_ssl_close_notify(&ssl_);
|
||||
} while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||
}
|
||||
|
||||
if(requires_free_) {
|
||||
mbedtls_net_free(&server_fd_);
|
||||
|
||||
mbedtls_x509_crt_free(&clicert_);
|
||||
mbedtls_x509_crt_free(&cacert_);
|
||||
mbedtls_pk_free(&pkey_);
|
||||
mbedtls_ssl_free(&ssl_);
|
||||
mbedtls_ssl_config_free(&conf_);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg_);
|
||||
mbedtls_entropy_free(&entropy_);
|
||||
requires_free_ = false;
|
||||
}
|
||||
|
||||
is_connected_ = false;
|
||||
|
||||
/* All other negative return values indicate connection needs to be reset.
|
||||
* No further action required since this is disconnect call */
|
||||
return ResponseCode::SUCCESS;
|
||||
}
|
||||
|
||||
MbedTLSConnection::~MbedTLSConnection() {
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
* express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file MbedTLSConnection.hpp
|
||||
* @brief Defines a reference implementation for an MbedTLS library wrapper *
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "mbedtls/config.h"
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
#ifdef MBEDTLS_NEW_HEADERS
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#else
|
||||
#include "mbedtls/net.h"
|
||||
#endif
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/certs.h"
|
||||
#include "mbedtls/x509.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/timing.h"
|
||||
|
||||
#include "NetworkConnection.hpp"
|
||||
#include "ResponseCode.hpp"
|
||||
|
||||
namespace awsiotsdk {
|
||||
namespace network {
|
||||
/**
|
||||
* @brief MbedTLS Wrapper Class
|
||||
*
|
||||
* Defines a reference wrapper for MbedTLS libraries
|
||||
*/
|
||||
class MbedTLSConnection : public NetworkConnection {
|
||||
protected:
|
||||
util::String root_ca_location_; ///< Pointer to string containing the filename (including path) of the root CA file.
|
||||
util::String device_cert_location_; ///< Pointer to string containing the filename (including path) of the device certificate.
|
||||
util::String device_private_key_location_; ///< Pointer to string containing the filename (including path) of the device private key file.
|
||||
std::atomic_bool server_verification_flag_; ///< Boolean. True = perform server certificate hostname validation. False = skip validation \b NOT recommended.
|
||||
std::atomic_bool is_connected_; ///< Boolean indicating connection status
|
||||
std::chrono::milliseconds tls_handshake_timeout_; ///< Timeout for TLS handshake command
|
||||
std::chrono::milliseconds tls_read_timeout_; ///< Timeout for the TLS Read command
|
||||
std::chrono::milliseconds tls_write_timeout_; ///< Timeout for the TLS Write command
|
||||
|
||||
// Endpoint information
|
||||
uint16_t endpoint_port_; ///< Endpoint port
|
||||
util::String endpoint_; ///< Endpoint for this connection
|
||||
|
||||
mbedtls_entropy_context entropy_;
|
||||
mbedtls_ctr_drbg_context ctr_drbg_;
|
||||
mbedtls_ssl_context ssl_;
|
||||
mbedtls_ssl_config conf_;
|
||||
uint32_t flags_;
|
||||
mbedtls_x509_crt cacert_;
|
||||
mbedtls_x509_crt clicert_;
|
||||
mbedtls_pk_context pkey_;
|
||||
mbedtls_net_context server_fd_;
|
||||
|
||||
// TODO: This is a Hotfix, requires a better approach
|
||||
std::atomic_bool requires_free_; ///< Boolean indicating whether the mbedtls struct variables have been allocated or not
|
||||
|
||||
/**
|
||||
* @brief Create a TLS socket and open the connection
|
||||
*
|
||||
* Creates an open socket connection including TLS handshake.
|
||||
*
|
||||
* @return ResponseCode - successful connection or TLS error
|
||||
*/
|
||||
ResponseCode ConnectInternal();
|
||||
|
||||
/**
|
||||
* @brief Write bytes to the network socket
|
||||
*
|
||||
* @param util::String - const reference to buffer which should be written to socket
|
||||
* @return size_t - number of bytes written or Network error
|
||||
* @return ResponseCode - successful write or Network error code
|
||||
*/
|
||||
ResponseCode WriteInternal(const util::String &buf, size_t &size_written_bytes_out);
|
||||
|
||||
/**
|
||||
* @brief Read bytes from the network socket
|
||||
*
|
||||
* @param util::String - reference to buffer where read bytes should be copied
|
||||
* @param size_t - number of bytes to read
|
||||
* @param size_t - reference to store number of bytes read
|
||||
* @return ResponseCode - successful read or TLS error code
|
||||
*/
|
||||
ResponseCode ReadInternal(util::Vector<unsigned char> &buf, size_t buf_read_offset,
|
||||
size_t size_bytes_to_read, size_t &size_read_bytes_out);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from network socket
|
||||
*
|
||||
* @return ResponseCode - successful read or TLS error code
|
||||
*/
|
||||
ResponseCode DisconnectInternal();
|
||||
|
||||
public:
|
||||
static int VerifyCertificate(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags);
|
||||
|
||||
/**
|
||||
* @brief Constructor for the MbedTLS TLS implementation
|
||||
*
|
||||
* Performs any initialization required by the TLS layer.
|
||||
*
|
||||
* @param util::String endpoint - The target endpoint to connect to
|
||||
* @param uint16_t endpoint_port - The port on the target to connect to
|
||||
* @param util::String root_ca_location - Path of the location of the Root CA
|
||||
* @param util::String device_cert_location - Path to the location of the Device Cert
|
||||
* @param util::String device_private_key_location - Path to the location of the device private key file
|
||||
* @param std::chrono::milliseconds tls_handshake_timeout - The value to use for timeout of handshake operation
|
||||
* @param std::chrono::milliseconds tls_read_timeout - The value to use for timeout of read operation
|
||||
* @param std::chrono::milliseconds tls_write_timeout - The value to use for timeout of write operation
|
||||
* @param bool server_verification_flag - used to decide whether server verification is needed or not
|
||||
*
|
||||
*/
|
||||
MbedTLSConnection(util::String endpoint, uint16_t endpoint_port, util::String root_ca_location,
|
||||
util::String device_cert_location, util::String device_private_key_location,
|
||||
std::chrono::milliseconds tls_handshake_timeout,
|
||||
std::chrono::milliseconds tls_read_timeout, std::chrono::milliseconds tls_write_timeout,
|
||||
bool server_verification_flag);
|
||||
|
||||
/**
|
||||
* @brief Check if TLS layer is still connected
|
||||
*
|
||||
* Called to check if the TLS layer is still connected or not.
|
||||
*
|
||||
* @return bool - indicating status of network TLS layer connection
|
||||
*/
|
||||
bool IsConnected();
|
||||
|
||||
/**
|
||||
* @brief Check if Network Physical layer is still connected
|
||||
*
|
||||
* Called to check if the Network Physical layer is still connected or not.
|
||||
*
|
||||
* @return bool - indicating status of network physical layer connection
|
||||
*/
|
||||
bool IsPhysicalLayerConnected();
|
||||
|
||||
/**
|
||||
* @brief sets the path to the root CA
|
||||
*
|
||||
* Called to change the location of the root CA after the constructor has initialized the OpenSSL object.
|
||||
*
|
||||
* @param root_ca_location
|
||||
*/
|
||||
void SetRootCAPath(util::String root_ca_location) { root_ca_location_ = root_ca_location; }
|
||||
|
||||
/**
|
||||
* @brief sets the endpoint and the port
|
||||
*
|
||||
* Called to change the endpoint and the port after the constructor has initialized the OpenSSL object.
|
||||
* @param endpoint
|
||||
* @param endpoint_port
|
||||
*/
|
||||
void SetEndpointAndPort(util::String endpoint, uint16_t endpoint_port) {
|
||||
endpoint_ = endpoint;
|
||||
endpoint_port_ = endpoint_port;
|
||||
}
|
||||
|
||||
virtual ~MbedTLSConnection();
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
The files in this folder have been taken from
|
||||
|
||||
https://github.com/aws/aws-iot-device-sdk-cpp
|
||||
|
||||
under the term of the Apache License, Version 2.0
|
||||
|
||||
572
libguh-core/OpenSSL/OpenSSLConnection.cpp
Normal file
572
libguh-core/OpenSSL/OpenSSLConnection.cpp
Normal file
@ -0,0 +1,572 @@
|
||||
/*
|
||||
* Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
* express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file OpenSSLConnection.hpp
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <util/memory/stl/Vector.hpp>
|
||||
|
||||
#include "OpenSSLConnection.hpp"
|
||||
#include "util/logging/LogMacros.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
#define MAX_PATH_LENGTH_ 260
|
||||
#include <direct.h>
|
||||
#define getcwd _getcwd // avoid MSFT "deprecation" warning
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <limits>
|
||||
#include <resolv.h>
|
||||
#define MAX_PATH_LENGTH_ PATH_MAX
|
||||
#endif
|
||||
|
||||
#define OPENSSL_WRAPPER_LOG_TAG "[OpenSSL Wrapper]"
|
||||
|
||||
namespace awsiotsdk {
|
||||
namespace network {
|
||||
OpenSSLInitializer::~OpenSSLInitializer() {
|
||||
CONF_modules_free();
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
ERR_remove_thread_state(NULL);
|
||||
#endif
|
||||
CONF_modules_unload(1);
|
||||
SSL_COMP_free_compression_methods();
|
||||
ERR_free_strings();
|
||||
EVP_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
}
|
||||
|
||||
OpenSSLInitializer *OpenSSLInitializer::getInstance() {
|
||||
static OpenSSLInitializer initializer;
|
||||
return &initializer;
|
||||
}
|
||||
|
||||
std::atomic_bool OpenSSLConnection::is_lib_initialized(false);
|
||||
|
||||
OpenSSLConnection::OpenSSLConnection(util::String endpoint, uint16_t endpoint_port,
|
||||
std::chrono::milliseconds tls_handshake_timeout,
|
||||
std::chrono::milliseconds tls_read_timeout,
|
||||
std::chrono::milliseconds tls_write_timeout,
|
||||
bool server_verification_flag) {
|
||||
endpoint_ = endpoint;
|
||||
endpoint_port_ = endpoint_port;
|
||||
server_verification_flag_ = server_verification_flag;
|
||||
int timeout_ms = static_cast<int>(tls_handshake_timeout.count());
|
||||
tls_handshake_timeout_ = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
|
||||
timeout_ms = static_cast<int>(tls_read_timeout.count());
|
||||
tls_read_timeout_ = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
|
||||
timeout_ms = static_cast<int>(tls_write_timeout.count());
|
||||
tls_write_timeout_ = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
|
||||
|
||||
is_connected_ = false;
|
||||
certificates_read_flag_ = false;
|
||||
initializer = OpenSSLInitializer::getInstance();
|
||||
p_ssl_handle_ = nullptr;
|
||||
}
|
||||
|
||||
OpenSSLConnection::OpenSSLConnection(util::String endpoint,
|
||||
uint16_t endpoint_port,
|
||||
util::String root_ca_location,
|
||||
util::String device_cert_location,
|
||||
util::String device_private_key_location,
|
||||
std::chrono::milliseconds tls_handshake_timeout,
|
||||
std::chrono::milliseconds tls_read_timeout,
|
||||
std::chrono::milliseconds tls_write_timeout,
|
||||
bool server_verification_flag)
|
||||
: OpenSSLConnection(endpoint, endpoint_port, tls_handshake_timeout, tls_read_timeout, tls_write_timeout,
|
||||
server_verification_flag) {
|
||||
root_ca_location_ = root_ca_location;
|
||||
device_cert_location_ = device_cert_location;
|
||||
device_private_key_location_ = device_private_key_location;
|
||||
}
|
||||
|
||||
OpenSSLConnection::OpenSSLConnection(util::String endpoint,
|
||||
uint16_t endpoint_port,
|
||||
util::String root_ca_location,
|
||||
std::chrono::milliseconds tls_handshake_timeout,
|
||||
std::chrono::milliseconds tls_read_timeout,
|
||||
std::chrono::milliseconds tls_write_timeout,
|
||||
bool server_verification_flag)
|
||||
: OpenSSLConnection(endpoint, endpoint_port, tls_handshake_timeout, tls_read_timeout, tls_write_timeout,
|
||||
server_verification_flag) {
|
||||
root_ca_location_ = root_ca_location;
|
||||
device_cert_location_.clear();
|
||||
device_private_key_location_.clear();
|
||||
}
|
||||
|
||||
int OpenSSLConnection::WaitForSelect(int error_code) {
|
||||
fd_set socketFds;
|
||||
struct timeval timeout = {tls_write_timeout_.tv_sec, tls_write_timeout_.tv_usec};
|
||||
FD_ZERO(&socketFds);
|
||||
FD_SET(server_tcp_socket_fd_, &socketFds);
|
||||
if (SSL_ERROR_WANT_READ == error_code) {
|
||||
return select(server_tcp_socket_fd_ + 1, &socketFds, NULL, NULL, &timeout);
|
||||
} else if (SSL_ERROR_WANT_WRITE == error_code) {
|
||||
return select(server_tcp_socket_fd_ + 1, NULL, &socketFds, NULL, &timeout);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::Initialize() {
|
||||
#ifdef WIN32
|
||||
// TODO : Check if it is possible to replace this with std::call_once
|
||||
WSADATA wsa_data;
|
||||
int result;
|
||||
bool was_wsa_initialized = true;
|
||||
int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if(INVALID_SOCKET == s) {
|
||||
if(WSANOTINITIALISED == WSAGetLastError()) {
|
||||
was_wsa_initialized = false;
|
||||
}
|
||||
} else {
|
||||
closesocket(s);
|
||||
}
|
||||
|
||||
if(!was_wsa_initialized) {
|
||||
// Initialize Winsock
|
||||
result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
if(0 != result) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, "WSAStartup failed: %d", result);
|
||||
return ResponseCode::NETWORK_SSL_INIT_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!is_lib_initialized) {
|
||||
OpenSSL_add_all_algorithms();
|
||||
ERR_load_BIO_strings();
|
||||
ERR_load_crypto_strings();
|
||||
SSL_load_error_strings();
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
is_lib_initialized = true;
|
||||
}
|
||||
const SSL_METHOD *method;
|
||||
|
||||
if (SSL_library_init() < 0) {
|
||||
return ResponseCode::NETWORK_SSL_INIT_ERROR;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
method = TLSv1_2_method();
|
||||
#else
|
||||
method = TLS_method();
|
||||
#endif
|
||||
|
||||
if ((p_ssl_context_ = SSL_CTX_new(method)) == NULL) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " SSL INIT Failed - Unable to create SSL Context");
|
||||
return ResponseCode::NETWORK_SSL_INIT_ERROR;
|
||||
}
|
||||
|
||||
return ResponseCode::SUCCESS;
|
||||
}
|
||||
|
||||
bool OpenSSLConnection::IsPhysicalLayerConnected() {
|
||||
// Use this to add implementation which can check for physical layer disconnect
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenSSLConnection::IsConnected() {
|
||||
return is_connected_;
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::ConnectTCPSocket() {
|
||||
const char *endpoint_char = endpoint_.c_str();
|
||||
if (nullptr == endpoint_char) {
|
||||
return ResponseCode::NETWORK_TCP_NO_ENDPOINT_SPECIFIED;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
if (res_init() == -1) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, "DNS initialize error");
|
||||
}
|
||||
#endif
|
||||
|
||||
hostent *host = gethostbyname(endpoint_char);
|
||||
if (nullptr == host) {
|
||||
return ResponseCode::NETWORK_TCP_NO_ENDPOINT_SPECIFIED;
|
||||
}
|
||||
|
||||
sockaddr_in dest_addr;
|
||||
|
||||
dest_addr.sin_family = AF_INET;
|
||||
dest_addr.sin_port = htons(endpoint_port_);
|
||||
dest_addr.sin_addr.s_addr = *(uint32_t *) (host->h_addr);
|
||||
memset(&(dest_addr.sin_zero), '\0', 8);
|
||||
|
||||
AWS_LOG_INFO(OPENSSL_WRAPPER_LOG_TAG,
|
||||
"resolved %s to %s",
|
||||
endpoint_.c_str(),
|
||||
inet_ntoa(dest_addr.sin_addr));
|
||||
|
||||
int connect_status = connect(server_tcp_socket_fd_, (sockaddr *) &dest_addr, sizeof(sockaddr));
|
||||
if (-1 != connect_status) {
|
||||
return ResponseCode::SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
closesocket(server_tcp_socket_fd_);
|
||||
#else
|
||||
close(server_tcp_socket_fd_);
|
||||
#endif
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, "connect - %s", strerror(errno));
|
||||
return ResponseCode::NETWORK_TCP_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::SetSocketToNonBlocking() {
|
||||
int status;
|
||||
ResponseCode ret_val = ResponseCode::SUCCESS;
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
u_long flag = 1L;
|
||||
status = ioctlsocket(server_tcp_socket_fd_, FIONBIO, &flag);
|
||||
if (0 > status) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, "ioctlsocket - %s", strerror(errno));
|
||||
ret_val = ResponseCode::NETWORK_TCP_CONNECT_ERROR;
|
||||
}
|
||||
#else
|
||||
int flags = fcntl(server_tcp_socket_fd_, F_GETFL, 0);
|
||||
// set underlying socket to non blocking
|
||||
if (0 > flags) {
|
||||
ret_val = ResponseCode::NETWORK_TCP_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
status = fcntl(server_tcp_socket_fd_, F_SETFL, flags | O_NONBLOCK);
|
||||
if (0 > status) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, "fcntl - %s", strerror(errno));
|
||||
ret_val = ResponseCode::NETWORK_TCP_CONNECT_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::AttemptConnect() {
|
||||
ResponseCode ret_val = ResponseCode::FAILURE;
|
||||
int rc = 0;
|
||||
int errorCode = 0;
|
||||
int select_retCode = 0;
|
||||
|
||||
do {
|
||||
ERR_clear_error();
|
||||
rc = SSL_connect(p_ssl_handle_);
|
||||
|
||||
if (1 == rc) { //1 = SSL_CONNECTED, <= 0 is Error
|
||||
ret_val = ResponseCode::SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
errorCode = SSL_get_error(p_ssl_handle_, rc);
|
||||
|
||||
if (SSL_ERROR_WANT_READ == errorCode) {
|
||||
select_retCode = WaitForSelect(errorCode);
|
||||
if (0 == select_retCode) { // 0 == SELECT_TIMEOUT
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " SSL Connect time out while waiting for read");
|
||||
ret_val = ResponseCode::NETWORK_SSL_CONNECT_TIMEOUT_ERROR;
|
||||
} else if (-1 == select_retCode) { // -1 == SELECT_ERROR
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " SSL Connect Select error for read %d", select_retCode);
|
||||
ret_val = ResponseCode::NETWORK_SSL_CONNECT_ERROR;
|
||||
}
|
||||
} else if (SSL_ERROR_WANT_WRITE == errorCode) {
|
||||
select_retCode = WaitForSelect(errorCode);
|
||||
if (0 == select_retCode) { // 0 == SELECT_TIMEOUT
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " SSL Connect time out while waiting for write");
|
||||
ret_val = ResponseCode::NETWORK_SSL_CONNECT_TIMEOUT_ERROR;
|
||||
} else if (-1 == select_retCode) { // -1 == SELECT_ERROR
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG,
|
||||
" SSL Connect Select error for write %d",
|
||||
select_retCode);
|
||||
ret_val = ResponseCode::NETWORK_SSL_CONNECT_ERROR;
|
||||
}
|
||||
} else {
|
||||
ret_val = ResponseCode::NETWORK_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
} while (ResponseCode::NETWORK_SSL_CONNECT_ERROR != ret_val &&
|
||||
ResponseCode::NETWORK_SSL_CONNECT_TIMEOUT_ERROR != ret_val);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::LoadCerts() {
|
||||
AWS_LOG_DEBUG(OPENSSL_WRAPPER_LOG_TAG, "Root CA : %s", root_ca_location_.c_str());
|
||||
if (!SSL_CTX_load_verify_locations(p_ssl_context_, root_ca_location_.c_str(), NULL)) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " Root CA Loading error");
|
||||
return ResponseCode::NETWORK_SSL_ROOT_CRT_PARSE_ERROR;
|
||||
}
|
||||
|
||||
// TODO: streamline error codes for TLS
|
||||
if (0 < device_cert_location_.length() && 0 < device_private_key_location_.length()) {
|
||||
AWS_LOG_DEBUG(OPENSSL_WRAPPER_LOG_TAG, "Device crt : %s", device_cert_location_.c_str());
|
||||
if (!SSL_CTX_use_certificate_chain_file(p_ssl_context_, device_cert_location_.c_str())) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " Device Certificate Loading error");
|
||||
return ResponseCode::NETWORK_SSL_DEVICE_CRT_PARSE_ERROR;
|
||||
}
|
||||
AWS_LOG_DEBUG(OPENSSL_WRAPPER_LOG_TAG, "Device privkey : %s", device_private_key_location_.c_str());
|
||||
if (1 != SSL_CTX_use_PrivateKey_file(p_ssl_context_,
|
||||
device_private_key_location_.c_str(),
|
||||
SSL_FILETYPE_PEM)) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " Device Private Key Loading error");
|
||||
return ResponseCode::NETWORK_SSL_KEY_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
certificates_read_flag_ = true;
|
||||
return ResponseCode::SUCCESS;
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::PerformSSLConnect() {
|
||||
ResponseCode networkResponse = ResponseCode::SUCCESS;
|
||||
|
||||
// Configure a non-zero callback if desired
|
||||
SSL_set_verify(p_ssl_handle_, SSL_VERIFY_PEER, nullptr);
|
||||
|
||||
server_tcp_socket_fd_ = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (-1 == server_tcp_socket_fd_) {
|
||||
return ResponseCode::NETWORK_TCP_SETUP_ERROR;
|
||||
}
|
||||
|
||||
networkResponse = ConnectTCPSocket();
|
||||
if (ResponseCode::SUCCESS != networkResponse) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, "TCP Connection error");
|
||||
return networkResponse;
|
||||
}
|
||||
|
||||
SSL_set_fd(p_ssl_handle_, server_tcp_socket_fd_);
|
||||
|
||||
networkResponse = SetSocketToNonBlocking();
|
||||
if (ResponseCode::SUCCESS != networkResponse) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " Unable to set the socket to Non-Blocking");
|
||||
} else {
|
||||
networkResponse = AttemptConnect();
|
||||
if (X509_V_OK != SSL_get_verify_result(p_ssl_handle_)) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " Server Certificate Verification failed.");
|
||||
networkResponse = ResponseCode::NETWORK_SSL_CONNECT_ERROR;
|
||||
} else {
|
||||
// ensure you have a valid certificate returned, otherwise no certificate exchange happened
|
||||
auto cert_destroyer = [](X509 *cert) {
|
||||
if (nullptr != cert) X509_free(cert);
|
||||
};
|
||||
std::unique_ptr<X509, decltype(cert_destroyer)> cert(SSL_get_peer_certificate(p_ssl_handle_),
|
||||
cert_destroyer);
|
||||
if (nullptr == cert) {
|
||||
AWS_LOG_ERROR(OPENSSL_WRAPPER_LOG_TAG, " No certificate exchange happened");
|
||||
networkResponse = ResponseCode::NETWORK_SSL_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ResponseCode::SUCCESS != networkResponse) {
|
||||
#ifdef WIN32
|
||||
closesocket(server_tcp_socket_fd_);
|
||||
#else
|
||||
close(server_tcp_socket_fd_);
|
||||
#endif
|
||||
}
|
||||
|
||||
return networkResponse;
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::ConnectInternal() {
|
||||
ResponseCode networkResponse = ResponseCode::SUCCESS;
|
||||
|
||||
X509_VERIFY_PARAM *param = nullptr;
|
||||
|
||||
if (!certificates_read_flag_) {
|
||||
networkResponse = LoadCerts();
|
||||
if (ResponseCode::SUCCESS != networkResponse) {
|
||||
return networkResponse;
|
||||
}
|
||||
}
|
||||
|
||||
if (nullptr == p_ssl_handle_) {
|
||||
p_ssl_handle_ = SSL_new(p_ssl_context_);
|
||||
}
|
||||
|
||||
// Requires OpenSSL v1.0.2 and above
|
||||
if (server_verification_flag_) {
|
||||
param = SSL_get0_param(p_ssl_handle_);
|
||||
// Enable automatic hostname checks
|
||||
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
|
||||
// Check if it is an IPv4 or an IPv6 address to enable ip checking
|
||||
// Enable host name check otherwise
|
||||
char dst[INET6_ADDRSTRLEN];
|
||||
if (inet_pton(AF_INET, endpoint_.c_str(), (void *) dst) ||
|
||||
inet_pton(AF_INET6, endpoint_.c_str(), (void *) dst)) {
|
||||
X509_VERIFY_PARAM_set1_ip_asc(param, endpoint_.c_str());
|
||||
} else {
|
||||
X509_VERIFY_PARAM_set1_host(param, endpoint_.c_str(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
networkResponse = PerformSSLConnect();
|
||||
if (ResponseCode::SUCCESS != networkResponse) {
|
||||
SSL_free(p_ssl_handle_);
|
||||
p_ssl_handle_ = nullptr;
|
||||
}
|
||||
|
||||
if (ResponseCode::SUCCESS == networkResponse) {
|
||||
is_connected_ = true;
|
||||
}
|
||||
|
||||
return networkResponse;
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::WriteInternal(const util::String &buf, size_t &size_written_bytes_out) {
|
||||
int error_code = 0;
|
||||
int select_retCode = -1;
|
||||
int cur_written_length = 0;
|
||||
size_t total_written_length = 0;
|
||||
ResponseCode rc = ResponseCode::SUCCESS;
|
||||
size_t bytes_to_write = buf.length();
|
||||
|
||||
do {
|
||||
ERR_clear_error();
|
||||
if (nullptr == p_ssl_handle_) {
|
||||
return ResponseCode::NETWORK_SSL_WRITE_ERROR;
|
||||
}
|
||||
cur_written_length = SSL_write(p_ssl_handle_, buf.c_str(), bytes_to_write);
|
||||
error_code = SSL_get_error(p_ssl_handle_, cur_written_length);
|
||||
if (0 < cur_written_length) {
|
||||
total_written_length += (size_t) cur_written_length;
|
||||
} else if (SSL_ERROR_WANT_WRITE == error_code) {
|
||||
select_retCode = WaitForSelect(error_code);
|
||||
if (0 == select_retCode) { //0 == SELECT_TIMEOUT
|
||||
rc = ResponseCode::NETWORK_SSL_WRITE_TIMEOUT_ERROR;
|
||||
} else if (-1 == select_retCode) { //-1 == SELECT_TIMEOUT
|
||||
rc = ResponseCode::NETWORK_SSL_WRITE_ERROR;
|
||||
}
|
||||
} else {
|
||||
rc = ResponseCode::NETWORK_SSL_WRITE_ERROR;
|
||||
}
|
||||
|
||||
} while (is_connected_ && ResponseCode::NETWORK_SSL_WRITE_ERROR != rc &&
|
||||
ResponseCode::NETWORK_SSL_WRITE_TIMEOUT_ERROR != rc &&
|
||||
total_written_length < bytes_to_write);
|
||||
|
||||
if (ResponseCode::SUCCESS == rc) {
|
||||
size_written_bytes_out = total_written_length;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::ReadInternal(util::Vector<unsigned char> &buf, size_t buf_read_offset,
|
||||
size_t size_bytes_to_read, size_t &size_read_bytes_out) {
|
||||
int ssl_retcode;
|
||||
int select_retCode;
|
||||
size_t total_read_length = buf_read_offset;
|
||||
size_t remaining_bytes_to_read = size_bytes_to_read;
|
||||
int cur_read_len = 0;
|
||||
ResponseCode errorStatus = ResponseCode::SUCCESS;
|
||||
|
||||
do {
|
||||
ERR_clear_error();
|
||||
if (nullptr == p_ssl_handle_) {
|
||||
return ResponseCode::NETWORK_SSL_READ_ERROR;
|
||||
}
|
||||
cur_read_len = SSL_read(p_ssl_handle_, &buf[total_read_length], (int) remaining_bytes_to_read);
|
||||
if (0 < cur_read_len) {
|
||||
total_read_length += (size_t) cur_read_len;
|
||||
remaining_bytes_to_read -= cur_read_len;
|
||||
} else {
|
||||
ssl_retcode = SSL_get_error(p_ssl_handle_, cur_read_len);
|
||||
switch (ssl_retcode) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
select_retCode = WaitForSelect(SSL_ERROR_WANT_READ);
|
||||
if (0 < select_retCode) {
|
||||
continue;
|
||||
} else if (0 == select_retCode) { //0 == SELECT_TIMEOUT
|
||||
errorStatus = ResponseCode::NETWORK_SSL_NOTHING_TO_READ;
|
||||
} else { // SELECT_ERROR
|
||||
errorStatus = ResponseCode::NETWORK_SSL_READ_ERROR;
|
||||
}
|
||||
break;
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
errorStatus = ResponseCode::NETWORK_SSL_CONNECTION_CLOSED_ERROR;
|
||||
break;
|
||||
default:
|
||||
errorStatus = ResponseCode::NETWORK_SSL_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ResponseCode::NETWORK_SSL_NOTHING_TO_READ == errorStatus ||
|
||||
ResponseCode::NETWORK_SSL_READ_ERROR == errorStatus ||
|
||||
ResponseCode::NETWORK_SSL_CONNECTION_CLOSED_ERROR == errorStatus) {
|
||||
break;
|
||||
}
|
||||
} while (is_connected_ && total_read_length < size_bytes_to_read);
|
||||
|
||||
if (ResponseCode::SUCCESS == errorStatus) {
|
||||
size_read_bytes_out = total_read_length;
|
||||
}
|
||||
|
||||
return errorStatus;
|
||||
}
|
||||
|
||||
ResponseCode OpenSSLConnection::DisconnectInternal() {
|
||||
if (!is_connected_) {
|
||||
return ResponseCode::SUCCESS;
|
||||
}
|
||||
is_connected_ = false;
|
||||
|
||||
std::chrono::milliseconds timeout = std::chrono::milliseconds(tls_read_timeout_.tv_sec * 1000 +
|
||||
tls_read_timeout_.tv_usec / 1000);
|
||||
|
||||
std::unique_lock<std::mutex> shutdown_lock(clean_shutdown_action_lock_);
|
||||
|
||||
// TODO: add config for disconnect timeout
|
||||
// wait for tls_read_timeout and then exit the shutdown loop if it is not successful
|
||||
this->shutdown_timeout_condition_.wait_for(shutdown_lock, std::chrono::milliseconds(timeout), [this] {
|
||||
int rc = SSL_shutdown(p_ssl_handle_);
|
||||
if (1 == rc) {
|
||||
return true;
|
||||
}
|
||||
int errorCode = SSL_get_error(p_ssl_handle_, rc);
|
||||
WaitForSelect(errorCode);
|
||||
return false;
|
||||
});
|
||||
|
||||
SSL_free(p_ssl_handle_);
|
||||
p_ssl_handle_ = nullptr;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
ERR_remove_thread_state(NULL);
|
||||
#endif
|
||||
|
||||
certificates_read_flag_ = false;
|
||||
#ifdef WIN32
|
||||
closesocket(server_tcp_socket_fd_);
|
||||
#else
|
||||
close(server_tcp_socket_fd_);
|
||||
#endif
|
||||
return ResponseCode::SUCCESS;
|
||||
}
|
||||
|
||||
OpenSSLConnection::~OpenSSLConnection() {
|
||||
if (is_connected_) {
|
||||
Disconnect();
|
||||
}
|
||||
SSL_CTX_free(p_ssl_context_);
|
||||
#ifdef WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
286
libguh-core/OpenSSL/OpenSSLConnection.hpp
Normal file
286
libguh-core/OpenSSL/OpenSSLConnection.hpp
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* A copy of the License is located at
|
||||
*
|
||||
* http://aws.amazon.com/apache2.0
|
||||
*
|
||||
* or in the "license" file accompanying this file. This file is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||
* express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file OpenSSLConnection.hpp
|
||||
* @brief Defines a reference implementation for an OpenSSL library wrapper
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment(lib,"ws2_32")
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/select.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "NetworkConnection.hpp"
|
||||
#include "ResponseCode.hpp"
|
||||
|
||||
namespace awsiotsdk {
|
||||
namespace network {
|
||||
/**
|
||||
* @brief Dummy class for uninitializing the OpenSSL library'
|
||||
*
|
||||
* TODO: This is a hotfix and will be updated after design changes
|
||||
*/
|
||||
class OpenSSLInitializer {
|
||||
private:
|
||||
// Rule of 5 stuff
|
||||
// Default constructor
|
||||
OpenSSLInitializer() = default;
|
||||
// Default Copy constructor
|
||||
OpenSSLInitializer(const OpenSSLInitializer &) = default;
|
||||
// Default Move constructor
|
||||
OpenSSLInitializer(OpenSSLInitializer &&) = default;
|
||||
// Default Copy assignment operator
|
||||
OpenSSLInitializer &operator=(const OpenSSLInitializer &) & = default;
|
||||
// Default Move assignment operator
|
||||
OpenSSLInitializer &operator=(OpenSSLInitializer &&) & = default;
|
||||
|
||||
public:
|
||||
static OpenSSLInitializer* getInstance();
|
||||
|
||||
~OpenSSLInitializer();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief OpenSSL Wrapper Class
|
||||
*
|
||||
* Defines a reference wrapper for OpenSSL libraries
|
||||
*/
|
||||
class OpenSSLConnection : public NetworkConnection {
|
||||
protected:
|
||||
static std::atomic_bool is_lib_initialized; ///< Boolean, True = Library is initialized, False otherwise
|
||||
OpenSSLInitializer *initializer; ///< Pointer to dummy library instance
|
||||
util::String root_ca_location_; ///< Pointer to string containing the filename (including path) of the root CA file.
|
||||
util::String device_cert_location_; ///< Pointer to string containing the filename (including path) of the device certificate.
|
||||
util::String device_private_key_location_; ///< Pointer to string containing the filename (including path) of the device private key file.
|
||||
bool server_verification_flag_; ///< Boolean. True = perform server certificate hostname validation. False = skip validation \b NOT recommended.
|
||||
std::atomic_bool is_connected_; ///< Boolean indicating connection status
|
||||
struct timeval tls_handshake_timeout_; ///< Timeout for TLS handshake command
|
||||
struct timeval tls_read_timeout_; ///< Timeout for the TLS Read command
|
||||
struct timeval tls_write_timeout_; ///< Timeout for the TLS Write command
|
||||
|
||||
// Endpoint information
|
||||
uint16_t endpoint_port_; ///< Endpoint port
|
||||
util::String endpoint_; ///< Endpoint for this connection
|
||||
|
||||
SSL_CTX *p_ssl_context_; ///< SSL Context instance
|
||||
SSL *p_ssl_handle_; ///< SSL Handle
|
||||
int server_tcp_socket_fd_; ///< Server Socket descriptor
|
||||
|
||||
bool certificates_read_flag_;
|
||||
|
||||
std::mutex clean_shutdown_action_lock_;
|
||||
std::condition_variable shutdown_timeout_condition_;
|
||||
|
||||
/**
|
||||
* @brief Wait for socket FDs to become ready for read or write operations
|
||||
*
|
||||
* It is assumed that this function will be called only on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
|
||||
*
|
||||
* @param error_code - error generated by preceding socket operation
|
||||
* @return int - return code of the select operation
|
||||
*/
|
||||
int WaitForSelect(int error_code);
|
||||
|
||||
/**
|
||||
* @brief Set TLS socket to non-blocking mode
|
||||
*
|
||||
* @return ResponseCode - successful operation or TLS error
|
||||
*/
|
||||
ResponseCode SetSocketToNonBlocking();
|
||||
|
||||
/**
|
||||
* @brief Create a TCP socket and open the connection
|
||||
*
|
||||
* Creates an open socket connection
|
||||
*
|
||||
* @return ResponseCode - successful connection or TCP error
|
||||
*/
|
||||
ResponseCode ConnectTCPSocket();
|
||||
|
||||
/**
|
||||
* @brief Attempt connection
|
||||
*
|
||||
* Attempts TLS Connection
|
||||
*
|
||||
* @return ResponseCode - successful connection or TLS error
|
||||
*/
|
||||
ResponseCode AttemptConnect();
|
||||
|
||||
/**
|
||||
* @brief Create a TLS socket and open the connection
|
||||
*
|
||||
* Creates an open socket connection including TLS handshake.
|
||||
*
|
||||
* @return ResponseCode - successful connection or TLS error
|
||||
*/
|
||||
ResponseCode LoadCerts();
|
||||
|
||||
/**
|
||||
* @brief Perform the connect process after creating the SSL handle and context
|
||||
*
|
||||
* Performs the steps necessary for connecting to an endpoint after the creation of the SSL instance
|
||||
*
|
||||
* @return ResponseCode - successful connection or TLS error
|
||||
*/
|
||||
ResponseCode PerformSSLConnect();
|
||||
|
||||
/**
|
||||
* @brief Create a TLS socket and open the connection
|
||||
*
|
||||
* Creates an open socket connection including TLS handshake.
|
||||
*
|
||||
* @return ResponseCode - successful connection or TLS error
|
||||
*/
|
||||
ResponseCode ConnectInternal();
|
||||
|
||||
/**
|
||||
* @brief Write bytes to the network socket
|
||||
*
|
||||
* @param util::String - const reference to buffer which should be written to socket
|
||||
* @return size_t - number of bytes written or Network error
|
||||
* @return ResponseCode - successful write or Network error code
|
||||
*/
|
||||
ResponseCode WriteInternal(const util::String &buf, size_t &size_written_bytes_out);
|
||||
|
||||
/**
|
||||
* @brief Read bytes from the network socket
|
||||
*
|
||||
* @param util::String - reference to buffer where read bytes should be copied
|
||||
* @param size_t - number of bytes to read
|
||||
* @param size_t - reference to store number of bytes read
|
||||
* @return ResponseCode - successful read or TLS error code
|
||||
*/
|
||||
ResponseCode ReadInternal(util::Vector<unsigned char> &buf, size_t buf_read_offset,
|
||||
size_t size_bytes_to_read, size_t &size_read_bytes_out);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from network socket
|
||||
*
|
||||
* @return ResponseCode - successful read or TLS error code
|
||||
*/
|
||||
ResponseCode DisconnectInternal();
|
||||
|
||||
public:
|
||||
|
||||
OpenSSLConnection(util::String endpoint, uint16_t endpoint_port,
|
||||
std::chrono::milliseconds tls_handshake_timeout,
|
||||
std::chrono::milliseconds tls_read_timeout,
|
||||
std::chrono::milliseconds tls_write_timeout,
|
||||
bool server_verification_flag);
|
||||
|
||||
/**
|
||||
* @brief Constructor for the OpenSSL TLS implementation
|
||||
*
|
||||
* Performs any initialization required by the TLS layer.
|
||||
*
|
||||
* @param util::String endpoint - The target endpoint to connect to
|
||||
* @param uint16_t endpoint_port - The port on the target to connect to
|
||||
* @param util::String root_ca_location - Path of the location of the Root CA
|
||||
* @param util::String device_cert_location - Path to the location of the Device Cert
|
||||
* @param util::String device_private_key_location - Path to the location of the device private key file
|
||||
* @param std::chrono::milliseconds tls_handshake_timeout - The value to use for timeout of handshake operation
|
||||
* @param std::chrono::milliseconds tls_read_timeout - The value to use for timeout of read operation
|
||||
* @param std::chrono::milliseconds tls_write_timeout - The value to use for timeout of write operation
|
||||
* @param bool server_verification_flag - used to decide whether server verification is needed or not
|
||||
*
|
||||
*/
|
||||
OpenSSLConnection(util::String endpoint, uint16_t endpoint_port, util::String root_ca_location,
|
||||
util::String device_cert_location, util::String device_private_key_location,
|
||||
std::chrono::milliseconds tls_handshake_timeout,
|
||||
std::chrono::milliseconds tls_read_timeout, std::chrono::milliseconds tls_write_timeout,
|
||||
bool server_verification_flag);
|
||||
|
||||
OpenSSLConnection(util::String endpoint, uint16_t endpoint_port, util::String root_ca_location,
|
||||
std::chrono::milliseconds tls_handshake_timeout,
|
||||
std::chrono::milliseconds tls_read_timeout, std::chrono::milliseconds tls_write_timeout,
|
||||
bool server_verification_flag);
|
||||
|
||||
/**
|
||||
* @brief Initialize the OpenSSL object
|
||||
*
|
||||
* Initializes the OpenSSL object
|
||||
*/
|
||||
ResponseCode Initialize();
|
||||
|
||||
/**
|
||||
* @brief sets the path to the root CA
|
||||
*
|
||||
* Called to change the location of the root CA after the constructor has initialized the OpenSSL object.
|
||||
*
|
||||
* @param root_ca_location
|
||||
*/
|
||||
void SetRootCAPath(util::String root_ca_location) {
|
||||
root_ca_location_ = root_ca_location;
|
||||
certificates_read_flag_ = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the endpoint and the port
|
||||
*
|
||||
* Called to change the endpoint and the port after the constructor has initialized the OpenSSL object.
|
||||
* @param endpoint
|
||||
* @param endpoint_port
|
||||
*/
|
||||
void SetEndpointAndPort(util::String endpoint, uint16_t endpoint_port) {
|
||||
endpoint_ = endpoint;
|
||||
endpoint_port_ = endpoint_port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if TLS layer is still connected
|
||||
*
|
||||
* Called to check if the TLS layer is still connected or not.
|
||||
*
|
||||
* @return bool - indicating status of network TLS layer connection
|
||||
*/
|
||||
bool IsConnected();
|
||||
|
||||
/**
|
||||
* @brief Check if Network Physical layer is still connected
|
||||
*
|
||||
* Called to check if the Network Physical layer is still connected or not.
|
||||
*
|
||||
* @return bool - indicating status of network physical layer connection
|
||||
*/
|
||||
bool IsPhysicalLayerConnected();
|
||||
|
||||
virtual ~OpenSSLConnection();
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -79,7 +79,7 @@ void AWSConnector::doConnect()
|
||||
{
|
||||
m_setupInProgress = true;
|
||||
m_subscriptionCache.clear();
|
||||
m_networkConnection = std::shared_ptr<MbedTLSConnection>(new MbedTLSConnection(
|
||||
m_networkConnection = std::shared_ptr<OpenSSLConnection>(new OpenSSLConnection(
|
||||
m_currentEndpoint.toStdString(),
|
||||
8883,
|
||||
m_caFile.toStdString(),
|
||||
@ -90,6 +90,7 @@ void AWSConnector::doConnect()
|
||||
std::chrono::milliseconds(3000),
|
||||
true
|
||||
));
|
||||
m_networkConnection->Initialize();
|
||||
m_client = MqttClient::Create(m_networkConnection, std::chrono::milliseconds(2800), &onDisconnectedCallback, m_disconnectContextData);
|
||||
|
||||
m_client->SetAutoReconnectEnabled(false);
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#include <QFuture>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "MbedTLS/MbedTLSConnection.hpp"
|
||||
#include "OpenSSL/OpenSSLConnection.hpp"
|
||||
#include <mqtt/Client.hpp>
|
||||
#include <mqtt/Common.hpp>
|
||||
#include "util/logging/Logging.hpp"
|
||||
@ -107,7 +107,7 @@ private:
|
||||
QString readSyncedNameCache();
|
||||
|
||||
private:
|
||||
std::shared_ptr<awsiotsdk::network::MbedTLSConnection> m_networkConnection;
|
||||
std::shared_ptr<awsiotsdk::network::OpenSSLConnection> m_networkConnection;
|
||||
std::shared_ptr<awsiotsdk::MqttClient> m_client;
|
||||
QString m_currentEndpoint;
|
||||
QString m_caFile;
|
||||
|
||||
@ -10,10 +10,6 @@ LIBS += -L$$top_builddir/libguh/ -lguh -lssl -lcrypto -lavahi-common -lavahi-cli
|
||||
target.path = /usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')
|
||||
INSTALLS += target
|
||||
|
||||
exists("/usr/include/mbedtls/net_sockets.h") {
|
||||
DEFINES += MBEDTLS_NEW_HEADERS
|
||||
}
|
||||
|
||||
# icons for the webserver
|
||||
RESOURCES += $$top_srcdir/icons.qrc \
|
||||
$$top_srcdir/data/debug-interface/debug-interface.qrc
|
||||
@ -76,7 +72,7 @@ HEADERS += guhcore.h \
|
||||
awsconnector.h \
|
||||
cloudmanager.h \
|
||||
cloudnotifications.h \
|
||||
MbedTLS/MbedTLSConnection.hpp \
|
||||
OpenSSL/OpenSSLConnection.hpp \
|
||||
janusconnector.h \
|
||||
pushbuttondbusservice.h \
|
||||
guhdbusservice.h \
|
||||
@ -155,7 +151,7 @@ SOURCES += guhcore.cpp \
|
||||
awsconnector.cpp \
|
||||
cloudmanager.cpp \
|
||||
cloudnotifications.cpp \
|
||||
MbedTLS/MbedTLSConnection.cpp \
|
||||
OpenSSL/OpenSSLConnection.cpp \
|
||||
janusconnector.cpp \
|
||||
pushbuttondbusservice.cpp \
|
||||
guhdbusservice.cpp \
|
||||
|
||||
@ -10,7 +10,7 @@ INSTALLS += target
|
||||
|
||||
QT *= sql xml websockets bluetooth dbus network
|
||||
|
||||
LIBS += -L$$top_builddir/libguh/ -lguh -L$$top_builddir/libguh-core -lguh-core -lssl -lcrypto -laws-iot-sdk-cpp -lmbedtls -lmbedx509 -lmbedcrypto
|
||||
LIBS += -L$$top_builddir/libguh/ -lguh -L$$top_builddir/libguh-core -lguh-core -lssl -lcrypto -laws-iot-sdk-cpp
|
||||
|
||||
# Server files
|
||||
include(qtservice/qtservice.pri)
|
||||
|
||||
@ -7,7 +7,7 @@ INCLUDEPATH += $$top_srcdir/libguh \
|
||||
$$top_srcdir/tests/auto/
|
||||
|
||||
LIBS += -L$$top_builddir/libguh/ -lguh -L$$top_builddir/plugins/mock/ \
|
||||
-L$$top_builddir/libguh-core/ -lguh-core -lssl -lcrypto -laws-iot-sdk-cpp -lmbedtls -lmbedx509 -lmbedcrypto -lavahi-common -lavahi-client
|
||||
-L$$top_builddir/libguh-core/ -lguh-core -lssl -lcrypto -laws-iot-sdk-cpp -lavahi-common -lavahi-client
|
||||
|
||||
SOURCES += ../guhtestbase.cpp \
|
||||
|
||||
|
||||
Reference in New Issue
Block a user