|
27 | 27 |
|
28 | 28 | #include "m_ctype.h" |
29 | 29 | #include "my_dbug.h" |
| 30 | +#include "my_dir.h" |
30 | 31 | #include "my_inttypes.h" |
31 | 32 | #include "my_loglevel.h" |
32 | 33 | #if !defined(HAVE_WOLFSSL) && !defined(HAVE_PSI_INTERFACE) |
@@ -189,48 +190,117 @@ const char *sslGetErrString(enum enum_ssl_init_error e) { |
189 | 190 | return ssl_error_string[e]; |
190 | 191 | } |
191 | 192 |
|
| 193 | +static bool check_same_file(const char *cert_file, const char *key_file) { |
| 194 | + MY_STAT cert_stat; |
| 195 | + MY_STAT key_stat; |
| 196 | + |
| 197 | + if (!my_stat(cert_file, &cert_stat, MYF(0)) || |
| 198 | + !my_stat(key_file, &key_stat, MYF(0))) { |
| 199 | + DBUG_PRINT("error", ("Unable to stat the files.")); |
| 200 | + return false; |
| 201 | + } |
| 202 | + |
| 203 | + return cert_stat.st_ino == key_stat.st_ino && |
| 204 | + cert_stat.st_dev == key_stat.st_dev; |
| 205 | +} |
| 206 | + |
| 207 | +static int vio_load_cert(SSL_CTX *ctx, const char *cert_file, BIO *bio) { |
| 208 | + X509 *cert = NULL; |
| 209 | + |
| 210 | + if (BIO_read_filename(bio, cert_file) != 1 || |
| 211 | + !PEM_read_bio_X509(bio, &cert, NULL, NULL)) { |
| 212 | + return 1; |
| 213 | + } |
| 214 | + |
| 215 | + int ret = SSL_CTX_use_certificate(ctx, cert); |
| 216 | + X509_free(cert); |
| 217 | + |
| 218 | + return ret <= 0; |
| 219 | +} |
| 220 | + |
| 221 | +static int vio_load_key(SSL_CTX *ctx, const char *key_file, bool same_file, |
| 222 | + BIO *bio) { |
| 223 | + // read key file if not in same file as cert |
| 224 | + if (!same_file) { |
| 225 | + if (BIO_read_filename(bio, key_file) != 1) { |
| 226 | + DBUG_PRINT("error", ("BIO_WRITE for key %s failed", key_file)); |
| 227 | + return 1; |
| 228 | + } |
| 229 | + } else { |
| 230 | + if (BIO_reset(bio) < 0) { |
| 231 | + DBUG_PRINT("error", ("BIO_reset failed ret")); |
| 232 | + return 1; |
| 233 | + } |
| 234 | + } |
| 235 | + |
| 236 | + EVP_PKEY *key = NULL; |
| 237 | + if (!PEM_read_bio_PrivateKey(bio, &key, NULL, NULL)) return 1; |
| 238 | + |
| 239 | + int ret = SSL_CTX_use_PrivateKey(ctx, key); |
| 240 | + EVP_PKEY_free(key); |
| 241 | + |
| 242 | + return ret <= 0; |
| 243 | +} |
| 244 | + |
192 | 245 | static int vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, |
193 | 246 | const char *key_file, |
194 | 247 | enum enum_ssl_init_error *error) { |
195 | 248 | DBUG_ENTER("vio_set_cert_stuff"); |
196 | 249 | DBUG_PRINT("enter", ("ctx: %p cert_file: %s key_file: %s", ctx, cert_file, |
197 | 250 | key_file)); |
198 | 251 |
|
199 | | - if (!cert_file && key_file) cert_file = key_file; |
| 252 | + *error = SSL_INITERR_NOERROR; |
| 253 | + bool same_file = false; |
200 | 254 |
|
201 | | - if (!key_file && cert_file) key_file = cert_file; |
| 255 | + if (cert_file == NULL) { |
| 256 | + if (key_file == NULL) DBUG_RETURN(0); |
202 | 257 |
|
203 | | - if (cert_file && |
204 | | - SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) { |
205 | | - *error = SSL_INITERR_CERT; |
206 | | - DBUG_PRINT("error", |
207 | | - ("%s from file '%s'", sslGetErrString(*error), cert_file)); |
208 | | - DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); |
209 | | - my_message_local(ERROR_LEVEL, EE_SSL_ERROR_FROM_FILE, |
210 | | - sslGetErrString(*error), cert_file); |
211 | | - DBUG_RETURN(1); |
212 | | - } |
| 258 | + cert_file = key_file; |
| 259 | + same_file = true; |
| 260 | + } else if (key_file == NULL) { |
| 261 | + key_file = cert_file; |
| 262 | + same_file = true; |
| 263 | + } else |
| 264 | + same_file = check_same_file(key_file, cert_file); |
213 | 265 |
|
214 | | - if (key_file && |
215 | | - SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { |
216 | | - *error = SSL_INITERR_KEY; |
217 | | - DBUG_PRINT("error", |
218 | | - ("%s from file '%s'", sslGetErrString(*error), key_file)); |
219 | | - DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); |
220 | | - my_message_local(ERROR_LEVEL, EE_SSL_ERROR_FROM_FILE, |
221 | | - sslGetErrString(*error), key_file); |
222 | | - DBUG_RETURN(1); |
| 266 | + const char *error_file = NULL; |
| 267 | + BIO *bio = BIO_new(BIO_s_file()); |
| 268 | + if (bio == NULL) |
| 269 | + *error = SSL_INITERR_MEMFAIL; |
| 270 | + else { |
| 271 | + // load the cert |
| 272 | + if (vio_load_cert(ctx, cert_file, bio)) { |
| 273 | + *error = SSL_INITERR_CERT; |
| 274 | + error_file = cert_file; |
| 275 | + } |
| 276 | + // load the key |
| 277 | + else if (vio_load_key(ctx, key_file, same_file, bio)) { |
| 278 | + *error = SSL_INITERR_KEY; |
| 279 | + error_file = key_file; |
| 280 | + } |
| 281 | + |
| 282 | + /* |
| 283 | + If we are using DSA, we can copy the parameters from the private key |
| 284 | + Now we know that a key and cert have been set against the SSL context |
| 285 | + */ |
| 286 | + else if (!SSL_CTX_check_private_key(ctx)) { |
| 287 | + *error = SSL_INITERR_NOMATCH; |
| 288 | + } |
| 289 | + |
| 290 | + BIO_free_all(bio); |
223 | 291 | } |
224 | 292 |
|
225 | | - /* |
226 | | - If we are using DSA, we can copy the parameters from the private key |
227 | | - Now we know that a key and cert have been set against the SSL context |
228 | | - */ |
229 | | - if (cert_file && !SSL_CTX_check_private_key(ctx)) { |
230 | | - *error = SSL_INITERR_NOMATCH; |
231 | | - DBUG_PRINT("error", ("%s", sslGetErrString(*error))); |
| 293 | + if (*error != SSL_INITERR_NOERROR) { |
| 294 | + char err_string[MYSQL_ERRMSG_SIZE]; |
| 295 | + if (error_file) |
| 296 | + snprintf(err_string, sizeof(err_string), "%s from '%s'", |
| 297 | + sslGetErrString(*error), error_file); |
| 298 | + else |
| 299 | + snprintf(err_string, sizeof(err_string), "%s", sslGetErrString(*error)); |
| 300 | + DBUG_PRINT("error", ("%s", err_string)); |
232 | 301 | DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); |
233 | | - my_message_local(ERROR_LEVEL, EE_SSL_ERROR, sslGetErrString(*error)); |
| 302 | + my_message_local(ERROR_LEVEL, EE_SSL_ERROR_FROM_FILE, |
| 303 | + sslGetErrString(*error), cert_file); |
234 | 304 | DBUG_RETURN(1); |
235 | 305 | } |
236 | 306 |
|
|
0 commit comments