mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 21:45:37 +00:00
[#1661] Revamped TLS headers
This commit is contained in:
@@ -17,6 +17,8 @@ libkea_asiolink_la_LDFLAGS += $(CRYPTO_LDFLAGS)
|
||||
libkea_asiolink_la_SOURCES = asiolink.h
|
||||
libkea_asiolink_la_SOURCES += asio_wrapper.h
|
||||
libkea_asiolink_la_SOURCES += addr_utilities.cc addr_utilities.h
|
||||
libkea_asiolink_la_SOURCES += botan_tls.h
|
||||
libkea_asiolink_la_SOURCES += common_tls.h
|
||||
libkea_asiolink_la_SOURCES += crypto_tls.h
|
||||
libkea_asiolink_la_SOURCES += dummy_io_cb.h
|
||||
libkea_asiolink_la_SOURCES += interval_timer.cc interval_timer.h
|
||||
@@ -28,6 +30,7 @@ libkea_asiolink_la_SOURCES += io_error.h
|
||||
libkea_asiolink_la_SOURCES += io_service.h io_service.cc
|
||||
libkea_asiolink_la_SOURCES += io_service_signal.cc io_service_signal.h
|
||||
libkea_asiolink_la_SOURCES += io_socket.h io_socket.cc
|
||||
libkea_asiolink_la_SOURCES += openssl_tls.h
|
||||
libkea_asiolink_la_SOURCES += process_spawn.h process_spawn.cc
|
||||
libkea_asiolink_la_SOURCES += tcp_acceptor.h
|
||||
libkea_asiolink_la_SOURCES += tcp_endpoint.h
|
||||
@@ -41,10 +44,10 @@ libkea_asiolink_la_SOURCES += unix_domain_socket_acceptor.h
|
||||
libkea_asiolink_la_SOURCES += unix_domain_socket_endpoint.h
|
||||
|
||||
if HAVE_BOTAN
|
||||
#libkea_asiolink_la_SOURCES += botan_tls.cc botan_tls.h
|
||||
#libkea_asiolink_la_SOURCES += botan_tls.cc
|
||||
endif
|
||||
if HAVE_OPENSSL
|
||||
libkea_asiolink_la_SOURCES += openssl_tls.cc openssl_tls.h
|
||||
libkea_asiolink_la_SOURCES += openssl_tls.cc
|
||||
endif
|
||||
|
||||
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
|
||||
@@ -60,6 +63,8 @@ libkea_asiolink_include_HEADERS = \
|
||||
addr_utilities.h \
|
||||
asio_wrapper.h \
|
||||
asiolink.h \
|
||||
botan_tls.h \
|
||||
common_tls.h \
|
||||
crypto_tls.h \
|
||||
dummy_io_cb.h \
|
||||
interval_timer.h \
|
||||
@@ -71,6 +76,7 @@ libkea_asiolink_include_HEADERS = \
|
||||
io_service.h \
|
||||
io_service_signal.h \
|
||||
io_socket.h \
|
||||
openssl_tls.h \
|
||||
process_spawn.h \
|
||||
tcp_acceptor.h \
|
||||
tcp_endpoint.h \
|
||||
|
@@ -4,11 +4,18 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Do not include this header directly: use crypto_tls.h instead.
|
||||
|
||||
#ifndef BOTAN_TLS_H
|
||||
#define BOTAN_TLS_H
|
||||
|
||||
#ifdef WITH_BOTAN
|
||||
|
||||
#include <asiolink/asio_wrapper.h>
|
||||
#include <asiolink/io_asio_socket.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/common_tls.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
|
170
src/lib/asiolink/common_tls.h
Normal file
170
src/lib/asiolink/common_tls.h
Normal file
@@ -0,0 +1,170 @@
|
||||
// Copyright (C) 2021 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Do not include this header directly: use crypto_tls.h instead.
|
||||
|
||||
#ifndef COMMON_TLS_H
|
||||
#define COMMON_TLS_H
|
||||
|
||||
/// @file common_tls.h Common TLS API.
|
||||
|
||||
// Verify that this file was not directly included.
|
||||
#ifndef CRYPTO_TLS_H
|
||||
#error crypto_tls.h must be included in place of common_tls.h
|
||||
#endif
|
||||
|
||||
#include <cryptolink/cryptolink.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// @brief Client and server roles.
|
||||
enum TlsRole { CLIENT, SERVER };
|
||||
|
||||
/// @brief TLS context base class.
|
||||
class TlsContextBase : private boost::noncopyable {
|
||||
public:
|
||||
/// @brief Destructor.
|
||||
virtual ~TlsContextBase() { }
|
||||
|
||||
/// @brief Create a fresh context.
|
||||
///
|
||||
/// @param role The TLS role client or server.
|
||||
explicit TlsContextBase(TlsRole role) : role_(role) { }
|
||||
|
||||
/// @brief Returns the role.
|
||||
TlsRole getRole() const {
|
||||
return (role_);
|
||||
}
|
||||
|
||||
/// @note No need for a role set method.
|
||||
|
||||
/// @brief Set the peer certificate requirement mode.
|
||||
///
|
||||
/// @param cert_required True if peer certificates are required,
|
||||
/// false if they are optional.
|
||||
virtual void setCertRequired(bool cert_required) = 0;
|
||||
|
||||
/// @brief Get the peer certificate requirement mode.
|
||||
///
|
||||
/// @return True if peer certificates are required, false if they
|
||||
/// are optional.
|
||||
virtual bool getCertRequired() const = 0;
|
||||
|
||||
/// @brief Load the trust anchor aka certificate authority.
|
||||
///
|
||||
/// @param ca_file The certificate file name.
|
||||
/// @throw isc::cryptolink::LibraryError on various errors as
|
||||
/// file not found, bad format, etc.
|
||||
virtual void loadCaFile(const std::string& ca_file) = 0;
|
||||
|
||||
/// @brief Load the trust anchor aka certificate authority.
|
||||
///
|
||||
/// @param ca_path The certificate directory name.
|
||||
/// @throw isc::cryptolink::LibraryError on various errors as
|
||||
/// file not found, bad format, etc.
|
||||
virtual void loadCaPath(const std::string& ca_path) = 0;
|
||||
|
||||
/// @brief Load the certificate file.
|
||||
///
|
||||
/// @param cert_file The certificate file name.
|
||||
/// @throw isc::cryptolink::LibraryError on various errors as
|
||||
/// file not found, bad format, etc.
|
||||
virtual void loadCertFile(const std::string& cert_file) = 0;
|
||||
|
||||
/// @brief Load the private key file name.
|
||||
///
|
||||
/// @param key_file The private key file name.
|
||||
/// @throw isc::cryptolink::LibraryError on various errors as
|
||||
/// file not found, bad format, etc.
|
||||
virtual void loadKeyFile(const std::string& key_file) = 0;
|
||||
|
||||
public:
|
||||
/// @brief The role i.e. client or server.
|
||||
TlsRole role_;
|
||||
};
|
||||
|
||||
/// @brief Forward declaration of OpenSSL TLS context.
|
||||
class TlsContext;
|
||||
|
||||
/// @brief The type of shared pointers to TlsContext objects.
|
||||
///
|
||||
/// @note Not clear we need shared pointers but they covers more use cases...
|
||||
typedef boost::shared_ptr<TlsContext> TlsContextPtr;
|
||||
|
||||
/// @brief TLS stream base class.
|
||||
///
|
||||
/// @tparam Callback The type of callbacks.
|
||||
/// @tparam TlsStreamImpl The type of underlying TLS streams.
|
||||
/// @tparam TlsCertificate The type of X509 certificates.
|
||||
template <typename Callback, typename TlsStreamImpl, typename TlsCertificate>
|
||||
class TlsStreamBase : public TlsStreamImpl {
|
||||
public:
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param service I/O Service object used to manage the stream.
|
||||
/// @param context Pointer to the TLS context.
|
||||
/// @note The caller must not provide a null pointer to the TLS context.
|
||||
TlsStreamBase(IOService& service, TlsContextPtr context);
|
||||
|
||||
/// @brief Destructor.
|
||||
virtual ~TlsStreamBase() { }
|
||||
|
||||
/// @brief Returns the role.
|
||||
TlsRole getRole() const {
|
||||
return (role_);
|
||||
}
|
||||
|
||||
/// @brief TLS Handshake.
|
||||
///
|
||||
/// @param callback Callback object.
|
||||
virtual void handshake(Callback& callback) = 0;
|
||||
|
||||
/// @brief TLS shutdown.
|
||||
///
|
||||
/// @param callback Callback object.
|
||||
virtual void shutdown(Callback& callback) = 0;
|
||||
|
||||
/// @brief Clear the TLS state.
|
||||
virtual void clear() = 0;
|
||||
|
||||
/// @brief Return the peer certificate.
|
||||
///
|
||||
/// @note The native_handle() method is used so it can't be made const.
|
||||
/// @note Do not forget to free it when no longer used.
|
||||
virtual TlsCertificate* getPeerCert() = 0;
|
||||
|
||||
/// @break Return the commonName part of the subjectName of
|
||||
/// the peer certificate.
|
||||
///
|
||||
/// First commonName when there are more than one, in UTF-8.
|
||||
///
|
||||
/// @return The commonName part of the subjectName or the empty string.
|
||||
virtual std::string getSubject() = 0;
|
||||
|
||||
/// @break Return the commonName part of the issuerName of
|
||||
/// the peer certificate.
|
||||
///
|
||||
/// First commonName when there are more than one, in UTF-8.
|
||||
///
|
||||
/// @return The commonName part of the issuerName or the empty string.
|
||||
virtual std::string getIssuer() = 0;
|
||||
|
||||
/// @brief The role i.e. client or server.
|
||||
TlsRole role_;
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
||||
#endif // COMMON_TLS_H
|
@@ -7,86 +7,20 @@
|
||||
#ifndef CRYPTO_TLS_H
|
||||
#define CRYPTO_TLS_H
|
||||
|
||||
#include <cryptolink/cryptolink.h>
|
||||
/// @file crypto_tls.h TLS API.
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
// Verify that config.h was included.
|
||||
#ifndef CONFIG_H_WAS_INCLUDED
|
||||
#error config.h must be included before crypto_tls.h
|
||||
#endif
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
// Include different versions.
|
||||
#include <asiolink/botan_tls.h>
|
||||
#include <asiolink/openssl_tls.h>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// @file crypto_tls.h Common TLS API.
|
||||
|
||||
/// @brief Client and server roles.
|
||||
enum TlsRole { CLIENT, SERVER };
|
||||
|
||||
/// @brief TLS context base class.
|
||||
class TlsContextBase : private boost::noncopyable {
|
||||
public:
|
||||
/// @brief Destructor.
|
||||
virtual ~TlsContextBase() { }
|
||||
|
||||
/// @brief Create a fresh context.
|
||||
///
|
||||
/// @param role The TLS role client or server.
|
||||
explicit TlsContextBase(TlsRole role) : role_(role) { }
|
||||
|
||||
/// @brief Returns the role.
|
||||
TlsRole getRole() const {
|
||||
return (role_);
|
||||
}
|
||||
|
||||
/// @note No need for a role set method.
|
||||
|
||||
/// @brief Set the peer certificate requirement mode.
|
||||
///
|
||||
/// @param cert_required True if peer certificates are required,
|
||||
/// false if they are optional.
|
||||
virtual void setCertRequired(bool cert_required) = 0;
|
||||
|
||||
/// @brief Get the peer certificate requirement mode.
|
||||
///
|
||||
/// @return True if peer certificates are required, false if they
|
||||
/// are optional.
|
||||
virtual bool getCertRequired() const = 0;
|
||||
|
||||
/// @brief Load the trust anchor aka certificate authority.
|
||||
///
|
||||
/// @param ca_file The certificate file name.
|
||||
/// @throw isc::cryptolink::LibraryError on various errors as
|
||||
/// file not found, bad format, etc.
|
||||
virtual void loadCaFile(const std::string& ca_file) = 0;
|
||||
|
||||
/// @brief Load the trust anchor aka certificate authority.
|
||||
///
|
||||
/// @param ca_path The certificate directory name.
|
||||
/// @throw isc::cryptolink::LibraryError on various errors as
|
||||
/// file not found, bad format, etc.
|
||||
virtual void loadCaPath(const std::string& ca_path) = 0;
|
||||
|
||||
/// @brief Load the certificate file.
|
||||
///
|
||||
/// @param cert_file The certificate file name.
|
||||
/// @throw isc::cryptolink::LibraryError on various errors as
|
||||
/// file not found, bad format, etc.
|
||||
virtual void loadCertFile(const std::string& cert_file) = 0;
|
||||
|
||||
/// @brief Load the private key file name.
|
||||
///
|
||||
/// @param key_file The private key file name.
|
||||
/// @throw isc::cryptolink::LibraryError on various errors as
|
||||
/// file not found, bad format, etc.
|
||||
virtual void loadKeyFile(const std::string& key_file) = 0;
|
||||
|
||||
public:
|
||||
/// @brief The role i.e. client or server.
|
||||
TlsRole role_;
|
||||
};
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
// Verify that one version matched.
|
||||
#ifndef COMMON_TLS_H
|
||||
#error no TLS backend was found
|
||||
#endif
|
||||
|
||||
#endif // CRYPTO_TLS_H
|
||||
|
@@ -10,7 +10,6 @@
|
||||
|
||||
#include <asiolink/asio_wrapper.h>
|
||||
#include <asiolink/crypto_tls.h>
|
||||
#include <asiolink/openssl_tls.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
@@ -4,28 +4,25 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Do not include this header directly: use crypto_tls.h instead.
|
||||
|
||||
#ifndef OPENSSL_TLS_H
|
||||
#define OPENSSL_TLS_H
|
||||
|
||||
/// @file openssl_tls.h OpenSSL implementation of the TLS API.
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
|
||||
#include <asiolink/asio_wrapper.h>
|
||||
#include <asiolink/io_asio_socket.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/common_tls.h>
|
||||
|
||||
#include <boost/asio/ssl.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace asiolink {
|
||||
|
||||
/// @brief Forward declaration of OpenSSL TLS context.
|
||||
class TlsContext;
|
||||
|
||||
/// @brief The type of shared pointers to TlsContext objects.
|
||||
///
|
||||
/// @note Not clear we need shared pointers but they covers more use cases...
|
||||
typedef boost::shared_ptr<TlsContext> TlsContextPtr;
|
||||
|
||||
/// @brief OpenSSL TLS context.
|
||||
class TlsContext : public TlsContextBase {
|
||||
public:
|
||||
@@ -109,40 +106,50 @@ typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> TlsStreamImpl;
|
||||
/// @brief The type of X509 certificates.
|
||||
typedef ::X509 TlsCertificate;
|
||||
|
||||
/// @brief TlsStreamBase constructor.
|
||||
/// @brief TLS stream base class.
|
||||
///
|
||||
/// @param Callback The type of callbacks.
|
||||
/// @param TlsStreamImpl The type of underlying TLS streams.
|
||||
/// @param TlsCertificate The type of X509 certificates.
|
||||
template <typename Callback, typename TlsStreamImpl, typename TlsCertificate>
|
||||
TlsStreamBase<Callback, TlsStreamImpl, TlsCertificate>::
|
||||
TlsStreamBase(IOService& service, TlsContextPtr context)
|
||||
: TlsStreamImpl(service.get_io_service(), context->getContext()),
|
||||
role_(context->getRole()) {
|
||||
}
|
||||
|
||||
/// @brief OpenSSL TLS stream.
|
||||
///
|
||||
/// @param callback The callback.
|
||||
template <typename Callback>
|
||||
class TlsStream : public TlsStreamImpl {
|
||||
class TlsStream : public TlsStreamBase<Callback, TlsStreamImpl, TlsCertificate> {
|
||||
public:
|
||||
|
||||
/// @brief Type of the base.
|
||||
typedef TlsStreamBase<Callback, TlsStreamImpl, TlsCertificate> Base;
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param service I/O Service object used to manage the stream.
|
||||
/// @param context Pointer to the TLS context.
|
||||
/// @note The caller must not provide a null pointer to the TLS context.
|
||||
TlsStream(IOService& service, TlsContextPtr context)
|
||||
: TlsStreamImpl(service.get_io_service(), context->getContext()),
|
||||
role_(context->getRole()) {
|
||||
: Base(service, context) {
|
||||
}
|
||||
|
||||
/// @brief Destructor.
|
||||
virtual ~TlsStream() { }
|
||||
|
||||
/// @brief Returns the role.
|
||||
TlsRole getRole() const {
|
||||
return (role_);
|
||||
}
|
||||
|
||||
/// @brief TLS Handshake.
|
||||
///
|
||||
/// @param callback Callback object.
|
||||
virtual void handshake(Callback& callback) {
|
||||
using namespace boost::asio::ssl;
|
||||
if (role_ == SERVER) {
|
||||
async_handshake(stream_base::server, callback);
|
||||
if (Base::getRole() == SERVER) {
|
||||
Base::async_handshake(stream_base::server, callback);
|
||||
} else {
|
||||
async_handshake(stream_base::client, callback);
|
||||
Base::async_handshake(stream_base::client, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +157,7 @@ public:
|
||||
///
|
||||
/// @param callback Callback object.
|
||||
virtual void shutdown(Callback& callback) {
|
||||
async_shutdown(callback);
|
||||
Base::async_shutdown(callback);
|
||||
}
|
||||
|
||||
/// @brief Clear the SSL object.
|
||||
@@ -166,16 +173,13 @@ public:
|
||||
return (::SSL_get_peer_certificate(this->native_handle()));
|
||||
}
|
||||
|
||||
/// @brief The role i.e. client or server.
|
||||
TlsRole role_;
|
||||
|
||||
/// @break Return the commonName part of the subjectName of
|
||||
/// the peer certificate.
|
||||
///
|
||||
/// First commonName when there are more than one, in UTF-8.
|
||||
///
|
||||
/// @return The commonName part of the subjectName or the empty string.
|
||||
std::string getSubject() {
|
||||
virtual std::string getSubject() {
|
||||
TlsCertificate* cert = getPeerCert();
|
||||
if (!cert) {
|
||||
return ("");
|
||||
@@ -205,7 +209,7 @@ public:
|
||||
/// First commonName when there are more than one, in UTF-8.
|
||||
///
|
||||
/// @return The commonName part of the issuerName or the empty string.
|
||||
std::string getIssuer() {
|
||||
virtual std::string getIssuer() {
|
||||
TlsCertificate* cert = getPeerCert();
|
||||
if (!cert) {
|
||||
return ("");
|
||||
@@ -230,7 +234,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace asiolink
|
||||
} // namespace isc
|
||||
|
||||
|
@@ -9,8 +9,6 @@
|
||||
#include <asiolink/asio_wrapper.h>
|
||||
#include <asiolink/io_service.h>
|
||||
#include <asiolink/crypto_tls.h>
|
||||
#include <asiolink/botan_tls.h>
|
||||
#include <asiolink/openssl_tls.h>
|
||||
#include <asiolink/tcp_endpoint.h>
|
||||
#include <asiolink/testutils/test_tls.h>
|
||||
#include <testutils/gtest_utils.h>
|
||||
|
@@ -12,8 +12,6 @@
|
||||
#endif
|
||||
|
||||
#include <asiolink/crypto_tls.h>
|
||||
#include <asiolink/botan_tls.h>
|
||||
#include <asiolink/openssl_tls.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@@ -12,8 +12,6 @@
|
||||
#endif
|
||||
|
||||
#include <asiolink/crypto_tls.h>
|
||||
#include <asiolink/botan_tls.h>
|
||||
#include <asiolink/openssl_tls.h>
|
||||
#include <asiolink/tcp_socket.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
Reference in New Issue
Block a user