static void check_permissions_only (GConfDefaults *mechanism, DBusGMethodInvocation *context, gchar **actions, AuthObtainedCallback auth_obtained_callback, gpointer user_data, GDestroyNotify destroy) { CheckAuthData *data; data = g_new0 (CheckAuthData, 1); data->mechanism = g_object_ref (mechanism); data->context = context; data->actions = actions; data->flags = 0; data->id = 0; data->check_auth_callback = (GAsyncReadyCallback)check_authorization_only_callback; data->auth_obtained_callback = NULL; data->user_data = NULL; data->destroy = NULL; data->subject = polkit_system_bus_name_new (dbus_g_method_get_sender (context)); data->challenge = FALSE; check_next_action (data); }
PolkitResult polkit_check_authorization_dname(const char *dbus_name, const char *action_id) { glib_init(); PolkitSubject *subject = polkit_system_bus_name_new(dbus_name); return do_check(subject, action_id); }
static void check_polkit_for_actions (GConfDefaults *mechanism, DBusGMethodInvocation *context, gchar **actions, AuthObtainedCallback auth_obtained_callback, gpointer user_data, GDestroyNotify destroy) { CheckAuthData *data; data = g_new0 (CheckAuthData, 1); data->mechanism = g_object_ref (mechanism); data->context = context; data->actions = actions; data->flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION; data->id = 0; data->auth_obtained_callback = auth_obtained_callback; data->check_auth_callback = (GAsyncReadyCallback)check_authorization_callback; data->user_data = user_data; data->destroy = destroy; data->subject = polkit_system_bus_name_new (dbus_g_method_get_sender (context)); data->challenge = FALSE; check_next_action (data); }
void sys_log (GDBusMethodInvocation *context, const gchar *format, ...) { va_list args; gchar *msg; va_start (args, format); msg = g_strdup_vprintf (format, args); va_end (args); if (context) { PolkitSubject *subject; gchar *cmdline = NULL; gchar *id; GPid pid = 0; gint uid = -1; gchar *tmp; subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (context)); id = polkit_subject_to_string (subject); if (get_caller_pid (context, &pid)) { cmdline = get_cmdline_of_pid (pid); } else { pid = 0; cmdline = NULL; } if (cmdline != NULL) { if (get_caller_uid (context, &uid)) { tmp = g_strdup_printf ("request by %s [%s pid:%d uid:%d]: %s", id, cmdline, (int) pid, uid, msg); } else { tmp = g_strdup_printf ("request by %s [%s pid:%d]: %s", id, cmdline, (int) pid, msg); } } else { if (get_caller_uid (context, &uid) && pid != 0) { tmp = g_strdup_printf ("request by %s [pid:%d uid:%d]: %s", id, (int) pid, uid, msg); } else if (pid != 0) { tmp = g_strdup_printf ("request by %s [pid:%d]: %s", id, (int) pid, msg); } else { tmp = g_strdup_printf ("request by %s: %s", id, msg); } } g_free (msg); msg = tmp; g_free (id); g_free (cmdline); g_object_unref (subject); } syslog (LOG_NOTICE, "%s", msg); g_free (msg); }
/* * This handler is run in a separate thread, so all operations can be * synchronous. */ static gboolean on_authorize_method_check (GDBusInterfaceSkeleton *interface, GDBusMethodInvocation *invocation, EmerDaemon *daemon) { const gchar *method_name = g_dbus_method_invocation_get_method_name (invocation); const AuthorizedMethod *authorized_method = lookup_authorized_method (method_name); if (authorized_method == NULL) return TRUE; GError *error = NULL; PolkitAuthority *authority = polkit_authority_get_sync (NULL /*GCancellable*/, &error); if (authority == NULL) { g_critical ("Could not get PolicyKit authority: %s.", error->message); g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); return FALSE; } const gchar *sender_name = g_dbus_method_invocation_get_sender (invocation); PolkitSubject *subject = polkit_system_bus_name_new (sender_name); PolkitAuthorizationResult *result = polkit_authority_check_authorization_sync (authority, subject, authorized_method->method_full_name, NULL /*PolkitDetails*/, POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE, NULL /*GCancellable*/, &error); g_object_unref (authority); g_object_unref (subject); if (result == NULL) { g_critical ("Could not get PolicyKit authorization result: %s.", error->message); g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); return FALSE; } gboolean authorized = polkit_authorization_result_get_is_authorized (result); if (!authorized) g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_AUTH_FAILED, authorized_method->error_message); g_object_unref (result); return authorized; }
/** * bus_installer_install_local_cb: */ static gboolean bus_installer_install_local_cb (LiProxyManager *mgr_bus, GDBusMethodInvocation *context, const gchar *fname, LiHelperDaemon *helper) { GError *error = NULL; LiInstaller *inst = NULL; PolkitAuthorizationResult *pres = NULL; PolkitSubject *subject; const gchar *sender; sender = g_dbus_method_invocation_get_sender (context); subject = polkit_system_bus_name_new (sender); pres = polkit_authority_check_authorization_sync (helper->authority, subject, "org.freedesktop.limba.install-package-local", NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, NULL, &error); g_object_unref (subject); if (error != NULL) { g_dbus_method_invocation_take_error (context, error); goto out; } if (!polkit_authorization_result_get_is_authorized (pres)) { g_dbus_method_invocation_return_dbus_error (context, "org.freedesktop.Limba.Installer.Error.NotAuthorized", "Authorization failed."); goto out; } /* initialize our job, in case it is idling */ if (!li_daemon_init_job (helper, mgr_bus, context)) goto out; /* do the thing */ li_daemon_job_run_install_local (helper->job, fname); li_proxy_manager_complete_install_local (mgr_bus, context); out: if (inst != NULL) g_object_unref (inst); if (pres != NULL) g_object_unref (pres); li_daemon_reset_timer (helper); return TRUE; }
static gboolean _add_call_polkit (NMAuthChain *self, const char *permission, gboolean allow_interaction) { PolkitSubject *subject; PolkitCheckAuthorizationFlags flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; AuthCall *call; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (self->owner || self->subject, FALSE); g_return_val_if_fail (permission != NULL, FALSE); call = auth_call_new (self, permission); if (self->authority == NULL) { /* No polkit, no authorization */ auth_call_schedule_complete_with_error (call, "PolicyKit not running"); return FALSE; } if (self->subject) { subject = g_object_ref (nm_auth_subject_get_polkit_subject (self->subject)); g_assert (subject); } else { g_assert (self->owner); subject = polkit_system_bus_name_new (self->owner); if (!subject) { auth_call_schedule_complete_with_error (call, "Failed to create polkit subject"); return FALSE; } } if (allow_interaction) flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION; call->cancellable = g_cancellable_new (); polkit_authority_check_authorization (self->authority, subject, permission, NULL, flags, call->cancellable, pk_call_cb, call); g_object_unref (subject); return TRUE; }
gboolean cpufreq_selector_service_can_set (CPUFreqSelectorService *service, DBusGMethodInvocation *context) { PolkitSubject *subject; PolkitAuthorizationResult *result; gchar *sender; gboolean ret; GError *error = NULL; reset_killtimer (); sender = dbus_g_method_get_sender (context); subject = polkit_system_bus_name_new (sender); g_free (sender); result = polkit_authority_check_authorization_sync (service->authority, subject, "org.consort.cpufreqselector", NULL, 0, NULL, &error); g_object_unref (subject); if (error) { dbus_g_method_return_error (context, error); g_error_free (error); return FALSE; } if (polkit_authorization_result_get_is_authorized (result)) { ret = TRUE; } else if (polkit_authorization_result_get_is_challenge (result)) { ret = TRUE; } else { ret = FALSE; } g_object_unref (result); dbus_g_method_return (context, ret); return TRUE; }
static gboolean _check_polkit_for_action (GsdDatetimeMechanism *mechanism, DBusGMethodInvocation *context) { const char *action = "org.gnome.settingsdaemon.datetimemechanism.configure"; const char *sender; GError *error; PolkitSubject *subject; PolkitAuthorizationResult *result; error = NULL; /* Check that caller is privileged */ sender = dbus_g_method_get_sender (context); subject = polkit_system_bus_name_new (sender); result = polkit_authority_check_authorization_sync (mechanism->priv->auth, subject, action, NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, NULL, &error); g_object_unref (subject); if (error) { dbus_g_method_return_error (context, error); g_error_free (error); return FALSE; } if (!polkit_authorization_result_get_is_authorized (result)) { error = g_error_new (GSD_DATETIME_MECHANISM_ERROR, GSD_DATETIME_MECHANISM_ERROR_NOT_PRIVILEGED, "Not Authorized for action %s", action); dbus_g_method_return_error (context, error); g_error_free (error); g_object_unref (result); return FALSE; } g_object_unref (result); return TRUE; }
static void authorize (MMAuthProvider *self, GDBusMethodInvocation *invocation, const gchar *authorization, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { MMAuthProviderPolkit *polkit = MM_AUTH_PROVIDER_POLKIT (self); AuthorizeContext *ctx; /* When creating the object, we actually allowed errors when looking for the * authority. If that is the case, we'll just forbid any incoming * authentication request */ if (!polkit->priv->authority) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "PolicyKit authorization error: " "'authority not found'"); return; } ctx = g_new (AuthorizeContext, 1); ctx->self = g_object_ref (self); ctx->invocation = g_object_ref (invocation); ctx->authorization = g_strdup (authorization); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; ctx->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, authorize); ctx->subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (ctx->invocation)); polkit_authority_check_authorization (polkit->priv->authority, ctx->subject, authorization, NULL, /* details */ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, ctx->cancellable, (GAsyncReadyCallback)check_authorization_ready, ctx); }
static void check_can_do (GsdDatetimeMechanism *mechanism, const char *action, DBusGMethodInvocation *context) { const char *sender; PolkitSubject *subject; PolkitAuthorizationResult *result; GError *error; /* Check that caller is privileged */ sender = dbus_g_method_get_sender (context); subject = polkit_system_bus_name_new (sender); error = NULL; result = polkit_authority_check_authorization_sync (mechanism->priv->auth, subject, action, NULL, 0, NULL, &error); g_object_unref (subject); if (error) { dbus_g_method_return_error (context, error); g_error_free (error); return; } if (polkit_authorization_result_get_is_authorized (result)) { dbus_g_method_return (context, 2); } else if (polkit_authorization_result_get_is_challenge (result)) { dbus_g_method_return (context, 1); } else { dbus_g_method_return (context, 0); } g_object_unref (result); }
/* PolicyKit */ static gboolean cpufreq_selector_service_check_policy (CPUFreqSelectorService *service, DBusGMethodInvocation *context, GError **error) { PolkitSubject *subject; PolkitAuthorizationResult *result; gchar *sender; gboolean ret; sender = dbus_g_method_get_sender (context); subject = polkit_system_bus_name_new (sender); g_free (sender); result = polkit_authority_check_authorization_sync (service->authority, subject, "org.consort.cpufreqselector", NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, NULL, error); g_object_unref (subject); if (*error) { g_warning ("Check policy: %s", (*error)->message); g_object_unref (result); return FALSE; } ret = polkit_authorization_result_get_is_authorized (result); if (!ret) { g_set_error (error, CPUFREQ_SELECTOR_SERVICE_ERROR, SERVICE_ERROR_NOT_AUTHORIZED, "Caller is not authorized"); } g_object_unref (result); return ret; }
static gboolean _fprint_device_check_polkit_for_action (FprintDevice *rdev, DBusGMethodInvocation *context, const char *action, GError **error) { FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); const char *sender; PolkitSubject *subject; PolkitAuthorizationResult *result; GError *_error = NULL; /* Check that caller is privileged */ sender = dbus_g_method_get_sender (context); subject = polkit_system_bus_name_new (sender); result = polkit_authority_check_authorization_sync (priv->auth, subject, action, NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, NULL, &_error); g_object_unref (subject); if (result == NULL) { g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_PERMISSION_DENIED, "Not Authorized: %s", _error->message); g_error_free (_error); return FALSE; } if (!polkit_authorization_result_get_is_authorized (result)) { g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_PERMISSION_DENIED, "Not Authorized: %s", action); g_object_unref (result); return FALSE; } g_object_unref (result); return TRUE; }
void daemon_local_check_auth (Daemon *daemon, User *user, const gchar *action_id, gboolean allow_interaction, AuthorizedCallback authorized_cb, GDBusMethodInvocation *context, gpointer authorized_cb_data, GDestroyNotify destroy_notify) { CheckAuthData *data; PolkitSubject *subject; PolkitCheckAuthorizationFlags flags; data = g_new0 (CheckAuthData, 1); data->daemon = g_object_ref (daemon); if (user) data->user = g_object_ref (user); data->context = context; data->authorized_cb = authorized_cb; data->data = authorized_cb_data; data->destroy_notify = destroy_notify; subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (context)); flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; if (allow_interaction) flags |= POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION; polkit_authority_check_authorization (daemon->priv->authority, subject, action_id, NULL, flags, NULL, (GAsyncReadyCallback) check_auth_cb, data); g_object_unref (subject); }
gboolean bm_auth_chain_add_call (BMAuthChain *self, const char *permission, gboolean allow_interaction) { PolkitCall *call; PolkitSubject *subject; PolkitCheckAuthorizationFlags flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (self->owner != NULL, FALSE); g_return_val_if_fail (permission != NULL, FALSE); subject = polkit_system_bus_name_new (self->owner); if (!subject) return FALSE; call = g_malloc0 (sizeof (PolkitCall)); call->chain = self; call->permission = g_strdup (permission); call->cancellable = g_cancellable_new (); self->calls = g_slist_append (self->calls, call); if (allow_interaction) flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION; polkit_authority_check_authorization (self->authority, subject, permission, NULL, flags, call->cancellable, pk_call_cb, call); g_object_unref (subject); return TRUE; }
GObject * mm_auth_request_polkit_new (PolkitAuthority *authority, const char *authorization, GObject *owner, DBusGMethodInvocation *context, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify) { GObject *obj; MMAuthRequestPolkitPrivate *priv; char *sender; g_return_val_if_fail (authorization != NULL, NULL); g_return_val_if_fail (owner != NULL, NULL); g_return_val_if_fail (callback != NULL, NULL); g_return_val_if_fail (context != NULL, NULL); obj = mm_auth_request_new (MM_TYPE_AUTH_REQUEST_POLKIT, authorization, owner, context, callback, callback_data, notify); if (obj) { priv = MM_AUTH_REQUEST_POLKIT_GET_PRIVATE (obj); priv->authority = authority; priv->cancellable = g_cancellable_new (); sender = dbus_g_method_get_sender (context); priv->subject = polkit_system_bus_name_new (sender); g_free (sender); } return obj; }
/** * cd_main_sender_authenticated: **/ gboolean cd_main_sender_authenticated (GDBusConnection *connection, const gchar *sender, const gchar *action_id, GError **error) { gboolean ret = FALSE; GError *error_local = NULL; guint uid; #ifdef USE_POLKIT PolkitAuthorizationResult *result = NULL; PolkitSubject *subject = NULL; PolkitAuthority *authority = NULL; #endif /* uid 0 is allowed to do all actions */ uid = cd_main_get_sender_uid (connection, sender, &error_local); if (uid == G_MAXUINT) { g_set_error (error, CD_CLIENT_ERROR, CD_CLIENT_ERROR_FAILED_TO_AUTHENTICATE, "could not get uid to authenticate %s: %s", action_id, error_local->message); g_error_free (error_local); goto out; } /* the root user can always do all actions */ if (uid == 0) { g_debug ("CdCommon: not checking %s for %s as uid 0", action_id, sender); ret = TRUE; goto out; } /* a client running as the daemon user may also do all actions */ if (uid == getuid ()) { g_debug ("CdCommon: not checking %s for %s as running as daemon user", action_id, sender); ret = TRUE; goto out; } #ifdef USE_POLKIT /* get authority */ authority = polkit_authority_get_sync (NULL, &error_local); if (authority == NULL) { g_set_error (error, CD_CLIENT_ERROR, CD_CLIENT_ERROR_FAILED_TO_AUTHENTICATE, "failed to get polkit authorit: %s", error_local->message); g_error_free (error_local); goto out; } /* do authorization async */ subject = polkit_system_bus_name_new (sender); result = polkit_authority_check_authorization_sync (authority, subject, action_id, NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, NULL, &error_local); if (result == NULL) { g_set_error (error, CD_CLIENT_ERROR, CD_CLIENT_ERROR_FAILED_TO_AUTHENTICATE, "could not check %s for auth: %s", action_id, error_local->message); g_error_free (error_local); goto out; } /* did not auth */ if (!polkit_authorization_result_get_is_authorized (result)) { g_set_error (error, CD_CLIENT_ERROR, CD_CLIENT_ERROR_FAILED_TO_AUTHENTICATE, "failed to obtain %s auth", action_id); goto out; } #else g_warning ("CdCommon: not checking %s for %s as no PolicyKit support", action_id, sender); #endif /* success */ ret = TRUE; out: #ifdef USE_POLKIT if (authority != NULL) g_object_unref (authority); if (result != NULL) g_object_unref (result); if (subject != NULL) g_object_unref (subject); #endif return ret; }
/** * udisks_daemon_util_check_authorization_sync: * @daemon: A #UDisksDaemon. * @object: (allow-none): The #GDBusObject that the call is on or %NULL. * @action_id: The action id to check for. * @options: (allow-none): A #GVariant to check for the <quote>auth.no_user_interaction</quote> option or %NULL. * @message: The message to convey (use N_). * @invocation: The invocation to check for. * * Checks if the caller represented by @invocation is authorized for * the action identified by @action_id, optionally displaying @message * if authentication is needed. Additionally, if the caller is not * authorized, the appropriate error is already returned to the caller * via @invocation. * * The calling thread is blocked for the duration of the authorization * check which could be a very long time since it may involve * presenting an authentication dialog and having a human user use * it. If <quote>auth.no_user_interaction</quote> in @options is %TRUE * no authentication dialog will be presented and the check is not * expected to take a long time. * * See <xref linkend="udisks-polkit-details"/> for the variables that * can be used in @message but note that not all variables can be used * in all checks. For example, any check involving a #UDisksDrive or a * #UDisksBlock object can safely include the fragment * <quote>$(drive)</quote> since it will always expand to the name of * the drive, e.g. <quote>INTEL SSDSA2MH080G1GC (/dev/sda1)</quote> or * the block device file e.g. <quote>/dev/vg_lucifer/lv_root</quote> * or <quote>/dev/sda1</quote>. However this won't work for operations * that isn't on a drive or block device, for example calls on the * <link linkend="gdbus-interface-org-freedesktop-UDisks2-Manager.top_of_page">Manager</link> * object. * * Returns: %TRUE if caller is authorized, %FALSE if not. */ gboolean udisks_daemon_util_check_authorization_sync (UDisksDaemon *daemon, UDisksObject *object, const gchar *action_id, GVariant *options, const gchar *message, GDBusMethodInvocation *invocation) { PolkitAuthority *authority = NULL; PolkitSubject *subject = NULL; PolkitDetails *details = NULL; PolkitCheckAuthorizationFlags flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; PolkitAuthorizationResult *result = NULL; GError *error = NULL; gboolean ret = FALSE; UDisksBlock *block = NULL; UDisksDrive *drive = NULL; UDisksPartition *partition = NULL; UDisksObject *block_object = NULL; UDisksObject *drive_object = NULL; gboolean auth_no_user_interaction = FALSE; const gchar *details_device = NULL; gchar *details_drive = NULL; authority = udisks_daemon_get_authority (daemon); if (authority == NULL) { ret = check_authorization_no_polkit (daemon, object, action_id, options, message, invocation); goto out; } subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (invocation)); if (options != NULL) { g_variant_lookup (options, "auth.no_user_interaction", "b", &auth_no_user_interaction); } if (!auth_no_user_interaction) flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION; details = polkit_details_new (); polkit_details_insert (details, "polkit.message", message); polkit_details_insert (details, "polkit.gettext_domain", "udisks2"); /* Find drive associated with the block device, if any */ if (object != NULL) { block = udisks_object_get_block (object); if (block != NULL) { block_object = g_object_ref (object); drive_object = udisks_daemon_find_object (daemon, udisks_block_get_drive (block)); if (drive_object != NULL) drive = udisks_object_get_drive (drive_object); } partition = udisks_object_get_partition (object); if (drive == NULL) drive = udisks_object_get_drive (object); } if (block != NULL) details_device = udisks_block_get_preferred_device (block); /* If we have a drive, use vendor/model in the message (in addition to Block:preferred-device) */ if (drive != NULL) { gchar *s; const gchar *vendor; const gchar *model; vendor = udisks_drive_get_vendor (drive); model = udisks_drive_get_model (drive); if (vendor == NULL) vendor = ""; if (model == NULL) model = ""; if (strlen (vendor) > 0 && strlen (model) > 0) s = g_strdup_printf ("%s %s", vendor, model); else if (strlen (vendor) > 0) s = g_strdup (vendor); else s = g_strdup (model); if (block != NULL) { details_drive = g_strdup_printf ("%s (%s)", s, udisks_block_get_preferred_device (block)); } else { details_drive = s; s = NULL; } g_free (s); _safe_polkit_details_insert (details, "drive.wwn", udisks_drive_get_wwn (drive)); _safe_polkit_details_insert (details, "drive.serial", udisks_drive_get_serial (drive)); _safe_polkit_details_insert (details, "drive.vendor", udisks_drive_get_vendor (drive)); _safe_polkit_details_insert (details, "drive.model", udisks_drive_get_model (drive)); _safe_polkit_details_insert (details, "drive.revision", udisks_drive_get_revision (drive)); if (udisks_drive_get_removable (drive)) { const gchar *const *media_compat; GString *media_compat_str; const gchar *sep = ","; polkit_details_insert (details, "drive.removable", "true"); _safe_polkit_details_insert (details, "drive.removable.bus", udisks_drive_get_connection_bus (drive)); media_compat_str = g_string_new (NULL); media_compat = udisks_drive_get_media_compatibility (drive); if (media_compat) { guint i; for (i = 0; media_compat[i] && strlen(media_compat[i]); i++) { if (i) g_string_append (media_compat_str, sep); g_string_append (media_compat_str, media_compat[i]); } } _safe_polkit_details_insert (details, "drive.removable.media", media_compat_str->str); g_string_free (media_compat_str, TRUE); } } if (block != NULL) { _safe_polkit_details_insert (details, "id.type", udisks_block_get_id_type (block)); _safe_polkit_details_insert (details, "id.usage", udisks_block_get_id_usage (block)); _safe_polkit_details_insert (details, "id.version", udisks_block_get_id_version (block)); _safe_polkit_details_insert (details, "id.label", udisks_block_get_id_label (block)); _safe_polkit_details_insert (details, "id.uuid", udisks_block_get_id_uuid (block)); } if (partition != NULL) { _safe_polkit_details_insert_int (details, "partition.number", udisks_partition_get_number (partition)); _safe_polkit_details_insert (details, "partition.type", udisks_partition_get_type_ (partition)); _safe_polkit_details_insert_uint64 (details, "partition.flags", udisks_partition_get_flags (partition)); _safe_polkit_details_insert (details, "partition.name", udisks_partition_get_name (partition)); _safe_polkit_details_insert (details, "partition.uuid", udisks_partition_get_uuid (partition)); } /* Fall back to Block:preferred-device */ if (details_drive == NULL && block != NULL) details_drive = udisks_block_dup_preferred_device (block); if (details_device != NULL) polkit_details_insert (details, "device", details_device); if (details_drive != NULL) polkit_details_insert (details, "drive", details_drive); error = NULL; result = polkit_authority_check_authorization_sync (authority, subject, action_id, details, flags, NULL, /* GCancellable* */ &error); if (result == NULL) { if (error->domain != POLKIT_ERROR) { /* assume polkit authority is not available (e.g. could be the service * manager returning org.freedesktop.systemd1.Masked) */ g_error_free (error); ret = check_authorization_no_polkit (daemon, object, action_id, options, message, invocation); } else { g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED, "Error checking authorization: %s (%s, %d)", error->message, g_quark_to_string (error->domain), error->code); g_error_free (error); } goto out; } if (!polkit_authorization_result_get_is_authorized (result)) { if (polkit_authorization_result_get_dismissed (result)) g_dbus_method_invocation_return_error_literal (invocation, UDISKS_ERROR, UDISKS_ERROR_NOT_AUTHORIZED_DISMISSED, "The authentication dialog was dismissed"); else g_dbus_method_invocation_return_error_literal (invocation, UDISKS_ERROR, polkit_authorization_result_get_is_challenge (result) ? UDISKS_ERROR_NOT_AUTHORIZED_CAN_OBTAIN : UDISKS_ERROR_NOT_AUTHORIZED, "Not authorized to perform operation"); goto out; } ret = TRUE; out: g_free (details_drive); g_clear_object (&block_object); g_clear_object (&drive_object); g_clear_object (&block); g_clear_object (&partition); g_clear_object (&drive); g_clear_object (&subject); g_clear_object (&details); g_clear_object (&result); return ret; }
static void invocation_client_create (GDBusConnection *connection, const gchar *bus_name) { InvocationClient *client; g_mutex_lock (&inv.mutex); client = g_hash_table_lookup (inv.clients, bus_name); g_mutex_unlock (&inv.mutex); if (client != NULL) return; /* * Each time we see an incoming function call, keep the service alive for * that client, and each invocation of the client * * We would also like to get client credentials here and not pass client * messages into the rest of the machinery until that has completed. * Unfortunately the necessary patch in gio has not yet been merged. * * So we do an async call and if it hasn't completed by the time we need * the caller credentials, then we block and wait for it. Since it's the * system bus responding, it should respond pretty quickly. * * See invocation_client_lookup() for the waiting side of things. */ client = g_new0 (InvocationClient, 1); client->bus_name = g_strdup (bus_name); client->subject = polkit_system_bus_name_new (bus_name); client->refs = 1; client->uid_peer = ~0; client->uid_state = UID_LOADING; client->watch = g_bus_watch_name_on_connection (connection, bus_name, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, on_client_vanished, NULL, NULL); g_debug ("GetConnectionUnixUser('%s') ...", bus_name); /* * This async call in the GDBusWorker thread main context will not * be blocked by the daemon main context blocking. */ g_dbus_connection_call (connection, "org.freedesktop.DBus", /* bus name */ "/org/freedesktop/DBus", /* object path */ "org.freedesktop.DBus", /* interface */ "GetConnectionUnixUser", /* method */ g_variant_new ("(s)", bus_name), G_VARIANT_TYPE ("(u)"), G_DBUS_CALL_FLAGS_NONE, -1, /* timeout_msec */ NULL, on_get_connection_unix_user, g_strdup (bus_name)); g_mutex_lock (&inv.mutex); if (!g_hash_table_lookup (inv.clients, bus_name)) { g_hash_table_replace (inv.clients, client->bus_name, client); client = NULL; } g_mutex_unlock (&inv.mutex); if (client) { invocation_client_unref (client); } else { g_main_context_invoke_full (NULL, G_PRIORITY_DEFAULT, on_invoke_client_appeared, g_strdup (bus_name), g_free); } }
static gboolean flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface, GDBusMethodInvocation *invocation, gpointer user_data) { const gchar *method_name = g_dbus_method_invocation_get_method_name (invocation); const gchar *sender = g_dbus_method_invocation_get_sender (invocation); GVariant *parameters = g_dbus_method_invocation_get_parameters (invocation); g_autoptr(AutoPolkitSubject) subject = polkit_system_bus_name_new (sender); g_autoptr(AutoPolkitDetails) details = polkit_details_new (); const gchar *action = NULL; gboolean authorized = FALSE; /* Ensure we don't idle exit */ schedule_idle_callback (); if (on_session_bus) { /* This is test code, make sure it never runs with privileges */ g_assert (geteuid () != 0); g_assert (getuid () != 0); g_assert (getegid () != 0); g_assert (getgid () != 0); authorized = TRUE; } else if (g_strcmp0 (method_name, "Deploy") == 0) { const char *ref, *origin; guint32 flags; gboolean is_update, is_app; g_variant_get_child (parameters, 1, "u", &flags); g_variant_get_child (parameters, 2, "&s", &ref); g_variant_get_child (parameters, 3, "&s", &origin); is_update = (flags & FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE) != 0; is_app = g_str_has_prefix (ref, "app/"); if (is_update) { if (is_app) action = "org.freedesktop.Flatpak.app-update"; else action = "org.freedesktop.Flatpak.runtime-update"; } else { if (is_app) action = "org.freedesktop.Flatpak.app-install"; else action = "org.freedesktop.Flatpak.runtime-install"; } polkit_details_insert (details, "origin", origin); polkit_details_insert (details, "ref", ref); } else if (g_strcmp0 (method_name, "DeployAppstream") == 0) { const char *arch, *origin; g_variant_get_child (parameters, 1, "&s", &origin); g_variant_get_child (parameters, 2, "&s", &arch); action = "org.freedesktop.Flatpak.appstream-update"; polkit_details_insert (details, "origin", origin); polkit_details_insert (details, "arch", arch); } else if (g_strcmp0 (method_name, "InstallBundle") == 0) { const char *path; g_variant_get_child (parameters, 0, "^&ay", &path); action = "org.freedesktop.Flatpak.install-bundle"; polkit_details_insert (details, "path", path); } else if (g_strcmp0 (method_name, "Uninstall") == 0) { const char *ref; gboolean is_app; g_variant_get_child (parameters, 1, "&s", &ref); is_app = g_str_has_prefix (ref, "app/"); if (is_app) action = "org.freedesktop.Flatpak.app-uninstall"; else action = "org.freedesktop.Flatpak.runtime-uninstall"; polkit_details_insert (details, "ref", ref); } else if (g_strcmp0 (method_name, "ConfigureRemote") == 0) { const char *remote; g_variant_get_child (parameters, 1, "&s", &remote); action = "org.freedesktop.Flatpak.configure-remote"; polkit_details_insert (details, "remote", remote); } if (action) { g_autoptr(AutoPolkitAuthorizationResult) result; g_autoptr(GError) error = NULL; result = polkit_authority_check_authorization_sync (authority, subject, action, details, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, NULL, &error); if (result == NULL) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Authorization error: %s", error->message); return FALSE; } authorized = polkit_authorization_result_get_is_authorized (result); } if (!authorized) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Flatpak system operation %s not allowed for user", method_name); } return authorized; }