CVE-2015-3152 (published 2016-05-16T10:59Z)

Oracle MySQL before 5.7.3, Oracle MySQL Connector/C (aka libmysqlclient) before 6.1.3, and MariaDB before 5.5.44 use the --ssl option to mean that SSL is optional, which allows man-in-the-middle attackers to spoof servers via a cleartext-downgrade attack, aka a "BACKRONYM" attack.

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:P/A:N)
CVSS v3 base score: 5.9, MEDIUM (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-295
cwe_name: Improper Certificate Validation
description: The product does not validate, or incorrectly validates, a certificate.
extended_description: When a certificate is invalid or malicious, it might allow an attacker to spoof a trusted entity by interfering in the communication path between the host and client. The product might connect to a malicious host while believing it is a trusted host, or the product might be deceived into accepting spoofed data that appears to originate from a trusted host.
         

Fix information:
repo_url: https://github.com/mysql/mysql-server
commit_details: repo_url: https://github.com/mysql/mysql-server
author: Georgi Kodinov
author_date: 2013-10-31 11:35:15+02:00
msg: WL#6791 : Redefine client --ssl option to imply enforced encryption

# Changed the meaning of the --ssl=1 option of all client binaries
to mean force ssl, not try ssl and fail over to eunecrypted
# Added a new MYSQL_OPT_SSL_ENFORCE mysql_options()
option to specify that an ssl connection is required.
# Added a new macro SSL_SET_OPTIONS() to the client
SSL handling headers that sets all the relevant SSL options at 
once.
# Revamped all of the current native clients to use the new macro
# Removed some Windows line endings.
# Added proper handling of the new option into the ssl helper
headers.
# If SSL is mandatory assume that the media is secure enough 
for the sha256 plugin to do unencrypted password exchange even
before establishing a connection.
# Set the default ssl cipher to DHE-RSA-AES256-SHA if none is 
specified.
# updated test cases that require a non-default cipher to spawn 
a mysql command line tool binary since mysqltest has no support
for specifying ciphers.
# updated the replication slave connection code to always enforce
SSL if any of the SSL config options is present.
# test cases added and updated.
# added a mysql_get_option() API to return mysql_options() 
values. Used the new API inside the sha256 plugin.
# Fixed compilation warnings because of unused variables.
# Fixed test failures (mysql_ssl and bug13115401)
# Fixed whitespace issues.
# Fully implemented the mysql_get_option() function.
# Added a test case for mysql_get_option()
# fixed some trailing whitespace issues
# fixed some uint/int warnings in mysql_client_test.c
# removed shared memory option from non-windows get_options
 tests
# moved MYSQL_OPT_LOCAL_INFILE to the uint options
repository: repo_url: https://github.com/mysql/mysql-server
repo_name: mysql/mysql-server
description: MySQL Server, the world's most popular open source database, and MySQL Cluster, a real-time, open source transactional database.
repo_language: C++
owner: mysql
file_changes: filename: mysql.cc
change_type: ModificationType.MODIFY
diff: @@ -4953,17 +4953,7 @@ init_connection_options(MYSQL *mysql)
   if (using_opt_local_infile)
     mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, (char*) &opt_local_infile);
 
-#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
-  if (opt_use_ssl)
-  {
-    mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-		  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-  }
-  mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                (char*) &opt_ssl_verify_server_cert);
-#endif
+  SSL_SET_OPTIONS(mysql);
 
   if (opt_protocol)
     mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);

programming_language: C
filename: mysql_secure_installation.cc
change_type: ModificationType.MODIFY
diff: @@ -158,17 +158,7 @@ my_arguments_get_one_option(int optid,
 static void
 init_connection_options(MYSQL *mysql)
 {
-#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
-  if (opt_use_ssl)
-  {
-    mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-                  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-  }
-  mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                (char*) &opt_ssl_verify_server_cert);
-#endif
+  SSL_SET_OPTIONS(mysql);
 
   if (opt_protocol)
     mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);

programming_language: C
filename: mysql_upgrade.c
change_type: ModificationType.MODIFY
diff: @@ -288,7 +288,7 @@ get_one_option(int optid, const struct my_option *opt,
   case OPT_WRITE_BINLOG:                        /* --write-binlog */
     add_option= FALSE;
     break;
-
+#include <sslopt-case.h>
   case 'h': /* --host */
   case 'W': /* --pipe */
   case 'P': /* --port */

programming_language: C
filename: mysqladmin.cc
change_type: ModificationType.MODIFY
diff: @@ -361,17 +361,7 @@ int main(int argc,char *argv[])
     uint tmp=opt_connect_timeout;
     mysql_options(&mysql,MYSQL_OPT_CONNECT_TIMEOUT, (char*) &tmp);
   }
-#ifdef HAVE_OPENSSL
-  if (opt_use_ssl)
-  {
-    mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-		  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-  }
-  mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                (char*)&opt_ssl_verify_server_cert);
-#endif
+  SSL_SET_OPTIONS(&mysql);
   if (opt_protocol)
     mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 #if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)

programming_language: C
filename: mysqlbinlog.cc
change_type: ModificationType.MODIFY
diff: @@ -1885,17 +1885,7 @@ static Exit_status safe_connect()
     return ERROR_STOP;
   }
 
-#ifdef HAVE_OPENSSL
-  if (opt_use_ssl)
-  {
-    mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-                  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-  }
-  mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                (char*) &opt_ssl_verify_server_cert);
-#endif
+  SSL_SET_OPTIONS(mysql);
 
   if (opt_plugin_dir && *opt_plugin_dir)
     mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);

programming_language: C
filename: mysqlcheck.c
change_type: ModificationType.MODIFY
diff: @@ -881,15 +881,7 @@ static int dbConnect(char *host, char *user, char *passwd)
   mysql_init(&mysql_connection);
   if (opt_compress)
     mysql_options(&mysql_connection, MYSQL_OPT_COMPRESS, NullS);
-#ifdef HAVE_OPENSSL
-  if (opt_use_ssl)
-  {
-    mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-		  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-  }
-#endif
+  SSL_SET_OPTIONS(&mysql_connection);
   if (opt_protocol)
     mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
   if (opt_bind_addr)

programming_language: C
filename: mysqldump.c
change_type: ModificationType.MODIFY
diff: @@ -1595,17 +1595,7 @@ static int connect_to_db(char *host, char *user,char *passwd)
   mysql_init(&mysql_connection);
   if (opt_compress)
     mysql_options(&mysql_connection,MYSQL_OPT_COMPRESS,NullS);
-#ifdef HAVE_OPENSSL
-  if (opt_use_ssl)
-  {
-    mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-                  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(&mysql_connection, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-  }
-  mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                (char*)&opt_ssl_verify_server_cert);
-#endif
+  SSL_SET_OPTIONS(&mysql_connection);
   if (opt_protocol)
     mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
   if (opt_bind_addr)

programming_language: C
filename: mysqlimport.c
change_type: ModificationType.MODIFY
diff: @@ -420,17 +420,7 @@ static MYSQL *db_connect(char *host, char *database,
   if (opt_local_file)
     mysql_options(mysql,MYSQL_OPT_LOCAL_INFILE,
 		  (char*) &opt_local_file);
-#ifdef HAVE_OPENSSL
-  if (opt_use_ssl)
-  {
-    mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-		  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-  }
-  mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                (char*)&opt_ssl_verify_server_cert);
-#endif
+  SSL_SET_OPTIONS(mysql);
   if (opt_protocol)
     mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
   if (opt_bind_addr)

programming_language: C
filename: mysqlshow.c
change_type: ModificationType.MODIFY
diff: @@ -117,17 +117,7 @@ int main(int argc, char **argv)
   mysql_init(&mysql);
   if (opt_compress)
     mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
-#ifdef HAVE_OPENSSL
-  if (opt_use_ssl)
-  {
-    mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-		  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-  }
-  mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                (char*)&opt_ssl_verify_server_cert);
-#endif
+  SSL_SET_OPTIONS(&mysql);
   if (opt_protocol)
     mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
   if (opt_bind_addr)

programming_language: C
filename: mysqlslap.c
change_type: ModificationType.MODIFY
diff: @@ -144,8 +144,8 @@ static my_bool opt_compress= FALSE, tty_password= FALSE,
 const char *auto_generate_sql_type= "mixed";
 
 static unsigned long connect_flags= CLIENT_MULTI_RESULTS |
-                                    CLIENT_MULTI_STATEMENTS |
-                                    CLIENT_REMEMBER_OPTIONS;
+                                    CLIENT_MULTI_STATEMENTS |
+                                    CLIENT_REMEMBER_OPTIONS;
 
 
 static int verbose, delimiter_length;
@@ -335,15 +335,7 @@ int main(int argc, char **argv)
   mysql_init(&mysql);
   if (opt_compress)
     mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
-#ifdef HAVE_OPENSSL
-  if (opt_use_ssl)
-  {
-    mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-                  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-  }
-#endif
+  SSL_SET_OPTIONS(&mysql);
   if (opt_protocol)
     mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 #if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)

programming_language: C
filename: mysqltest.cc
change_type: ModificationType.MODIFY
diff: @@ -5507,6 +5507,9 @@ void do_connect(struct st_command *command)
   my_bool con_pipe= 0, con_shm= 0, con_cleartext_enable= 0;
   my_bool con_secure_auth= 1;
   struct st_connection* con_slot;
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+  my_bool save_opt_use_ssl= opt_use_ssl;
+#endif
 
   static DYNAMIC_STRING ds_connection_name;
   static DYNAMIC_STRING ds_host;
@@ -5641,23 +5644,22 @@ void do_connect(struct st_command *command)
 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
   if (opt_use_ssl)
     con_ssl= 1;
-#endif
 
-  if (con_ssl)
+  opt_use_ssl= con_ssl;
+
+  if (opt_use_ssl)
   {
-#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
-    mysql_ssl_set(&con_slot->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-		  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(&con_slot->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(&con_slot->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-#if MYSQL_VERSION_ID >= 50000
     /* Turn on ssl_verify_server_cert only if host is "localhost" */
     opt_ssl_verify_server_cert= !strcmp(ds_host.str, "localhost");
-    mysql_options(&con_slot->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                  &opt_ssl_verify_server_cert);
+  }
+#else
+  /* keep the compiler happy about con_ssl */
+  con_ssl = con_ssl ? TRUE : FALSE;
 #endif
+  SSL_SET_OPTIONS(&con_slot->mysql);
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+  opt_use_ssl= save_opt_use_ssl;
 #endif
-  }
 
   if (con_pipe)
   {
@@ -8764,22 +8766,16 @@ int main(int argc, char **argv)
     mysql_options(&con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
 #endif
 
-#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
   if (opt_use_ssl)
   {
-    mysql_ssl_set(&con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
-		  opt_ssl_capath, opt_ssl_cipher);
-    mysql_options(&con->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
-    mysql_options(&con->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
-#if MYSQL_VERSION_ID >= 50000
     /* Turn on ssl_verify_server_cert only if host is "localhost" */
     opt_ssl_verify_server_cert= opt_host && !strcmp(opt_host, "localhost");
-    mysql_options(&con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
-                  &opt_ssl_verify_server_cert);
-#endif
   }
 #endif
+  SSL_SET_OPTIONS(&con->mysql);
+
 
 #if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)
   if (shared_memory_base_name)

programming_language: C
filename: mysql_version.cmake
change_type: ModificationType.MODIFY
diff: @@ -18,7 +18,7 @@
 #
 
 SET(SHARED_LIB_MAJOR_VERSION "18")
-SET(SHARED_LIB_MINOR_VERSION "1")
+SET(SHARED_LIB_MINOR_VERSION "2")
 SET(PROTOCOL_VERSION "10")
 SET(DOT_FRM_VERSION "6")
 

programming_language: Shell
filename: mysql.h
change_type: ModificationType.MODIFY
diff: @@ -159,7 +159,8 @@ enum mysql_option
   MYSQL_OPT_CONNECT_ATTR_DELETE,
   MYSQL_SERVER_PUBLIC_KEY,
   MYSQL_ENABLE_CLEARTEXT_PLUGIN,
-  MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS
+  MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
+  MYSQL_OPT_SSL_ENFORCE
 };
 
 /**
@@ -451,6 +452,8 @@ int		STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
 				      const void *arg);
 int		STDCALL mysql_options4(MYSQL *mysql,enum mysql_option option,
                                        const void *arg1, const void *arg2);
+int             STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option,
+                                         const void *arg);
 void		STDCALL mysql_free_result(MYSQL_RES *result);
 void		STDCALL mysql_data_seek(MYSQL_RES *result,
 					my_ulonglong offset);

programming_language: C
filename: mysql.h.pp
change_type: ModificationType.MODIFY
diff: @@ -316,7 +316,8 @@ enum mysql_option
   MYSQL_OPT_CONNECT_ATTR_DELETE,
   MYSQL_SERVER_PUBLIC_KEY,
   MYSQL_ENABLE_CLEARTEXT_PLUGIN,
-  MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS
+  MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
+  MYSQL_OPT_SSL_ENFORCE
 };
 struct st_mysql_options_extention;
 struct st_mysql_options {
@@ -518,6 +519,8 @@ int mysql_options(MYSQL *mysql,enum mysql_option option,
           const void *arg);
 int mysql_options4(MYSQL *mysql,enum mysql_option option,
                                        const void *arg1, const void *arg2);
+int mysql_get_option(MYSQL *mysql, enum mysql_option option,
+                                         const void *arg);
 void mysql_free_result(MYSQL_RES *result);
 void mysql_data_seek(MYSQL_RES *result,
      my_ulonglong offset);

programming_language: C
filename: sql_common.h
change_type: ModificationType.MODIFY
diff: @@ -67,6 +67,8 @@ struct st_mysql_options_extention {
   char *server_public_key_path;
   size_t connection_attributes_length;
   my_bool enable_cleartext_plugin;
+  /** false if it is possible to fall back on unencrypted connections */
+  my_bool ssl_enforce;
 };
 
 typedef struct st_mysql_methods

programming_language: C
filename: sslopt-case.h
change_type: ModificationType.MODIFY
diff: @@ -17,6 +17,17 @@
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+#ifdef MYSQL_CLIENT
+    case OPT_SSL_SSL:
+      /*
+        A client side --ssl option handling.
+        --ssl=1 means enforce (use=1, enforce=1)
+	--ssl=0 means can't enforce (use=0, enforce=0)
+	no --ssl means default : no enforce (use=1), just try (enforce=1)
+      */
+      opt_ssl_enforce= opt_use_ssl;
+      break;
+#endif
     case OPT_SSL_KEY:
     case OPT_SSL_CERT:
     case OPT_SSL_CA:
@@ -28,7 +39,7 @@
       Enable use of SSL if we are using any ssl option
       One can disable SSL later by using --skip-ssl or --ssl=0
     */
-      opt_use_ssl= 1;
+      opt_use_ssl= TRUE;
     /* crl has no effect in yaSSL */  
 #ifdef HAVE_YASSL
       opt_ssl_crl= NULL;

programming_language: C
filename: sslopt-longopts.h
change_type: ModificationType.MODIFY
diff: @@ -19,30 +19,32 @@
 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
   {"ssl", OPT_SSL_SSL,
-   "Enable SSL for connection (automatically enabled with other flags).",
+   "If set to ON, this option enforces that SSL is established before client "
+   "attempts to authenticate to the server. To disable client SSL capabilities "
+   "use --ssl=OFF.",
    &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
   {"ssl-ca", OPT_SSL_CA,
-   "CA file in PEM format (check OpenSSL docs, implies --ssl).",
+   "CA file in PEM format.",
    &opt_ssl_ca, &opt_ssl_ca, 0, GET_STR, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
   {"ssl-capath", OPT_SSL_CAPATH,
-   "CA directory (check OpenSSL docs, implies --ssl).",
+   "CA directory.",
    &opt_ssl_capath, &opt_ssl_capath, 0, GET_STR, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
-  {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format (implies --ssl).",
+  {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format.",
    &opt_ssl_cert, &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
-  {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).",
+  {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use.",
    &opt_ssl_cipher, &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
-  {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl).",
+  {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format.",
    &opt_ssl_key, &opt_ssl_key, 0, GET_STR, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
-  {"ssl-crl", OPT_SSL_CRL, "Certificate revocation list (implies --ssl).",
+  {"ssl-crl", OPT_SSL_CRL, "Certificate revocation list.",
    &opt_ssl_crl, &opt_ssl_crl, 0, GET_STR, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
   {"ssl-crlpath", OPT_SSL_CRLPATH, 
-    "Certificate revocation list path (implies --ssl).",
+    "Certificate revocation list path.",
    &opt_ssl_crlpath, &opt_ssl_crlpath, 0, GET_STR, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
 #ifdef MYSQL_CLIENT

programming_language: C
filename: sslopt-vars.h
change_type: ModificationType.MODIFY
diff: @@ -17,7 +17,10 @@
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
-static my_bool opt_use_ssl   = 0;
+/* Always try to use SSL per default */
+static my_bool opt_use_ssl   = TRUE;
+/* Fall back on unencrypted connections per default */
+static my_bool opt_ssl_enforce= FALSE;
 static char *opt_ssl_ca      = 0;
 static char *opt_ssl_capath  = 0;
 static char *opt_ssl_cert    = 0;
@@ -25,8 +28,23 @@ static char *opt_ssl_cipher  = 0;
 static char *opt_ssl_key     = 0;
 static char *opt_ssl_crl     = 0;
 static char *opt_ssl_crlpath = 0;
-#ifdef MYSQL_CLIENT
-static my_bool opt_ssl_verify_server_cert= 0;
+#ifndef MYSQL_CLIENT
+#error This header is supposed to be used only in the client
 #endif
+#define SSL_SET_OPTIONS(mysql) \
+  if (opt_use_ssl) \
+  { \
+    mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, \
+      opt_ssl_capath, opt_ssl_cipher); \
+    mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); \
+    mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); \
+    mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &opt_ssl_enforce); \
+  } \
+  mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, \
+    (char*)&opt_ssl_verify_server_cert)
+
+static my_bool opt_ssl_verify_server_cert= 0;
+#else
+#define SSL_SET_OPTIONS(mysql) do { } while(0)
 #endif
 #endif /* SSLOPT_VARS_INCLUDED */

programming_language: C
filename: mysql_ssl.result
change_type: ModificationType.ADD
diff: @@ -0,0 +1,5 @@
+#
+# WL#6791 Redefine client --ssl option to imply enforced encryption
+#
+# verify that --ssl makes SSL required against a no-ssl server
+End of 5.7 tests

programming_language: Shell
filename: plugin_auth_sha256_server_default_tls.result
change_type: ModificationType.MODIFY
diff: @@ -27,11 +27,8 @@ SELECT USER(),CURRENT_USER();
 USER()	CURRENT_USER()
 kristofer2@localhost	kristofer2@localhost
 **** Client default_auth=sha_256_password and server default auth=sha256_password
-#### Test is disabled because it requires RSA-keys and this only works 
-#### with OpenSSL. The reason is that the current client library
-#### framework can't know if SSL was attempted or not when the default
-#### client auth is switched and hence it will only report that the 
-#### connection is unencrypted.
+user()	current_user()
+kristofer@localhost	kristofer@localhost
 **** Client default_auth=native and server default auth=sha256_password
 user()	current_user()
 kristofer@localhost	kristofer@localhost

programming_language: SQL
filename: ssl_cipher.result
change_type: ModificationType.MODIFY
diff: @@ -1,9 +1,9 @@
 #
 # BUG#11760210 - SSL_CIPHER_LIST NOT SET OR RETURNED FOR "SHOW STATUS LIKE 'SSL_CIPHER_LIST'"
 #
-SHOW STATUS LIKE 'Ssl_cipher';
+# must return AES128-SHA
 Variable_name	Value
 Ssl_cipher	AES128-SHA
-SHOW STATUS LIKE 'Ssl_cipher_list';
 Variable_name	Value
 Ssl_cipher_list	AES128-SHA
+# must fail since the default SSL cipher is not compatible

programming_language: Shell
filename: mysql_ssl-master.opt
change_type: ModificationType.ADD
diff: @@ -0,0 +1 @@
+--skip-ssl

programming_language: Batchfile
filename: mysql_ssl.test
change_type: ModificationType.ADD
diff: @@ -0,0 +1,26 @@
+#Want to skip this test from daily Valgrind execution
+--source include/no_valgrind_without_big.inc
+
+# This test should work in embedded server after we fix mysqltest
+-- source include/not_embedded.inc
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+--echo #
+--echo # WL#6791 Redefine client --ssl option to imply enforced encryption
+--echo #
+
+--echo # verify that --ssl makes SSL required against a no-ssl server
+--error 1
+--exec $MYSQL --ssl -e "SHOW STATUS like 'Ssl_cipher'"
+
+
+--echo End of 5.7 tests
+
+
+# Wait till all disconnects are completed
+--source include/wait_until_count_sessions.inc
+
+##  This test file is for testing encrypted communication only, not other
+##  encryption routines that the SSL library happens to provide!

programming_language: Markdown
filename: plugin_auth_sha256_server_default_tls.test
change_type: ModificationType.MODIFY
diff: @@ -36,12 +36,15 @@ SELECT USER(),CURRENT_USER();
 connection default;
 disconnect con2;
 --echo **** Client default_auth=sha_256_password and server default auth=sha256_password
---echo #### Test is disabled because it requires RSA-keys and this only works 
---echo #### with OpenSSL. The reason is that the current client library
---echo #### framework can't know if SSL was attempted or not when the default
---echo #### client auth is switched and hence it will only report that the 
---echo #### connection is unencrypted.
-# --exec xterm -e gdb --args $MYSQL -ukristofer -psecret2 --default_auth=sha256_password --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem -e "select user(), current_user()"
+# Why using sha256_password requires --ssl=1 ?
+# The current client library can't know if SSL was attempted or not
+# when the default client auth is switched and hence it will only report
+# that the connection is unencrypted forcing the client to ask for RSA keys.
+# However, it is possible to inform the client library to enforce SSL using
+# MYSQL_OPT_ENFORCE_SSL (or --ssl=1) and this will be enough for the
+# sha256_password plugin to safely assume a secure connection despite it hasn't
+# really been established yet.
+--exec $MYSQL -ukristofer -psecret2 --default_auth=sha256_password --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem --ssl -e "select user(), current_user()"
 --echo **** Client default_auth=native and server default auth=sha256_password
 --exec $MYSQL -ukristofer -psecret2 --default_auth=mysql_native_password --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem -e "select user(), current_user()"
 

programming_language: Shell
filename: ssl_cipher.test
change_type: ModificationType.MODIFY
diff: @@ -3,6 +3,8 @@
 #but needs to be kept for tests that would need MyISAM in future.
 --source include/force_myisam_default.inc
 
+--source include/not_embedded.inc
+
 # Turn on ssl between the client and server
 # and run a number of tests
 
@@ -15,14 +17,14 @@
 # Save the initial number of concurrent sessions
 --source include/count_sessions.inc
 
-connect (ssl_con,localhost,root,,,,,SSL);
+--echo # must return AES128-SHA
+# need to use mysql since mysqltest doesn't support --ssl-cipher
+--exec $MYSQL --host=localhost -e "SHOW STATUS LIKE 'Ssl_cipher'; SHOW STATUS LIKE 'Ssl_cipher_list'" --ssl --ssl-cipher=AES128-SHA
 
-# Check Cipher Name and Cipher List
-SHOW STATUS LIKE 'Ssl_cipher';
-SHOW STATUS LIKE 'Ssl_cipher_list';
 
-connection default;
-disconnect ssl_con;
+--echo # must fail since the default SSL cipher is not compatible
+--error 1
+--exec $MYSQL --host=localhost -e "SHOW STATUS LIKE 'Ssl_cipher'; SHOW STATUS LIKE 'Ssl_cipher_list'" --ssl
 
 # Wait till all disconnects are completed
 --source include/wait_until_count_sessions.inc

programming_language: Shell
filename: client.c
change_type: ModificationType.MODIFY
diff: @@ -145,6 +145,7 @@ void init_client_psi_keys(void)
 
 #endif /* HAVE_PSI_INTERFACE */
 
+const char      *default_ssl_cipher= "DHE-RSA-AES256-SHA";
 uint		mysql_port=0;
 char		*mysql_unix_port= 0;
 const char	*unknown_sqlstate= "HY000";
@@ -1248,19 +1249,28 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd)
                   (STR), MYF(MY_WME)) : NULL;                    \
     } while (0)
 
-#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
-#define SET_SSL_OPTION(opt_var,arg) \
+#define SET_OPTION(opt_var,arg) \
+  do { \
     if (mysql->options.opt_var) \
       my_free(mysql->options.opt_var); \
-    mysql->options.opt_var= arg ? my_strdup(key_memory_mysql_options, arg, MYF(MY_WME)) : NULL; \
+    mysql->options.opt_var = arg ? my_strdup(key_memory_mysql_options, arg, MYF(MY_WME)) : NULL; \
+  } while (0)
+
+
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+#define SET_SSL_OPTION(opt_var,arg) \
+  do { \
+    SET_OPTION(opt_var, arg); \
     if (mysql->options.opt_var) \
-      mysql->options.use_ssl= 1
+      mysql->options.use_ssl = TRUE; \
+  } while (0)
+
 #define EXTENSION_SET_SSL_STRING(OPTS, X, STR) \
+  do { \
     EXTENSION_SET_STRING(OPTS, X, STR); \
     if ((OPTS)->extension->X) \
-      (OPTS)->use_ssl= 1
-    
-    
+      (OPTS)->use_ssl = TRUE; \
+  } while (0)
 #else
 #define SET_SSL_OPTION(opt_var,arg) \
     do { \
@@ -2808,14 +2818,16 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
     mysql->client_flag|= CLIENT_MULTI_RESULTS;
 
 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+  /* consider SSL if any of the SSL mysql_options() is issued */
   if (mysql->options.ssl_key || mysql->options.ssl_cert ||
       mysql->options.ssl_ca || mysql->options.ssl_capath ||
       mysql->options.ssl_cipher ||
-      (mysql->options.extension && mysql->options.extension->ssl_crl) || 
-      (mysql->options.extension && mysql->options.extension->ssl_crlpath))
-    mysql->options.use_ssl= 1;
+      (mysql->options.extension && mysql->options.extension->ssl_crl) ||
+      (mysql->options.extension && mysql->options.extension->ssl_crlpath) ||
+      (mysql->options.extension && mysql->options.extension->ssl_enforce))
+    mysql->options.use_ssl = TRUE;
   if (mysql->options.use_ssl)
-    mysql->client_flag|= CLIENT_SSL;
+    mysql->client_flag |= CLIENT_SSL;
 #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/
   if (mpvio->db)
     mysql->client_flag|= CLIENT_CONNECT_WITH_DB;
@@ -2847,7 +2859,37 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
     end= buff+5;
   }
 #ifdef HAVE_OPENSSL
-  if (mysql->client_flag & CLIENT_SSL)
+
+  if (mysql->options.extension && mysql->options.extension->ssl_enforce)
+  {
+    /*
+      ssl_enforce=1 means enforce ssl
+      Don't fallback on unencrypted connection.
+    */
+    /* can't turn enforce on without turning on use_ssl too */
+    DBUG_ASSERT(mysql->options.use_ssl);
+    /* enforce=true takes precendence over use=false */
+    if (!(mysql->server_capabilities & CLIENT_SSL))
+    {
+      set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate,
+                               ER(CR_SSL_CONNECTION_ERROR),
+                               "SSL is required but the server doesn't "
+                               "support it"
+                               );
+      goto error;
+    }
+  }
+
+  /*
+
+   use_ssl=0 => Disable ssl and connect using unencrypted channel if server
+     allows it
+
+   use_ssl=1, ssl_enforce=0 (default) => attempt ssl connection if possible but
+     fallback on unencrypted connection if possible.
+
+  */
+  if ((mysql->server_capabilities & CLIENT_SSL) && mysql->options.use_ssl)
   {
     /* Do the SSL layering. */
     struct st_mysql_options *options= &mysql->options;
@@ -2856,6 +2898,11 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
     const char *cert_error;
     unsigned long ssl_error;
 
+    if (!mysql->options.ssl_cipher)
+    {
+      SET_OPTION(ssl_cipher, default_ssl_cipher);
+    }
+
     /*
       Send mysql->client_flag, max_packet_size - unencrypted otherwise
       the server does not know we want to do SSL
@@ -2918,6 +2965,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
     MYSQL_TRACE(SSL_CONNECTED, mysql, ());
     MYSQL_TRACE_STAGE(mysql, AUTHENTICATE);
   }
+
 #endif /* HAVE_OPENSSL */
 
   DBUG_PRINT("info",("Server version = '%s'  capabilites: %lu  status: %u  client_flag: %lu",
@@ -4728,6 +4776,11 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
   case MYSQL_OPT_SSL_CRLPATH:  EXTENSION_SET_SSL_STRING(&mysql->options,
                                                         ssl_crlpath, arg);
                                break;
+  case MYSQL_OPT_SSL_ENFORCE:  ENSURE_EXTENSIONS_PRESENT(&mysql->options);
+	                       mysql->options.extension->ssl_enforce=
+				 (*(my_bool *) arg) ? TRUE : FALSE;
+                               mysql->options.use_ssl= TRUE;
+                               break;
   case MYSQL_SERVER_PUBLIC_KEY:
     EXTENSION_SET_STRING(&mysql->options, server_public_key_path, arg);
     break;
@@ -4788,6 +4841,187 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
 }
 
 
+/**
+  Return the current values for the options settable through mysql_options()
+
+  Returns the current values for all of the connection options.
+  Callers should not manipulate the returned data !
+  Data are valid at the time of returning them until the next C API CALL
+  arg should always be a pointer to a variable of the appropriate type.
+  type of variable, based on the parameter:
+
+  uint
+    MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT,
+    MYSQL_OPT_PROTOCOL
+
+  my_bool
+    MYSQL_OPT_COMPRESS, MYSQL_OPT_LOCAL_INFILE, MYSQL_OPT_USE_REMOTE_CONNECTION,
+    MYSQL_OPT_USE_EMBEDDED_CONNECTION, MYSQL_OPT_GUESS_CONNECTION,
+    MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
+    MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_OPT_SSL_ENFORCE,
+    MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS
+
+  const char *
+    MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,
+    MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, MYSQL_SHARED_MEMORY_BASE_NAME,
+    MYSQL_SET_CLIENT_IP, MYSQL_OPT_BIND, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH,
+    MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CERT, MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CAPATH,
+    MYSQL_OPT_SSL_CIPHER, MYSQL_OPT_SSL_CRL, MYSQL_OPT_SSL_CRLPATH,
+    MYSQL_SERVER_PUBLIC_KEY
+
+  <none, error returned>
+    MYSQL_OPT_NAMED_PIPE, MYSQL_OPT_CONNECT_ATTR_RESET,
+    MYSQL_OPT_CONNECT_ATTR_DELETE, MYSQL_INIT_COMMAND
+
+  @param      mysql       The MYSQL connection to operate on
+  @param      option      The option to return the value for
+  @param  out arg         Must be non-null. Receives the current value.
+  @return status
+  @retval 0 SUCCESS
+*/
+
+int STDCALL
+mysql_get_option(MYSQL *mysql, enum mysql_option option, const void *arg)
+{
+  DBUG_ENTER("mysql_option");
+  DBUG_PRINT("enter", ("option: %d", (int)option));
+
+  if (!arg)
+    DBUG_RETURN(1);
+
+  switch (option) {
+  case MYSQL_OPT_CONNECT_TIMEOUT:
+    *((uint *)arg) = mysql->options.connect_timeout;
+    break;
+  case MYSQL_OPT_READ_TIMEOUT:
+    *((uint *)arg)= mysql->options.read_timeout;
+    break;
+  case MYSQL_OPT_WRITE_TIMEOUT:
+    *((uint *)arg)= mysql->options.write_timeout;
+    break;
+  case MYSQL_OPT_COMPRESS:
+    *((my_bool *)arg) = mysql->options.compress ? TRUE : FALSE;
+    break;
+  case MYSQL_OPT_LOCAL_INFILE:			/* Allow LOAD DATA LOCAL ?*/
+    *((uint *)arg)= (mysql->options.client_flag & CLIENT_LOCAL_FILES) ?
+                    TRUE : FALSE;
+    break;
+  case MYSQL_READ_DEFAULT_FILE:
+    *((char **)arg)= mysql->options.my_cnf_file;
+    break;
+  case MYSQL_READ_DEFAULT_GROUP:
+    *((char **)arg)= mysql->options.my_cnf_group;
+    break;
+  case MYSQL_SET_CHARSET_DIR:
+    *((char **)arg)= mysql->options.charset_dir;
+    break;
+  case MYSQL_SET_CHARSET_NAME:
+    *((char **)arg)= mysql->options.charset_name;
+    break;
+  case MYSQL_OPT_PROTOCOL:
+    *((uint *)arg)= mysql->options.protocol;
+    break;
+  case MYSQL_SHARED_MEMORY_BASE_NAME:
+#if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)
+    *((char **)arg)= mysql->options.shared_memory_base_name;
+#else
+    *((const char **)arg)= "";
+#endif
+    break;
+  case MYSQL_OPT_USE_REMOTE_CONNECTION:
+    *((my_bool *)arg)=
+      (mysql->options.methods_to_use == MYSQL_OPT_USE_REMOTE_CONNECTION) ?
+                                        TRUE : FALSE;
+    break;
+  case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
+    *((my_bool *)arg) =
+      (mysql->options.methods_to_use == MYSQL_OPT_USE_EMBEDDED_CONNECTION) ?
+    TRUE : FALSE;
+    break;
+  case MYSQL_OPT_GUESS_CONNECTION:
+    *((my_bool *)arg) =
+      (mysql->options.methods_to_use == MYSQL_OPT_GUESS_CONNECTION) ?
+    TRUE : FALSE;
+    break;
+  case MYSQL_SET_CLIENT_IP:
+    *((char **)arg) = mysql->options.ci.client_ip;
+    break;
+  case MYSQL_SECURE_AUTH:
+    *((my_bool *)arg)= mysql->options.secure_auth;
+    break;
+  case MYSQL_REPORT_DATA_TRUNCATION:
+    *((my_bool *)arg)= mysql->options.report_data_truncation;
+    break;
+  case MYSQL_OPT_RECONNECT:
+    *((my_bool *)arg)= mysql->reconnect;
+    break;
+  case MYSQL_OPT_BIND:
+    *((char **)arg)= mysql->options.ci.bind_address;
+    break;
+  case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
+    *((my_bool *)arg) = (mysql->options.client_flag &
+                         CLIENT_SSL_VERIFY_SERVER_CERT) ? TRUE : FALSE;
+    break;
+  case MYSQL_PLUGIN_DIR:
+    *((char **)arg)= mysql->options.extension ?
+                     mysql->options.extension->plugin_dir : NULL;
+    break;
+  case MYSQL_DEFAULT_AUTH:
+    *((char **)arg)= mysql->options.extension ?
+                     mysql->options.extension->default_auth : NULL;
+    break;
+  case MYSQL_OPT_SSL_KEY:
+    *((char **)arg)= mysql->options.ssl_key;
+    break;
+  case MYSQL_OPT_SSL_CERT:
+    *((char **)arg)= mysql->options.ssl_cert;
+    break;
+  case MYSQL_OPT_SSL_CA:
+    *((char **)arg)= mysql->options.ssl_ca;
+    break;
+  case MYSQL_OPT_SSL_CAPATH:
+    *((char **)arg)= mysql->options.ssl_capath;
+    break;
+  case MYSQL_OPT_SSL_CIPHER:
+    *((char **)arg)= mysql->options.ssl_cipher;
+    break;
+  case MYSQL_OPT_SSL_CRL:
+    *((char **)arg)= mysql->options.extension ?
+                     mysql->options.extension->ssl_crl : NULL;
+    break;
+  case MYSQL_OPT_SSL_CRLPATH:
+    *((char **)arg)= mysql->options.extension ?
+                     mysql->options.extension->ssl_crlpath : NULL;
+    break;
+  case MYSQL_OPT_SSL_ENFORCE:
+    *((my_bool *)arg)= (mysql->options.extension &&
+                        mysql->options.extension->ssl_enforce) ? TRUE : FALSE;
+    break;
+  case MYSQL_SERVER_PUBLIC_KEY:
+    *((char **)arg)= mysql->options.extension ?
+                     mysql->options.extension->server_public_key_path : NULL;
+    break;
+  case MYSQL_ENABLE_CLEARTEXT_PLUGIN:
+    *((my_bool *)arg)= (mysql->options.extension &&
+                        mysql->options.extension->enable_cleartext_plugin) ?
+			TRUE : FALSE;
+    break;
+  case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
+    *((my_bool*)arg)= (mysql->options.client_flag &
+                       CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS) ? TRUE : FALSE;
+    break;
+
+  case MYSQL_OPT_NAMED_PIPE:			/* This option is depricated */
+  case MYSQL_INIT_COMMAND:                      /* Cumulative */
+  case MYSQL_OPT_CONNECT_ATTR_RESET:            /* Cumulative */
+  case MYSQL_OPT_CONNECT_ATTR_DELETE:           /* Cumulative */
+  default:
+    DBUG_RETURN(1);
+  }
+  DBUG_RETURN(0);
+}
+
+
 /**
   A function to return the key from a connection attribute
 */

programming_language: C
filename: client_authentication.cc
change_type: ModificationType.MODIFY
diff: @@ -145,6 +145,7 @@ int sha256_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
   bool connection_is_secure= false;
   unsigned char scramble_pkt[20];
   unsigned char *pkt;
+  my_bool ssl_enforce= FALSE;
 
 
   DBUG_ENTER("sha256_password_auth_client");
@@ -164,9 +165,26 @@ int sha256_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
   */
   memcpy(scramble_pkt, pkt, SCRAMBLE_LENGTH);
 
+  if (mysql_get_option(mysql, MYSQL_OPT_SSL_ENFORCE, &ssl_enforce))
+    ssl_enforce= FALSE;
+
   if (mysql_get_ssl_cipher(mysql) != NULL)
     connection_is_secure= true;
-  
+  /*
+    If set to the default plugin, then the client and server haven't
+    attempted a SSL connection yet and there is no way of knowing if this will
+    be successful later on when encryption is needed.
+
+    The only way to be sure that SSL will be established is to check if the
+    client enforce SSL.
+
+    If MYSQL_OPT_ENFORCE_SSL flag isn't set then SSL might be established but
+    the client will still expect RSA keys from the server and fail if those
+    aren't available.
+  */
+  else if (ssl_enforce)
+    connection_is_secure= true; // Safely assume connection will be encrypted
+
   /* If connection isn't secure attempt to get the RSA public key file */
   if (!connection_is_secure)
   {

programming_language: C
filename: rpl_slave.cc
change_type: ModificationType.MODIFY
diff: @@ -6966,18 +6966,21 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi,
 #ifdef HAVE_OPENSSL
   if (mi->ssl)
   {
+    const static my_bool ssl_enforce_true= TRUE;
     mysql_ssl_set(mysql,
                   mi->ssl_key[0]?mi->ssl_key:0,
                   mi->ssl_cert[0]?mi->ssl_cert:0,
                   mi->ssl_ca[0]?mi->ssl_ca:0,
                   mi->ssl_capath[0]?mi->ssl_capath:0,
                   mi->ssl_cipher[0]?mi->ssl_cipher:0);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRL, 
+    mysql_options(mysql, MYSQL_OPT_SSL_CRL,
                   mi->ssl_crl[0] ? mi->ssl_crl : 0);
-    mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, 
+    mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH,
                   mi->ssl_crlpath[0] ? mi->ssl_crlpath : 0);
     mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
                   &mi->ssl_verify_server_cert);
+    /* we always enforce SSL if SSL is turned on */
+    mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &ssl_enforce_true);
   }
 #endif
 

programming_language: C
filename: mysql_client_test.c
change_type: ModificationType.MODIFY
diff: @@ -19514,6 +19514,114 @@ static void test_wl6797()
   mysql_stmt_close(stmt);
 }
 
+
+static void test_wl6791()
+{
+  int        rc;
+  uint       idx;
+  MYSQL      *l_mysql;
+  enum mysql_option
+  uint_opts[] = {
+    MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT,
+    MYSQL_OPT_PROTOCOL, MYSQL_OPT_LOCAL_INFILE
+  },
+  my_bool_opts[] = {
+    MYSQL_OPT_COMPRESS, MYSQL_OPT_USE_REMOTE_CONNECTION,
+    MYSQL_OPT_USE_EMBEDDED_CONNECTION, MYSQL_OPT_GUESS_CONNECTION,
+    MYSQL_SECURE_AUTH, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
+    MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_OPT_SSL_ENFORCE,
+    MYSQL_ENABLE_CLEARTEXT_PLUGIN, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS
+  },
+  const_char_opts[] = {
+    MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,
+    MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, 
+#if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)
+    /* mysql_options() is a no-op on non-supporting platforms. */
+    MYSQL_SHARED_MEMORY_BASE_NAME,
+#endif
+    MYSQL_SET_CLIENT_IP, MYSQL_OPT_BIND, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH,
+    MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CERT, MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CAPATH,
+    MYSQL_OPT_SSL_CIPHER, MYSQL_OPT_SSL_CRL, MYSQL_OPT_SSL_CRLPATH,
+    MYSQL_SERVER_PUBLIC_KEY
+  },
+  err_opts[] = {
+    MYSQL_OPT_NAMED_PIPE, MYSQL_OPT_CONNECT_ATTR_RESET,
+    MYSQL_OPT_CONNECT_ATTR_DELETE, MYSQL_INIT_COMMAND
+  };
+
+  myheader("test_wl6791");
+
+  /* prepare the connection */
+  l_mysql = mysql_client_init(NULL);
+  DIE_UNLESS(l_mysql != NULL);
+
+  for (idx= 0; idx < sizeof(uint_opts) / sizeof(enum mysql_option); idx++)
+  {
+    uint opt_before= 1, opt_after= 0;
+
+    if (!opt_silent)
+      fprintf(stdout, "testing uint option #%d (%d)\n", idx,
+              (int) uint_opts[idx]);
+    rc= mysql_options(l_mysql, uint_opts[idx], &opt_before);
+    DIE_UNLESS(rc == 0);
+
+    rc = mysql_get_option(l_mysql, uint_opts[idx], &opt_after);
+    DIE_UNLESS(rc == 0);
+
+    DIE_UNLESS(opt_before == opt_after);
+  }
+
+  for (idx= 0; idx < sizeof(my_bool_opts) / sizeof(enum mysql_option); idx++)
+  {
+    my_bool opt_before = TRUE, opt_after = FALSE;
+
+    if (!opt_silent)
+      fprintf(stdout, "testing my_bool option #%d (%d)\n", idx,
+      (int)my_bool_opts[idx]);
+
+    rc = mysql_options(l_mysql, my_bool_opts[idx], &opt_before);
+    DIE_UNLESS(rc == 0);
+
+    rc = mysql_get_option(l_mysql, my_bool_opts[idx], &opt_after);
+    DIE_UNLESS(rc == 0);
+
+    DIE_UNLESS(opt_before == opt_after);
+  }
+
+  for (idx= 0; idx < sizeof(const_char_opts) / sizeof(enum mysql_option); idx++)
+  {
+    const char *opt_before = "TEST", *opt_after = NULL;
+
+    if (!opt_silent)
+      fprintf(stdout, "testing const char * option #%d (%d)\n", idx,
+      (int)const_char_opts[idx]);
+
+    rc = mysql_options(l_mysql, const_char_opts[idx], opt_before);
+    DIE_UNLESS(rc == 0);
+
+    rc = mysql_get_option(l_mysql, const_char_opts[idx], &opt_after);
+    DIE_UNLESS(rc == 0);
+
+    DIE_UNLESS(opt_before && opt_after &&
+               0 == strcmp(opt_before, opt_after));
+  }
+
+  for (idx= 0; idx < sizeof(err_opts) / sizeof(enum mysql_option); idx++)
+  {
+    void *dummy_arg;
+    if (!opt_silent)
+      fprintf(stdout, "testing invalid option #%d (%d)\n", idx,
+      (int)err_opts[idx]);
+
+    rc = mysql_get_option(l_mysql, err_opts[idx], &dummy_arg);
+    DIE_UNLESS(rc != 0);
+  }
+
+  /* clean up */
+  mysql_close(l_mysql);
+}
+
+
 static struct my_tests_st my_tests[]= {
   { "disable_query_logs", disable_query_logs },
   { "test_view_sp_list_fields", test_view_sp_list_fields },
@@ -19785,6 +19893,7 @@ static struct my_tests_st my_tests[]= {
   { "test_wl6587", test_wl6587 },
   { "test_wl5928", test_wl5928 },
   { "test_wl6797", test_wl6797 },
+  { "test_wl6791", test_wl6791 },
   { 0, 0 }
 };
 

programming_language: SQL