forked from trdtnguyen/mysql-plnvm
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathkeyring.cc
213 lines (189 loc) · 7.42 KB
/
keyring.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/* Copyright (c) 2016, 2017, 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 as published by
the Free Software Foundation; version 2 of the License.
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 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_global.h>
#include <mysql/plugin_keyring.h>
#include "keyring.h"
#include "buffered_file_io.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::Keys_container;
using keyring::Logger;
mysql_rwlock_t LOCK_keyring;
int check_keyring_file_data(MYSQL_THD thd MY_ATTRIBUTE((unused)),
struct st_mysql_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);
boost::movelib::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(MY_ERROR_LEVEL, "keyring_file_data cannot be set to new value"
" as the keyring file cannot be created/accessed in the provided path");
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 struct st_mysql_sys_var *keyring_file_system_variables[]= {
MYSQL_SYSVAR(data),
NULL
};
static int keyring_init(MYSQL_PLUGIN plugin_info)
{
try
{
#ifdef HAVE_PSI_INTERFACE
keyring_init_psi_keys();
#endif
if (init_keyring_locks())
return TRUE;
logger.reset(new Logger(plugin_info));
if (create_keyring_dir_if_does_not_exist(keyring_file_data_value))
{
logger->log(MY_ERROR_LEVEL, "Could not create keyring directory "
"The keyring_file will stay unusable until correct path to the keyring "
"directory gets provided");
return FALSE;
}
keys.reset(new Keys_container(logger.get()));
IKeyring_io *keyring_io= new Buffered_file_io(logger.get());
if (keys->init(keyring_io, keyring_file_data_value))
{
is_keys_container_initialized = FALSE;
logger->log(MY_ERROR_LEVEL, "keyring_file initialization failure. Please check"
" if the keyring_file_data points to readable keyring file or keyring file"
" can be created in the specified location. "
"The keyring_file will stay unusable until correct path to the keyring file "
"gets provided");
return FALSE;
}
is_keys_container_initialized = TRUE;
return FALSE;
}
catch (...)
{
if (logger != NULL)
logger->log(MY_ERROR_LEVEL, "keyring_file initialization failure due to internal"
" exception inside the plugin");
return TRUE;
}
}
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
keys.reset();
logger.reset();
keyring_file_data.reset();
mysql_rwlock_destroy(&LOCK_keyring);
return 0;
}
my_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");
}
my_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");
}
my_bool mysql_key_remove(const char *key_id, const char *user_id)
{
return mysql_key_remove<keyring::Key>(key_id, user_id, "keyring_file");
}
my_bool mysql_key_generate(const char *key_id, const char *key_type,
const char *user_id, size_t key_len)
{
try
{
boost::movelib::unique_ptr<IKey> key_candidate(new keyring::Key(key_id, key_type, user_id, NULL, 0));
boost::movelib::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(MY_ERROR_LEVEL, "Failed to generate a key due to internal exception inside keyring_file plugin");
return TRUE;
}
}
/* 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_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) */
keyring_deinit, /* deinit function (when unloaded) */
0x0100, /* version */
NULL, /* status variables */
keyring_file_system_variables, /* system variables */
NULL,
0,
}
mysql_declare_plugin_end;