/** * daemon_authorize_method: * @daemon: a #Daemon * @invocation: method invocation handle * * Global hook used to authorize DBus methods. We restrict them to * root at the moment (but this forces the bridge to run as root). * * Possibly a better long term fix is that the bridge actually starts * cockpitd as root, opens a private socketpair between them to speak * DBus, then drops privileges. * * Returns: %TRUE if call should be authorized, %FALSE otherwise */ gboolean daemon_authorize_method (Daemon *daemon, GDBusMethodInvocation *invocation) { GError *error = NULL; gboolean is_authorized = FALSE; if (!authorize_method (daemon, invocation, &is_authorized, NULL, &error)) { g_warning ("Error while authorizing method %s.%s: %s", g_dbus_method_invocation_get_interface_name (invocation), g_dbus_method_invocation_get_method_name (invocation), error->message); g_clear_error (&error); return FALSE; } if (!is_authorized) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Method %s.%s cannot be invoked by non-root", g_dbus_method_invocation_get_interface_name (invocation), g_dbus_method_invocation_get_method_name (invocation)); } return is_authorized; }
static void List(cDBusObject *Object, GVariant *Parameters, GDBusMethodInvocation *Invocation) { if (g_strcmp0(g_dbus_method_invocation_get_interface_name(Invocation), DBUS_VDR_PLUGIN_INTERFACE) == 0) esyslog("dbus2vdr: use of deprecated interface: 'List' should be called with the interface '%s'!", DBUS_VDR_PLUGINMANAGER_INTERFACE); #define EMPTY(s) (s == NULL ? "" : s) GVariantBuilder *array = g_variant_builder_new(G_VARIANT_TYPE("a(ss)")); int index = 0; do { cPlugin *plugin = cPluginManager::GetPlugin(index); if (plugin == NULL) break; const char *name = plugin->Name(); const char *version = plugin->Version(); g_variant_builder_add(array, "(ss)", EMPTY(name), EMPTY(version)); index++; } while (true); #undef EMPTY GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("(a(ss))")); g_variant_builder_add_value(builder, g_variant_builder_end(array)); g_dbus_method_invocation_return_value(Invocation, g_variant_builder_end(builder)); g_variant_builder_unref(array); g_variant_builder_unref(builder); }
gboolean auth_check_uid_role (GDBusMethodInvocation *invocation, uid_t uid, const gchar *role) { int err = 0; gs_free struct passwd *pw = NULL; gs_free struct group *wheel_gr = NULL; gs_free struct group *role_gr = NULL; gs_free gid_t *gids = NULL; if (uid == 0) return TRUE; pw = getpwuid_a (uid, &err); if (pw == NULL) goto error; wheel_gr = getgrnam_a ("wheel", NULL); role_gr = role ? getgrnam_a (role, NULL) : NULL; int n_groups; gids = getgrouplist_a (pw->pw_name, pw->pw_gid, &n_groups, &err); if (gids == NULL) goto error; for (int i = 0; i < n_groups; i++) if ((wheel_gr && gids[i] == wheel_gr->gr_gid) || (role_gr && gids[i] == role_gr->gr_gid)) return TRUE; error: if (err) g_dbus_method_invocation_return_error (invocation, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "%s", strerror(err)); else g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Method %s.%s needs role '%s'", g_dbus_method_invocation_get_interface_name (invocation), g_dbus_method_invocation_get_method_name (invocation), role ? role : "wheel"); return FALSE; }