diff --git a/etc-conf/dbus/polkit/com.redhat.RHSM1.policy b/etc-conf/dbus/polkit/com.redhat.RHSM1.policy
index 8d0407d4a8..746b1aa776 100644
--- a/etc-conf/dbus/polkit/com.redhat.RHSM1.policy
+++ b/etc-conf/dbus/polkit/com.redhat.RHSM1.policy
@@ -6,13 +6,17 @@
Red Hat Subscription Management
http://redhat.com
+
RHSM default
System policy prevents access to com.redhat.RHSM1
- yes
- yes
- yes
+ auth_admin
+ auth_admin
+ auth_admin_keep
diff --git a/etc-conf/dbus/system.d/com.redhat.RHSM1.conf b/etc-conf/dbus/system.d/com.redhat.RHSM1.conf
index 48b38e0c59..44c3dfa3ae 100644
--- a/etc-conf/dbus/system.d/com.redhat.RHSM1.conf
+++ b/etc-conf/dbus/system.d/com.redhat.RHSM1.conf
@@ -88,6 +88,21 @@
send_interface="com.redhat.RHSM1.Consumer"
send_member="GetUuid"/>
+
+
+
+
+
+
+
diff --git a/src/rhsmlib/client_info.py b/src/rhsmlib/client_info.py
index a7132266d3..f1346b03d5 100644
--- a/src/rhsmlib/client_info.py
+++ b/src/rhsmlib/client_info.py
@@ -36,6 +36,11 @@ class DBusSender:
@rhsm.utils.call_once
def __init__(self):
self._cmd_line = None
+ self._sender = None
+
+ @property
+ def sender(self):
+ return self._sender
@property
def cmd_line(self):
@@ -70,6 +75,7 @@ def set_cmd_line(self, sender, cmd_line=None, bus=None):
"""
if cmd_line is None:
self.cmd_line = self.get_cmd_line(sender, bus)
+ self._sender = sender
else:
self.cmd_line = cmd_line
log.debug("D-Bus sender: %s (cmd-line: %s)" % (sender, self.cmd_line))
diff --git a/src/rhsmlib/dbus/objects/register.py b/src/rhsmlib/dbus/objects/register.py
index c31151ddf0..b1f0df6ea3 100644
--- a/src/rhsmlib/dbus/objects/register.py
+++ b/src/rhsmlib/dbus/objects/register.py
@@ -94,8 +94,10 @@ def __init__(self, conn=None, object_path=None, bus_name=None):
out_signature="s",
)
@util.dbus_handle_sender
+ @util.dbus_admin_auth_policy
@util.dbus_handle_exceptions
def Start(self, locale, sender=None):
+ log.debug(f"D-Bus method: Start({locale}, {sender})")
locale = dbus_utils.dbus_to_python(locale, expected_type=str)
Locale.set(locale)
@@ -108,8 +110,10 @@ def Start(self, locale, sender=None):
out_signature="b",
)
@util.dbus_handle_sender
+ @util.dbus_admin_auth_policy
@util.dbus_handle_exceptions
def Stop(self, locale, sender=None):
+ log.debug(f"D-Bus method: Stop({locale}, {sender})")
locale = dbus_utils.dbus_to_python(locale, expected_type=str)
Locale.set(locale)
diff --git a/src/rhsmlib/dbus/objects/unregister.py b/src/rhsmlib/dbus/objects/unregister.py
index 8627045b02..29b029b6c4 100644
--- a/src/rhsmlib/dbus/objects/unregister.py
+++ b/src/rhsmlib/dbus/objects/unregister.py
@@ -73,6 +73,7 @@ def __init__(self, conn=None, object_path=None, bus_name=None):
out_signature="",
)
@util.dbus_handle_sender
+ @util.dbus_admin_auth_policy
@util.dbus_handle_exceptions
def Unregister(self, proxy_options, locale, sender=None):
"""
diff --git a/src/rhsmlib/dbus/util.py b/src/rhsmlib/dbus/util.py
index 266a8cba96..6dcc41c89d 100644
--- a/src/rhsmlib/dbus/util.py
+++ b/src/rhsmlib/dbus/util.py
@@ -14,16 +14,20 @@
import logging
import sys
import decorator
+import dbus
import dbus.service
import json
import re
from rhsmlib.dbus import exceptions
from rhsmlib.client_info import DBusSender
+from rhsmlib.dbus.dbus_utils import pid_of_sender, dbus_to_python
log = logging.getLogger(__name__)
__all__ = [
+ "dbus_admin_auth_policy",
+ "dbus_domain_admin_auth_policy",
"dbus_handle_exceptions",
"dbus_handle_sender",
"dbus_service_method",
@@ -31,6 +35,83 @@
]
+def _check_polkit_policy(sender, func, *args, **kwargs):
+ """
+ Check if given sender is authorized to call given function
+ """
+ bus = dbus.SystemBus()
+ try:
+ pid = pid_of_sender(bus, sender)
+ except Exception as err:
+ raise exceptions.RHSM1DBusException(f"Unable to get PID of sender: {sender}: {err}")
+ dbus_obj = bus.get_object("org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority")
+ dbus_iface = dbus.Interface(dbus_obj, "org.freedesktop.PolicyKit1.Authority")
+ subject = (
+ "unix-process",
+ {"pid": dbus.UInt32(pid), "start-time": dbus.UInt64(0)}
+ )
+ # TODO: Modify code to be able to use at least two IDs (one for "register" and another
+ # for "unregister")
+ action_id = "com.redhat.RHSM1.default"
+ details = {}
+ flags = 1
+ cancellation_id = ""
+
+ try:
+ is_authorized, is_challenge, details = dbus_iface.CheckAuthorization(
+ subject, action_id, details, flags, cancellation_id)
+ except Exception as err:
+ raise exceptions.RHSM1DBusException(f"Unable to check authorization of {sender}: {err}")
+ else:
+ is_authorized = dbus_to_python(is_authorized, expected_type=bool)
+ if is_authorized is True:
+ return func(*args, **kwargs)
+ else:
+ details = dbus_to_python(details, expected_type=dict)
+ raise exceptions.RHSM1DBusException(f"{sender} is not authorized to call {func}: {details}")
+
+
+@decorator.decorator
+def dbus_admin_auth_policy(func, *args, **kwargs):
+ """
+ When this decorator is used, then it is required that sender process
+ is admin authenticated. This is workaround for some applications using
+ our D-Bus API.
+ """
+
+ sender = None
+ # Get sender from arguments
+ if "sender" in kwargs:
+ sender = kwargs["sender"]
+ elif len(args) > 0:
+ sender = args[-1]
+
+ if sender is not None:
+ return _check_polkit_policy(sender, func, *args, **kwargs)
+ else:
+ raise exceptions.RHSM1DBusException(f"No sender specified, unable to check authorization for calling {func}")
+
+
+@decorator.decorator
+def dbus_domain_admin_auth_policy(func, *args, **kwargs):
+ """
+ This modified version of decorator dbus_admin_auth_policy(), but this could be
+ used in the case, when unix socket is used for registration
+ """
+ # TODO: This does not work as expected and it is not used ATM.
+ # The pid_of_sender() in _check_polkit_policy() is not able to
+ # find process for some reason, but process communicating over
+ # unix socket should be authorized by polkit.
+ with DBusSender() as dbus_sender:
+ sender = dbus_sender.sender
+ if sender is not None:
+ return _check_polkit_policy(sender, func, *args, **kwargs)
+ else:
+ raise exceptions.RHSM1DBusException(
+ f"No sender specified, unable to check authorization for calling {func}"
+ )
+
+
@decorator.decorator
def dbus_handle_sender(func, *args, **kwargs):
"""