paramiko / paramiko/paramiko

TypeError Excepiton during connect (probably incorrect usage of instance method)

Open
#1,182 13 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Ready for review
Dominant language
Python
Stars
9.9k
Forks
2.1k
PR merge metrics
No merged PRs in 30d

Description

Hello.

The problem looks like a bug, but I don’t sure.

My environment:

###
uname -a
Linux motkb-dev-app 3.10.0-514.el7.x86_64 #1 SMP Wed Oct 19 11:24:13 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux

###
cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.3 (Maipo)

###
yum list installed | grep python36
rh-python36-python.x86_64             3.6.3-1.el7               @asm_dev_local
rh-python36-python-devel.x86_64       3.6.3-1.el7               @asm_dev_local
rh-python36-python-libs.x86_64        3.6.3-1.el7               @asm_dev_local
rh-python36-python-pip.noarch         9.0.1-2.el7               @asm_dev_local
rh-python36-python-setuptools.noarch  36.5.0-1.el7              @asm_dev_local
rh-python36-python-tkinter.x86_64     3.6.3-1.el7               @asm_dev_local
rh-python36-python-tools.x86_64       3.6.3-1.el7               @asm_dev_local
rh-python36-python-virtualenv.noarch  15.1.0-2.el7              @asm_dev_local
rh-python36-runtime.x86_64            2.0-1.el7                 @asm_dev_local

###
python --version
Python 3.6.3

###
Python 3.6.3 (default, Oct 25 2017, 13:35:50)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux

###
pip list
Package        Version
-------------- -------
asn1crypto     0.24.0
bcrypt         3.1.4
cffi           1.11.5
cryptography   2.2
docopt         0.6.2
idna           2.6
jedi           0.11.1
paramiko       2.4.1
parso          0.1.1
pip            9.0.1
prompt-toolkit 1.0.15
ptpython       0.41
pyasn1         0.4.2
pycparser      2.18
Pygments       2.2.0
PyNaCl         1.2.1
setuptools     28.8.0
six            1.11.0
wcwidth        0.1.7
wheel          0.29.0

Steps to reproduce the problem:

steps_to_reproduce_the_problem.py

import paramiko

host = '127.0.0.1'

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

client.connect(hostname=host)


stdin, stdout, stderr = client.exec_command('ls -l')
data = stdout.read() + stderr.read()
print(data)
client.close()

The execution of the code above produce an error:

Unknown exception: an integer is required (got type bytes)
Traceback (most recent call last):
  File "/home/someone/adir/venv_paramiko_test/lib/python3.6/site-packages/paramiko/transport.py", line 1925, in run
    self.kex_engine.parse_next(ptype, m)
  File "/home/someone/adir/venv_paramiko_test/lib/python3.6/site-packages/paramiko/kex_ecdh_nist.py", line 47, in parse_next
    return self._parse_kexecdh_reply(m)
  File "/home/someone/adir/venv_paramiko_test/lib/python3.6/site-packages/paramiko/kex_ecdh_nist.py", line 106, in _parse_kexecdh_reply
    self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest())
  File "/home/someone/adir/venv_paramiko_test/lib64/python3.6/hashlib.py", line 90, in inner
    return func(*args, **kwargs)
TypeError: an integer is required (got type bytes)

Traceback (most recent call last):
  File "steps_to_reproduce_the_problem.py", line 9, in <module>
    client.connect(hostname=host)
  File "/home/someone/adir/venv_paramiko_test/lib/python3.6/site-packages/paramiko/client.py", line 392, in connect
    t.start_client(timeout=timeout)
  File "/home/someone/adir/venv_paramiko_test/lib/python3.6/site-packages/paramiko/transport.py", line 545, in start_client
    raise e
  File "/home/someone/adir/venv_paramiko_test/lib/python3.6/site-packages/paramiko/transport.py", line 1925, in run
    self.kex_engine.parse_next(ptype, m)
  File "/home/someone/adir/venv_paramiko_test/lib/python3.6/site-packages/paramiko/kex_ecdh_nist.py", line 47, in parse_next
    return self._parse_kexecdh_reply(m)
  File "/home/someone/adir/venv_paramiko_test/lib/python3.6/site-packages/paramiko/kex_ecdh_nist.py", line 106, in _parse_kexecdh_reply
    self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest())
  File "/home/someone/adir/venv_paramiko_test/lib64/python3.6/hashlib.py", line 90, in inner
    return func(*args, **kwargs)
TypeError: an integer is required (got type bytes)

Preliminary conclusions

I performed some investigation on kex_ecdh_nist.py, and found(I hope so) the reason of the error.

Here is a patch that I used to fix the issue:

21c21
<     hash_algo = sha256
---
>     hash_algo = staticmethod(sha256)
113c113
<     hash_algo = sha384
---
>     hash_algo = staticmethod(sha384)
119c119
<     hash_algo = sha512
---
>     hash_algo = staticmethod(sha512)

And some explanations: the class KexNistp256 has an attribute hash_algo, it points to the function sha256(from hashlib), and here is the code:

    ..................
    18  class KexNistp256():
    19
    20      name = "ecdh-sha2-nistp256"
    21      hash_algo = sha256
    22      curve = ec.SECP256R1()
    23
    ..................

Then, later, the call of the hash_algo:

    ..................
   104          hm.add_string(Q_S_bytes)
   105          hm.add_mpint(K)
   106          self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest())
   107          self.transport._verify_key(K_S, sig)
   108          self.transport._activate_outbound()
    ..................

And the call self.hash_algo(hm.asbytes()) it the reason of the error.

This happened because for the instance of the class, hash_algo, is not a function, but a bind method, and a bind method, during the call of KexNistp256.hash_algo puts object that called the method(in our case it is self) as a first argument of the method, and then, puts all other arguments, so in a nutshell, final call looks like this:

sha256(self, hm.asbytes())

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with paramiko/kex_ecdh_nist.py and the provided steps_to_reproduce_the_problem.py, then inspect how each hash_algo attribute is called during key exchange. Confirm the reported Python 3.6 connection failure and verify that the correction makes client.connect and the subsequent command execution complete successfully.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
networking
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.