← Back to team overview

yahoo-eng-team team mailing list archive

[Bug 1607119] [NEW] TOTP auth not functional in python3

 

Public bug reported:

Because of how python3 handles byte>str conversion, the passcode
generation function produces a mangled result in python3. The reason the
unit tests still pass in python3 is because the tests also use the same
function and thus the server and the tests are both sending and
expecting the same mangled passcode.

This would then mean that anyone correctly generating the passcode and
attempting to authenticate via TOTP would fail because the server is
expecting a mangled passcode.

The fix is to not use six.text_type, as it does the wrong thing, and
instead use .decode('utf-8') which produces the correct result in both
python2 and python3.

Example of why and how this happens:
Python2:

>>> passcode = b'123456'
>>> print passcode
123456
>>> type(passcode)
<type 'str'>
>>> import six
>>> six.text_type(passcode)
u'123456'
>>> type(six.text_type(passcode))
<type 'unicode'>
>>> otherstring = "openstack"
>>> otherstring + passcode
'openstack123456'
>>> passcode.decode('utf-8')
u'123456'
>>> type(passcode.decode('utf-8'))
<type 'unicode'>

Python3:

>>> passcode = b'123456'
>>> print(passcode)
b'123456'
>>> type(passcode)
<class 'bytes'>
>>> import six
>>> six.text_type(passcode)
"b'123456'"
>>> type(six.text_type(passcode))
<class 'str'>
>>> otherstring = "openstack"
>>> otherstring + passcode
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'bytes' object to str implicitly
>>> otherstring + str(passcode)
"openstackb'123456'"
>>> passcode.decode('utf-8')
'123456'
>>> type(passcode.decode('utf-8'))
<class 'str'>

** Affects: keystone
     Importance: Undecided
     Assignee: Adrian Turjak (adriant-y)
         Status: New

** Description changed:

  Because of how python3 handles byte>str conversion, the passcode
  generation function produces a mangled result in python3. The reason the
  unit tests still pass in python3 is because the tests also use the same
  function and thus the server and the tests are both sending and
  expecting the same mangled passcode.
+ 
+ This would then mean that anyone correctly generating the passcode and
+ attempting to authenticate via TOTP would fail because the server is
+ expecting a mangled passcode.
  
  The fix is to not use six.text_type, as it does the wrong thing, and
  instead use .decode('utf-8') which produces the correct result in both
  python2 and python3.
  
  Example of why and how this happens:
  Python2:
  
  >>> passcode = b'123456'
  >>> print passcode
  123456
  >>> type(passcode)
  <type 'str'>
  >>> import six
  >>> six.text_type(passcode)
  u'123456'
  >>> type(six.text_type(passcode))
  <type 'unicode'>
  >>> otherstring = "openstack"
  >>> otherstring + passcode
  'openstack123456'
  >>> passcode.decode('utf-8')
  u'123456'
  >>> type(passcode.decode('utf-8'))
  <type 'unicode'>
  
  Python3:
  
  >>> passcode = b'123456'
  >>> print(passcode)
  b'123456'
  >>> type(passcode)
  <class 'bytes'>
  >>> import six
  >>> six.text_type(passcode)
  "b'123456'"
  >>> type(six.text_type(passcode))
  <class 'str'>
  >>> otherstring = "openstack"
  >>> otherstring + passcode
  Traceback (most recent call last):
-   File "<stdin>", line 1, in <module>
+   File "<stdin>", line 1, in <module>
  TypeError: Can't convert 'bytes' object to str implicitly
  >>> otherstring + str(passcode)
  "openstackb'123456'"
  >>> passcode.decode('utf-8')
  '123456'
  >>> type(passcode.decode('utf-8'))
  <class 'str'>

-- 
You received this bug notification because you are a member of Yahoo!
Engineering Team, which is subscribed to OpenStack Identity (keystone).
https://bugs.launchpad.net/bugs/1607119

Title:
  TOTP auth not functional in python3

Status in OpenStack Identity (keystone):
  New

Bug description:
  Because of how python3 handles byte>str conversion, the passcode
  generation function produces a mangled result in python3. The reason
  the unit tests still pass in python3 is because the tests also use the
  same function and thus the server and the tests are both sending and
  expecting the same mangled passcode.

  This would then mean that anyone correctly generating the passcode and
  attempting to authenticate via TOTP would fail because the server is
  expecting a mangled passcode.

  The fix is to not use six.text_type, as it does the wrong thing, and
  instead use .decode('utf-8') which produces the correct result in both
  python2 and python3.

  Example of why and how this happens:
  Python2:

  >>> passcode = b'123456'
  >>> print passcode
  123456
  >>> type(passcode)
  <type 'str'>
  >>> import six
  >>> six.text_type(passcode)
  u'123456'
  >>> type(six.text_type(passcode))
  <type 'unicode'>
  >>> otherstring = "openstack"
  >>> otherstring + passcode
  'openstack123456'
  >>> passcode.decode('utf-8')
  u'123456'
  >>> type(passcode.decode('utf-8'))
  <type 'unicode'>

  Python3:

  >>> passcode = b'123456'
  >>> print(passcode)
  b'123456'
  >>> type(passcode)
  <class 'bytes'>
  >>> import six
  >>> six.text_type(passcode)
  "b'123456'"
  >>> type(six.text_type(passcode))
  <class 'str'>
  >>> otherstring = "openstack"
  >>> otherstring + passcode
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  TypeError: Can't convert 'bytes' object to str implicitly
  >>> otherstring + str(passcode)
  "openstackb'123456'"
  >>> passcode.decode('utf-8')
  '123456'
  >>> type(passcode.decode('utf-8'))
  <class 'str'>

To manage notifications about this bug go to:
https://bugs.launchpad.net/keystone/+bug/1607119/+subscriptions


Follow ups