Skip to content

Commit

Permalink
Support ssl=True
Browse files Browse the repository at this point in the history
MySQL use ssl by default but MariaDB don't.

Until mysqlclient<=2.2.1, `ssl=True` unintentionally allowed and
it called `mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL)`.
Although it is no-op in MySQL Connector, MariaDB Connector silently
set MYSQL_OPT_SSL_ENFORCE when the API is called. (See #698)

In case of PyMySQL, ssl is not used by default but `ssl=True` behave like
`sslmode="PREFERRED"`.

For better backward compatibility and compatibility with PyMySQL and
security, I decided to allow ssl=True and it means sslmode="REQUIRED".
  • Loading branch information
methane committed Feb 8, 2024
1 parent 1fa31fd commit d79eabf
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
30 changes: 21 additions & 9 deletions src/MySQLdb/_mysql.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ _mysql_ConnectionObject_Initialize(
MYSQL *conn = NULL;
PyObject *conv = NULL;
PyObject *ssl = NULL;
char *ssl_mode = NULL;
const char *ssl_mode = NULL;
const char *key = NULL, *cert = NULL, *ca = NULL,
*capath = NULL, *cipher = NULL;
PyObject *ssl_keepref[5] = {NULL};
Expand All @@ -437,7 +437,7 @@ _mysql_ConnectionObject_Initialize(
int read_timeout = 0;
int write_timeout = 0;
int compress = -1, named_pipe = -1, local_infile = -1;
int ssl_mode_num = SSLMODE_DISABLED;
int ssl_mode_num = SSLMODE_PREFERRED;
char *init_command=NULL,
*read_default_file=NULL,
*read_default_group=NULL,
Expand Down Expand Up @@ -470,19 +470,31 @@ _mysql_ConnectionObject_Initialize(
if(t){d=PyUnicode_AsUTF8(t);ssl_keepref[n_ssl_keepref++]=t;}\
PyErr_Clear();}

char ssl_mode_set = 0;
if (ssl) {
PyObject *value = NULL;
_stringsuck(ca, value, ssl);
_stringsuck(capath, value, ssl);
_stringsuck(cert, value, ssl);
_stringsuck(key, value, ssl);
_stringsuck(cipher, value, ssl);
if (PyMapping_Check(ssl)) {
PyObject *value = NULL;
_stringsuck(ca, value, ssl);
_stringsuck(capath, value, ssl);
_stringsuck(cert, value, ssl);
_stringsuck(key, value, ssl);
_stringsuck(cipher, value, ssl);
} else if (PyObject_IsTrue(ssl)) {
// Support ssl=True from mysqlclient 2.2.4.
// for compatibility with PyMySQL and mysqlclient==2.2.1&libmariadb.
ssl_mode_num = SSLMODE_REQUIRED;
ssl_mode_set = 1;
} else {
ssl_mode_num = SSLMODE_DISABLED;
ssl_mode_set = 1;
}
}
if (ssl_mode) {
if ((ssl_mode_num = _get_ssl_mode_num(ssl_mode)) <= 0) {
PyErr_SetString(_mysql_NotSupportedError, "Unknown ssl_mode specification");
return -1;
}
ssl_mode_set = 1;
}

conn = mysql_init(&(self->connection));
Expand Down Expand Up @@ -531,7 +543,7 @@ _mysql_ConnectionObject_Initialize(
mysql_options(&(self->connection), MYSQL_OPT_SSL_CIPHER, cipher);
}

if (ssl_mode) {
if (ssl_mode_set) {
#ifdef HAVE_ENUM_MYSQL_OPT_SSL_MODE
mysql_options(&(self->connection), MYSQL_OPT_SSL_MODE, &ssl_mode_num);
#else
Expand Down
2 changes: 2 additions & 0 deletions src/MySQLdb/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ class object, used to create cursors (keyword only)
see the MySQL documentation for more details
(mysql_ssl_set()). If this is set, and the client does not
support SSL, NotSupportedError will be raised.
Since mysqlclient 2.2.4, ssl=True is alias of ssl_mode=REQUIRED
for better compatibility with PyMySQL and MariaDB.
:param bool local_infile:
enables LOAD LOCAL INFILE; zero disables
Expand Down

0 comments on commit d79eabf

Please sign in to comment.