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