Skip to content

Commit

Permalink
Fix Python 3 error when using unicode characters in passwords
Browse files Browse the repository at this point in the history
This patch fix the error when using unicode characters in passwords
with Python 3. This happens because they must be encoded before using
hashlib.sha1 for hashing the password.

Tests were added for regression.
  • Loading branch information
nmariz committed Aug 25, 2016
1 parent 51a286e commit b130a26
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ License information can be found in the LICENSE.txt file.
Requirements
============

Python Protobuf (version >= 2.6.1)
Python Protobuf (version >= 3.0.0)
https://developers.google.com/protocol-buffers/docs/downloads


Expand Down
19 changes: 14 additions & 5 deletions lib/mysqlx/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,32 @@
"""Implementation of MySQL Authentication Plugin."""

import hashlib
import struct

from .compat import PY3, UNICODE_TYPES, hexlify


class MySQL41AuthPlugin(object):
def __init__(self, username, password):
self._username = username
self._password = password
self._password = password.encode("utf-8") \
if isinstance(password, UNICODE_TYPES) else password

def name(self):
return "MySQL 4.1 Authentication Plugin"

def auth_name(self):
return "MYSQL41"

def xor_string(self, a, b):
def xor_string(self, hash1, hash2):
"""Encrypt/Decrypt function used for password encryption in
authentication, using a simple XOR.
"""
return "".join([chr(ord(x) ^ ord(y)) for x, y in zip(a, b)])
if PY3:
xored = [h1 ^ h2 for (h1, h2) in zip(hash1, hash2)]
else:
xored = [ord(h1) ^ ord(h2) for (h1, h2) in zip(hash1, hash2)]
return struct.pack("20B", *xored)

def build_authentication_response(self, data):
"""Hashing for MySQL 4.1 authentication
Expand All @@ -50,7 +58,8 @@ def build_authentication_response(self, data):
h1 = hashlib.sha1(self._password).digest()
h2 = hashlib.sha1(h1).digest()
auth_response = self.xor_string(
h1, hashlib.sha1(data + h2).digest()).encode("hex")
return "{0}\0{1}\0*{2}\0".format("", self._username, auth_response)
h1, hashlib.sha1(data + h2).digest())
return "{0}\0{1}\0*{2}\0".format("", self._username,
hexlify(auth_response))
else:
return "{0}\0{1}\0".format("", self._username)
12 changes: 12 additions & 0 deletions lib/mysqlx/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,31 @@

import sys
import decimal
import binascii


PY3 = sys.version_info.major == 3


if PY3:
from urllib.parse import urlparse

def hexlify(data):
return binascii.hexlify(data).decode("utf-8")

NUMERIC_TYPES = (int, float, decimal.Decimal,)
INT_TYPES = (int,)
UNICODE_TYPES = (str,)
STRING_TYPES = (str,)
BYTE_TYPES = (bytearray, bytes,)


else:
from urlparse import urlparse

def hexlify(data):
return data.encode("hex")

NUMERIC_TYPES = (int, float, decimal.Decimal, long,)
INT_TYPES = (int, long,)
UNICODE_TYPES = (unicode,)
Expand Down
9 changes: 7 additions & 2 deletions tests/test_mysqlx_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,17 @@
("áé'í'óú:unicode@127.0.0.1",
{"schema": "", "host": "127.0.0.1", "password": "unicode",
"port": 33060, "user": "áé'í'óú"}),
("unicode:áé'í'óú@127.0.0.1",
{"schema": "", "host": "127.0.0.1", "password": "áé'í'óú",
"port": 33060, "user": "unicode"}),
)


_ROUTER_LIST_RESULTS = ( # (uri, result)
("áé'í'óú:unicode@127.0.0.1", {"schema": "", "host": "127.0.0.1", "port": 33060,
"password": "unicode", "user": "áé'í'óú"}),
("áé'í'óú:unicode@127.0.0.1", {"schema": "", "host": "127.0.0.1",
"port": 33060, "password": "unicode", "user": "áé'í'óú"}),
("unicode:áé'í'óú@127.0.0.1", {"schema": "", "host": "127.0.0.1",
"port": 33060, "password": "áé'í'óú", "user": "unicode"}),
("user:password@[127.0.0.1, localhost]", {"schema": "", "routers":
[{"host": "127.0.0.1", "port": 33060}, {"host": "localhost", "port":
33060}], "password": "password", "user": "user"}),
Expand Down

0 comments on commit b130a26

Please sign in to comment.