CVE-2015-3152 (C, published 2016-05-16T10:59Z)
Description: value: 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 v3 base score: 5.9)
Weakness: CWE-295 \u2014 Improper Certificate Validation
The product does not validate, or incorrectly validates, a certificate.
Repository: https://github.com/mysql/mysql-server
Files changed:
client/mysql.cc
client/mysql_secure_installation.cc
client/mysql_upgrade.c
client/mysqladmin.cc
client/mysqlbinlog.cc
client/mysqlcheck.c
client/mysqldump.c
client/mysqlimport.c
client/mysqlshow.c
client/mysqlslap.c
client/mysqltest.cc
cmake/mysql_version.cmake
include/mysql.h
include/mysql.h.pp
include/sql_common.h
include/sslopt-case.h
include/sslopt-longopts.h
include/sslopt-vars.h
mysql-test/r/mysql_ssl.result
mysql-test/r/plugin_auth_sha256_server_default_tls.result
mysql-test/r/ssl_cipher.result
mysql-test/t/mysql_ssl-master.opt
mysql-test/t/mysql_ssl.test
mysql-test/t/plugin_auth_sha256_server_default_tls.test
mysql-test/t/ssl_cipher.test
sql-common/client.c
sql-common/client_authentication.cc
sql/rpl_slave.cc
tests/mysql_client_test.c
Commit message: 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

Vulnerable code:
#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
#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

#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
#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
#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
#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
#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
#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
                                    CLIENT_MULTI_STATEMENTS |
                                    CLIENT_REMEMBER_OPTIONS;
#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
#endif
  if (con_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
    mysql_options(&con_slot->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
                  &opt_ssl_verify_server_cert);
  }
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
    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
    mysql_options(&con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
                  &opt_ssl_verify_server_cert);
#endif
SET(SHARED_LIB_MINOR_VERSION "1")
  MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS
  MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS
      opt_use_ssl= 1;
   "Enable SSL for connection (automatically enabled with other flags).",
   "CA file in PEM format (check OpenSSL docs, implies --ssl).",
   "CA directory (check OpenSSL docs, implies --ssl).",
  {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format (implies --ssl).",
  {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).",
  {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl).",
  {"ssl-crl", OPT_SSL_CRL, "Certificate revocation list (implies --ssl).",
    "Certificate revocation list path (implies --ssl).",
static my_bool opt_use_ssl   = 0;
#ifdef MYSQL_CLIENT
static my_bool opt_ssl_verify_server_cert= 0;
#### 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.
SHOW STATUS LIKE 'Ssl_cipher';
SHOW STATUS LIKE 'Ssl_cipher_list';
# --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()"
connect (ssl_con,localhost,root,,,,,SSL);
# Check Cipher Name and Cipher List
SHOW STATUS LIKE 'Ssl_cipher';
SHOW STATUS LIKE 'Ssl_cipher_list';
connection default;
disconnect ssl_con;
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
#define SET_SSL_OPTION(opt_var,arg) \
    mysql->options.opt_var= arg ? my_strdup(key_memory_mysql_options, arg, MYF(MY_WME)) : NULL; \
      mysql->options.use_ssl= 1
      (OPTS)->use_ssl= 1
    
    
      (mysql->options.extension && mysql->options.extension->ssl_crl) || 
      (mysql->options.extension && mysql->options.extension->ssl_crlpath))
    mysql->options.use_ssl= 1;
    mysql->client_flag|= CLIENT_SSL;
  if (mysql->client_flag & CLIENT_SSL)
  
    mysql_options(mysql, MYSQL_OPT_SSL_CRL, 
    mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, 

Fixed code:
  SSL_SET_OPTIONS(mysql);
  SSL_SET_OPTIONS(mysql);
#include <sslopt-case.h>
  SSL_SET_OPTIONS(&mysql);
  SSL_SET_OPTIONS(mysql);
  SSL_SET_OPTIONS(&mysql_connection);
  SSL_SET_OPTIONS(&mysql_connection);
  SSL_SET_OPTIONS(mysql);
  SSL_SET_OPTIONS(&mysql);
                                    CLIENT_MULTI_STATEMENTS |
                                    CLIENT_REMEMBER_OPTIONS;
  SSL_SET_OPTIONS(&mysql);
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
  my_bool save_opt_use_ssl= opt_use_ssl;
#endif
  opt_use_ssl= con_ssl;

  if (opt_use_ssl)
  }
#else
  /* keep the compiler happy about con_ssl */
  con_ssl = con_ssl ? TRUE : FALSE;
  SSL_SET_OPTIONS(&con_slot->mysql);
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
  opt_use_ssl= save_opt_use_ssl;
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
  SSL_SET_OPTIONS(&con->mysql);

SET(SHARED_LIB_MINOR_VERSION "2")
  MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
  MYSQL_OPT_SSL_ENFORCE
int             STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option,
                                         const void *arg);
  MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
  MYSQL_OPT_SSL_ENFORCE
int mysql_get_option(MYSQL *mysql, enum mysql_option option,
                                         const void *arg);
  /** false if it is possible to fall back on unencrypted connections */
  my_bool ssl_enforce;
#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
      opt_use_ssl= TRUE;
   "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.",
   "CA file in PEM format.",
   "CA directory.",
  {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format.",
  {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use.",
  {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format.",
  {"ssl-crl", OPT_SSL_CRL, "Certificate revocation list.",
    "Certificate revocation list path.",
/* 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;
#ifndef MYSQL_CLIENT
#error This header is supposed to be used only in the client
#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)
#
# 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
user()	current_user()
kristofer@localhost	kristofer@localhost
# must return AES128-SHA
# must fail since the default SSL cipher is not compatible
--skip-ssl
#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!
# 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()"
--source include/not_embedded.inc

--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
--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
const char      *default_ssl_cipher= "DHE-RSA-AES256-SHA";
#define SET_OPTION(opt_var,arg) \
  do { \
    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); \
      mysql->options.use_ssl = TRUE; \
  } while (0)

  do { \
      (OPTS)->use_ssl = TRUE; \
  } while (0)
  /* consider SSL if any of the SSL mysql_options() is issued */
      (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;
    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)
    if (!mysql->options.ssl_cipher)
    {
      SET_OPTION(ssl_cipher, default_ssl_cipher);
    }


  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;
/**
  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);
}


  my_bool ssl_enforce= FALSE;
  if (mysql_get_option(mysql, MYSQL_OPT_SSL_ENFORCE, &ssl_enforce))
    ssl_enforce= FALSE;

  /*
    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

    const static my_bool ssl_enforce_true= TRUE;
    mysql_options(mysql, MYSQL_OPT_SSL_CRL,
    mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH,
    /* we always enforce SSL if SSL is turned on */
    mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &ssl_enforce_true);

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);
}


  { "test_wl6791", test_wl6791 },