1 /* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include "my_dbug.h" /* DBUG_ASSERT */
24 #include "mysql/components/services/log_builtins.h" /* LogErr */
25 #include "mysql/status_var.h" /* SHOW_VAR */
26 #include "mysqld_error.h" /* Error/Warning macros */
27 #include "sql/ssl_acceptor_context_status.h" /* Status functions */
28
29 #include "sql/ssl_acceptor_context_operator.h"
30
31 Ssl_acceptor_context_container *mysql_main;
32 Ssl_acceptor_context_container *mysql_admin;
33
Ssl_acceptor_context_container(Ssl_acceptor_context_data * data)34 Ssl_acceptor_context_container::Ssl_acceptor_context_container(
35 Ssl_acceptor_context_data *data)
36 : lock_(nullptr) {
37 lock_ = new Ssl_acceptor_context_data_lock(data);
38 }
39
~Ssl_acceptor_context_container()40 Ssl_acceptor_context_container ::~Ssl_acceptor_context_container() {
41 if (lock_ != nullptr) delete lock_;
42 lock_ = nullptr;
43 }
44
switch_data(Ssl_acceptor_context_data * new_data)45 void Ssl_acceptor_context_container::switch_data(
46 Ssl_acceptor_context_data *new_data) {
47 if (lock_ != nullptr) lock_->write_wait_and_delete(new_data);
48 }
49
singleton_init(Ssl_acceptor_context_container ** out,std::string channel,bool use_ssl_arg,Ssl_init_callback * callbacks,bool db_init)50 bool TLS_channel::singleton_init(Ssl_acceptor_context_container **out,
51 std::string channel, bool use_ssl_arg,
52 Ssl_init_callback *callbacks, bool db_init) {
53 if (out == nullptr || callbacks == nullptr) return true;
54 *out = nullptr;
55 /*
56 No need to take the ssl_ctx_lock lock here since it's being called
57 from singleton_init().
58 */
59 if (use_ssl_arg && callbacks->provision_certs()) return true;
60
61 /*
62 No real need for opt_use_ssl to be enabled in bootstrap mode,
63 but we want the SSL material generation and/or validation
64 (if supplied). So, we keep it on.
65
66 We don't hush the option since it would indicate a failure
67 in auto-generation, bad key material explicitly specified or
68 auto-generation disabled explcitly while SSL is still on.
69 */
70 Ssl_acceptor_context_data *news =
71 new Ssl_acceptor_context_data(channel, use_ssl_arg, callbacks);
72 Ssl_acceptor_context_container *new_container =
73 new Ssl_acceptor_context_container(news);
74 if (news == nullptr || new_container == nullptr) {
75 LogErr(WARNING_LEVEL, ER_SSL_LIBRARY_ERROR,
76 "Error initializing the SSL context system structure");
77 if (new_container) delete new_container;
78 return true;
79 }
80
81 if (news->have_ssl() && callbacks->warn_self_signed_ca()) {
82 /* This would delete Ssl_acceptor_context_data too */
83 delete new_container;
84 return true;
85 }
86
87 if (!db_init && news->have_ssl())
88 LogErr(SYSTEM_LEVEL, ER_TLS_CONFIGURED_FOR_CHANNEL, channel.c_str());
89
90 *out = new_container;
91 return false;
92 }
93
singleton_deinit(Ssl_acceptor_context_container * container)94 void TLS_channel::singleton_deinit(Ssl_acceptor_context_container *container) {
95 if (container == nullptr) return;
96 delete container;
97 }
98
singleton_flush(Ssl_acceptor_context_container * container,std::string channel,Ssl_init_callback * callbacks,enum enum_ssl_init_error * error,bool force)99 void TLS_channel::singleton_flush(Ssl_acceptor_context_container *container,
100 std::string channel,
101 Ssl_init_callback *callbacks,
102 enum enum_ssl_init_error *error, bool force) {
103 if (container == nullptr) return;
104 Ssl_acceptor_context_data *news =
105 new Ssl_acceptor_context_data(channel, true, callbacks, false, error);
106 if (*error != SSL_INITERR_NOERROR && !force) {
107 delete news;
108 return;
109 }
110 (void)container->switch_data(news);
111 return;
112 }
113
show_property(Ssl_acceptor_context_property_type property_type)114 std::string Lock_and_access_ssl_acceptor_context::show_property(
115 Ssl_acceptor_context_property_type property_type) {
116 const Ssl_acceptor_context_data *data = read_lock_;
117 return (data != nullptr ? data->show_property(property_type) : std::string{});
118 }
119
channel_name()120 std::string Lock_and_access_ssl_acceptor_context::channel_name() {
121 const Ssl_acceptor_context_data *data = read_lock_;
122 return (data != nullptr ? data->channel_name() : std::string{});
123 }
124
have_ssl()125 bool Lock_and_access_ssl_acceptor_context::have_ssl() {
126 const Ssl_acceptor_context_data *data = read_lock_;
127 return (data != nullptr ? data->have_ssl() : false);
128 }
129
have_ssl()130 bool have_ssl() {
131 if (mysql_main != nullptr) {
132 Lock_and_access_ssl_acceptor_context context(mysql_main);
133 if (context.have_ssl()) return true;
134 }
135 if (mysql_admin != nullptr) {
136 Lock_and_access_ssl_acceptor_context context(mysql_admin);
137 if (context.have_ssl()) return true;
138 }
139 return false;
140 }
141
142 /* Helpers */
show_long_status(SHOW_VAR * var,char * buff,Ssl_acceptor_context_property_type property_type)143 static int show_long_status(SHOW_VAR *var, char *buff,
144 Ssl_acceptor_context_property_type property_type) {
145 std::string property;
146 if (mysql_main != nullptr) {
147 Lock_and_access_ssl_acceptor_context main(mysql_main);
148 property = main.show_property(property_type);
149 }
150 var->type = SHOW_LONG;
151 var->value = buff;
152 *((long *)buff) = std::stol(property);
153
154 return 0;
155 }
156
show_char_status(SHOW_VAR * var,char * buff,Ssl_acceptor_context_property_type property_type)157 static int show_char_status(SHOW_VAR *var, char *buff,
158 Ssl_acceptor_context_property_type property_type) {
159 std::string property;
160 if (mysql_main != nullptr) {
161 Lock_and_access_ssl_acceptor_context main(mysql_main);
162 property = main.show_property(property_type);
163 }
164 var->type = SHOW_CHAR;
165 strncpy(buff, property.c_str(), SHOW_VAR_FUNC_BUFF_SIZE);
166 buff[SHOW_VAR_FUNC_BUFF_SIZE - 1] = 0;
167 var->value = buff;
168
169 return 0;
170 }
171 /* Helpers end */
172
173 /* Status functions for mysql_main TLS context */
174
show_ssl_ctx_sess_accept(THD *,SHOW_VAR * var,char * buff)175 int Ssl_mysql_main_status::show_ssl_ctx_sess_accept(THD *, SHOW_VAR *var,
176 char *buff) {
177 return show_long_status(var, buff,
178 Ssl_acceptor_context_property_type::accepts);
179 }
180
show_ssl_ctx_sess_accept_good(THD *,SHOW_VAR * var,char * buff)181 int Ssl_mysql_main_status::show_ssl_ctx_sess_accept_good(THD *, SHOW_VAR *var,
182 char *buff) {
183 return show_long_status(var, buff,
184 Ssl_acceptor_context_property_type::finished_accepts);
185 }
186
show_ssl_ctx_sess_connect_good(THD *,SHOW_VAR * var,char * buff)187 int Ssl_mysql_main_status::show_ssl_ctx_sess_connect_good(THD *, SHOW_VAR *var,
188 char *buff) {
189 return show_long_status(
190 var, buff, Ssl_acceptor_context_property_type::finished_connects);
191 }
192
show_ssl_ctx_sess_accept_renegotiate(THD *,SHOW_VAR * var,char * buff)193 int Ssl_mysql_main_status::show_ssl_ctx_sess_accept_renegotiate(THD *,
194 SHOW_VAR *var,
195 char *buff) {
196 return show_long_status(
197 var, buff, Ssl_acceptor_context_property_type::callback_cache_hits);
198 }
199
show_ssl_ctx_sess_connect_renegotiate(THD *,SHOW_VAR * var,char * buff)200 int Ssl_mysql_main_status::show_ssl_ctx_sess_connect_renegotiate(THD *,
201 SHOW_VAR *var,
202 char *buff) {
203 return show_long_status(
204 var, buff, Ssl_acceptor_context_property_type::callback_cache_hits);
205 }
206
show_ssl_ctx_sess_cb_hits(THD *,SHOW_VAR * var,char * buff)207 int Ssl_mysql_main_status::show_ssl_ctx_sess_cb_hits(THD *, SHOW_VAR *var,
208 char *buff) {
209 return show_long_status(
210 var, buff, Ssl_acceptor_context_property_type::callback_cache_hits);
211 }
212
show_ssl_ctx_sess_hits(THD *,SHOW_VAR * var,char * buff)213 int Ssl_mysql_main_status::show_ssl_ctx_sess_hits(THD *, SHOW_VAR *var,
214 char *buff) {
215 return show_long_status(
216 var, buff, Ssl_acceptor_context_property_type::session_cache_hits);
217 }
218
show_ssl_ctx_sess_cache_full(THD *,SHOW_VAR * var,char * buff)219 int Ssl_mysql_main_status::show_ssl_ctx_sess_cache_full(THD *, SHOW_VAR *var,
220 char *buff) {
221 return show_long_status(
222 var, buff, Ssl_acceptor_context_property_type::session_cache_overflows);
223 }
224
show_ssl_ctx_sess_misses(THD *,SHOW_VAR * var,char * buff)225 int Ssl_mysql_main_status::show_ssl_ctx_sess_misses(THD *, SHOW_VAR *var,
226 char *buff) {
227 return show_long_status(
228 var, buff, Ssl_acceptor_context_property_type::session_cache_misses);
229 }
230
show_ssl_ctx_sess_timeouts(THD *,SHOW_VAR * var,char * buff)231 int Ssl_mysql_main_status::show_ssl_ctx_sess_timeouts(THD *, SHOW_VAR *var,
232 char *buff) {
233 return show_long_status(
234 var, buff, Ssl_acceptor_context_property_type::session_cache_timeouts);
235 }
236
show_ssl_ctx_sess_number(THD *,SHOW_VAR * var,char * buff)237 int Ssl_mysql_main_status::show_ssl_ctx_sess_number(THD *, SHOW_VAR *var,
238 char *buff) {
239 return show_long_status(
240 var, buff,
241 Ssl_acceptor_context_property_type::used_session_cache_entries);
242 }
243
show_ssl_ctx_sess_connect(THD *,SHOW_VAR * var,char * buff)244 int Ssl_mysql_main_status::show_ssl_ctx_sess_connect(THD *, SHOW_VAR *var,
245 char *buff) {
246 return show_long_status(var, buff,
247 Ssl_acceptor_context_property_type::client_connects);
248 }
249
show_ssl_ctx_sess_get_cache_size(THD *,SHOW_VAR * var,char * buff)250 int Ssl_mysql_main_status::show_ssl_ctx_sess_get_cache_size(THD *,
251 SHOW_VAR *var,
252 char *buff) {
253 return show_long_status(
254 var, buff, Ssl_acceptor_context_property_type::session_cache_size);
255 }
256
show_ssl_ctx_get_verify_mode(THD *,SHOW_VAR * var,char * buff)257 int Ssl_mysql_main_status::show_ssl_ctx_get_verify_mode(THD *, SHOW_VAR *var,
258 char *buff) {
259 return show_long_status(var, buff,
260 Ssl_acceptor_context_property_type::ctx_verify_mode);
261 }
262
show_ssl_ctx_get_verify_depth(THD *,SHOW_VAR * var,char * buff)263 int Ssl_mysql_main_status::show_ssl_ctx_get_verify_depth(THD *, SHOW_VAR *var,
264 char *buff) {
265 return show_long_status(var, buff,
266 Ssl_acceptor_context_property_type::ctx_verify_depth);
267 }
268
show_ssl_ctx_get_session_cache_mode(THD *,SHOW_VAR * var,char * buff)269 int Ssl_mysql_main_status::show_ssl_ctx_get_session_cache_mode(THD *,
270 SHOW_VAR *var,
271 char *buff) {
272 return show_char_status(
273 var, buff, Ssl_acceptor_context_property_type::session_cache_mode);
274 }
275
show_ssl_get_server_not_before(THD *,SHOW_VAR * var,char * buff)276 int Ssl_mysql_main_status::show_ssl_get_server_not_before(THD *, SHOW_VAR *var,
277 char *buff) {
278 return show_char_status(
279 var, buff, Ssl_acceptor_context_property_type::server_not_before);
280 }
281
show_ssl_get_server_not_after(THD *,SHOW_VAR * var,char * buff)282 int Ssl_mysql_main_status::show_ssl_get_server_not_after(THD *, SHOW_VAR *var,
283 char *buff) {
284 return show_char_status(var, buff,
285 Ssl_acceptor_context_property_type::server_not_after);
286 }
287
show_ssl_get_ssl_ca(THD *,SHOW_VAR * var,char * buff)288 int Ssl_mysql_main_status::show_ssl_get_ssl_ca(THD *, SHOW_VAR *var,
289 char *buff) {
290 return show_char_status(var, buff,
291 Ssl_acceptor_context_property_type::current_tls_ca);
292 }
293
show_ssl_get_ssl_capath(THD *,SHOW_VAR * var,char * buff)294 int Ssl_mysql_main_status::show_ssl_get_ssl_capath(THD *, SHOW_VAR *var,
295 char *buff) {
296 return show_char_status(
297 var, buff, Ssl_acceptor_context_property_type::current_tls_capath);
298 }
299
show_ssl_get_ssl_cert(THD *,SHOW_VAR * var,char * buff)300 int Ssl_mysql_main_status::show_ssl_get_ssl_cert(THD *, SHOW_VAR *var,
301 char *buff) {
302 return show_char_status(var, buff,
303 Ssl_acceptor_context_property_type::current_tls_cert);
304 }
305
show_ssl_get_ssl_key(THD *,SHOW_VAR * var,char * buff)306 int Ssl_mysql_main_status::show_ssl_get_ssl_key(THD *, SHOW_VAR *var,
307 char *buff) {
308 return show_char_status(var, buff,
309 Ssl_acceptor_context_property_type::current_tls_key);
310 }
311
show_ssl_get_ssl_cipher(THD *,SHOW_VAR * var,char * buff)312 int Ssl_mysql_main_status::show_ssl_get_ssl_cipher(THD *, SHOW_VAR *var,
313 char *buff) {
314 return show_char_status(
315 var, buff, Ssl_acceptor_context_property_type::current_tls_cipher);
316 }
317
show_ssl_get_tls_ciphersuites(THD *,SHOW_VAR * var,char * buff)318 int Ssl_mysql_main_status::show_ssl_get_tls_ciphersuites(THD *, SHOW_VAR *var,
319 char *buff) {
320 return show_char_status(
321 var, buff, Ssl_acceptor_context_property_type::current_tls_ciphersuites);
322 }
323
show_ssl_get_tls_version(THD *,SHOW_VAR * var,char * buff)324 int Ssl_mysql_main_status::show_ssl_get_tls_version(THD *, SHOW_VAR *var,
325 char *buff) {
326 return show_char_status(
327 var, buff, Ssl_acceptor_context_property_type::current_tls_version);
328 }
329
show_ssl_get_ssl_crl(THD *,SHOW_VAR * var,char * buff)330 int Ssl_mysql_main_status::show_ssl_get_ssl_crl(THD *, SHOW_VAR *var,
331 char *buff) {
332 return show_char_status(var, buff,
333 Ssl_acceptor_context_property_type::current_tls_crl);
334 }
335
show_ssl_get_ssl_crlpath(THD *,SHOW_VAR * var,char * buff)336 int Ssl_mysql_main_status::show_ssl_get_ssl_crlpath(THD *, SHOW_VAR *var,
337 char *buff) {
338 return show_char_status(
339 var, buff, Ssl_acceptor_context_property_type::current_tls_crlpath);
340 }
341