用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

261 lines
9.6 KiB

/* Copyright (c) 2016, 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 */
#include "my_config.h"
#include <mysql/plugin_keyring.h>
#include <memory>
#include <mysql/components/my_service.h>
#include <mysql/components/services/log_builtins.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include "my_compiler.h"
#include "my_inttypes.h"
#include "my_io.h"
#include "my_psi_config.h"
#include "mysqld_error.h"
#include "plugin/keyring/buffered_file_io.h"
#include "plugin/keyring/common/keyring.h"
#ifdef _WIN32
#define MYSQL_DEFAULT_KEYRINGFILE MYSQL_KEYRINGDIR "\\keyring"
#else
#define MYSQL_DEFAULT_KEYRINGFILE MYSQL_KEYRINGDIR "/keyring"
#endif
using keyring::Buffered_file_io;
using keyring::Key;
using keyring::Keys_container;
using keyring::Keys_iterator;
using keyring::Logger;
mysql_rwlock_t LOCK_keyring;
int check_keyring_file_data(MYSQL_THD thd MY_ATTRIBUTE((unused)),
SYS_VAR *var MY_ATTRIBUTE((unused)), void *save,
st_mysql_value *value) {
char buff[FN_REFLEN + 1];
const char *keyring_filename;
int len = sizeof(buff);
std::unique_ptr<IKeys_container> new_keys(new Keys_container(logger.get()));
(*(const char **)save) = NULL;
keyring_filename = value->val_str(value, buff, &len);
mysql_rwlock_wrlock(&LOCK_keyring);
if (create_keyring_dir_if_does_not_exist(keyring_filename)) {
mysql_rwlock_unlock(&LOCK_keyring);
logger->log(ERROR_LEVEL, ER_KEYRING_FAILED_TO_SET_KEYRING_FILE_DATA);
return 1;
}
try {
IKeyring_io *keyring_io(new Buffered_file_io(logger.get()));
if (new_keys->init(keyring_io, keyring_filename)) {
mysql_rwlock_unlock(&LOCK_keyring);
return 1;
}
*reinterpret_cast<IKeys_container **>(save) = new_keys.get();
new_keys.release();
mysql_rwlock_unlock(&LOCK_keyring);
} catch (...) {
mysql_rwlock_unlock(&LOCK_keyring);
return 1;
}
return (0);
}
static char *keyring_file_data_value = NULL;
static MYSQL_SYSVAR_STR(
data, /* name */
keyring_file_data_value, /* value */
PLUGIN_VAR_RQCMDARG, /* flags */
"The path to the keyring file. Must be specified", /* comment */
check_keyring_file_data, /* check() */
update_keyring_file_data, /* update() */
MYSQL_DEFAULT_KEYRINGFILE /* default */
);
static MYSQL_SYSVAR_BOOL(open_mode, keyring_open_mode,
PLUGIN_VAR_INVISIBLE | PLUGIN_VAR_RQCMDARG,
"Mode in which keyring file should be opened", NULL,
NULL, true);
static SYS_VAR *keyring_file_system_variables[] = {
MYSQL_SYSVAR(data), MYSQL_SYSVAR(open_mode), NULL};
static SERVICE_TYPE(registry) *reg_srv = nullptr;
SERVICE_TYPE(log_builtins) *log_bi = nullptr;
SERVICE_TYPE(log_builtins_string) *log_bs = nullptr;
static int keyring_init(MYSQL_PLUGIN plugin_info MY_ATTRIBUTE((unused))) {
if (init_logging_service_for_plugin(&reg_srv, &log_bi, &log_bs)) return true;
try {
SSL_library_init(); // always returns 1
ERR_load_BIO_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
#ifdef HAVE_PSI_INTERFACE
keyring_init_psi_keys();
#endif
DBUG_EXECUTE_IF("simulate_keyring_init_error", return true;);
if (init_keyring_locks()) return true;
logger.reset(new Logger());
if (create_keyring_dir_if_does_not_exist(keyring_file_data_value)) {
logger->log(ERROR_LEVEL, ER_KEYRING_FAILED_TO_CREATE_KEYRING_DIR);
return true;
}
keys.reset(new Keys_container(logger.get()));
std::vector<std::string> allowedFileVersionsToInit;
// this keyring will work with keyring files in the following versions:
allowedFileVersionsToInit.push_back(keyring::keyring_file_version_2_0);
allowedFileVersionsToInit.push_back(keyring::keyring_file_version_1_0);
IKeyring_io *keyring_io =
new Buffered_file_io(logger.get(), &allowedFileVersionsToInit);
if (keys->init(keyring_io, keyring_file_data_value)) {
is_keys_container_initialized = false;
logger->log(ERROR_LEVEL, ER_KEYRING_FILE_INIT_FAILED);
return true;
}
is_keys_container_initialized = true;
return false;
} catch (...) {
if (logger != NULL)
logger->log(ERROR_LEVEL, ER_KEYRING_INTERNAL_EXCEPTION_FAILED_FILE_INIT);
deinit_logging_service_for_plugin(&reg_srv, &log_bi, &log_bs);
return true;
}
}
static int keyring_deinit(void *arg MY_ATTRIBUTE((unused))) {
// not taking a lock here as the calls to keyring_deinit are serialized by
// the plugin framework
#if OPENSSL_VERSION_NUMBER < 0x10100000L
ERR_remove_thread_state(0);
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
keys.reset();
logger.reset();
keyring_file_data.reset();
mysql_rwlock_destroy(&LOCK_keyring);
deinit_logging_service_for_plugin(&reg_srv, &log_bi, &log_bs);
return 0;
}
static bool mysql_key_fetch(const char *key_id, char **key_type,
const char *user_id, void **key, size_t *key_len) {
return mysql_key_fetch<keyring::Key>(key_id, key_type, user_id, key, key_len,
"keyring_file");
}
static bool mysql_key_store(const char *key_id, const char *key_type,
const char *user_id, const void *key,
size_t key_len) {
return mysql_key_store<keyring::Key>(key_id, key_type, user_id, key, key_len,
"keyring_file");
}
static bool mysql_key_remove(const char *key_id, const char *user_id) {
return mysql_key_remove<keyring::Key>(key_id, user_id, "keyring_file");
}
static bool mysql_key_generate(const char *key_id, const char *key_type,
const char *user_id, size_t key_len) {
try {
std::unique_ptr<IKey> key_candidate(
new Key(key_id, key_type, user_id, NULL, 0));
std::unique_ptr<uchar[]> key(new uchar[key_len]);
if (key.get() == NULL) return true;
memset(key.get(), 0, key_len);
if (is_keys_container_initialized == false ||
check_key_for_writing(key_candidate.get(), "generating") ||
my_rand_buffer(key.get(), key_len))
return true;
return mysql_key_store(key_id, key_type, user_id, key.get(), key_len) ==
true;
} catch (...) {
if (logger != NULL)
logger->log(ERROR_LEVEL, ER_KEYRING_FAILED_TO_GENERATE_KEY);
return true;
}
}
static void mysql_key_iterator_init(void **key_iterator) {
*key_iterator = new Keys_iterator(logger.get());
if (mysql_key_iterator_init<keyring::Key>(
static_cast<Keys_iterator *>(*key_iterator), "keyring_file") ==
true) {
delete static_cast<Keys_iterator *>(*key_iterator);
*key_iterator = nullptr;
}
}
static void mysql_key_iterator_deinit(void *key_iterator) {
mysql_key_iterator_deinit<keyring::Key>(
static_cast<Keys_iterator *>(key_iterator), "keyring_file");
delete static_cast<Keys_iterator *>(key_iterator);
}
static bool mysql_key_iterator_get_key(void *key_iterator, char *key_id,
char *user_id) {
return mysql_key_iterator_get_key<keyring::Key>(
static_cast<Keys_iterator *>(key_iterator), key_id, user_id,
"keyring_file");
}
/* Plugin type-specific descriptor */
static struct st_mysql_keyring keyring_descriptor = {
MYSQL_KEYRING_INTERFACE_VERSION,
mysql_key_store,
mysql_key_fetch,
mysql_key_remove,
mysql_key_generate,
mysql_key_iterator_init,
mysql_key_iterator_deinit,
mysql_key_iterator_get_key};
mysql_declare_plugin(keyring_file){
MYSQL_KEYRING_PLUGIN, /* type */
&keyring_descriptor, /* descriptor */
"keyring_file", /* name */
"Oracle Corporation", /* author */
"store/fetch authentication data to/from a flat file", /* description */
PLUGIN_LICENSE_GPL,
keyring_init, /* init function (when loaded) */
NULL, /* check uninstall function */
keyring_deinit, /* deinit function (when unloaded) */
0x0100, /* version */
NULL, /* status variables */
keyring_file_system_variables, /* system variables */
NULL,
PLUGIN_OPT_ALLOW_EARLY,
} mysql_declare_plugin_end;