Example #1
0
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);
}
Example #2
0
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);
}
Example #3
0
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;
}
Example #6
0
/**
 * 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;
}
Example #7
0
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);
}
Example #15
0
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;
}
Example #17
0
/**
 * 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;
}
Example #18
0
/**
 * 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;
}
Example #19
0
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);
    }
}
Example #20
0
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;
}