polkit-github-migration-bot / t4_polkit

Other
0 stars 0 forks source link

Allow non-root user make dbus method calls #194

Closed polkit-github-migration-bot closed 7 months ago

polkit-github-migration-bot commented 1 year ago

In gitlab.freedesktop.org by arunlalkm-intel on Mar 20, 2023, 18:38

Link to the original issue: https://gitlab.freedesktop.org/polkit/polkit/-/issues/192 I am trying to allow non-root user to make dbus-method calls. As shows as bellow. busctl call xyz.openbmc_project.xxx /xyz/openbmc_project/xxx/data xyz.openbmc_project.Data GetData

But this is met with access denied from systemd. I would like to use polkit to solve this problem.

But since I am new to polkit, some guidance would be helpful.

polkit-github-migration-bot commented 1 year ago

In gitlab.freedesktop.org by halfline on Mar 20, 2023, 20:10

you don't need polkit to allow a non-root user to make method calls on a system bus service.

Instead, you need to install a conf file in /usr/share/dbus-1/system.d/ that allows non-root users access. Something like /usr/share/dbus-1/system.d/xyz.openbmc_project.xxx.conf

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE busconfig PUBLIC
 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">

<busconfig>
  <policy context="default">
    <allow send_destination="xyz.openbmc_project.xxx"
           send_interface="xyz.openbmc_project.Data"/>
  </policy>
</busconfig>

Of course that opens the call up to anyone. You could create a polkit action associated with the method call (or have one action for a group of related method calls), and only allow certain users to perform that action. Your dbus service would use polkit then to check if the caller is allowed to perform the action.

polkit-github-migration-bot commented 1 year ago

In gitlab.freedesktop.org by arunlalkm-intel on Mar 21, 2023, 06:43

I had already tried the conf file in /usr/share/dbus-1/system.d/ approach. And my observations are below. 1) These conf files are parsed by dbus-broker repo. 2) The default dbus configuration is to allow method calls, so if we do not add a conf file, it is still allowed. 3) "deny" can be done using conf files and was tested.

Coming back to issue I am facing. 1) dbus-broker and policy check is not the reason why method calls are failing for me. The call gets rejected from systemd. 2) 'Access Denied' failure response was coming from systemd recipe. From file systemd\src\libsystemd\sd-bus\bus-convenience.c method_callbacks_run->check_access fails

In case of root check_access->sd_bus_query_sender_privilege returns 1 because of the following condition

if (sender_uid == our_uid)
return 1;

In case of non-root check_access->sd_bus_query_sender_privilege function returns 0.

3) I reached out to systemd mailing list and polkit was given as suggestion.

Your following reply seems very promising to me. Can you tell me how to do this? :smile: "You could create a polkit action associated with the method call (or have one action for a group of related method calls), and only allow certain users to perform that action. Your dbus service would use polkit then to check if the caller is allowed to perform the action."

polkit-github-migration-bot commented 1 year ago

In gitlab.freedesktop.org by halfline on Mar 21, 2023, 15:56

oh I didn't realize you were using sd-bus. I'm not actually that familiar with it, but looking at the code, check_access has this:

•
static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) {•
...
        /* If the member is marked UNPRIVILEGED let's grant access */•
        if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED)•
                return 0;•
...
        r = sd_bus_query_sender_privilege(m, cap);•
...
}•

So it looks like there's a UNPRIVILEGED flag to allow different users to connect to the service.

╎❯ git grep SD_BUS_VTABLE_UNPRIVILEGED
...
test-bus-watch-bind.c:        SD_BUS_METHOD("Foobar", NULL, NULL, method_foobar, SD_BUS_VTABLE_UNPRIVILEGED),
test-bus-watch-bind.c:        SD_BUS_METHOD("Exit", NULL, NULL, method_exit, SD_BUS_VTABLE_UNPRIVILEGED),
test-vtable-data.h:        SD_BUS_METHOD("AlterSomething", "s", "s", handler, SD_BUS_VTABLE_UNPRIVILEGED),

So probably you need to put SD_BUS_VTABLE_UNPRIVILEGED in your SD_BUS_METHOD call to stop getting access denied.

(you could use polkit to lock things down in a more fine grained way after opening them up with UNPRIVILEGED, I think, but you're not going to be able to use polkit if sd-bus is denying the call before you even see it. But I believe using polkit requires adding api calls in your method handler to check if the user has permission to continue. I doubt sd-bus has builtin support for transparently using polkit, but I could be wrong.)

polkit-github-migration-bot commented 1 year ago

In gitlab.freedesktop.org by arunlalkm-intel on Mar 21, 2023, 16:55

check_access is from systemd. And from what reply I got from systemd maintainers, polkit is supported.

This is reply from systemd folks "method calls systemd#s services provide are usually protected by at least three levels: dbus policy (which as mentioned we mostly configure to be entirely open), polkit, and then selinux if that's available. Only if all three say "yes" we'll allow a call to go through."

Assuming that I open up calls to interface using SD_BUS_VTABLE_UNPRIVILEGED. How do I use polkit to say only root and user that I have configured can make method calls to these interfaces.

Can you give more clarity on following statement? "But I believe using polkit requires adding api calls in your method handler to check if the user has permission to continue."

And on "I doubt sd-bus has builtin support for transparently using polkit", is there a way I can check this?

From my observation calls are denied from systemd and not from sd-bus. I was hoping to use polkit to allow the same. Is this understanding correct?

polkit-github-migration-bot commented 1 year ago

In gitlab.freedesktop.org by halfline on Mar 21, 2023, 17:39

I'm not saying it's unlikely to be supported, I'm saying it's unlikely to be "built in" (but again I don't know the sd-bus api, so might be wrong). with the dbus libraries i've used, polkit, is usually a layer on top. So the call has to get through in the first place before you can bring polkit into the mix.

From your method call handler you might do something like:

authority = polkit_authority_get_sync (NULL, NULL);
subject = polkit_system_bus_name_new (bus_unique_name_of_sender);
result = polkit_authority_check_authorization_sync (authority,
                                                    subject,
                                                    "xyz.openbmc_project.readonly-data-access",
                                                    NULL,
                                                    POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
                                                    NULL,
                                                    NULL);

if (!polkit_authorization_result_is_authorized (result))
   return access denied error reply

(Or the equivalent using direct d-bus calls to org.freedesktop.PolicyKit1.Authority.CheckAuthorization)

then you'd have a polkit action installed like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
 "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
    <action id="xyz.openbmc_project.readonly-data-access">
      <description>Read-only access to openbmc data</description>
      <message>System policy prevents fetching openbmc data</message>
      <defaults>
        <allow_any>auth_admin_keep</allow_any>
        <allow_inactive>auth_admin_keep</allow_inactive>
        <allow_active>auth_admin_keep</allow_active>
      </defaults>
    </action>
</policyconfig>

This allows admin users access.

To allow a non-admin user named 'openbmcuser' access, you would add a polkit rule like:

polkit.addRule(function(action, subject) {
    // this rule only applies to the openbmcuser user
    if (subject.user !== 'openbmcuser')
        return undefined;

    // this rule only applies to the below action 
    if (action.id !== 'xyz.openbmc_project.readonly-data-access') 
        return undefined;

    return polkit.Result.YES;
});

afaict, check_access is part of sd-bus not dbus-broker or systemd or whatever. it's called before sd-bus dispatches an incoming method call to the service. aiui, polkit is not integrated with sd-bus, it gets run by the service after the method call has been dispatched.

polkit-github-migration-bot commented 1 year ago

In gitlab.freedesktop.org by halfline on Mar 21, 2023, 17:52

just poking around a little, it looks like projects inside the systemd source tree have access to a function called bus_verify_polkit_async which is the equivalent of polkit_authority_check_authorization_sync. That function is in src/shared/bus-polkit.c but it's not shipped as part of sd-bus, so it's only useful for projects shipped with systemd in-tree.

It could be something you might look to crib off of though.

polkit-github-migration-bot commented 1 year ago

In gitlab.freedesktop.org by halfline on Mar 21, 2023, 17:55

I'm going to go ahead and close this issue out since this isn't really a bug report.