Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS #17

Open
wants to merge 46 commits into
base: master
Choose a base branch
from
Open

TLS #17

Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
784dc09
Stateless read/write methods (read_r, etc.)
snej Sep 3, 2019
3dd60e6
Support for connect() timeouts
snej Sep 7, 2019
591c3ac
Added TLS API, and an mbedTLS-based implementation
snej Aug 16, 2019
a1b2572
TLS bug fixes and some API changes
snej Sep 25, 2019
d51c925
mbedtls_context: logging support
snej Oct 2, 2019
968e7c7
Add 'functional' include needed by Litecore
victorbergeronsemi Nov 27, 2019
1df0481
Merge pull request #1 from stratadeveloperstudio/cmake-windows-fix
borrrden Nov 27, 2019
fb16db9
Fixed build error on iOS
snej Dec 4, 2019
a1a2846
Fix two Windows socket bugs
borrrden Dec 6, 2019
3cc18d0
Windows needs to check exceptfds for connect errors
borrrden Dec 7, 2019
f820081
Don't call shutdown on an invalid socket
borrrden Jan 14, 2020
c9f5e79
Use the behavior of SO_REUSEPORT isntead of SO_REUSEADDR
borrrden Jan 14, 2020
1f9efb5
Android improperly defines _GNU_SOURCE
borrrden Jan 22, 2020
a1271fb
Fix incompatible ssize_t definition (Windows)
borrrden Feb 7, 2020
be70fd4
Ignore positive integer errors from mbedtls_x509_crt_parse
borrrden Feb 4, 2020
77fd477
Replace positive error when throwing
borrrden Feb 7, 2020
0a4ebc7
Added TLS auth callback
snej Apr 1, 2020
05c413b
TLS: Pass TLS fatal alert codes to the client
snej Apr 1, 2020
a1ec3b6
TLS: Fixed handling of bad peer cert
snej Apr 1, 2020
41e477d
Add Windows code to convert TLS certificates to PEM (#3)
victorbergeronsemi Apr 7, 2020
c6efa7e
Fix Windows compiler warning
borrrden Apr 8, 2020
a56b153
Remove SO_REUSEPORT from listen
borrrden Apr 24, 2020
cc94d62
socket::shutdown() should NOT release the handle_
snej Apr 29, 2020
e235162
mbedtls_socket: Orderly shutdown on handshake error
snej Apr 29, 2020
02e05f4
acceptor: always set SO_REUSEADDR
snej Apr 29, 2020
13331d2
Made tls_socket::stream() public
snej Apr 29, 2020
79e1cb1
Add is_shutdown method to socket
borrrden May 2, 2020
63332e5
Don't use SO_REUSEADDR on Windows
borrrden May 2, 2020
b4dd2b6
Changes needed for UWP
borrrden May 22, 2020
0def6c1
Need to ifdef gai_strerror between Windows and Unix
borrrden May 22, 2020
039097d
TLS: Added callback-based root cert lookup
snej May 30, 2020
f57cd23
TLS: Better logging in mbedtls_context
snej May 30, 2020
7e36636
Set dual stack mode for IPv6
borrrden Jun 12, 2020
d0a3653
Brush up a couple of logical points regarding validation
borrrden Jun 26, 2020
0e0ce99
Ensure that the peer certificate can be retrieved
borrrden Jul 1, 2020
13d818c
Don't reparse the certificate in mbedtls_context
borrrden Jul 1, 2020
182df13
Add the option to control sending client cert CA list
borrrden Jul 13, 2020
b339863
Adapt read_system_root_certs to Android
borrrden Jul 31, 2020
584a66c
UWP Fix: Add manual entropy source
borrrden Aug 5, 2020
8dad5c3
Fix mistake in last commit
borrrden Aug 5, 2020
d5921ba
CBL-1438: Fix handling of WSAEWOULDBLOCK (#6)
cosmin42 Nov 19, 2020
853d447
Fix up breakage in previous commit
borrrden Nov 19, 2020
ffde73a
Change to explicit wide string variant of WSASocket
borrrden Nov 27, 2020
db1955b
Fixed build when MBEDTLS_DEBUG_C is turned off
snej Apr 26, 2021
40d4273
TLS: Fix blocking/nonblocking mixup setting up bio
snej Sep 2, 2021
0172214
TLS: Fixed bogus error result
snej Sep 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions include/sockpp/connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class connector : public stream_socket
connector(const connector&) =delete;
connector& operator=(const connector&) =delete;

bool recreate(const sock_address& addr);

public:
/**
* Creates an unconnected connector.
Expand All @@ -80,6 +82,14 @@ class connector : public stream_socket
* @param addr The remote server address.
*/
connector(const sock_address& addr) { connect(addr); }
/**
* Creates the connector and attempts to connect to the specified
* address, with a timeout.
* If the operation times out, the \ref last_error will be set to ETIMEOUT.
* @param addr The remote server address.
* @param t The duration after which to give up. Zero means never.
*/
connector(const sock_address& addr, std::chrono::milliseconds t) { connect(addr, t); }
/**
* Move constructor.
* Creates a connector by moving the other connector to this one.
Expand Down Expand Up @@ -112,6 +122,16 @@ class connector : public stream_socket
* @return @em true on success, @em false on error
*/
bool connect(const sock_address& addr);
/**
* Attempts to connect to the specified server, with a timeout.
* If the socket is currently connected, this will close the current
* connection and open the new one.
* If the operation times out, the \ref last_error will be set to ETIMEOUT.
* @param addr The remote server address.
* @param timeout The duration after which to give up. Zero means never.
* @return @em true on success, @em false on error
*/
bool connect(const sock_address& addr, std::chrono::microseconds timeout);
};

/////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -182,6 +202,18 @@ class connector_tmpl : public connector
* @return @em true on success, @em false on error
*/
bool connect(const addr_t& addr) { return base::connect(addr); }
/**
* Attempts to connect to the specified server, with a timeout.
* If the socket is currently connected, this will close the current
* connection and open the new one.
* If the operation times out, the \ref last_error will be set to ETIMEOUT.
* @param addr The remote server address.
* @param timeout The duration after which to give up. Zero means never.
* @return @em true on success, @em false on error
*/
bool connect(const addr_t& addr, std::chrono::microseconds timeout) {
return base::connect(addr, timeout);
}
};

/////////////////////////////////////////////////////////////////////////////
Expand Down
120 changes: 120 additions & 0 deletions include/sockpp/mbedtls_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/**
* @file mbedtls_socket.h
*
* TLS (SSL) socket implementation using mbedTLS.
*
* @author Jens Alfke
* @author Couchbase, Inc.
* @author www.couchbase.com
*
* @date August 2019
*/

// --------------------------------------------------------------------------
// This file is part of the "sockpp" C++ socket library.
//
// Copyright (c) 2014-2019 Frank Pagliughi
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// --------------------------------------------------------------------------

#ifndef __sockpp_mbedtls_socket_h
#define __sockpp_mbedtls_socket_h

#include "sockpp/tls_context.h"
#include "sockpp/tls_socket.h"
#include <memory>
#include <string>
#include <functional>

struct mbedtls_pk_context;
struct mbedtls_ssl_config;
struct mbedtls_x509_crt;

namespace sockpp {

/**
* A concrete implementation of \ref tls_context, using the mbedTLS library.
* You probably don't want to use this class directly, unless you want to instantiate a
* custom context so you can have different contexts for different sockets.
*/
class mbedtls_context : public tls_context {
public:
mbedtls_context(role_t = CLIENT);
~mbedtls_context() override;

void set_root_certs(const std::string &certData) override;
void require_peer_cert(role_t, bool) override;
void allow_only_certificate(const std::string &certData) override;

void allow_only_certificate(mbedtls_x509_crt *certificate);

/**
* Sets the identity certificate and private key using mbedTLS objects.
*/
void set_identity(mbedtls_x509_crt *certificate,
mbedtls_pk_context *private_key);

void set_identity(const std::string &certificate_data,
const std::string &private_key_data) override;

std::unique_ptr<tls_socket> wrap_socket(std::unique_ptr<stream_socket> socket,
role_t,
const std::string &peer_name) override;

role_t role();

static mbedtls_x509_crt* get_system_root_certs();

using Logger = std::function<void(int level, const char *filename, int line, const char *message)>;
void set_logger(int threshold, Logger);

private:
struct cert;
struct key;

int verify_callback(mbedtls_x509_crt *crt, int depth, uint32_t *flags);
static std::unique_ptr<cert> parse_cert(const std::string &cert_data, bool partialOk);

std::unique_ptr<mbedtls_ssl_config> ssl_config_;
std::unique_ptr<cert> root_certs_;
std::unique_ptr<cert> pinned_cert_;

std::unique_ptr<cert> identity_cert_;
std::unique_ptr<key> identity_key_;
Logger logger_;

static cert *s_system_root_certs;

friend class mbedtls_socket;
};

}

#endif
6 changes: 1 addition & 5 deletions include/sockpp/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,7 @@
#ifndef _SSIZE_T_DEFINED
#define _SSIZE_T_DEFINED
#undef ssize_t
#ifdef _WIN64
using ssize_t = int64_t;
#else
using ssize_t = int;
#endif // _WIN64
using ssize_t = SSIZE_T;
#endif // _SSIZE_T_DEFINED

#ifndef _SUSECONDS_T
Expand Down
8 changes: 5 additions & 3 deletions include/sockpp/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ class socket
* @param on Whether to turn non-blocking mode on or off.
* @return @em true on success, @em false on failure.
*/
bool set_non_blocking(bool on=true);
virtual bool set_non_blocking(bool on=true);
/**
* Gets a string describing the specified error.
* This is typically the returned message from the system strerror().
Expand Down Expand Up @@ -445,14 +445,16 @@ class socket
* @li SHUT_RDWR (2) Further reads and writes disallowed.
* @return @em true on success, @em false on error.
*/
bool shutdown(int how=SHUT_RDWR);
virtual bool shutdown(int how=SHUT_RDWR);
/**
* Closes the socket.
* After closing the socket, the handle is @em invalid, and can not be
* used again until reassigned.
* @return @em true if the sock is closed, @em false on error.
*/
bool close();
virtual bool close();

friend struct ioresult;
};

/////////////////////////////////////////////////////////////////////////////
Expand Down
26 changes: 26 additions & 0 deletions include/sockpp/stream_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,26 @@ namespace sockpp {

/////////////////////////////////////////////////////////////////////////////

/**
* Result of a thread-safe read or write
* (\ref read_r, \ref read_n_r, \ref write_r, \ref write_n_r)
*/
struct ioresult {
size_t count = 0; ///< Byte count, or 0 on error or EOF
int error = 0; ///< errno value (0 if no error or EOF)

ioresult() = default;

ioresult(size_t c, int e) :count(c), error(e) { }

explicit inline ioresult(ssize_t n) {
if (n >= 0)
count = size_t(n);
else
error = socket::get_last_error();
}
};

/**
* Base class for streaming sockets, such as TCP and Unix Domain.
* This is the streaming connection between two peers. It looks like a
Expand Down Expand Up @@ -206,6 +226,12 @@ class stream_socket : public socket
bool write_timeout(const std::chrono::duration<Rep,Period>& to) {
return write_timeout(std::chrono::duration_cast<std::chrono::microseconds>(to));
}

virtual ioresult read_r(void *buf, size_t n);
virtual ioresult read_n_r(void *buf, size_t n);
virtual ioresult write_r(const void *buf, size_t n);
virtual ioresult write_n_r(const void *buf, size_t n);

};

/////////////////////////////////////////////////////////////////////////////
Expand Down
Loading