Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

Commit bee2a1f

Browse files
committed
WL#13075: Support TLS session reuse in the C API
RB#27093
1 parent 4a17d55 commit bee2a1f

63 files changed

Lines changed: 1642 additions & 260 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎client/base/mysql_connection_options.cc‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2014, 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2014, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -214,6 +214,11 @@ MYSQL *Mysql_connection_options::create_connection() {
214214
return nullptr;
215215
}
216216

217+
if (this->m_ssl_options_provider.check_connection(connection)) {
218+
mysql_close(connection);
219+
return nullptr;
220+
}
221+
217222
/* Reset auto-commit to the default */
218223
if (mysql_autocommit(connection, true)) {
219224
this->db_error(connection, "while resetting auto-commit");

‎client/base/mysql_connection_options.h‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2014, 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2014, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -63,6 +63,11 @@ class Mysql_connection_options : public Composite_options_provider,
6363
*/
6464
bool apply_for_connection(MYSQL *connection);
6565

66+
/**
67+
Checks the connection for SSL validity
68+
*/
69+
bool check_connection(MYSQL *connection);
70+
6671
private:
6772
std::optional<std::string> m_ssl_mode_string;
6873
std::optional<std::string> m_ssl_fips_mode_string;

‎client/base/ssl_options.cc‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2014, 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2014, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -69,6 +69,13 @@ void Mysql_connection_options::Ssl_options::create_options() {
6969
->add_callback(new std::function<void(char *)>(std::bind(
7070
&Mysql_connection_options::Ssl_options::fips_mode_option_callback,
7171
this, _1)));
72+
this->create_new_option(
73+
&::opt_ssl_session_data, "ssl-session-data",
74+
"Session data file to use to enable ssl session reuse");
75+
this->create_new_option(&::opt_ssl_session_data_continue_on_failed_reuse,
76+
"ssl-session-data-continue-on-failed-reuse",
77+
"If set to ON, this option will allow connection to "
78+
"succeed even if session data cannot be reused.");
7279
}
7380

7481
void Mysql_connection_options::Ssl_options::ca_option_callback(char *argument [
@@ -96,3 +103,9 @@ bool Mysql_connection_options::Ssl_options::apply_for_connection(
96103
}
97104
return false;
98105
}
106+
107+
bool Mysql_connection_options::Ssl_options::check_connection(
108+
MYSQL *connection) {
109+
return ssl_client_check_post_connect_ssl_setup(
110+
connection, [](const char *err) { std::cerr << err << std::endl; });
111+
}

���client/client_priv.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2001, 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2001, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -180,6 +180,8 @@ enum options_client {
180180
OPT_DELETE_MASTER_LOGS_DEPRECATED,
181181
OPT_MYSQLDUMP_SLAVE_DATA_DEPRECATED,
182182
OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT_DEPRECATED,
183+
OPT_SSL_SESSION_DATA,
184+
OPT_SSL_SESSION_DATA_CONTINUE_ON_FAILED_REUSE,
183185
/* Add new option above this */
184186
OPT_MAX_CLIENT_OPTION
185187
};

‎client/migrate_keyring/options.cc‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2021, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -42,6 +42,9 @@
4242
#include "options.h"
4343
#include "utilities.h"
4444

45+
/* TLS variables */
46+
#include "sslopt-vars.h"
47+
4548
namespace options {
4649

4750
/** MEM_ROOT for arguments */
@@ -66,6 +69,8 @@ enum migration_options {
6669
OPT_SSL_FIPS_MODE,
6770
OPT_TLS_CIPHERSUITES,
6871
OPT_SERVER_PUBLIC_KEY,
72+
OPT_SSL_SESSION_DATA,
73+
OPT_SSL_SESSION_DATA_CONTINUE_ON_FAILED_REUSE,
6974
/* Add new value above this */
7075
OPT_LAST
7176
};
@@ -85,8 +90,6 @@ char *Options::s_password = nullptr;
8590
char *Options::s_socket = nullptr;
8691
bool Options::s_tty_password = false;
8792

88-
/* TLS variables */
89-
#include "sslopt-vars.h"
9093
/* Caching sha2 password variables */
9194
#include "caching_sha2_passwordopt-vars.h"
9295

@@ -333,6 +336,10 @@ Mysql_connection::Mysql_connection(bool connect) : ok_(false), mysql(nullptr) {
333336
<< mysql_error(mysql) << std::endl;
334337
return;
335338
}
339+
if (ssl_client_check_post_connect_ssl_setup(
340+
mysql, [](const char *err) { log_error << err << std::endl; }))
341+
return;
342+
336343
log_info << "Successfully connected to MySQL server" << std::endl;
337344

338345
ok_ = true;

‎client/mysql.cc‎

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -237,6 +237,7 @@ static char *opt_oci_config_file = nullptr;
237237
#include "sslopt-vars.h"
238238

239239
const char *default_dbug_option = "d:t:o,/tmp/mysql.trace";
240+
static void *ssl_session_data = nullptr;
240241

241242
/*
242243
completion_hash is an auxiliary feature for mysql client to complete
@@ -313,7 +314,8 @@ static int com_quit(String *str, char *), com_go(String *str, char *),
313314
com_prompt(String *str, char *), com_delimiter(String *str, char *),
314315
com_warnings(String *str, char *), com_nowarnings(String *str, char *),
315316
com_resetconnection(String *str, char *),
316-
com_query_attributes(String *str, char *);
317+
com_query_attributes(String *str, char *),
318+
com_ssl_session_data_print(String *str, char *);
317319
static int com_shell(String *str, char *);
318320

319321
#ifdef USE_POPEN
@@ -328,6 +330,7 @@ static const char *server_version_string(MYSQL *mysql);
328330
static int put_info(const char *str, INFO_TYPE info, uint error = 0,
329331
const char *sql_state = nullptr);
330332
static int put_error(MYSQL *mysql);
333+
static void put_error_if_any(MYSQL *mysql);
331334
static void safe_put_field(const char *pos, ulong length);
332335
static void xmlencode_print(const char *src, uint length);
333336
static void init_pager();
@@ -409,6 +412,8 @@ static COMMANDS commands[] = {
409412
{"query_attributes", 0, com_query_attributes, true,
410413
"Sets string parameters (name1 value1 name2 value2 ...) for the next "
411414
"query to pick up."},
415+
{"ssl_session_data_print", 0, com_ssl_session_data_print, true,
416+
"Serializes the current SSL session data to stdout or file"},
412417
/* Get bash-like expansion for some commands */
413418
{"create table", 0, nullptr, false, ""},
414419
{"create database", 0, nullptr, false, ""},
@@ -1456,6 +1461,7 @@ void mysql_end(int sig) {
14561461
signal(SIGHUP, SIG_IGN);
14571462
#endif
14581463

1464+
if (ssl_session_data) mysql_free_ssl_session_data(&mysql, ssl_session_data);
14591465
mysql_close(&mysql);
14601466
#ifdef HAVE_READLINE
14611467
if (!status.batch && !quick && histfile && histfile[0]) {
@@ -4410,6 +4416,43 @@ static int com_query_attributes(String *buffer [[maybe_unused]], char *line) {
44104416
return 0;
44114417
}
44124418

4419+
static int com_ssl_session_data_print(String *buffer [[maybe_unused]],
4420+
char *line) {
4421+
char msgbuf[256];
4422+
char *param = get_arg(line, false);
4423+
const char *err_text = nullptr;
4424+
FILE *fo = nullptr;
4425+
void *data = nullptr;
4426+
4427+
if (param) {
4428+
if (nullptr == (fo = fopen(param, "w"))) {
4429+
err_text = "Failed to open the output file";
4430+
goto end;
4431+
}
4432+
} else
4433+
fo = stdout;
4434+
4435+
data = mysql_get_ssl_session_data(&mysql, 0, nullptr);
4436+
if (!data) {
4437+
err_text = nullptr;
4438+
put_error(&mysql);
4439+
goto end;
4440+
}
4441+
if (0 > fputs(reinterpret_cast<char *>(data), fo)) {
4442+
snprintf(msgbuf, sizeof(msgbuf), "Write of session data failed: %d (%s)",
4443+
errno, strerror(errno));
4444+
err_text = &msgbuf[0];
4445+
goto end;
4446+
}
4447+
if (fo == stdout) fputs("\n", fo);
4448+
4449+
end:
4450+
if (data) mysql_free_ssl_session_data(&mysql, data);
4451+
if (fo && fo != stdout) fclose(fo);
4452+
if (err_text) return put_info(err_text, INFO_ERROR);
4453+
return 0;
4454+
}
4455+
44134456
/*
44144457
Gets argument from a command on the command line. If get_next_arg is
44154458
not defined, skips the command and returns the first argument. The
@@ -4488,7 +4531,7 @@ static int sql_real_connect(char *host, char *database, char *user, char *,
44884531

44894532
mysql_init(&mysql);
44904533
if (init_connection_options(&mysql)) {
4491-
(void)put_error(&mysql);
4534+
put_error_if_any(&mysql);
44924535
(void)fflush(stdout);
44934536
return ignore_errors ? -1 : 1;
44944537
}
@@ -4573,6 +4616,18 @@ static int sql_real_connect(char *host, char *database, char *user, char *,
45734616
}
45744617
#endif
45754618

4619+
if (ssl_client_check_post_connect_ssl_setup(
4620+
&mysql, [](const char *err) { put_info(err, INFO_ERROR); }))
4621+
return 1;
4622+
4623+
void *new_ssl_session_data = mysql_get_ssl_session_data(&mysql, 0, nullptr);
4624+
if (new_ssl_session_data != nullptr) {
4625+
if (ssl_session_data != nullptr)
4626+
mysql_free_ssl_session_data(&mysql, ssl_session_data);
4627+
ssl_session_data = new_ssl_session_data;
4628+
} else {
4629+
DBUG_PRINT("error", ("unable to save SSL session"));
4630+
}
45764631
#ifdef _WIN32
45774632
/* Convert --execute buffer from UTF8MB4 to connection character set */
45784633
if (!execute_buffer_conversion_done && status.line_buff &&
@@ -4642,6 +4697,10 @@ static bool init_connection_options(MYSQL *mysql) {
46424697
tee_fprintf(stdout, "%s", SSL_SET_OPTIONS_ERROR);
46434698
return true;
46444699
}
4700+
4701+
if (ssl_session_data)
4702+
mysql_options(mysql, MYSQL_OPT_SSL_SESSION_DATA, ssl_session_data);
4703+
46454704
if (opt_protocol)
46464705
mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char *)&opt_protocol);
46474706

@@ -4815,6 +4874,8 @@ static int com_status(String *buffer [[maybe_unused]],
48154874
tee_fprintf(stdout, "UNIX socket:\t\t%s\n", mysql.unix_socket);
48164875
if (mysql.net.compress) tee_fprintf(stdout, "Protocol:\t\tCompressed\n");
48174876
if (opt_binhex) tee_fprintf(stdout, "Binary data as:\t\tHexadecimal\n");
4877+
if (mysql_get_ssl_session_reused(&mysql))
4878+
tee_fprintf(stdout, "SSL session reused:\ttrue\n");
48184879

48194880
if ((status_str = mysql_stat(&mysql)) && !mysql_error(&mysql)[0]) {
48204881
ulong sec;
@@ -4934,6 +4995,19 @@ static int put_error(MYSQL *con) {
49344995
mysql_sqlstate(con));
49354996
}
49364997

4998+
/**
4999+
Prints the SQL error, if any
5000+
5001+
Similar to @ref put_error, but prints the error only if there is any.
5002+
5003+
@param con the connection to check for errors
5004+
*/
5005+
static void put_error_if_any(MYSQL *con) {
5006+
const char *err = mysql_error(con);
5007+
if (err && *err)
5008+
put_info(err, INFO_ERROR, mysql_errno(con), mysql_sqlstate(con));
5009+
}
5010+
49375011
static void remove_cntrl(String *buffer) {
49385012
const char *start = buffer->ptr();
49395013
const char *end = start + buffer->length();

‎client/mysqladmin.cc‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -582,6 +582,10 @@ static bool sql_connect(MYSQL *mysql, uint wait) {
582582
for (;;) {
583583
if (mysql_real_connect(mysql, host, user, nullptr, NullS, tcp_port,
584584
unix_port, CLIENT_REMEMBER_OPTIONS)) {
585+
if (ssl_client_check_post_connect_ssl_setup(
586+
mysql, [](const char *err) { fprintf(stderr, "%s\n", err); }))
587+
return true;
588+
585589
mysql->reconnect = true;
586590
if (info) {
587591
fputs("\n", stderr);

‎client/mysqlbinlog.cc‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -2364,6 +2364,10 @@ static Exit_status safe_connect() {
23642364
error("Failed on connect: %s", mysql_error(mysql));
23652365
return ERROR_STOP;
23662366
}
2367+
2368+
if (ssl_client_check_post_connect_ssl_setup(
2369+
mysql, [](const char *err) { error("%s", err); }))
2370+
return ERROR_STOP;
23672371
mysql->reconnect = true;
23682372
return OK_CONTINUE;
23692373
}

‎client/mysqldump.cc‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -1601,6 +1601,10 @@ static int connect_to_db(char *host, char *user) {
16011601
DB_error(&mysql_connection, "when trying to connect");
16021602
return 1;
16031603
}
1604+
1605+
if (ssl_client_check_post_connect_ssl_setup(
1606+
mysql, [](const char *err) { fprintf(stderr, "%s\n", err); }))
1607+
return 1;
16041608
if (mysql_get_server_version(&mysql_connection) < 40100) {
16051609
/* Don't dump SET NAMES with a pre-4.1 server (bug#7997). */
16061610
opt_set_charset = false;

‎client/mysqlimport.cc‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2+
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -472,6 +472,11 @@ static MYSQL *db_connect(char *host, char *database, char *user, char *) {
472472
if (mysql) mysql_close(mysql);
473473
return nullptr;
474474
}
475+
if (ssl_client_check_post_connect_ssl_setup(
476+
mysql, [](const char *err) { fprintf(stderr, "%s\n", err); })) {
477+
if (mysql) mysql_close(mysql);
478+
return nullptr;
479+
}
475480
mysql->reconnect = false;
476481
if (verbose) fprintf(stdout, "Selecting database %s\n", database);
477482
if (mysql_select_db(mysql, database)) {

0 commit comments

Comments
 (0)