Avi Drissman | 8ba1bad | 2022-09-13 19:22:36 | [diff] [blame] | 1 | // Copyright 2019 The Chromium Authors |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Arthur Sonzogni | b948e67 | 2024-07-31 08:29:04 | [diff] [blame] | 5 | #ifdef UNSAFE_BUFFERS_BUILD |
| 6 | // TODO(crbug.com/40285824): Remove this and convert code to safer constructs. |
| 7 | #pragma allow_unsafe_buffers |
| 8 | #endif |
| 9 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 10 | #include "components/openscreen_platform/tls_connection_factory.h" |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 11 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 12 | #include <openssl/pool.h> |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 13 | #include <utility> |
| 14 | |
Hans Wennborg | df87046c | 2020-04-28 11:06:24 | [diff] [blame] | 15 | #include "base/notreached.h" |
btolsch | 4bdffd9 | 2020-04-08 07:27:25 | [diff] [blame] | 16 | #include "components/openscreen_platform/network_context.h" |
Fabrice de Gans-Riberi | e17abf54b | 2020-01-28 00:29:54 | [diff] [blame] | 17 | #include "components/openscreen_platform/network_util.h" |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 18 | #include "components/openscreen_platform/tls_client_connection.h" |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 19 | #include "net/base/host_port_pair.h" |
| 20 | #include "net/base/net_errors.h" |
| 21 | #include "net/ssl/ssl_info.h" |
| 22 | #include "net/traffic_annotation/network_traffic_annotation.h" |
btolsch | 4bdffd9 | 2020-04-08 07:27:25 | [diff] [blame] | 23 | #include "services/network/public/mojom/network_context.mojom.h" |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 24 | #include "third_party/openscreen/src/platform/api/tls_connection.h" |
| 25 | #include "third_party/openscreen/src/platform/base/tls_connect_options.h" |
| 26 | #include "third_party/openscreen/src/platform/base/tls_credentials.h" |
| 27 | #include "third_party/openscreen/src/platform/base/tls_listen_options.h" |
| 28 | |
| 29 | namespace openscreen { |
Yuri Wiitala | 9fca519b3 | 2019-12-06 02:03:52 | [diff] [blame] | 30 | |
mark a. foltz | 1044475 | 2023-06-17 00:11:59 | [diff] [blame] | 31 | class TaskRunner; |
| 32 | |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 33 | std::unique_ptr<TlsConnectionFactory> TlsConnectionFactory::CreateFactory( |
mark a. foltz | 19c2ea33 | 2024-04-03 18:55:04 | [diff] [blame] | 34 | Client& client, |
mark a. foltz | 1044475 | 2023-06-17 00:11:59 | [diff] [blame] | 35 | TaskRunner& task_runner) { |
| 36 | return std::make_unique<openscreen_platform::TlsConnectionFactory>(client); |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 37 | } |
Yuri Wiitala | 9fca519b3 | 2019-12-06 02:03:52 | [diff] [blame] | 38 | |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 39 | } // namespace openscreen |
| 40 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 41 | namespace openscreen_platform { |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 42 | |
| 43 | namespace { |
| 44 | |
| 45 | using openscreen::IPEndpoint; |
Yuri Wiitala | 9fca519b3 | 2019-12-06 02:03:52 | [diff] [blame] | 46 | using openscreen::TlsConnectOptions; |
| 47 | using openscreen::TlsCredentials; |
| 48 | using openscreen::TlsListenOptions; |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 49 | |
| 50 | constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 51 | net::DefineNetworkTrafficAnnotation("openscreen_tls_message", R"( |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 52 | semantics { |
| 53 | sender: "Open Screen" |
| 54 | description: |
| 55 | "Open Screen TLS messages are used by the third_party Open Screen " |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 56 | "library, primarily for the libcast CastSocket implementation." |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 57 | trigger: |
| 58 | "Any TLS encrypted message that needs to be sent or received by " |
| 59 | "the Open Screen library." |
| 60 | data: |
| 61 | "Messages defined by the Open Screen Protocol specification." |
| 62 | destination: OTHER |
| 63 | destination_other: |
| 64 | "The connection is made to an Open Screen endpoint on the LAN " |
| 65 | "selected by the user, i.e. via a dialog." |
| 66 | } |
| 67 | policy { |
| 68 | cookies_allowed: NO |
| 69 | setting: |
| 70 | "This request cannot be disabled, but it would not be sent if user " |
| 71 | "does not connect to a Open Screen endpoint on the local network." |
| 72 | policy_exception_justification: "Not implemented." |
| 73 | })"); |
| 74 | |
| 75 | } // namespace |
| 76 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 77 | TlsConnectionFactory::~TlsConnectionFactory() = default; |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 78 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 79 | void TlsConnectionFactory::Connect(const IPEndpoint& remote_address, |
| 80 | const TlsConnectOptions& options) { |
btolsch | 4bdffd9 | 2020-04-08 07:27:25 | [diff] [blame] | 81 | network::mojom::NetworkContext* network_context = |
| 82 | openscreen_platform::GetNetworkContext(); |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 83 | if (!network_context) { |
| 84 | client_->OnError(this, openscreen::Error::Code::kItemNotFound); |
| 85 | return; |
| 86 | } |
| 87 | |
| 88 | TcpConnectRequest request(options, remote_address, |
| 89 | mojo::Remote<network::mojom::TCPConnectedSocket>{}); |
| 90 | |
| 91 | const net::AddressList address_list( |
Fabrice de Gans-Riberi | e17abf54b | 2020-01-28 00:29:54 | [diff] [blame] | 92 | openscreen_platform::ToNetEndPoint(remote_address)); |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 93 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 94 | mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver = |
| 95 | request.tcp_socket.BindNewPipeAndPassReceiver(); |
| 96 | |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 97 | network_context->CreateTCPConnectedSocket( |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 98 | std::nullopt /* local_addr */, address_list, |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 99 | nullptr /* tcp_connected_socket_options */, |
| 100 | net::MutableNetworkTrafficAnnotationTag(kTrafficAnnotation), |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 101 | std::move(receiver), mojo::NullRemote(), /* observer */ |
| 102 | base::BindOnce(&TlsConnectionFactory::OnTcpConnect, |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 103 | weak_factory_.GetWeakPtr(), std::move(request))); |
| 104 | } |
| 105 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 106 | void TlsConnectionFactory::SetListenCredentials( |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 107 | const TlsCredentials& credentials) { |
| 108 | NOTIMPLEMENTED(); |
| 109 | } |
| 110 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 111 | void TlsConnectionFactory::Listen(const IPEndpoint& local_address, |
| 112 | const TlsListenOptions& options) { |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 113 | NOTIMPLEMENTED(); |
| 114 | } |
| 115 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 116 | TlsConnectionFactory::TlsConnectionFactory( |
mark a. foltz | 19c2ea33 | 2024-04-03 18:55:04 | [diff] [blame] | 117 | openscreen::TlsConnectionFactory::Client& client) |
mark a. foltz | 1044475 | 2023-06-17 00:11:59 | [diff] [blame] | 118 | : client_(client) {} |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 119 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 120 | TlsConnectionFactory::TcpConnectRequest::TcpConnectRequest( |
Yuri Wiitala | 9fca519b3 | 2019-12-06 02:03:52 | [diff] [blame] | 121 | openscreen::TlsConnectOptions options_in, |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 122 | openscreen::IPEndpoint remote_address_in, |
| 123 | mojo::Remote<network::mojom::TCPConnectedSocket> tcp_socket_in) |
| 124 | : options(std::move(options_in)), |
| 125 | remote_address(std::move(remote_address_in)), |
| 126 | tcp_socket(std::move(tcp_socket_in)) {} |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 127 | TlsConnectionFactory::TcpConnectRequest::TcpConnectRequest( |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 128 | TcpConnectRequest&&) = default; |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 129 | TlsConnectionFactory::TcpConnectRequest& |
| 130 | TlsConnectionFactory::TcpConnectRequest::operator=(TcpConnectRequest&&) = |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 131 | default; |
| 132 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 133 | TlsConnectionFactory::TcpConnectRequest::~TcpConnectRequest() = default; |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 134 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 135 | TlsConnectionFactory::TlsUpgradeRequest::TlsUpgradeRequest( |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 136 | openscreen::IPEndpoint local_address_in, |
| 137 | openscreen::IPEndpoint remote_address_in, |
| 138 | mojo::Remote<network::mojom::TCPConnectedSocket> tcp_socket_in, |
| 139 | mojo::Remote<network::mojom::TLSClientSocket> tls_socket_in) |
| 140 | : local_address(std::move(local_address_in)), |
| 141 | remote_address(std::move(remote_address_in)), |
| 142 | tcp_socket(std::move(tcp_socket_in)), |
| 143 | tls_socket(std::move(tls_socket_in)) {} |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 144 | TlsConnectionFactory::TlsUpgradeRequest::TlsUpgradeRequest( |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 145 | TlsUpgradeRequest&&) = default; |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 146 | TlsConnectionFactory::TlsUpgradeRequest& |
| 147 | TlsConnectionFactory::TlsUpgradeRequest::operator=(TlsUpgradeRequest&&) = |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 148 | default; |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 149 | TlsConnectionFactory::TlsUpgradeRequest::~TlsUpgradeRequest() = default; |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 150 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 151 | void TlsConnectionFactory::OnTcpConnect( |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 152 | TcpConnectRequest request, |
| 153 | int32_t net_result, |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 154 | const std::optional<net::IPEndPoint>& local_address, |
| 155 | const std::optional<net::IPEndPoint>& remote_address, |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 156 | mojo::ScopedDataPipeConsumerHandle receive_stream, |
| 157 | mojo::ScopedDataPipeProducerHandle send_stream) { |
| 158 | // We only care about net_result, since local_address doesn't matter, |
| 159 | // remote_address should be 1 out of 1 addresses provided in the connect |
| 160 | // call, and the streams must be closed before upgrading is allowed. |
| 161 | if (net_result != net::OK) { |
| 162 | client_->OnConnectionFailed(this, request.remote_address); |
| 163 | return; |
| 164 | } |
| 165 | |
| 166 | net::HostPortPair host_port_pair = net::HostPortPair::FromIPEndPoint( |
Fabrice de Gans-Riberi | e17abf54b | 2020-01-28 00:29:54 | [diff] [blame] | 167 | openscreen_platform::ToNetEndPoint(request.remote_address)); |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 168 | network::mojom::TLSClientSocketOptionsPtr options = |
| 169 | network::mojom::TLSClientSocketOptions::New(); |
| 170 | options->unsafely_skip_cert_verification = |
| 171 | request.options.unsafely_skip_certificate_validation; |
| 172 | |
| 173 | openscreen::IPEndpoint local_endpoint{}; |
| 174 | if (local_address) { |
Fabrice de Gans-Riberi | e17abf54b | 2020-01-28 00:29:54 | [diff] [blame] | 175 | local_endpoint = |
| 176 | openscreen_platform::ToOpenScreenEndPoint(local_address.value()); |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | TlsUpgradeRequest upgrade_request( |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 180 | std::move(local_endpoint), std::move(request.remote_address), |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 181 | std::move(request.tcp_socket), |
| 182 | mojo::Remote<network::mojom::TLSClientSocket>{}); |
| 183 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 184 | network::mojom::TCPConnectedSocket* tcp_socket = |
| 185 | upgrade_request.tcp_socket.get(); |
| 186 | mojo::PendingReceiver<network::mojom::TLSClientSocket> tls_receiver = |
| 187 | upgrade_request.tls_socket.BindNewPipeAndPassReceiver(); |
| 188 | |
| 189 | tcp_socket->UpgradeToTLS( |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 190 | host_port_pair, std::move(options), |
| 191 | net::MutableNetworkTrafficAnnotationTag(kTrafficAnnotation), |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 192 | std::move(tls_receiver), mojo::NullRemote() /* observer */, |
| 193 | base::BindOnce(&TlsConnectionFactory::OnTlsUpgrade, |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 194 | weak_factory_.GetWeakPtr(), std::move(upgrade_request))); |
| 195 | } |
| 196 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 197 | void TlsConnectionFactory::OnTlsUpgrade( |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 198 | TlsUpgradeRequest request, |
| 199 | int32_t net_result, |
| 200 | mojo::ScopedDataPipeConsumerHandle receive_stream, |
| 201 | mojo::ScopedDataPipeProducerHandle send_stream, |
Arthur Sonzogni | c571efb | 2024-01-26 20:26:18 | [diff] [blame] | 202 | const std::optional<net::SSLInfo>& ssl_info) { |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 203 | if (net_result != net::OK) { |
| 204 | client_->OnConnectionFailed(this, request.remote_address); |
| 205 | return; |
| 206 | } |
| 207 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 208 | auto tls_connection = std::make_unique<TlsClientConnection>( |
mark a. foltz | 1044475 | 2023-06-17 00:11:59 | [diff] [blame] | 209 | request.local_address, request.remote_address, std::move(receive_stream), |
| 210 | std::move(send_stream), std::move(request.tcp_socket), |
| 211 | std::move(request.tls_socket)); |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 212 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 213 | CRYPTO_BUFFER* der_buffer = ssl_info.value().unverified_cert->cert_buffer(); |
| 214 | const uint8_t* data = CRYPTO_BUFFER_data(der_buffer); |
| 215 | std::vector<uint8_t> der_x509_certificate( |
| 216 | data, data + CRYPTO_BUFFER_len(der_buffer)); |
| 217 | client_->OnConnected(this, std::move(der_x509_certificate), |
| 218 | std::move(tls_connection)); |
Jordan Bayles | 95bb73e | 2019-11-20 22:09:36 | [diff] [blame] | 219 | } |
| 220 | |
btolsch | 496b728df | 2020-02-21 06:01:18 | [diff] [blame] | 221 | } // namespace openscreen_platform |