aboutsummaryrefslogtreecommitdiff
path: root/src/mm-auth-provider-polkit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-auth-provider-polkit.c')
-rw-r--r--src/mm-auth-provider-polkit.c232
1 files changed, 133 insertions, 99 deletions
diff --git a/src/mm-auth-provider-polkit.c b/src/mm-auth-provider-polkit.c
index 05c3bf35..9c1a11ea 100644
--- a/src/mm-auth-provider-polkit.c
+++ b/src/mm-auth-provider-polkit.c
@@ -10,32 +10,28 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
- * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2010 - 2012 Red Hat, Inc.
+ * Copyright (C) 2012 Google, Inc.
*/
#include <polkit/polkit.h>
#include <config.h>
-#include "mm-auth-request-polkit.h"
+
+#include <libmm-common.h>
+
+#include "mm-log.h"
#include "mm-auth-provider-polkit.h"
G_DEFINE_TYPE (MMAuthProviderPolkit, mm_auth_provider_polkit, MM_TYPE_AUTH_PROVIDER)
-#define MM_AUTH_PROVIDER_POLKIT_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_AUTH_PROVIDER_POLKIT, MMAuthProviderPolkitPrivate))
-
-typedef struct {
+struct _MMAuthProviderPolkitPrivate {
PolkitAuthority *authority;
- guint auth_changed_id;
-} MMAuthProviderPolkitPrivate;
-
-enum {
- PROP_NAME = 1000,
};
/*****************************************************************************/
-GObject *
+MMAuthProvider *
mm_auth_provider_polkit_new (void)
{
return g_object_new (MM_TYPE_AUTH_PROVIDER_POLKIT, NULL);
@@ -43,112 +39,155 @@ mm_auth_provider_polkit_new (void)
/*****************************************************************************/
-static void
-pk_authority_changed_cb (GObject *object, gpointer user_data)
-{
- /* Let clients know they should re-check their authorization */
-}
-
-/*****************************************************************************/
+typedef struct {
+ MMAuthProvider *self;
+ GCancellable *cancellable;
+ PolkitSubject *subject;
+ gchar *authorization;
+ GDBusMethodInvocation *invocation;
+ GSimpleAsyncResult *result;
+} AuthorizeContext;
-static MMAuthRequest *
-real_create_request (MMAuthProvider *provider,
- const char *authorization,
- GObject *owner,
- GDBusMethodInvocation *context,
- MMAuthRequestCb callback,
- gpointer callback_data,
- GDestroyNotify notify)
+static void
+authorize_context_complete_and_free (AuthorizeContext *ctx)
{
- MMAuthProviderPolkitPrivate *priv = MM_AUTH_PROVIDER_POLKIT_GET_PRIVATE (provider);
-
- return (MMAuthRequest *) mm_auth_request_polkit_new (priv->authority,
- authorization,
- owner,
- context,
- callback,
- callback_data,
- notify);
+ g_simple_async_result_complete (ctx->result);
+ g_object_unref (ctx->result);
+ if (ctx->cancellable)
+ g_object_unref (ctx->cancellable);
+ g_object_unref (ctx->invocation);
+ g_object_unref (ctx->subject);
+ g_object_unref (ctx->self);
+ g_free (ctx->authorization);
+ g_free (ctx);
}
-/*****************************************************************************/
-
-/* Fix for polkit 0.97 and later */
-#if !HAVE_POLKIT_AUTHORITY_GET_SYNC
-static inline PolkitAuthority *
-polkit_authority_get_sync (GCancellable *cancellable, GError **error)
+static gboolean
+authorize_finish (MMAuthProvider *self,
+ GAsyncResult *res,
+ GError **error)
{
- PolkitAuthority *authority;
-
- authority = polkit_authority_get ();
- if (!authority)
- g_set_error (error, 0, 0, "failed to get the PolicyKit authority");
- return authority;
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
}
-#endif
static void
-mm_auth_provider_polkit_init (MMAuthProviderPolkit *self)
+check_authorization_ready (PolkitAuthority *authority,
+ GAsyncResult *res,
+ AuthorizeContext *ctx)
{
- MMAuthProviderPolkitPrivate *priv = MM_AUTH_PROVIDER_POLKIT_GET_PRIVATE (self);
- GError *error = NULL;
+ PolkitAuthorizationResult *pk_result;
+ GError *error = NULL;
+
+ if (g_cancellable_is_cancelled (ctx->cancellable)) {
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_CANCELLED,
+ "PolicyKit authorization attempt cancelled");
+ authorize_context_complete_and_free (ctx);
+ return;
+ }
- priv->authority = polkit_authority_get_sync (NULL, &error);
- if (priv->authority) {
- priv->auth_changed_id = g_signal_connect (priv->authority,
- "changed",
- G_CALLBACK (pk_authority_changed_cb),
- self);
+ pk_result = polkit_authority_check_authorization_finish (authority, res, &error);
+ if (!pk_result) {
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "PolicyKit authorization failed: '%s'",
+ error->message);
+ g_error_free (error);
} else {
- g_warning ("%s: failed to create PolicyKit authority: (%d) %s",
- __func__,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- g_clear_error (&error);
+ if (polkit_authorization_result_get_is_authorized (pk_result))
+ /* Good! */
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ else if (polkit_authorization_result_get_is_challenge (pk_result))
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNAUTHORIZED,
+ "PolicyKit authorization failed: challenge needed for '%s'",
+ ctx->authorization);
+ else
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNAUTHORIZED,
+ "PolicyKit authorization failed: not authorized for '%s'",
+ ctx->authorization);
+ g_object_unref (pk_result);
}
+
+ authorize_context_complete_and_free (ctx);
}
static void
-set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+authorize (MMAuthProvider *self,
+ GDBusMethodInvocation *invocation,
+ const gchar *authorization,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- switch (prop_id) {
- case PROP_NAME:
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ 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
-get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+mm_auth_provider_polkit_init (MMAuthProviderPolkit *self)
{
- switch (prop_id) {
- case PROP_NAME:
- g_value_set_string (value, "polkit");
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ GError *error = NULL;
+
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self),
+ MM_TYPE_AUTH_PROVIDER_POLKIT,
+ MMAuthProviderPolkitPrivate);
+
+ self->priv->authority = polkit_authority_get_sync (NULL, &error);
+ if (!self->priv->authority) {
+ /* NOTE: we failed to create the polkit authority, but we still create
+ * our AuthProvider. Every request will fail, though. */
+ mm_warn ("failed to create PolicyKit authority: '%s'",
+ error ? error->message : "unknown");
+ g_clear_error (&error);
}
}
static void
dispose (GObject *object)
{
- MMAuthProviderPolkit *self = MM_AUTH_PROVIDER_POLKIT (object);
- MMAuthProviderPolkitPrivate *priv = MM_AUTH_PROVIDER_POLKIT_GET_PRIVATE (self);
-
- if (priv->auth_changed_id) {
- g_signal_handler_disconnect (priv->authority, priv->auth_changed_id);
- priv->auth_changed_id = 0;
- }
+ g_clear_object (MM_AUTH_PROVIDER_POLKIT (object)->priv->authority);
G_OBJECT_CLASS (mm_auth_provider_polkit_parent_class)->dispose (object);
}
@@ -157,17 +196,12 @@ static void
mm_auth_provider_polkit_class_init (MMAuthProviderPolkitClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
- MMAuthProviderClass *ap_class = MM_AUTH_PROVIDER_CLASS (class);
+ MMAuthProviderClass *auth_provider_class = MM_AUTH_PROVIDER_CLASS (class);
- mm_auth_provider_polkit_parent_class = g_type_class_peek_parent (class);
g_type_class_add_private (class, sizeof (MMAuthProviderPolkitPrivate));
/* Virtual methods */
- object_class->set_property = set_property;
- object_class->get_property = get_property;
object_class->dispose = dispose;
- ap_class->create_request = real_create_request;
-
- /* Properties */
- g_object_class_override_property (object_class, PROP_NAME, MM_AUTH_PROVIDER_NAME);
+ auth_provider_class->authorize = authorize;
+ auth_provider_class->authorize_finish = authorize_finish;
}