/src/libtorrent/src/ssl.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | |
3 | | Copyright (c) 2020, Paul-Louis Ageneau |
4 | | Copyright (c) 2018, Alexandre Janniaux |
5 | | Copyright (c) 2020, Arvid Norberg |
6 | | All rights reserved. |
7 | | |
8 | | Redistribution and use in source and binary forms, with or without |
9 | | modification, are permitted provided that the following conditions |
10 | | are met: |
11 | | |
12 | | * Redistributions of source code must retain the above copyright |
13 | | notice, this list of conditions and the following disclaimer. |
14 | | * Redistributions in binary form must reproduce the above copyright |
15 | | notice, this list of conditions and the following disclaimer in |
16 | | the documentation and/or other materials provided with the distribution. |
17 | | * Neither the name of the author nor the names of its |
18 | | contributors may be used to endorse or promote products derived |
19 | | from this software without specific prior written permission. |
20 | | |
21 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
22 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
25 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 | | POSSIBILITY OF SUCH DAMAGE. |
32 | | |
33 | | */ |
34 | | |
35 | | #include "libtorrent/ssl.hpp" |
36 | | |
37 | | #if TORRENT_USE_SSL |
38 | | |
39 | | #ifdef TORRENT_USE_OPENSSL |
40 | | #include <openssl/x509v3.h> // for GENERAL_NAME |
41 | | #endif |
42 | | |
43 | | #ifdef TORRENT_USE_GNUTLS |
44 | | #include <gnutls/x509.h> |
45 | | #endif |
46 | | |
47 | | namespace libtorrent { |
48 | | namespace ssl { |
49 | | |
50 | | void set_trust_certificate(native_context_type nc, string_view pem, error_code &ec) |
51 | 0 | { |
52 | 0 | #if defined TORRENT_USE_OPENSSL |
53 | | // create a new X.509 certificate store |
54 | 0 | X509_STORE* cert_store = X509_STORE_new(); |
55 | 0 | if (!cert_store) |
56 | 0 | { |
57 | 0 | ec = error_code(int(ERR_get_error()), error::get_ssl_category()); |
58 | 0 | return; |
59 | 0 | } |
60 | | |
61 | | // wrap the PEM certificate in a BIO, for openssl to read |
62 | 0 | BIO* bp = BIO_new_mem_buf( |
63 | 0 | const_cast<char*>(pem.data()), |
64 | 0 | int(pem.size())); |
65 | | |
66 | | // parse the certificate into OpenSSL's internal representation |
67 | 0 | X509* cert = PEM_read_bio_X509_AUX(bp, nullptr, nullptr, nullptr); |
68 | 0 | BIO_free(bp); |
69 | |
|
70 | 0 | if (!cert) |
71 | 0 | { |
72 | 0 | X509_STORE_free(cert_store); |
73 | 0 | ec = error_code(int(ERR_get_error()), error::get_ssl_category()); |
74 | 0 | return; |
75 | 0 | } |
76 | | |
77 | | // add cert to cert_store |
78 | 0 | X509_STORE_add_cert(cert_store, cert); |
79 | 0 | X509_free(cert); |
80 | | |
81 | | // and lastly, replace the default cert store with ours |
82 | 0 | SSL_CTX_set_cert_store(nc, cert_store); |
83 | |
|
84 | | #elif defined TORRENT_USE_GNUTLS |
85 | | gnutls_datum_t ca; |
86 | | ca.data = reinterpret_cast<unsigned char*>(const_cast<char*>(pem.data())); |
87 | | ca.size = unsigned(pem.size()); |
88 | | |
89 | | // Warning: returns the number of certificates processed or a negative error code on error |
90 | | int ret = gnutls_certificate_set_x509_trust_mem(nc, &ca, GNUTLS_X509_FMT_PEM); |
91 | | if(ret < 0) |
92 | | ec = error_code(ret, error::get_ssl_category()); |
93 | | #endif |
94 | 0 | } |
95 | | |
96 | | void set_server_name_callback(context_handle_type c, server_name_callback_type cb, void* arg, error_code& ec) |
97 | 0 | { |
98 | 0 | #if defined TORRENT_USE_OPENSSL |
99 | 0 | TORRENT_UNUSED(ec); |
100 | 0 | #if defined __clang__ |
101 | 0 | #pragma clang diagnostic push |
102 | 0 | #pragma clang diagnostic ignored "-Wold-style-cast" |
103 | 0 | #pragma clang diagnostic ignored "-Wcast-function-type-strict" |
104 | 0 | #pragma clang diagnostic ignored "-Wunknown-warning-option" |
105 | 0 | #endif |
106 | 0 | SSL_CTX_set_tlsext_servername_callback(c, cb); |
107 | 0 | SSL_CTX_set_tlsext_servername_arg(c, arg); |
108 | 0 | #if defined __clang__ |
109 | 0 | #pragma clang diagnostic pop |
110 | 0 | #endif |
111 | |
|
112 | | #elif defined TORRENT_USE_GNUTLS |
113 | | if(cb) |
114 | | c->set_server_name_callback( |
115 | | [cb, arg](stream_base& s, std::string const& name) |
116 | | { |
117 | | return cb(&s, name, arg); |
118 | | } |
119 | | , ec); |
120 | | else |
121 | | c->set_server_name_callback(nullptr); |
122 | | #endif |
123 | 0 | } |
124 | | |
125 | | void set_host_name(stream_handle_type s, std::string const& name, error_code& ec) |
126 | 0 | { |
127 | 0 | #if defined TORRENT_USE_OPENSSL |
128 | 0 | TORRENT_UNUSED(ec); |
129 | 0 | #if defined __clang__ |
130 | 0 | #pragma clang diagnostic push |
131 | 0 | #pragma clang diagnostic ignored "-Wold-style-cast" |
132 | 0 | #pragma clang diagnostic ignored "-Wcast-qual" |
133 | 0 | #endif |
134 | 0 | SSL_set_tlsext_host_name(s, name.c_str()); |
135 | 0 | #if defined __clang__ |
136 | 0 | #pragma clang diagnostic pop |
137 | 0 | #endif |
138 | |
|
139 | | #elif defined TORRENT_USE_GNUTLS |
140 | | s->set_host_name(name, ec); |
141 | | #endif |
142 | 0 | } |
143 | | |
144 | | void set_context(stream_handle_type s, context_handle_type c) |
145 | 0 | { |
146 | 0 | #if defined TORRENT_USE_OPENSSL |
147 | 0 | SSL_set_SSL_CTX(s, c); |
148 | 0 | SSL_set_verify(s |
149 | 0 | , SSL_CTX_get_verify_mode(c) |
150 | 0 | , SSL_CTX_get_verify_callback(c)); |
151 | | #elif defined TORRENT_USE_GNUTLS |
152 | | s->set_context(*c); |
153 | | #endif |
154 | 0 | } |
155 | | |
156 | | bool has_context(stream_handle_type s, context_handle_type c) |
157 | 0 | { |
158 | 0 | context_handle_type stream_ctx = get_context(s); |
159 | 0 | #if defined TORRENT_USE_OPENSSL |
160 | 0 | return stream_ctx == c; |
161 | | #elif defined TORRENT_USE_GNUTLS |
162 | | return stream_ctx->native_handle() == c->native_handle(); |
163 | | #endif |
164 | 0 | } |
165 | | |
166 | | context_handle_type get_context(stream_handle_type s) |
167 | 0 | { |
168 | 0 | #if defined TORRENT_USE_OPENSSL |
169 | 0 | return SSL_get_SSL_CTX(s); |
170 | | #elif defined TORRENT_USE_GNUTLS |
171 | | return &s->get_context(); |
172 | | #endif |
173 | 0 | } |
174 | | |
175 | | #if defined TORRENT_USE_OPENSSL |
176 | | namespace { |
177 | | struct lifecycle |
178 | | { |
179 | | lifecycle() |
180 | 2 | { |
181 | | // this is needed for openssl < 1.0 to decrypt keys created by openssl 1.0+ |
182 | 2 | #if !defined(OPENSSL_API_COMPAT) || (OPENSSL_API_COMPAT < 0x10100000L) |
183 | 2 | OpenSSL_add_all_algorithms(); |
184 | | #else |
185 | | OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, nullptr); |
186 | | #endif |
187 | 2 | } |
188 | | |
189 | | ~lifecycle() |
190 | 0 | { |
191 | | // by openssl changelog at https://www.openssl.org/news/changelog.html |
192 | | // Changes between 1.0.2h and 1.1.0 [25 Aug 2016] |
193 | | // - Most global cleanup functions are no longer required because they are handled |
194 | | // via auto-deinit. Affected function CRYPTO_cleanup_all_ex_data() |
195 | 0 | #if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L |
196 | | #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO |
197 | | #pragma clang diagnostic push |
198 | | #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
199 | | #endif |
200 | | // openssl requires this to clean up internal structures it allocates |
201 | 0 | CRYPTO_cleanup_all_ex_data(); |
202 | | #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO |
203 | | #pragma clang diagnostic pop |
204 | | #endif |
205 | 0 | #endif |
206 | 0 | } |
207 | | } global; |
208 | | } |
209 | | #endif |
210 | | |
211 | | } // ssl |
212 | | } // libtorrent |
213 | | #endif |
214 | | |