Skip to content

Added to pass ssl_mode in configuration. #347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Dec 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions MySQLdb/_mysql.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ PERFORMANCE OF THIS SOFTWARE.
#define my_bool _Bool
#endif

#if ((MYSQL_VERSION_ID >= 50555 && MYSQL_VERSION_ID <= 50599) || \
(MYSQL_VERSION_ID >= 50636 && MYSQL_VERSION_ID <= 50699) || \
(MYSQL_VERSION_ID >= 50711 && MYSQL_VERSION_ID <= 50799) || \
(MYSQL_VERSION_ID >= 80000)) && \
!defined(MARIADB_BASE_VERSION) && !defined(MARIADB_VERSION_ID)
#define HAVE_ENUM_MYSQL_OPT_SSL_MODE
#endif

#define PY_SSIZE_T_CLEAN 1
#include "Python.h"

Expand Down Expand Up @@ -371,6 +379,23 @@ static int _mysql_ResultObject_clear(_mysql_ResultObject *self)
return 0;
}

#ifdef HAVE_ENUM_MYSQL_OPT_SSL_MODE
static int
_get_ssl_mode_num(char *ssl_mode)
{
static char *ssl_mode_list[] = { "DISABLED", "PREFERRED",
"REQUIRED", "VERIFY_CA", "VERIFY_IDENTITY" };
unsigned int i;
for (i=0; i < sizeof(ssl_mode_list)/sizeof(ssl_mode_list[0]); i++) {
if (strcmp(ssl_mode, ssl_mode_list[i]) == 0) {
// SSL_MODE one-based
return i + 1;
}
}
return -1;
}
#endif

static int
_mysql_ConnectionObject_Initialize(
_mysql_ConnectionObject *self,
Expand All @@ -380,6 +405,7 @@ _mysql_ConnectionObject_Initialize(
MYSQL *conn = NULL;
PyObject *conv = NULL;
PyObject *ssl = NULL;
char *ssl_mode = NULL;
const char *key = NULL, *cert = NULL, *ca = NULL,
*capath = NULL, *cipher = NULL;
PyObject *ssl_keepref[5] = {NULL};
Expand All @@ -393,7 +419,7 @@ _mysql_ConnectionObject_Initialize(
"connect_timeout", "compress",
"named_pipe", "init_command",
"read_default_file", "read_default_group",
"client_flag", "ssl",
"client_flag", "ssl", "ssl_mode",
"local_infile",
"read_timeout", "write_timeout", "charset",
"auth_plugin",
Expand All @@ -412,15 +438,15 @@ _mysql_ConnectionObject_Initialize(
self->open = 0;

if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"|ssssisOiiisssiOiiiss:connect",
"|ssssisOiiisssiOsiiiss:connect",
kwlist,
&host, &user, &passwd, &db,
&port, &unix_socket, &conv,
&connect_timeout,
&compress, &named_pipe,
&init_command, &read_default_file,
&read_default_group,
&client_flag, &ssl,
&client_flag, &ssl, &ssl_mode,
&local_infile,
&read_timeout,
&write_timeout,
Expand All @@ -441,6 +467,17 @@ _mysql_ConnectionObject_Initialize(
_stringsuck(key, value, ssl);
_stringsuck(cipher, value, ssl);
}
if (ssl_mode) {
#ifdef HAVE_ENUM_MYSQL_OPT_SSL_MODE
if (_get_ssl_mode_num(ssl_mode) <= 0) {
PyErr_SetString(_mysql_NotSupportedError, "Unknown ssl_mode specification");
return -1;
}
#else
PyErr_SetString(_mysql_NotSupportedError, "MySQL client library does not support ssl_mode specification");
return -1;
#endif
}

conn = mysql_init(&(self->connection));
if (!conn) {
Expand Down Expand Up @@ -483,6 +520,12 @@ _mysql_ConnectionObject_Initialize(
if (ssl) {
mysql_ssl_set(&(self->connection), key, cert, ca, capath, cipher);
}
#ifdef HAVE_ENUM_MYSQL_OPT_SSL_MODE
if (ssl_mode) {
int ssl_mode_num = _get_ssl_mode_num(ssl_mode);
mysql_options(&(self->connection), MYSQL_OPT_SSL_MODE, &ssl_mode_num);
}
#endif
if (charset) {
mysql_options(&(self->connection), MYSQL_SET_CHARSET_NAME, charset);
}
Expand Down
7 changes: 7 additions & 0 deletions MySQLdb/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ class object, used to create cursors (keyword only)
:param int client_flag:
flags to use or 0 (see MySQL docs or constants/CLIENTS.py)

:param str ssl_mode:
specify the security settings for connection to the server;
see the MySQL documentation for more details
(mysql_option(), MYSQL_OPT_SSL_MODE).
Only one of 'DISABLED', 'PREFERRED', 'REQUIRED',
'VERIFY_CA', 'VERIFY_IDENTITY' can be specified.

:param dict ssl:
dictionary or mapping contains SSL connection parameters;
see the MySQL documentation for more details
Expand Down
1 change: 0 additions & 1 deletion doc/MySQLdb.constants.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,3 @@ constants Package
:members:
:undoc-members:
:show-inheritance:

12 changes: 12 additions & 0 deletions doc/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,18 @@ connect(parameters...)

*This must be a keyword parameter.*

ssl_mode
If present, specify the security settings for the
connection to the server. For more information on ssl_mode,
see the MySQL documentation. Only one of 'DISABLED',
'PREFERRED', 'REQUIRED', 'VERIFY_CA', 'VERIFY_IDENTITY'
can be specified.

If not present, the session ssl_mode will be unchanged,
but in version 5.7 and later, the default is PREFERRED.

*This must be a keyword parameter.*

ssl
This parameter takes a dictionary or mapping, where the
keys are parameter names used by the mysql_ssl_set_ MySQL
Expand Down