Skip to content

Commit 33c200e

Browse files
committed
BUG21420906: Fix connect using SHA256 user with blank password
Connect was failing with "Access denied" error while connecting to MySQL server with a user identified with "sha256_password" plugin and a blank password. We fix this issue by correctly sending the auth_response packet. Unit tests are updated with this patch.
1 parent 16aaf98 commit 33c200e

File tree

4 files changed

+61
-54
lines changed

4 files changed

+61
-54
lines changed

lib/mysql/connector/authentication.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def prepare_password(self):
9292
raise errors.InterfaceError("Missing authentication data (seed)")
9393

9494
if not self._password:
95-
return b'\x00'
95+
return b''
9696
password = self._password
9797

9898
if isstr(self._password):

lib/mysql/connector/connection.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,7 @@ def _auth_switch_request(self, username=None, password=None):
167167
auth = get_auth_plugin(new_auth_plugin)(
168168
auth_data, password=password, ssl_enabled=self._ssl_active)
169169
response = auth.auth_response()
170-
if response == b'\x00':
171-
self._socket.send(b'')
172-
else:
173-
self._socket.send(response)
170+
self._socket.send(response)
174171
packet = self._socket.recv()
175172
if packet[4] != 1:
176173
return self._handle_ok(packet)

tests/test_authentication.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
# MySQL Connector/Python - MySQL driver written in Python.
3-
# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3+
# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
44

55
# MySQL Connector/Python is licensed under the terms of the GPLv2
66
# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
@@ -125,7 +125,7 @@ def test_prepare_password(self):
125125
auth_plugin.prepare_password)
126126

127127
if PY2:
128-
empty = '\x00'
128+
empty = ''
129129
auth_data = (
130130
'\x3b\x55\x78\x7d\x2c\x5f\x7c\x72\x49\x52'
131131
'\x3f\x28\x47\x6f\x77\x28\x5f\x28\x46\x69'
@@ -135,7 +135,7 @@ def test_prepare_password(self):
135135
'\x29\x88\xaa\xae\xdb\x00\xb3\x4d\x91\x5b'
136136
)
137137
else:
138-
empty = b'\x00'
138+
empty = b''
139139
auth_data = (
140140
b'\x3b\x55\x78\x7d\x2c\x5f\x7c\x72\x49\x52'
141141
b'\x3f\x28\x47\x6f\x77\x28\x5f\x28\x46\x69'

tests/test_bugs.py

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,16 @@ class BugOra16217765(tests.MySQLConnectorTests):
22202220
'password': 'nativeP@ss',
22212221
},
22222222
}
2223+
users_nopass = {
2224+
'sha256_password': {
2225+
'username': 'sha256user_np',
2226+
'password': '',
2227+
},
2228+
'mysql_native_password': {
2229+
'username': 'nativeuser_np',
2230+
'password': '',
2231+
},
2232+
}
22232233

22242234
def _create_user(self, cnx, user, password, host, database,
22252235
plugin):
@@ -2281,28 +2291,28 @@ def test_sha256(self):
22812291
})
22822292

22832293
auth_plugin = 'sha256_password'
2284-
user = self.users[auth_plugin]
2285-
self._create_user(self.admin_cnx, user['username'],
2286-
user['password'],
2287-
self.host,
2288-
config['database'],
2289-
plugin=auth_plugin)
2294+
for user in (self.users[auth_plugin], self.users_nopass[auth_plugin]):
2295+
self._create_user(self.admin_cnx, user['username'],
2296+
user['password'],
2297+
self.host,
2298+
config['database'],
2299+
plugin=auth_plugin)
22902300

2291-
config['user'] = user['username']
2292-
config['password'] = user['password']
2293-
config['client_flags'] = [constants.ClientFlag.PLUGIN_AUTH]
2301+
config['user'] = user['username']
2302+
config['password'] = user['password']
2303+
config['client_flags'] = [constants.ClientFlag.PLUGIN_AUTH]
22942304

2295-
try:
2296-
cnx = connection.MySQLConnection(**config)
2297-
except:
2298-
import traceback
2299-
traceback.print_exc()
2300-
self.fail("Connecting using sha256_password auth failed")
2305+
try:
2306+
cnx = connection.MySQLConnection(**config)
2307+
except:
2308+
import traceback
2309+
traceback.print_exc()
2310+
self.fail("Connecting using sha256_password auth failed")
23012311

2302-
try:
2303-
cnx.cmd_change_user(config['user'], config['password'])
2304-
except:
2305-
self.fail("Changing user using sha256_password auth failed")
2312+
try:
2313+
cnx.cmd_change_user(config['user'], config['password'])
2314+
except:
2315+
self.fail("Changing user using sha256_password auth failed")
23062316

23072317
@unittest.skipIf(tests.MYSQL_VERSION < (5, 6, 6),
23082318
"MySQL {0} does not support sha256_password auth".format(
@@ -2312,18 +2322,18 @@ def test_sha256_nonssl(self):
23122322
config['unix_socket'] = None
23132323

23142324
auth_plugin = 'sha256_password'
2315-
user = self.users[auth_plugin]
2316-
self._create_user(self.admin_cnx, user['username'],
2317-
user['password'],
2318-
self.host,
2319-
config['database'],
2320-
plugin=auth_plugin)
2321-
2322-
config['user'] = user['username']
2323-
config['password'] = user['password']
2324-
config['client_flags'] = [constants.ClientFlag.PLUGIN_AUTH]
2325-
self.assertRaises(errors.InterfaceError, connection.MySQLConnection,
2326-
**config)
2325+
for user in (self.users[auth_plugin], self.users_nopass[auth_plugin]):
2326+
self._create_user(self.admin_cnx, user['username'],
2327+
user['password'],
2328+
self.host,
2329+
config['database'],
2330+
plugin=auth_plugin)
2331+
2332+
config['user'] = user['username']
2333+
config['password'] = user['password']
2334+
config['client_flags'] = [constants.ClientFlag.PLUGIN_AUTH]
2335+
self.assertRaises(errors.InterfaceError, connection.MySQLConnection,
2336+
**config)
23272337

23282338
@unittest.skipIf(tests.MYSQL_VERSION < (5, 5, 7),
23292339
"MySQL {0} does not support authentication plugins".format(
@@ -2333,21 +2343,21 @@ def test_native(self):
23332343
config['unix_socket'] = None
23342344

23352345
auth_plugin = 'mysql_native_password'
2336-
user = self.users[auth_plugin]
2337-
self._create_user(self.admin_cnx, user['username'],
2338-
user['password'],
2339-
self.host,
2340-
config['database'],
2341-
plugin=auth_plugin)
2342-
2343-
config['user'] = user['username']
2344-
config['password'] = user['password']
2345-
config['client_flags'] = [constants.ClientFlag.PLUGIN_AUTH]
2346-
try:
2347-
cnx = connection.MySQLConnection(**config)
2348-
except Exception as exc:
2349-
self.fail("Connecting using {0} auth failed: {1}".format(
2350-
auth_plugin, exc))
2346+
for user in (self.users[auth_plugin], self.users_nopass[auth_plugin]):
2347+
self._create_user(self.admin_cnx, user['username'],
2348+
user['password'],
2349+
self.host,
2350+
config['database'],
2351+
plugin=auth_plugin)
2352+
2353+
config['user'] = user['username']
2354+
config['password'] = user['password']
2355+
config['client_flags'] = [constants.ClientFlag.PLUGIN_AUTH]
2356+
try:
2357+
cnx = connection.MySQLConnection(**config)
2358+
except Exception as exc:
2359+
self.fail("Connecting using {0} auth failed: {1}".format(
2360+
auth_plugin, exc))
23512361

23522362

23532363
class BugOra18144971(tests.MySQLConnectorTests):

0 commit comments

Comments
 (0)