11/*
2- Copyright (c) 2000, 2021 , Oracle and/or its affiliates.
2+ Copyright (c) 2000, 2022 , Oracle and/or its affiliates.
33
44This program is free software; you can redistribute it and/or modify
55it 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
239239const 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 *);
317319static int com_shell (String *str, char *);
318320
319321#ifdef USE_POPEN
@@ -328,6 +330,7 @@ static const char *server_version_string(MYSQL *mysql);
328330static int put_info (const char *str, INFO_TYPE info, uint error = 0 ,
329331 const char *sql_state = nullptr );
330332static int put_error (MYSQL *mysql);
333+ static void put_error_if_any (MYSQL *mysql);
331334static void safe_put_field (const char *pos, ulong length);
332335static void xmlencode_print (const char *src, uint length);
333336static 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\t Compressed\n " );
48174876 if (opt_binhex) tee_fprintf (stdout, " Binary data as:\t\t Hexadecimal\n " );
4877+ if (mysql_get_ssl_session_reused (&mysql))
4878+ tee_fprintf (stdout, " SSL session reused:\t true\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+
49375011static void remove_cntrl (String *buffer) {
49385012 const char *start = buffer->ptr ();
49395013 const char *end = start + buffer->length ();
0 commit comments