289 lines
10 KiB
C++
289 lines
10 KiB
C++
/* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
#ifndef SSL_ACCEPTOR_CONTEXT_INCLUDED
|
|
#define SSL_ACCEPTOR_CONTEXT_INCLUDED
|
|
|
|
#include <my_rcu_lock.h>
|
|
#include <mysql/status_var.h>
|
|
#include <sql/sql_class.h>
|
|
#include <violite.h>
|
|
#include <atomic>
|
|
#include "my_sys.h"
|
|
|
|
/** helper class to deal with optionally empty strings */
|
|
class OptionalString {
|
|
public:
|
|
OptionalString() : value_(), empty_(true) {}
|
|
OptionalString(const char *s) : value_(s ? s : ""), empty_(!s) {}
|
|
~OptionalString() {}
|
|
OptionalString(const OptionalString &) = default;
|
|
|
|
const char *c_str() const { return empty_ ? NULL : value_.c_str(); }
|
|
OptionalString &assign(const char *s) {
|
|
value_.assign(s ? s : "");
|
|
empty_ = !s;
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
std::string value_;
|
|
bool empty_;
|
|
};
|
|
|
|
/**
|
|
Class to encapsulate the Server SSL acceptor context
|
|
*/
|
|
class SslAcceptorContext {
|
|
public:
|
|
/**
|
|
Initialize the single instance of the acceptor
|
|
|
|
@param use_ssl_arg Pass false if you don't want the actual
|
|
SSL context created (as in when SSL is initially disabled)
|
|
@retval true failure to init
|
|
@retval false initialized ok
|
|
*/
|
|
static bool singleton_init(bool use_ssl_arg);
|
|
/** De-initialize the single instance of the acceptor */
|
|
static void singleton_deinit();
|
|
/**
|
|
Re-initialize the single instance of the acceptor
|
|
|
|
@param[out] error
|
|
@param force activate the SSL settings even if this will lead to
|
|
disabling SSL
|
|
*/
|
|
static void singleton_flush(enum enum_ssl_init_error *error, bool force);
|
|
|
|
// info functions, to be called for the session vars
|
|
|
|
static int show_ssl_ctx_sess_accept(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_accept_good(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_connect_good(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_accept_renegotiate(THD *, SHOW_VAR *var,
|
|
char *buff);
|
|
static int show_ssl_ctx_sess_connect_renegotiate(THD *, SHOW_VAR *var,
|
|
char *buff);
|
|
static int show_ssl_ctx_sess_cb_hits(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_hits(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_cache_full(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_misses(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_timeouts(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_number(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_connect(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_sess_get_cache_size(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_get_verify_mode(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_get_verify_depth(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_ctx_get_session_cache_mode(THD *, SHOW_VAR *var,
|
|
char *buff);
|
|
static int show_ssl_get_server_not_before(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_get_server_not_after(THD *, SHOW_VAR *var, char *buff);
|
|
|
|
// info about the current set of ssl_ctx parameters
|
|
static int show_ssl_get_ssl_ca(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_get_ssl_capath(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_get_ssl_cert(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_get_ssl_key(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_get_ssl_cipher(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_get_tls_ciphersuites(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_get_tls_version(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_get_ssl_crl(THD *, SHOW_VAR *var, char *buff);
|
|
static int show_ssl_get_ssl_crlpath(THD *, SHOW_VAR *var, char *buff);
|
|
|
|
/**
|
|
Check if SSL was initialized
|
|
|
|
retval true if the singleton holds a properly initialized SSL_CTX
|
|
*/
|
|
static bool have_ssl();
|
|
|
|
/**
|
|
An RCU lock type for @ref SslAcceptorContext
|
|
*/
|
|
typedef MyRcuLock<SslAcceptorContext> SslAcceptorContextLockType;
|
|
|
|
/**
|
|
The prefered way to *read* SSL parameters.
|
|
This is a scope lock class. So initialize it and hold it for
|
|
as long as you need to access the data.
|
|
@note It's OK to release it and still use the data *ONLY*
|
|
if you apply other means to protect your data (e.g. SSL context
|
|
reference counts etc).
|
|
|
|
@sa MyRcuLock, SslAcceptorContext
|
|
*/
|
|
class AutoLock : SslAcceptorContextLockType::ReadLock {
|
|
public:
|
|
AutoLock()
|
|
: SslAcceptorContextLockType::ReadLock(SslAcceptorContext::lock) {}
|
|
~AutoLock() {}
|
|
|
|
/**
|
|
Access to the SSL_CTX from the protected @ref SslAcceptorContext
|
|
*/
|
|
operator SSL_CTX *() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->ssl_acceptor_fd->ssl_context;
|
|
}
|
|
/**
|
|
Access to the SSL from the protected @ref SslAcceptorContext
|
|
*/
|
|
operator SSL *() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->acceptor;
|
|
}
|
|
operator struct st_VioSSLFd *() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->ssl_acceptor_fd;
|
|
}
|
|
/**
|
|
Check if the SSL context actually contains a valid SSL_CTX
|
|
@retval true there's no valid SSL_CTX
|
|
@retval false there's a valid SSL_CTX, SSL and st_VioSSLFd
|
|
*/
|
|
bool empty() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->ssl_acceptor_fd == NULL;
|
|
}
|
|
|
|
// functions to return the cached values for the parameters so that the
|
|
// status vars work.
|
|
|
|
const char *get_current_ca() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->current_ca_.c_str();
|
|
}
|
|
const char *get_current_capath() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->current_capath_.c_str();
|
|
}
|
|
const char *get_current_cert() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->current_cert_.c_str();
|
|
}
|
|
const char *get_current_key() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->current_key_.c_str();
|
|
}
|
|
const char *get_current_version() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->current_version_.c_str();
|
|
}
|
|
const char *get_current_crl() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->current_crl_.c_str();
|
|
}
|
|
const char *get_current_crlpath() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->current_crlpath_.c_str();
|
|
}
|
|
const char *get_current_cipher() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->current_cipher_.c_str();
|
|
}
|
|
const char *get_current_ciphersuites() {
|
|
const SslAcceptorContext *c = *this;
|
|
return c->current_ciphersuites_.c_str();
|
|
}
|
|
};
|
|
|
|
~SslAcceptorContext();
|
|
|
|
/**
|
|
A workaround for consumers that need to read the values
|
|
|
|
This is a temporary workaround for the subsystems that
|
|
are trying to access the mysql protocol TLS context parameters.
|
|
TODO: to be removed once these migrate to access the system variables.
|
|
|
|
To use pass a non-null pointer to an std::string to any of the args
|
|
to receive a copy of the relevant value that you will then need to
|
|
dispose of.
|
|
|
|
@param [out] ca
|
|
@param [out] capath
|
|
@param [out] version
|
|
@param [out] cert
|
|
@param [out] cipher
|
|
@param [out] ciphersuites
|
|
@param [out] key
|
|
@param [out] crl
|
|
@param [out] crl_path
|
|
*/
|
|
static void read_parameters(
|
|
OptionalString *ca = nullptr, OptionalString *capath = nullptr,
|
|
OptionalString *version = nullptr, OptionalString *cert = nullptr,
|
|
OptionalString *cipher = nullptr, OptionalString *ciphersuites = nullptr,
|
|
OptionalString *key = nullptr, OptionalString *crl = nullptr,
|
|
OptionalString *crl_path = nullptr);
|
|
|
|
protected:
|
|
/**
|
|
A protected constructor since it's only instantiated via the static
|
|
functions.
|
|
|
|
@param use_ssl_arg don't bother at all to try and construct an SSL_CTX and
|
|
just make an empty SslAcceptorContext. Used to pass the --ssl option at
|
|
startup.
|
|
@param report_ssl_error report any SSL errors resulting from trying to
|
|
initialize the SSL_CTX to the server's error log.
|
|
@param [out] out_error an optional slot to return the SSL_CTX initialization
|
|
error location.
|
|
*/
|
|
SslAcceptorContext(bool use_ssl_arg, bool report_ssl_error = true,
|
|
enum enum_ssl_init_error *out_error = nullptr);
|
|
/** Disable the copy constructor */
|
|
SslAcceptorContext(const SslAcceptorContext &) = delete;
|
|
/** Disable assignment operator */
|
|
SslAcceptorContext operator=(const SslAcceptorContext) = delete;
|
|
|
|
/** Try to auto-detect the SSL key material files. Called by @ref
|
|
* singleton_init */
|
|
static ssl_artifacts_status auto_detect_ssl();
|
|
|
|
/** Put up a warning in the error log if the CA used is self-signed. Called by
|
|
* @ref singleton_init */
|
|
static int warn_self_signed_ca();
|
|
|
|
protected:
|
|
/** SSL_CTX barerer */
|
|
struct st_VioSSLFd *ssl_acceptor_fd;
|
|
/**
|
|
An SSL for @ref ssl_acceptor_fd to allow access to parameters not in
|
|
SSL_CTX to be available even if the current connection is not encrypted.
|
|
*/
|
|
SSL *acceptor;
|
|
|
|
/**
|
|
Copies of the current effective values for quick return via the status vars
|
|
*/
|
|
OptionalString current_ca_, current_capath_, current_version_, current_cert_,
|
|
current_cipher_, current_ciphersuites_, current_key_, current_crl_,
|
|
current_crlpath_;
|
|
|
|
/** singleton lock */
|
|
static SslAcceptorContextLockType *lock;
|
|
};
|
|
|
|
#endif // SSL_ACCEPTOR_CONTEXT_INCLUDED
|