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

Provide a SSLContext() API #19

Open
paravoid opened this issue Jan 9, 2020 · 5 comments
Open

Provide a SSLContext() API #19

paravoid opened this issue Jan 9, 2020 · 5 comments

Comments

@paravoid
Copy link

paravoid commented Jan 9, 2020

The Python ssl module documentation says:

Since Python 3.2 and 2.7.9, it is recommended to use the SSLContext.wrap_socket() of an SSLContext instance to wrap sockets as SSLSocket objects. The helper functions create_default_context() returns a new context with secure default settings. The old wrap_socket() function is deprecated since it is both inefficient and has no support for server name indication (SNI) and hostname matching.

It'd be nice if sslpsk followed suit and provided a similar API. It seems that 3.7+ provides some core API improvements that would make this possible. I played around and this seemed to work:

def _ssl_setup_psk_callbacks(sslobj):
    psk = sslobj.context.psk
    hint = sslobj.context.hint
    if psk:
        if sslobj.server_side:
            cb = psk if callable(psk) else lambda _identity: psk
            _ssl_set_psk_server_callback(sslobj, cb, hint)
        else:
            cb = psk if callable(psk) else lambda _hint: psk if isinstance(psk, tuple) else (psk, b"")
            _ssl_set_psk_client_callback(sslobj, cb)



class SSLPSKContext(ssl.SSLContext):
    @property
    def psk(self):
        return getattr(self, "_psk", None)

    @psk.setter
    def psk(self, psk):
        self._psk = psk

    @property
    def hint(self):
        return getattr(self, "_hint", None)

    @hint.setter
    def hint(self, hint):
        self._hint = hint


class SSLPSKObject(ssl.SSLObject):
    def do_handshake(self, *args, **kwargs):
        _ssl_setup_psk_callbacks(self)
        super().do_handshake(*args, **kwargs)


class SSLPSKSocket(ssl.SSLSocket):
    def do_handshake(self, *args, **kwargs):
        _ssl_setup_psk_callbacks(self)
        super().do_handshake(*args, **kwargs)


SSLPSKContext.sslobject_class = SSLPSKObject
SSLPSKContext.sslsocket_class = SSLPSKSocket

(It seems like SSLPSKSocket alone is useful to replace the existing functionality. I think SSLPSKObject is useful only under certain frameworks. I could not test that, so perhaps it'd be smarter to even avoid including that for now.)

With that, one can use SSLPSKContext where they'd use SSLContext before, and SSLPSKContext.psk = … to set the PSK (and .hint = … for the hint).

A backwards-compatible sslpsk.wrap_socket() can still be offered with:

def wrap_socket(sock, psk, hint=None,
                server_side=False,
                ssl_version=ssl.PROTOCOL_TLS,
                do_handshake_on_connect=True,
                suppress_ragged_eofs=True,
                ciphers=None):

    context = SSLPSKContext(ssl_version)
    if ciphers:
        context.set_ciphers(ciphers)
    context.psk = psk
    context.hint = hint

    return context.wrap_socket(
        sock=sock, server_side=server_side,
        do_handshake_on_connect=do_handshake_on_connect,
        suppress_ragged_eofs=suppress_ragged_eofs
    )
@paravoid
Copy link
Author

FWIW, in theory an an SSLContext + SSLObject API would allow this to work with asyncio. Sadly, I haven't managed to make that work with the above code, however. The OpenSSL library calls are never made and I haven't figured out why yet...

@gennadykr
Copy link

This makes it possible to add PSK support to paho-mqtt client.
A problem only appears with PSK ciphers, and context.set_ciphers('PSK') didn't help till I patched sslpsk a bit to work with python3.8.
Thanks a lot!

@maovidal
Copy link

I'm trying to make work the proposed by @paravoid on the paho-mqtt client. So far I haven't been able to achieve it. Here is what I have done so far: https://github.com/maovidal/paho_sslpsk2_demo/blob/main/paho_sslpsk2_demo.py

Any help would be much appreciated.

@ddurham2
Copy link

ddurham2 commented Aug 29, 2022

Wouldn't it be great to see this whole thing as an effort against python/cpython#63284

It states:

Please feel free to re-open it with a patch ...

doronz88 added a commit to doronz88/sslpsk that referenced this issue Nov 26, 2023
@doronz88
Copy link

@drbild I just submitted a tested PR with this fix and this works great. I would really appreciate it if you could review it

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

No branches or pull requests

5 participants