summaryrefslogtreecommitdiff
path: root/src/mm-auth-provider.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-auth-provider.c')
-rw-r--r--src/mm-auth-provider.c218
1 files changed, 168 insertions, 50 deletions
diff --git a/src/mm-auth-provider.c b/src/mm-auth-provider.c
index 4ef56234..5b4b13f3 100644
--- a/src/mm-auth-provider.c
+++ b/src/mm-auth-provider.c
@@ -12,91 +12,209 @@
*
* Copyright (C) 2010 - 2012 Red Hat, Inc.
* Copyright (C) 2012 Google, Inc.
+ * Copyright (C) 2020 Aleksander Morgado <aleksander@aleksander.es>
*/
+#include <config.h>
+
+#include <ModemManager.h>
+#include "mm-errors-types.h"
+#include "mm-log-object.h"
+#include "mm-utils.h"
#include "mm-auth-provider.h"
-G_DEFINE_TYPE (MMAuthProvider, mm_auth_provider, G_TYPE_OBJECT)
+#if defined WITH_POLKIT
+# include <polkit/polkit.h>
+#endif
+
+struct _MMAuthProvider {
+ GObject parent;
+#if defined WITH_POLKIT
+ PolkitAuthority *authority;
+#endif
+};
+
+struct _MMAuthProviderClass {
+ GObjectClass parent;
+};
+
+static void log_object_iface_init (MMLogObjectInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (MMAuthProvider, mm_auth_provider, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init))
/*****************************************************************************/
-MMAuthProvider *
-mm_auth_provider_new (void)
+gboolean
+mm_auth_provider_authorize_finish (MMAuthProvider *self,
+ GAsyncResult *res,
+ GError **error)
{
- return g_object_new (MM_TYPE_AUTH_PROVIDER, NULL);
+ return g_task_propagate_boolean (G_TASK (res), error);
}
-/*****************************************************************************/
+#if defined WITH_POLKIT
-gboolean
-mm_auth_provider_authorize_finish (MMAuthProvider *self,
- GAsyncResult *res,
- GError **error)
+typedef struct {
+ PolkitSubject *subject;
+ gchar *authorization;
+ GDBusMethodInvocation *invocation;
+} AuthorizeContext;
+
+static void
+authorize_context_free (AuthorizeContext *ctx)
{
- g_return_val_if_fail (MM_IS_AUTH_PROVIDER (self), FALSE);
+ g_object_unref (ctx->invocation);
+ g_object_unref (ctx->subject);
+ g_free (ctx->authorization);
+ g_free (ctx);
+}
- return MM_AUTH_PROVIDER_GET_CLASS (self)->authorize_finish (self, res, error);
+static void
+check_authorization_ready (PolkitAuthority *authority,
+ GAsyncResult *res,
+ GTask *task)
+{
+ PolkitAuthorizationResult *pk_result;
+ GError *error = NULL;
+ AuthorizeContext *ctx;
+
+ if (g_task_return_error_if_cancelled (task)) {
+ g_object_unref (task);
+ return;
+ }
+
+ ctx = g_task_get_task_data (task);
+ pk_result = polkit_authority_check_authorization_finish (authority, res, &error);
+ if (!pk_result) {
+ g_task_return_new_error (task,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "PolicyKit authorization failed: '%s'",
+ error->message);
+ g_error_free (error);
+ } else {
+ if (polkit_authorization_result_get_is_authorized (pk_result))
+ /* Good! */
+ g_task_return_boolean (task, TRUE);
+ else if (polkit_authorization_result_get_is_challenge (pk_result))
+ g_task_return_new_error (task,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNAUTHORIZED,
+ "PolicyKit authorization failed: challenge needed for '%s'",
+ ctx->authorization);
+ else
+ g_task_return_new_error (task,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNAUTHORIZED,
+ "PolicyKit authorization failed: not authorized for '%s'",
+ ctx->authorization);
+ g_object_unref (pk_result);
+ }
+
+ g_object_unref (task);
}
+#endif
void
-mm_auth_provider_authorize (MMAuthProvider *self,
+mm_auth_provider_authorize (MMAuthProvider *self,
GDBusMethodInvocation *invocation,
- const gchar *authorization,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+ const gchar *authorization,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- g_return_if_fail (MM_IS_AUTH_PROVIDER (self));
-
- MM_AUTH_PROVIDER_GET_CLASS (self)->authorize (self,
- invocation,
- authorization,
- cancellable,
- callback,
- user_data);
+ GTask *task;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+#if defined WITH_POLKIT
+ {
+ 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 (!self->authority) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "PolicyKit authorization error: 'authority not found'");
+ g_object_unref (task);
+ return;
+ }
+
+ ctx = g_new (AuthorizeContext, 1);
+ ctx->invocation = g_object_ref (invocation);
+ ctx->authorization = g_strdup (authorization);
+ ctx->subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (ctx->invocation));
+ g_task_set_task_data (task, ctx, (GDestroyNotify)authorize_context_free);
+
+ polkit_authority_check_authorization (self->authority,
+ ctx->subject,
+ authorization,
+ NULL, /* details */
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+ cancellable,
+ (GAsyncReadyCallback)check_authorization_ready,
+ task);
+ }
+#else
+ /* Just create the result and complete it */
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+#endif
}
/*****************************************************************************/
-static gboolean
-authorize_finish (MMAuthProvider *self,
- GAsyncResult *res,
- GError **error)
+static gchar *
+log_object_build_id (MMLogObject *_self)
{
- /* Null auth; everything passes */
- return TRUE;
+ return g_strdup ("auth-provider");
}
+/*****************************************************************************/
+
static void
-authorize (MMAuthProvider *self,
- GDBusMethodInvocation *invocation,
- const gchar *authorization,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+mm_auth_provider_init (MMAuthProvider *self)
{
- GSimpleAsyncResult *result;
-
- /* Just create the result and complete it */
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- authorize);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
+#if defined WITH_POLKIT
+ {
+ GError *error = NULL;
+
+ self->authority = polkit_authority_get_sync (NULL, &error);
+ if (!self->authority) {
+ /* NOTE: we failed to create the polkit authority, but we still create
+ * our AuthProvider. Every request will fail, though. */
+ mm_obj_warn (self, "failed to create PolicyKit authority: '%s'",
+ error ? error->message : "unknown");
+ g_clear_error (&error);
+ }
+ }
+#endif
}
-/*****************************************************************************/
+static void
+dispose (GObject *object)
+{
+#if defined WITH_POLKIT
+ g_clear_object (&(MM_AUTH_PROVIDER (object)->authority));
+#endif
+
+ G_OBJECT_CLASS (mm_auth_provider_parent_class)->dispose (object);
+}
static void
-mm_auth_provider_init (MMAuthProvider *self)
+log_object_iface_init (MMLogObjectInterface *iface)
{
+ iface->build_id = log_object_build_id;
}
static void
mm_auth_provider_class_init (MMAuthProviderClass *class)
{
- /* Virtual methods */
- class->authorize = authorize;
- class->authorize_finish = authorize_finish;
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = dispose;
}
+
+MM_DEFINE_SINGLETON_GETTER (MMAuthProvider, mm_auth_provider_get, MM_TYPE_AUTH_PROVIDER)