diff --git a/src/dbus_fast/auth.py b/src/dbus_fast/auth.py index 5ce353e5..5730fa17 100644 --- a/src/dbus_fast/auth.py +++ b/src/dbus_fast/auth.py @@ -4,6 +4,8 @@ from .errors import AuthError +UID_NOT_SPECIFIED = -1 + # The auth interface here is unstable. I would like to eventually open this up # for people to define their own custom authentication protocols, but I'm not # familiar with what's needed for that exactly. To work with any message bus @@ -57,6 +59,9 @@ class AuthExternal(Authenticator): """An authenticator class for the external auth protocol for use with the :class:`MessageBus `. + :param uid: The uid to use when connecting to the message bus. Use UID_NOT_SPECIFIED to use the uid known to the kernel. + :vartype uid: int + :sealso: https://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol """ @@ -68,6 +73,8 @@ def __init__(self, uid: int = None) -> None: def _authentication_start(self, negotiate_unix_fd: bool = False) -> str: self.negotiate_unix_fd = negotiate_unix_fd uid = self.uid + if uid == UID_NOT_SPECIFIED: + return "AUTH EXTERNAL" if uid is None: uid = os.getuid() hex_uid = str(uid).encode().hex() @@ -86,6 +93,9 @@ def _receive_line(self, line: str) -> str: if response is _AuthResponse.AGREE_UNIX_FD: return "BEGIN" + if response is _AuthResponse.DATA and self.uid == UID_NOT_SPECIFIED: + return "DATA" + raise AuthError(f"authentication failed: {response.value}: {args}") diff --git a/tests/test_auth.py b/tests/test_auth.py index 4fec0002..8c86056d 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -3,9 +3,19 @@ import pytest -from dbus_fast.auth import AuthExternal +from dbus_fast.auth import UID_NOT_SPECIFIED, AuthExternal +from dbus_fast.errors import AuthError def test_uid_is_set(): auth = AuthExternal(uid=999) assert auth._authentication_start() == "AUTH EXTERNAL 393939" + + +def test_auth_external_no_uid(): + """Test AuthExternal with UID_NOT_SPECIFIED""" + auth = AuthExternal(uid=UID_NOT_SPECIFIED) + assert auth._authentication_start() == "AUTH EXTERNAL" + assert auth._receive_line("DATA") == "DATA" + with pytest.raises(AuthError): + auth._receive_line("REJECTED")