Line data Source code
1 : #ifndef THINGER_ASIO_SSL_SOCKET_HPP
2 : #define THINGER_ASIO_SSL_SOCKET_HPP
3 :
4 : #include "tcp_socket.hpp"
5 : #include "../ssl/certificate_manager.hpp"
6 : #include "../ssl/client_verify.hpp"
7 : #include <boost/asio.hpp>
8 : #include <boost/asio/ssl.hpp>
9 :
10 : namespace thinger::asio {
11 :
12 : class ssl_socket : public tcp_socket {
13 : public:
14 : // constructors and destructors
15 : ssl_socket(const std::string& context, boost::asio::io_context& io_context,
16 : const std::shared_ptr<boost::asio::ssl::context>& ssl_context);
17 : ssl_socket(const std::string& context, const std::shared_ptr<tcp_socket>& socket,
18 : const std::shared_ptr<boost::asio::ssl::context>& ssl_context);
19 : ~ssl_socket() override;
20 :
21 : // socket control
22 : void close() override;
23 : bool requires_handshake() const override;
24 : // Without a host, the server handshake: it fails if an earlier session is resumed
25 : // without a client certificate where the host name requires one (see
26 : // certificate_manager::set_client_verify()), as no certificate is asked for then
27 : awaitable<boost::system::error_code> handshake(const std::string& host = "") override;
28 :
29 : // read operations
30 : awaitable<io_result> read_some(uint8_t buffer[], size_t max_size) override;
31 : awaitable<io_result> read_some_cancellable(uint8_t buffer[], size_t max_size,
32 : boost::asio::cancellation_slot slot) override;
33 : awaitable<io_result> read(uint8_t buffer[], size_t size) override;
34 : awaitable<io_result> read(boost::asio::streambuf& buffer, size_t size) override;
35 : awaitable<io_result> read_until(boost::asio::streambuf& buffer, std::string_view delim) override;
36 :
37 : // wait
38 : awaitable<boost::system::error_code> wait(boost::asio::socket_base::wait_type type) override;
39 : awaitable<boost::system::error_code> peer_closed() override;
40 :
41 : // write operations
42 : awaitable<io_result> write(const uint8_t buffer[], size_t size) override;
43 : awaitable<io_result> write(std::string_view str) override;
44 : awaitable<io_result> write(const std::vector<boost::asio::const_buffer>& buffers) override;
45 : // Writes go through the TLS stream: never written without waiting
46 6623 : size_t write_now(const std::vector<boost::asio::const_buffer>& buffers, boost::system::error_code& ec) override {
47 6623 : return socket::write_now(buffers, ec);
48 : }
49 :
50 : // some getters to check the state
51 : bool is_secure() const override;
52 : // Decrypted data waiting to be read counts too
53 : bool readable_now() const override;
54 : // Once the handshake is done (none before, or once closed)
55 : std::optional<tls_session> tls() const override;
56 : // Checked against the record of the server handshake (none on the client side)
57 3845 : bool misdirected(std::string_view host) const override { return handshake_.misdirected(host); }
58 :
59 : // The certificate of the peer (its leaf), without copying it: null if it sent none (or
60 : // before the handshake). Owned by the connection: not to be used once the socket is closed
61 : // or destroyed (X509_up_ref() it to keep it)
62 : X509* peer_certificate() const;
63 : // The certificates the peer sent, without copying them, as OpenSSL keeps them: on the
64 : // server side without the leaf (see peer_certificate()), on the client side with it first.
65 : // Null if none; owned by the connection, as peer_certificate()
66 : STACK_OF(X509)* peer_chain() const;
67 :
68 : // OpenSSL handle of the TLS stream, e.g. to set the name a client verifies in the
69 : // certificate of the server before the handshake
70 261 : SSL* native_handle() { return ssl_stream_.native_handle(); }
71 :
72 : // Internal: only listener calls it, until tls_socket (0.10); applications set
73 : // listener_options::client_verify. Ask the client for its certificate with `policy` (see
74 : // client_verify_policy), kept as long as the socket; before the server handshake
75 : void set_client_verify(std::shared_ptr<const client_verify_policy> policy);
76 :
77 : private:
78 : // Move up to `size` bytes of read_ahead_ to `buffer`; how many were moved
79 : size_t take_read_ahead(uint8_t buffer[], size_t size);
80 : // Move read_ahead_ to `buffer`
81 : void take_read_ahead(boost::asio::streambuf& buffer, size_t max_size);
82 :
83 : boost::asio::ssl::stream<boost::asio::ip::tcp::socket&> ssl_stream_;
84 : // Data already decrypted by peer_closed(), served before reading from the stream
85 : std::string read_ahead_;
86 : std::shared_ptr<boost::asio::ssl::context> ssl_context_;
87 : // Client certificates asked for (server side), referred to by the SSL
88 : std::shared_ptr<const client_verify_policy> client_verify_;
89 : // What the server handshake chose by the host name of its client, kept once it completes
90 : tls_handshake_record handshake_;
91 : };
92 :
93 : }
94 :
95 : #endif
|