Skip to content

Commit

Permalink
Merge pull request #1 from ESTOS/tls
Browse files Browse the repository at this point in the history
After another review with martin -> ok
  • Loading branch information
stemi1 authored Aug 30, 2021
2 parents c025604 + 9124e10 commit ef58851
Show file tree
Hide file tree
Showing 12 changed files with 923 additions and 25 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ESTOS - Readme

(no changes yet - just to divert from original README by now)
Supports TLS encrypted connections (Windows client only).

# Important

Expand Down
3 changes: 2 additions & 1 deletion includes/tacopie/network/tcp_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ class tcp_client {
//! \param host Hostname of the target server
//! \param port Port of the target server
//! \param timeout_msecs maximum time to connect (will block until connect succeed or timeout expire). 0 will block undefinitely. If timeout expires, connection fails
//! \param use_encryption enables TLS when set to true
//!
void connect(const std::string& host, std::uint32_t port, std::uint32_t timeout_msecs = 0);
void connect(const std::string& host, std::uint32_t port, std::uint32_t timeout_msecs, bool use_encryption);

//!
//! Disconnect the tcp_client if it was currently connected.
Expand Down
10 changes: 9 additions & 1 deletion includes/tacopie/network/tcp_socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <vector>

#include <tacopie/utils/typedefs.hpp>
#include <tacopie/network/tls.hpp>

namespace tacopie {

Expand Down Expand Up @@ -115,8 +116,9 @@ class tcp_socket {
//! \param host Hostname of the target server
//! \param port Port of the target server
//! \param timeout_msecs maximum time to connect (will block until connect succeed or timeout expire). 0 will block undefinitely. If timeout expires, connection fails
//! \param use_encryption enables TLS when set to true
//!
void connect(const std::string& host, std::uint32_t port, std::uint32_t timeout_msecs = 0);
void connect(const std::string& host, std::uint32_t port, std::uint32_t timeout_msecs, bool use_encryption);

//!
//! Binds the socket to the given host and port.
Expand Down Expand Up @@ -218,6 +220,12 @@ class tcp_socket {
//! type of the socket
//!
type m_type;

//!
//! optional tls (Windows only)
//!
tls m_tls;

};

} // namespace tacopie
114 changes: 114 additions & 0 deletions includes/tacopie/network/tls.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// Copyright (c) 2021 Martin Unger for estos GmbH
//
// Based on code available at https://github.com/John-Ad/Schannel-https-implementation
// No license attached as of 2021-08-27.
//
// Code was substantially modified for our purpose and these changes are put under the
// following license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#pragma once

#include <tacopie/utils/typedefs.hpp>

#ifdef _WIN32
#include <cstdint>
#include <string>
#include <vector>
#include <sspi.h>
#include <schannel.h>
#include <wchar.h>
#endif

#pragma comment(lib, "Secur32.lib")
#pragma comment(lib, "Crypt32.Lib")


namespace tacopie {

//!
//! used to force poll to wake up
//! simply make poll watch for read events on one side of the pipe and write to the other side
//!
class tls {
public:
//! ctor
tls(void);
//! dtor
virtual ~tls(void);

public:

//!
//! connect
//!
void
establish_connection(const fd_t& socket, const std::string& host);

//!
//! Encrypt and send data (synchronous)
//!
//! \param socket
//! \param unencrypted data
//! \return Returns amount of unencrypted data sent (caller does not know about encrypted size)
//!
std::size_t
send_encrypted(const fd_t& socket, const std::vector<char>& unencrypted_data);

//!
//! Receive data from the socket until able to decrypt completely (synchronous).
//! "Completely" here means at least a single encryptable block, may be more.
//!
//! \param socket
//! \return Returns vector with decrypted data. Size is as large as needed. You need to handle this.
//!
std::vector<char>
recv_decrypt(const fd_t& socket);

//!
//! is encryption active
//!
bool
is_encryption_active() const { return m_encryption_active; }

private:

#ifdef _WIN32
CredHandle m_credentials;
CtxtHandle m_context;
SecPkgContext_StreamSizes m_stream_sizes;
bool m_encryption_active;

// we need to preserve encrypted data received over several calls of recv_decrypt
std::vector<char> m_encrypted_data;
int m_encrypted_bytes = 0;

void get_schannel_credentials();
void handshake_loop(const fd_t& socket, const std::string &host);
int tls_receive(SOCKET socket, char* buffer, int length);
int tls_send(SOCKET socket, const char* buffer, int length);
std::string get_sspi_result_string(SECURITY_STATUS SecurityStatus);

#else
#endif /* _WIN32 */
};

} // namespace tacopie
8 changes: 4 additions & 4 deletions includes/tacopie/utils/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ extern std::unique_ptr<logger_iface> active_logger;

//!
//! debug logging
//! convenience function used internaly to call the logger
//! convenience function used internally to call the logger
//!
//! \param msg message to be logged
//! \param file file from which the message is coming
Expand All @@ -175,7 +175,7 @@ void debug(const std::string& msg, const std::string& file, std::size_t line);

//!
//! info logging
//! convenience function used internaly to call the logger
//! convenience function used internally to call the logger
//!
//! \param msg message to be logged
//! \param file file from which the message is coming
Expand All @@ -185,7 +185,7 @@ void info(const std::string& msg, const std::string& file, std::size_t line);

//!
//! warn logging
//! convenience function used internaly to call the logger
//! convenience function used internally to call the logger
//!
//! \param msg message to be logged
//! \param file file from which the message is coming
Expand All @@ -195,7 +195,7 @@ void warn(const std::string& msg, const std::string& file, std::size_t line);

//!
//! error logging
//! convenience function used internaly to call the logger
//! convenience function used internally to call the logger
//!
//! \param msg message to be logged
//! \param file file from which the message is coming
Expand Down
28 changes: 28 additions & 0 deletions msvc19/tacopie.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tacopie", "tacopie.vcxproj", "{5DC28D31-04A5-4509-8EE3-CF16DE77475B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5DC28D31-04A5-4509-8EE3-CF16DE77475B}.Debug|x64.ActiveCfg = Debug|x64
{5DC28D31-04A5-4509-8EE3-CF16DE77475B}.Debug|x64.Build.0 = Debug|x64
{5DC28D31-04A5-4509-8EE3-CF16DE77475B}.Debug|x86.ActiveCfg = Debug|Win32
{5DC28D31-04A5-4509-8EE3-CF16DE77475B}.Debug|x86.Build.0 = Debug|Win32
{5DC28D31-04A5-4509-8EE3-CF16DE77475B}.Release|x64.ActiveCfg = Release|x64
{5DC28D31-04A5-4509-8EE3-CF16DE77475B}.Release|x64.Build.0 = Release|x64
{5DC28D31-04A5-4509-8EE3-CF16DE77475B}.Release|x86.ActiveCfg = Release|Win32
{5DC28D31-04A5-4509-8EE3-CF16DE77475B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Loading

0 comments on commit ef58851

Please sign in to comment.