1 /* Copyright (c) 2000, 2019, 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 Without limiting anything contained in the foregoing, this file,
15 which is part of C Driver for MySQL (Connector/C), is also subject to the
16 Universal FOSS Exception, version 1.0, a copy of which can be found at
17 http://oss.oracle.com/licenses/universal-foss-exception.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License, version 2.0, for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
27
28 #include "vio_priv.h"
29
30 #ifdef HAVE_OPENSSL
31
32 #define TLS_VERSION_OPTION_SIZE 256
33 #define SSL_CIPHER_LIST_SIZE 4096
34
35 static const char tls_ciphers_list[]="ECDHE-ECDSA-AES128-GCM-SHA256:"
36 "ECDHE-ECDSA-AES256-GCM-SHA384:"
37 "ECDHE-RSA-AES128-GCM-SHA256:"
38 "ECDHE-RSA-AES256-GCM-SHA384:"
39 "ECDHE-ECDSA-AES128-SHA256:"
40 "ECDHE-RSA-AES128-SHA256:"
41 "ECDHE-ECDSA-AES256-SHA384:"
42 "ECDHE-RSA-AES256-SHA384:"
43 "DHE-RSA-AES128-GCM-SHA256:"
44 "DHE-DSS-AES128-GCM-SHA256:"
45 "DHE-RSA-AES128-SHA256:"
46 "DHE-DSS-AES128-SHA256:"
47 "DHE-DSS-AES256-GCM-SHA384:"
48 "DHE-RSA-AES256-SHA256:"
49 "DHE-DSS-AES256-SHA256:"
50 "ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:"
51 "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:"
52 "DHE-DSS-AES128-SHA:DHE-RSA-AES128-SHA:"
53 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA:DHE-RSA-AES256-SHA:"
54 "AES128-GCM-SHA256:DH-DSS-AES128-GCM-SHA256:"
55 "ECDH-ECDSA-AES128-GCM-SHA256:AES256-GCM-SHA384:"
56 "DH-DSS-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:"
57 "AES128-SHA256:DH-DSS-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:AES256-SHA256:"
58 "DH-DSS-AES256-SHA256:ECDH-ECDSA-AES256-SHA384:AES128-SHA:"
59 "DH-DSS-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES256-SHA:"
60 "DH-DSS-AES256-SHA:ECDH-ECDSA-AES256-SHA:DHE-RSA-AES256-GCM-SHA384:"
61 "DH-RSA-AES128-GCM-SHA256:ECDH-RSA-AES128-GCM-SHA256:DH-RSA-AES256-GCM-SHA384:"
62 "ECDH-RSA-AES256-GCM-SHA384:DH-RSA-AES128-SHA256:"
63 "ECDH-RSA-AES128-SHA256:DH-RSA-AES256-SHA256:"
64 "ECDH-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:"
65 "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA:"
66 "ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES128-SHA:DHE-RSA-AES128-SHA:"
67 "TLS_DHE_DSS_WITH_AES_256_CBC_SHA:DHE-RSA-AES256-SHA:"
68 "AES128-SHA:DH-DSS-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES256-SHA:"
69 "DH-DSS-AES256-SHA:ECDH-ECDSA-AES256-SHA:DH-RSA-AES128-SHA:"
70 "ECDH-RSA-AES128-SHA:DH-RSA-AES256-SHA:ECDH-RSA-AES256-SHA:DES-CBC3-SHA";
71 static const char tls_cipher_blocked[]= "!aNULL:!eNULL:!EXPORT:!LOW:!MD5:!DES:!RC2:!RC4:!PSK:"
72 "!DHE-DSS-DES-CBC3-SHA:!DHE-RSA-DES-CBC3-SHA:"
73 "!ECDH-RSA-DES-CBC3-SHA:!ECDH-ECDSA-DES-CBC3-SHA:"
74 "!ECDHE-RSA-DES-CBC3-SHA:!ECDHE-ECDSA-DES-CBC3-SHA:";
75
76
77 static my_bool ssl_algorithms_added = FALSE;
78 static my_bool ssl_error_strings_loaded= FALSE;
79
80 /*
81 Diffie-Hellman key.
82 Generated using: >openssl dhparam -5 -C 2048
83
84 -----BEGIN DH PARAMETERS-----
85 MIIBCAKCAQEAil36wGZ2TmH6ysA3V1xtP4MKofXx5n88xq/aiybmGnReZMviCPEJ
86 46+7VCktl/RZ5iaDH1XNG1dVQmznt9pu2G3usU+k1/VB4bQL4ZgW4u0Wzxh9PyXD
87 glm99I9Xyj4Z5PVE4MyAsxCRGA1kWQpD9/zKAegUBPLNqSo886Uqg9hmn8ksyU9E
88 BV5eAEciCuawh6V0O+Sj/C3cSfLhgA0GcXp3OqlmcDu6jS5gWjn3LdP1U0duVxMB
89 h/neTSCSvtce4CAMYMjKNVh9P1nu+2d9ZH2Od2xhRIqMTfAS1KTqF3VmSWzPFCjG
90 mjxx/bg6bOOjpgZapvB6ABWlWmRmAAWFtwIBBQ==
91 -----END DH PARAMETERS-----
92 */
93 static unsigned char dh2048_p[]=
94 {
95 0x8A, 0x5D, 0xFA, 0xC0, 0x66, 0x76, 0x4E, 0x61, 0xFA, 0xCA, 0xC0, 0x37,
96 0x57, 0x5C, 0x6D, 0x3F, 0x83, 0x0A, 0xA1, 0xF5, 0xF1, 0xE6, 0x7F, 0x3C,
97 0xC6, 0xAF, 0xDA, 0x8B, 0x26, 0xE6, 0x1A, 0x74, 0x5E, 0x64, 0xCB, 0xE2,
98 0x08, 0xF1, 0x09, 0xE3, 0xAF, 0xBB, 0x54, 0x29, 0x2D, 0x97, 0xF4, 0x59,
99 0xE6, 0x26, 0x83, 0x1F, 0x55, 0xCD, 0x1B, 0x57, 0x55, 0x42, 0x6C, 0xE7,
100 0xB7, 0xDA, 0x6E, 0xD8, 0x6D, 0xEE, 0xB1, 0x4F, 0xA4, 0xD7, 0xF5, 0x41,
101 0xE1, 0xB4, 0x0B, 0xE1, 0x98, 0x16, 0xE2, 0xED, 0x16, 0xCF, 0x18, 0x7D,
102 0x3F, 0x25, 0xC3, 0x82, 0x59, 0xBD, 0xF4, 0x8F, 0x57, 0xCA, 0x3E, 0x19,
103 0xE4, 0xF5, 0x44, 0xE0, 0xCC, 0x80, 0xB3, 0x10, 0x91, 0x18, 0x0D, 0x64,
104 0x59, 0x0A, 0x43, 0xF7, 0xFC, 0xCA, 0x01, 0xE8, 0x14, 0x04, 0xF2, 0xCD,
105 0xA9, 0x2A, 0x3C, 0xF3, 0xA5, 0x2A, 0x83, 0xD8, 0x66, 0x9F, 0xC9, 0x2C,
106 0xC9, 0x4F, 0x44, 0x05, 0x5E, 0x5E, 0x00, 0x47, 0x22, 0x0A, 0xE6, 0xB0,
107 0x87, 0xA5, 0x74, 0x3B, 0xE4, 0xA3, 0xFC, 0x2D, 0xDC, 0x49, 0xF2, 0xE1,
108 0x80, 0x0D, 0x06, 0x71, 0x7A, 0x77, 0x3A, 0xA9, 0x66, 0x70, 0x3B, 0xBA,
109 0x8D, 0x2E, 0x60, 0x5A, 0x39, 0xF7, 0x2D, 0xD3, 0xF5, 0x53, 0x47, 0x6E,
110 0x57, 0x13, 0x01, 0x87, 0xF9, 0xDE, 0x4D, 0x20, 0x92, 0xBE, 0xD7, 0x1E,
111 0xE0, 0x20, 0x0C, 0x60, 0xC8, 0xCA, 0x35, 0x58, 0x7D, 0x3F, 0x59, 0xEE,
112 0xFB, 0x67, 0x7D, 0x64, 0x7D, 0x8E, 0x77, 0x6C, 0x61, 0x44, 0x8A, 0x8C,
113 0x4D, 0xF0, 0x12, 0xD4, 0xA4, 0xEA, 0x17, 0x75, 0x66, 0x49, 0x6C, 0xCF,
114 0x14, 0x28, 0xC6, 0x9A, 0x3C, 0x71, 0xFD, 0xB8, 0x3A, 0x6C, 0xE3, 0xA3,
115 0xA6, 0x06, 0x5A, 0xA6, 0xF0, 0x7A, 0x00, 0x15, 0xA5, 0x5A, 0x64, 0x66,
116 0x00, 0x05, 0x85, 0xB7,
117 };
118
119 static unsigned char dh2048_g[]={
120 0x05,
121 };
122
get_dh2048(void)123 static DH *get_dh2048(void)
124 {
125 DH *dh;
126 if ((dh=DH_new()))
127 {
128 BIGNUM *p= BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
129 BIGNUM *g= BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
130 if (!p || !g
131 #if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined( LIBRESSL_VERSION_NUMBER )
132 || !DH_set0_pqg(dh, p, NULL, g)
133 #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
134 ) {
135 /* DH_free() will free 'p' and 'g' at once. */
136 DH_free(dh);
137 return NULL;
138 }
139 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined( LIBRESSL_VERSION_NUMBER )
140 dh->p= p;
141 dh->g= g;
142 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
143 }
144 return(dh);
145 }
146
147
148 static void
report_errors()149 report_errors()
150 {
151 unsigned long l;
152 const char* file;
153 const char* data;
154 int line,flags;
155
156 DBUG_ENTER("report_errors");
157
158 while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
159 {
160 #ifndef DBUG_OFF /* Avoid warning */
161 char buf[200];
162 DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
163 file,line,(flags & ERR_TXT_STRING) ? data : "")) ;
164 #endif
165 }
166 DBUG_VOID_RETURN;
167 }
168
169 static const char*
170 ssl_error_string[] =
171 {
172 "No error",
173 "Unable to get certificate",
174 "Unable to get private key",
175 "Private key does not match the certificate public key",
176 "SSL_CTX_set_default_verify_paths failed",
177 "Failed to set ciphers to use",
178 "SSL_CTX_new failed",
179 "SSL_CTX_set_tmp_dh failed"
180 };
181
182 const char*
sslGetErrString(enum enum_ssl_init_error e)183 sslGetErrString(enum enum_ssl_init_error e)
184 {
185 DBUG_ASSERT(SSL_INITERR_NOERROR < e && e < SSL_INITERR_LASTERR);
186 return ssl_error_string[e];
187 }
188
189 static int
vio_set_cert_stuff(SSL_CTX * ctx,const char * cert_file,const char * key_file,enum enum_ssl_init_error * error)190 vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file,
191 enum enum_ssl_init_error* error)
192 {
193 DBUG_ENTER("vio_set_cert_stuff");
194 DBUG_PRINT("enter", ("ctx: 0x%lx cert_file: %s key_file: %s",
195 (long) ctx, cert_file, key_file));
196
197 if (!cert_file && key_file)
198 cert_file= key_file;
199
200 if (!key_file && cert_file)
201 key_file= cert_file;
202
203 if (cert_file &&
204 SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0)
205 {
206 *error= SSL_INITERR_CERT;
207 DBUG_PRINT("error",("%s from file '%s'", sslGetErrString(*error), cert_file));
208 DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
209 fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error),
210 cert_file);
211 fflush(stderr);
212 DBUG_RETURN(1);
213 }
214
215 if (key_file &&
216 SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0)
217 {
218 *error= SSL_INITERR_KEY;
219 DBUG_PRINT("error", ("%s from file '%s'", sslGetErrString(*error), key_file));
220 DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
221 fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error),
222 key_file);
223 fflush(stderr);
224 DBUG_RETURN(1);
225 }
226
227 /*
228 If we are using DSA, we can copy the parameters from the private key
229 Now we know that a key and cert have been set against the SSL context
230 */
231 if (cert_file && !SSL_CTX_check_private_key(ctx))
232 {
233 *error= SSL_INITERR_NOMATCH;
234 DBUG_PRINT("error", ("%s",sslGetErrString(*error)));
235 DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
236 fprintf(stderr, "SSL error: %s\n", sslGetErrString(*error));
237 fflush(stderr);
238 DBUG_RETURN(1);
239 }
240
241 DBUG_RETURN(0);
242 }
243
244
ssl_start()245 void ssl_start()
246 {
247 if (!ssl_algorithms_added)
248 {
249 ssl_algorithms_added= TRUE;
250 SSL_library_init();
251 OpenSSL_add_all_algorithms();
252
253 }
254
255 if (!ssl_error_strings_loaded)
256 {
257 ssl_error_strings_loaded= TRUE;
258 SSL_load_error_strings();
259 }
260 }
261
process_tls_version(const char * tls_version)262 long process_tls_version(const char *tls_version)
263 {
264 const char *separator= ",";
265 char *token, *lasts= NULL;
266
267 const char *tls_version_name_list[]= {"TLSv1"
268 #ifdef SSL_OP_NO_TLSv1_1
269 ,"TLSv1.1"
270 #endif
271 #ifdef SSL_OP_NO_TLSv1_2
272 ,"TLSv1.2"
273 #endif
274 };
275
276 const char ctx_flag_default[]=
277 #ifdef SSL_OP_NO_TLSv1_2
278 "TLSv1.1,TLSv1.2";
279 #elif defined(SSL_OP_NO_TLSv1_1)
280 "TLSv1.1";
281 #else
282 "TLSv1";
283 #endif
284
285 const long tls_ctx_list[]= {SSL_OP_NO_TLSv1
286 #ifdef SSL_OP_NO_TLSv1_1
287 ,SSL_OP_NO_TLSv1_1
288 #endif
289 #ifdef SSL_OP_NO_TLSv1_2
290 ,SSL_OP_NO_TLSv1_2
291 #endif
292 };
293 size_t tls_versions_count= sizeof(tls_ctx_list) / sizeof(tls_ctx_list[0]);
294 long tls_ctx_flag= 0;
295 unsigned int index= 0;
296 char tls_version_option[TLS_VERSION_OPTION_SIZE]= "";
297 int tls_found= 0;
298
299 for (index = 0; index < tls_versions_count; index++)
300 tls_ctx_flag|= tls_ctx_list[index];
301
302 if (!tls_version || !my_strcasecmp(&my_charset_latin1, tls_version,
303 ctx_flag_default))
304 return 0;
305
306 if (strlen(tls_version)-1 > sizeof(tls_version_option))
307 return -1;
308
309 strncpy(tls_version_option, tls_version, sizeof(tls_version_option));
310 token= my_strtok_r(tls_version_option, separator, &lasts);
311 while (token)
312 {
313 for (index=0; index < tls_versions_count; index++)
314 {
315 if (!my_strcasecmp(&my_charset_latin1, tls_version_name_list[index],
316 token))
317 {
318 tls_found= 1;
319 tls_ctx_flag= tls_ctx_flag & (~tls_ctx_list[index]);
320 break;
321 }
322 }
323 token= my_strtok_r(NULL, separator, &lasts);
324 }
325
326 if (!tls_found)
327 return -1;
328 else
329 return tls_ctx_flag;
330 }
331
332 /************************ VioSSLFd **********************************/
333 static struct st_VioSSLFd *
new_VioSSLFd(const char * key_file,const char * cert_file,const char * ca_file,const char * ca_path,const char * cipher,my_bool is_client,enum enum_ssl_init_error * error,const char * crl_file,const char * crl_path,const long ssl_ctx_flags)334 new_VioSSLFd(const char *key_file, const char *cert_file,
335 const char *ca_file, const char *ca_path,
336 const char *cipher, my_bool is_client,
337 enum enum_ssl_init_error *error,
338 const char *crl_file, const char *crl_path,
339 const long ssl_ctx_flags)
340 {
341 DH *dh;
342 struct st_VioSSLFd *ssl_fd;
343 /* MySQL 5.6 supports TLS up to v1.2, explicitly disable TLSv1.3. */
344 long ssl_ctx_options= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
345 #if !defined(LIBRESSL_VERSION_NUMBER) || defined(SSL_OP_NO_TLSv1_3)
346 #ifdef HAVE_TLSv13
347 SSL_OP_NO_TLSv1_3 |
348 #endif /* HAVE_TLSv13 */
349 #endif
350 SSL_OP_NO_TICKET;
351 int ret_set_cipherlist= 0;
352 char cipher_list[SSL_CIPHER_LIST_SIZE]= {0};
353 #if defined(OPENSSL_EC_NAMED_CURVE) && (OPENSSL_VERSION_NUMBER < 0x10002000L)
354 EC_KEY *ecdh;
355 #endif
356 DBUG_ENTER("new_VioSSLFd");
357 DBUG_PRINT("enter",
358 ("key_file: '%s' cert_file: '%s' ca_file: '%s' ca_path: '%s' "
359 "cipher: '%s' crl_file: '%s' crl_path: '%s' flags: '%lX'",
360 key_file ? key_file : "NULL",
361 cert_file ? cert_file : "NULL",
362 ca_file ? ca_file : "NULL",
363 ca_path ? ca_path : "NULL",
364 cipher ? cipher : "NULL",
365 crl_file ? crl_file : "NULL",
366 crl_path ? crl_path : "NULL",
367 ssl_ctx_flags));
368
369 if (ssl_ctx_flags < 0)
370 {
371 *error= SSL_TLS_VERSION_INVALID;
372 DBUG_PRINT("error", ("TLS version invalid : %s", sslGetErrString(*error)));
373 report_errors();
374 DBUG_RETURN(0);
375 }
376
377 ssl_ctx_options= (ssl_ctx_options | ssl_ctx_flags) &
378 (SSL_OP_NO_SSLv2 |
379 SSL_OP_NO_SSLv3 |
380 #if !defined(LIBRESSL_VERSION_NUMBER) || defined(SSL_OP_NO_TLSv1_3)
381 #ifdef HAVE_TLSv13
382 SSL_OP_NO_TLSv1_3 |
383 #endif /* HAVE_TLSv13 */
384 #endif
385 SSL_OP_NO_TLSv1
386 #ifdef SSL_OP_NO_TLSv1_1
387 | SSL_OP_NO_TLSv1_1
388 #endif
389 #ifdef SSL_OP_NO_TLSv1_2
390 | SSL_OP_NO_TLSv1_2
391 #endif
392 );
393
394 ssl_start();
395
396 if (!(ssl_fd= ((struct st_VioSSLFd*)
397 my_malloc(sizeof(struct st_VioSSLFd),MYF(0)))))
398 DBUG_RETURN(0);
399
400 if (!(ssl_fd->ssl_context= SSL_CTX_new(is_client ?
401 #if OPENSSL_VERSION_NUMBER < 0x10100000L
402 SSLv23_client_method() :
403 SSLv23_server_method()
404 #else /* OPENSSL_VERSION_NUMBER < 0x10100000L */
405 TLS_client_method() :
406 TLS_server_method()
407 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
408 )))
409 {
410 *error= SSL_INITERR_MEMFAIL;
411 DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
412 report_errors();
413 my_free(ssl_fd);
414 DBUG_RETURN(0);
415 }
416
417 SSL_CTX_set_options(ssl_fd->ssl_context, ssl_ctx_options);
418
419 #ifndef LIBRESSL_VERSION_NUMBER
420 #ifdef HAVE_TLSv13
421 /*
422 MySQL 5.6 doesn't support TLSv1.3 - set empty TLSv1.3 ciphersuites.
423 */
424 if (0 == SSL_CTX_set_ciphersuites(ssl_fd->ssl_context, ""))
425 {
426 *error = SSL_INITERR_CIPHERS;
427 DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
428 report_errors();
429 SSL_CTX_free(ssl_fd->ssl_context);
430 my_free(ssl_fd);
431 DBUG_RETURN(0);
432 }
433 #endif /* HAVE_TLSv13 */
434 #endif
435
436 /*
437 Set the ciphers that can be used
438 NOTE: SSL_CTX_set_cipher_list will return 0 if
439 none of the provided ciphers could be selected
440 */
441 DBUG_ASSERT(strlen(tls_cipher_blocked) + 1 <= sizeof(cipher_list));
442 strcat(cipher_list, tls_cipher_blocked);
443 if (cipher)
444 {
445 if (strlen(cipher_list) + strlen(cipher) + 1 > sizeof(cipher_list))
446 {
447 *error= SSL_INITERR_CIPHERS;
448 DBUG_PRINT("error", ("User specified cipher too long"));
449 SSL_CTX_free(ssl_fd->ssl_context);
450 my_free(ssl_fd);
451 DBUG_RETURN(0);
452 }
453 strcat(cipher_list, cipher);
454 }
455 else
456 {
457 DBUG_ASSERT(strlen(cipher_list) + strlen(tls_ciphers_list) + 1
458 <= sizeof(cipher_list));
459 strcat(cipher_list, tls_ciphers_list);
460 }
461
462 if (ret_set_cipherlist == SSL_CTX_set_cipher_list(ssl_fd->ssl_context,
463 cipher_list))
464 {
465 *error= SSL_INITERR_CIPHERS;
466 DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
467 report_errors();
468 SSL_CTX_free(ssl_fd->ssl_context);
469 my_free(ssl_fd);
470 DBUG_RETURN(0);
471 }
472
473 /* Load certs from the trusted ca */
474 if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) <= 0)
475 {
476 DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
477 if (ca_file || ca_path)
478 {
479 /* fail only if ca file or ca path were supplied and looking into
480 them fails. */
481 *error= SSL_INITERR_BAD_PATHS;
482 DBUG_PRINT("error", ("SSL_CTX_load_verify_locations failed : %s",
483 sslGetErrString(*error)));
484 report_errors();
485 SSL_CTX_free(ssl_fd->ssl_context);
486 my_free(ssl_fd);
487 DBUG_RETURN(0);
488 }
489
490 /* otherwise go use the defaults */
491 if (SSL_CTX_set_default_verify_paths(ssl_fd->ssl_context) == 0)
492 {
493 *error= SSL_INITERR_BAD_PATHS;
494 DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
495 report_errors();
496 SSL_CTX_free(ssl_fd->ssl_context);
497 my_free(ssl_fd);
498 DBUG_RETURN(0);
499 }
500 }
501
502 if (crl_file || crl_path)
503 {
504 X509_STORE *store= SSL_CTX_get_cert_store(ssl_fd->ssl_context);
505 /* Load crls from the trusted ca */
506 if (X509_STORE_load_locations(store, crl_file, crl_path) == 0 ||
507 X509_STORE_set_flags(store,
508 X509_V_FLAG_CRL_CHECK |
509 X509_V_FLAG_CRL_CHECK_ALL) == 0)
510 {
511 DBUG_PRINT("warning", ("X509_STORE_load_locations for CRL failed"));
512 *error= SSL_INITERR_BAD_PATHS;
513 DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
514 report_errors();
515 SSL_CTX_free(ssl_fd->ssl_context);
516 my_free(ssl_fd);
517 DBUG_RETURN(0);
518 }
519 }
520
521 if (vio_set_cert_stuff(ssl_fd->ssl_context, cert_file, key_file, error))
522 {
523 DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
524 report_errors();
525 SSL_CTX_free(ssl_fd->ssl_context);
526 my_free(ssl_fd);
527 DBUG_RETURN(0);
528 }
529
530 /* DH stuff */
531 dh= get_dh2048();
532 if (SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh) == 0)
533 {
534 *error= SSL_INITERR_DHFAIL;
535 DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
536 report_errors();
537 DH_free(dh);
538 SSL_CTX_free(ssl_fd->ssl_context);
539 my_free(ssl_fd);
540 DBUG_RETURN(0);
541 }
542 DH_free(dh);
543
544 #ifdef OPENSSL_EC_NAMED_CURVE
545 #if OPENSSL_VERSION_NUMBER < 0x10002000L
546 ecdh= EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
547 if (!ecdh)
548 {
549 *error= SSL_INITERR_DHFAIL;
550 DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
551 report_errors();
552 SSL_CTX_free(ssl_fd->ssl_context);
553 my_free(ssl_fd);
554 DBUG_RETURN(0);
555 }
556
557 if (SSL_CTX_set_tmp_ecdh(ssl_fd->ssl_context, ecdh) != 1)
558 {
559 *error= SSL_INITERR_DHFAIL;
560 DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
561 report_errors();
562 EC_KEY_free(ecdh);
563 SSL_CTX_free(ssl_fd->ssl_context);
564 my_free(ssl_fd);
565 DBUG_RETURN(0);
566 }
567 EC_KEY_free(ecdh);
568
569 #else /* OPENSSL_VERSION_NUMBER < 0x10002000L */
570
571 if (SSL_CTX_set_ecdh_auto(ssl_fd->ssl_context, 1) != 1)
572 {
573 *error= SSL_INITERR_DHFAIL;
574 DBUG_PRINT("error", ("%s", sslGetErrString(*error)));
575 report_errors();
576 SSL_CTX_free(ssl_fd->ssl_context);
577 my_free(ssl_fd);
578 DBUG_RETURN(0);
579 }
580 #endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */
581 #endif /* OPENSSL_EC_NAMED_CURVE */
582
583 DBUG_PRINT("exit", ("OK 1"));
584
585 DBUG_RETURN(ssl_fd);
586 }
587
588
589 /************************ VioSSLConnectorFd **********************************/
590 struct st_VioSSLFd *
new_VioSSLConnectorFd(const char * key_file,const char * cert_file,const char * ca_file,const char * ca_path,const char * cipher,enum enum_ssl_init_error * error,const char * crl_file,const char * crl_path,const long ssl_ctx_flags)591 new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
592 const char *ca_file, const char *ca_path,
593 const char *cipher, enum enum_ssl_init_error* error,
594 const char *crl_file, const char *crl_path,
595 const long ssl_ctx_flags)
596 {
597 struct st_VioSSLFd *ssl_fd;
598 int verify= SSL_VERIFY_PEER;
599
600 /*
601 Turn off verification of servers certificate if both
602 ca_file and ca_path is set to NULL
603 */
604 if (ca_file == 0 && ca_path == 0)
605 verify= SSL_VERIFY_NONE;
606
607 if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
608 ca_path, cipher, TRUE, error,
609 crl_file, crl_path, ssl_ctx_flags)))
610 {
611 return 0;
612 }
613
614 /* Init the VioSSLFd as a "connector" ie. the client side */
615
616 SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL);
617
618 return ssl_fd;
619 }
620
621
622 /************************ VioSSLAcceptorFd **********************************/
623 struct st_VioSSLFd *
new_VioSSLAcceptorFd(const char * key_file,const char * cert_file,const char * ca_file,const char * ca_path,const char * cipher,enum enum_ssl_init_error * error,const char * crl_file,const char * crl_path,const long ssl_ctx_flags)624 new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
625 const char *ca_file, const char *ca_path,
626 const char *cipher, enum enum_ssl_init_error* error,
627 const char *crl_file, const char *crl_path,
628 const long ssl_ctx_flags)
629 {
630 struct st_VioSSLFd *ssl_fd;
631 int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
632 if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
633 ca_path, cipher, FALSE, error,
634 crl_file, crl_path, ssl_ctx_flags)))
635 {
636 return 0;
637 }
638 /* Init the the VioSSLFd as a "acceptor" ie. the server side */
639
640 /* Set max number of cached sessions, returns the previous size */
641 SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128);
642
643 SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL);
644
645 /*
646 Set session_id - an identifier for this server session
647 Use the ssl_fd pointer
648 */
649 SSL_CTX_set_session_id_context(ssl_fd->ssl_context,
650 (const unsigned char *)ssl_fd,
651 sizeof(ssl_fd));
652
653 return ssl_fd;
654 }
655
free_vio_ssl_acceptor_fd(struct st_VioSSLFd * fd)656 void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd)
657 {
658 SSL_CTX_free(fd->ssl_context);
659 my_free(fd);
660 }
661 #endif /* HAVE_OPENSSL */
662