Skip to content
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

[BUG] - crypto - macs - local_mac misses umac-128@openssh.com,umac-128-etm@openssh.com in the structure #2310

Open
0x7162 opened this issue Oct 10, 2023 · 6 comments
Labels

Comments

@0x7162
Copy link

0x7162 commented Oct 10, 2023

Are you using paramiko as a client or server?

Client

What feature(s) aren't working right?

Keys/auth

What version(s) of paramiko are you using?

3.3.1

What version(s) of Python are you using?

3.7.16

What operating system and version are you using?

Amazon Linux 2

If you're connecting as a client, which SSH server are you connecting to?

SSH-2.0-OpenSSH_8.7 FreeBSD-openssh-portable-8.7.p1_1

If you're using paramiko as part of another tool, which tool/version?

No response

Expected/desired behavior

connection establishes with preferred macs "umac-128@openssh.com" or "umac-128-etm@openssh.com"

Actual behavior

ERROR:paramiko.transport:Unknown exception: 'umac-128@openssh.com'
ERROR:paramiko.transport:Traceback (most recent call last):
ERROR:paramiko.transport:  File "/home/user/.local/lib/python3.7/site-packages/paramiko/transport.py", line 2151, in run
ERROR:paramiko.transport:    self.kex_engine.parse_next(ptype, m)
ERROR:paramiko.transport:  File "/home/user/.local/lib/python3.7/site-packages/paramiko/kex_curve25519.py", line 64, in parse_next
ERROR:paramiko.transport:    return self._parse_kexecdh_reply(m)
ERROR:paramiko.transport:  File "/home/user/.local/lib/python3.7/site-packages/paramiko/kex_curve25519.py", line 131, in _parse_kexecdh_reply
ERROR:paramiko.transport:    self.transport._activate_outbound()
ERROR:paramiko.transport:  File "/home/user/.local/lib/python3.7/site-packages/paramiko/transport.py", line 2679, in _activate_outbound
ERROR:paramiko.transport:    mac_size = self._mac_info[self.local_mac]["size"]
ERROR:paramiko.transport:KeyError: 'umac-128-etm@openssh.com'

code:

        etm = "etm@openssh.com" in self.local_mac
        mac_size = self._mac_info[self.local_mac]["size"]
        mac_engine = self._mac_info[self.local_mac]["class"]

where self.local_mac struct is:

{'hmac-sha1': {'class': <built-in function openssl_sha1>, 'size': 20}, 'hmac-sha1-96': {'class': <built-in function openssl_sha1>, 'size': 12}, 'hmac-sha2-256': {'class': <built-in function openssl_sha256>, 'size': 32}, 'hmac-sha2-256-etm@openssh.com': {'class': <built-in function openssl_sha256>, 'size': 32}, 'hmac-sha2-512': {'class': <built-in function openssl_sha512>, 'size': 64}, 'hmac-sha2-512-etm@openssh.com': {'class': <built-in function openssl_sha512>, 'size': 64}, 'hmac-md5': {'class': <built-in function openssl_md5>, 'size': 16}, 'hmac-md5-96': {'class': <built-in function openssl_md5>, 'size': 12}}

it is absent there, though debug output gives us it is supported:

...
DEBUG:paramiko.transport:client mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
DEBUG:paramiko.transport:server mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
...

How to reproduce

import paramiko

import logging
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
logging.getLogger("paramiko").setLevel(logging.DEBUG)

paramiko.Transport._preferred_macs = ('umac-128-etm@openssh.com',)

hostname="..."
username="..."
key_filename="./xxx.pem"

s = paramiko.SSHClient()
s.load_system_host_keys()
s.connect(hostname, 22, username, key_filename=key_filename)

Anything else?

standart ssh linux client uses (ssh -vv mode):

debug1: kex: server->client cipher: aes128-ctr MAC: umac-128-etm@openssh.com compression: none
debug1: kex: client->server cipher: aes128-ctr MAC: umac-128-etm@openssh.com compression: none
@0x7162 0x7162 added the Bug label Oct 10, 2023
@0x7162 0x7162 changed the title [BUG] - crypto - macs - local_mac misses umac-128@openssh.com in the structure [BUG] - crypto - macs - local_mac misses umac-128@openssh.com,umac-128-etm@openssh.com in the structure Oct 10, 2023
@jun66j5
Copy link
Contributor

jun66j5 commented Oct 10, 2023

paramiko currently doesn't support umac-*@openssh.com mac algorithm. You must use algorithms which are declared in Transport._mac_info. See https://github.com/paramiko/paramiko/blob/3.3.1/paramiko/transport.py#L265-L274 .

@0x7162
Copy link
Author

0x7162 commented Oct 10, 2023

@jun66j5
why it is listed in the debug message as being supported by the client (client-mac)?

...
DEBUG:paramiko.transport:client mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
DEBUG:paramiko.transport:server mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
...

@jun66j5
Copy link
Contributor

jun66j5 commented Oct 10, 2023

That is due to incorrectly directly setting to Transport._preferred_macs like:

paramiko.Transport._preferred_macs = ('umac-128-etm@openssh.com',)

Instead, use SecurityOptions.digests to prefer MAC algorithms, and an exception is raised for unavailable algorithm:

>>> import paramiko
>>>
>>> def transport_factory(*args, **kwargs):
...     t = paramiko.Transport(*args, **kwargs)
...     opts = t.get_security_options()
...     opts.digests = ['umac-128@openssh.com', 'umac-128-etm@openssh.com']
...     return t
...
>>> cli = paramiko.SSHClient()
>>> cli.set_missing_host_key_policy(paramiko.AutoAddPolicy)
>>> cli.connect('::1', transport_factory=transport_factory)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jun66j5/src/paramiko/paramiko/client.py", line 413, in connect
    t = self._transport = transport_factory(
                          ^^^^^^^^^^^^^^^^^^
  File "<stdin>", line 4, in transport_factory
  File "/home/jun66j5/src/paramiko/paramiko/transport.py", line 3072, in digests
    self._set("_preferred_macs", "_mac_info", x)
  File "/home/jun66j5/src/paramiko/paramiko/transport.py", line 3053, in _set
    raise ValueError("unknown cipher")
ValueError: unknown cipher
>>>

@0x7162
Copy link
Author

0x7162 commented Oct 10, 2023

@jun66j5 thank you for the example.

It looks like the error message could be incorrect? (cipher != digest aka macs)

also, as I mentioned, the debug message confused me:

...
DEBUG:paramiko.transport:client mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
DEBUG:paramiko.transport:server mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
...

so client_mac_algo_list looks equal to server_mac_algo_list,
and I suppose if umac-128@openssh.com is not supported - it should not be in client_mac_algo_list

        self._log(DEBUG, "=== Key exchange possibilities ===")
        for prefix, value in (
            ("kex algos", kex_algo_list),
            ("server key", server_key_algo_list),
            # TODO: shouldn't these two lines say "cipher" to match usual
            # terminology (including elsewhere in paramiko!)?
            ("client encrypt", client_encrypt_algo_list),
            ("server encrypt", server_encrypt_algo_list),
            ("client mac", client_mac_algo_list),
            ("server mac", server_mac_algo_list),
            ("client compress", client_compress_algo_list),
            ("server compress", server_compress_algo_list),
            ("client lang", client_lang_list),
            ("server lang", server_lang_list),
        ):
  

( https://github.com/paramiko/paramiko/blob/3.3.1/paramiko/transport.py#L2437 )

@jun66j5
Copy link
Contributor

jun66j5 commented Oct 11, 2023

It looks like the error message could be incorrect? (cipher != digest aka macs)

No. I don't think so.

>>> import paramiko
>>> import socket
>>> s = socket.socket()
>>> t = paramiko.Transport(s)
>>> opts = t.get_security_options()
>>> for prop in ('ciphers', 'digests', 'key_types', 'kex'):
...   try:
...     setattr(opts, prop, ['unknown'])
...   except ValueError as e:
...     print('%s: %r' % (prop, e))
...
ciphers: ValueError('unknown cipher')
digests: ValueError('unknown cipher')
key_types: ValueError('unknown cipher')
kex: ValueError('unknown cipher')

The same message is used and raised for all of algorithm options. If you want better messages for this, you could create a PR.

See also

also, as I mentioned, the debug message confused me:

...
DEBUG:paramiko.transport:client mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
DEBUG:paramiko.transport:server mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
...

Huh? That is the result of incorrect setting to paramiko.Transport._preferred_macs. Remove the incorrect setting.

0x7162 pushed a commit to 0x7162/paramiko that referenced this issue Oct 12, 2023
@0x7162
Copy link
Author

0x7162 commented Oct 12, 2023

@jun66j5 I addressed logging issue (cipher)

as for such messages, it is not relevant to the incorrect setting.

you can use standart settings and get the same bug,
i.e.

import paramiko

import logging
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
logging.getLogger("paramiko").setLevel(logging.DEBUG)

hostname="xxx"
username="xxx"
key_filename="xxx"

s = paramiko.SSHClient()
s.load_system_host_keys()
s.connect(hostname, 22, username, key_filename=key_filename)

run and grep:

python client_mac.py 2>&1 | grep "client mac" -A 1

DEBUG:paramiko.transport:client mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
DEBUG:paramiko.transport:server mac: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants