From 438a047935f941e8f7d8df27a0069c70e4b4ea05 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 26 Feb 2010 18:01:55 -0800 Subject: core: add authorization providers and optional PolicyKit support When the support is complete, use --with-polkit to enable PolicyKit support. It's not there yet, but this commit adds an authorization provider framework which will be extended to allow hooking into PolicyKit. --- src/Makefile.am | 19 +- src/mm-auth-provider-factory.c | 45 +++++ src/mm-auth-provider.c | 405 +++++++++++++++++++++++++++++++++++++++++ src/mm-auth-provider.h | 99 ++++++++++ src/mm-errors.c | 1 + src/mm-errors.h | 3 +- src/mm-modem-base.c | 108 +++++++++++ src/mm-modem-cdma.c | 35 +++- src/mm-modem-gsm-card.c | 262 ++++++++++++++++++++++++-- src/mm-modem-gsm-network.c | 32 +++- src/mm-modem.c | 46 +++++ src/mm-modem.h | 32 ++++ 12 files changed, 1068 insertions(+), 19 deletions(-) create mode 100644 src/mm-auth-provider-factory.c create mode 100644 src/mm-auth-provider.c create mode 100644 src/mm-auth-provider.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 9209b55f..2ed7e603 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,12 +19,20 @@ modem_manager_CPPFLAGS = \ -I${top_builddir}/marshallers \ -DPLUGINDIR=\"$(pkglibdir)\" +if WITH_POLKIT +modem_manager_CPPFLAGS += $(POLKIT_CFLAGS) +endif + modem_manager_LDADD = \ $(MM_LIBS) \ $(GUDEV_LIBS) \ $(top_builddir)/marshallers/libmarshallers.la \ $(builddir)/libmodem-helpers.la +if WITH_POLKIT +modem_manager_LDADD += $(POLKIT_LIBS) +endif + modem_manager_SOURCES = \ main.c \ mm-callback-info.c \ @@ -63,7 +71,16 @@ modem_manager_SOURCES = \ mm-plugin-base.c \ mm-plugin-base.h \ mm-properties-changed-signal.c \ - mm-properties-changed-signal.h + mm-properties-changed-signal.h \ + mm-auth-provider.h \ + mm-auth-provider.c \ + mm-auth-provider-factory.c + +if WITH_POLKIT +modem_manager_SOURCES += \ + mm-auth-provider-polkit.c \ + mm-auth-provider-polkit.h +endif mm-manager-glue.h: $(top_srcdir)/introspection/mm-manager.xml dbus-binding-tool --prefix=mm_manager --mode=glib-server --output=$@ $< diff --git a/src/mm-auth-provider-factory.c b/src/mm-auth-provider-factory.c new file mode 100644 index 00000000..356dcf21 --- /dev/null +++ b/src/mm-auth-provider-factory.c @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#include + +#include "config.h" +#include "mm-auth-provider.h" + +GObject *mm_auth_provider_new (void); + +#ifdef WITH_POLKIT +#define IN_AUTH_PROVIDER_FACTORY_C +#include "mm-auth-provider-polkit.h" +#undef IN_AUTH_PROVIDER_FACTORY_C +#endif + +MMAuthProvider * +mm_auth_provider_get (void) +{ + static MMAuthProvider *singleton; + + if (!singleton) { +#if WITH_POLKIT + singleton = (MMAuthProvider *) mm_auth_provider_polkit_new (); +#else + singleton = (MMAuthProvider *) mm_auth_provider_new (); +#endif + } + + g_assert (singleton); + return singleton; +} + diff --git a/src/mm-auth-provider.c b/src/mm-auth-provider.c new file mode 100644 index 00000000..0ff4baff --- /dev/null +++ b/src/mm-auth-provider.c @@ -0,0 +1,405 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#include + +#include "mm-marshal.h" +#include "mm-auth-provider.h" + +GObject *mm_auth_provider_new (void); + +G_DEFINE_TYPE (MMAuthProvider, mm_auth_provider, G_TYPE_OBJECT) + +#define MM_AUTH_PROVIDER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_AUTH_PROVIDER, MMAuthProviderPrivate)) + +typedef struct { + GHashTable *requests; + guint process_id; +} MMAuthProviderPrivate; + +enum { + PROP_0, + PROP_NAME, + LAST_PROP +}; + +enum { + REQUEST_ADDED, + REQUEST_REMOVED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + + +/*****************************************************************************/ + +GObject * +mm_auth_provider_new (void) +{ + return g_object_new (MM_TYPE_AUTH_PROVIDER, NULL); +} + +/*****************************************************************************/ + +struct MMAuthRequest { + guint32 refcount; + guint32 id; + char *auth; + GObject *instance; + + MMAuthResult result; + + MMAuthRequestCb callback; + gpointer callback_data; + GDestroyNotify notify; +}; + +static MMAuthRequest * +mm_auth_request_new (const char *authorization, + GObject *instance, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify) +{ + static guint32 id = 1; + MMAuthRequest *req; + + g_return_val_if_fail (authorization != NULL, NULL); + g_return_val_if_fail (callback != NULL, NULL); + + req = g_malloc0 (sizeof (MMAuthRequest)); + req->id = id++; + req->refcount = 1; + req->auth = g_strdup (authorization); + req->instance = instance; + req->callback = callback; + req->callback_data = callback_data; + req->notify = notify; + + return req; +} + +MMAuthRequest * +mm_auth_request_ref (MMAuthRequest *req) +{ + g_return_val_if_fail (req != NULL, NULL); + g_return_val_if_fail (req->refcount > 0, NULL); + + req->refcount++; + return req; +} + +void +mm_auth_request_unref (MMAuthRequest *req) +{ + g_return_if_fail (req != NULL); + g_return_if_fail (req->refcount > 0); + + req->refcount--; + if (req->refcount == 0) { + g_free (req->auth); + memset (req, 0, sizeof (MMAuthRequest)); + g_free (req); + } +} + +guint32 +mm_auth_request_get_id (MMAuthRequest *req) +{ + g_return_val_if_fail (req != NULL, 0); + g_return_val_if_fail (req->refcount > 0, 0); + + return req->id; +} + +const char * +mm_auth_request_get_authorization (MMAuthRequest *req) +{ + g_return_val_if_fail (req != NULL, 0); + g_return_val_if_fail (req->refcount > 0, 0); + + return req->auth; +} + +/*****************************************************************************/ + +MMAuthRequest * +mm_auth_provider_get_request (MMAuthProvider *provider, guint32 reqid) +{ + MMAuthProviderPrivate *priv; + + g_return_val_if_fail (provider != NULL, NULL); + g_return_val_if_fail (MM_IS_AUTH_PROVIDER (provider), NULL); + g_return_val_if_fail (reqid > 0, NULL); + + priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); + return (MMAuthRequest *) g_hash_table_lookup (priv->requests, GUINT_TO_POINTER (reqid)); +} + +static gboolean +process_complete_requests (gpointer user_data) +{ + MMAuthProvider *self = MM_AUTH_PROVIDER (user_data); + MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (self); + GHashTableIter iter; + gpointer value; + GSList *remove = NULL; + MMAuthRequest *req; + + priv->process_id = 0; + + /* Call finished request's callbacks */ + g_hash_table_iter_init (&iter, priv->requests); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + req = (MMAuthRequest *) value; + if (req->result != MM_AUTH_RESULT_UNKNOWN) { + req->callback (req->instance, req->id, req->result, req->callback_data); + + /* Let the caller clean up the request's callback data */ + if (req->notify) + req->notify (req->callback_data); + + remove = g_slist_prepend (remove, req); + } + } + + /* And remove those requests from our pending request list */ + while (remove) { + req = (MMAuthRequest *) remove->data; + g_signal_emit (self, signals[REQUEST_REMOVED], 0, req->instance, req->id); + g_hash_table_remove (priv->requests, GUINT_TO_POINTER (req->id)); + remove = g_slist_remove (remove, req); + } + + return FALSE; +} + +void +mm_auth_provider_finish_request (MMAuthProvider *provider, + guint32 reqid, + MMAuthResult result) +{ + MMAuthProviderPrivate *priv; + MMAuthRequest *req; + + g_return_if_fail (provider != NULL); + g_return_if_fail (MM_IS_AUTH_PROVIDER (provider)); + g_return_if_fail (reqid > 0); + g_return_if_fail (result != MM_AUTH_RESULT_UNKNOWN); + + priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); + req = (MMAuthRequest *) g_hash_table_lookup (priv->requests, GUINT_TO_POINTER (reqid)); + g_return_if_fail (req != NULL); + + req->result = result; + + if (priv->process_id == 0) + priv->process_id = g_idle_add (process_complete_requests, provider); +} + +void +mm_auth_provider_cancel_request (MMAuthProvider *provider, guint32 reqid) +{ + MMAuthProviderPrivate *priv; + MMAuthRequest *req; + + g_return_if_fail (provider != NULL); + g_return_if_fail (MM_IS_AUTH_PROVIDER (provider)); + g_return_if_fail (reqid > 0); + + priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); + + req = (MMAuthRequest *) g_hash_table_lookup (priv->requests, GUINT_TO_POINTER (reqid)); + g_return_if_fail (req != NULL); + + /* Let the caller clean up the request's callback data */ + if (req->notify) + req->notify (req->callback_data); + + /* We don't signal removal here as it's assumed the caller + * handles that itself instead of by the signal. + */ + g_hash_table_remove (priv->requests, GUINT_TO_POINTER (reqid)); +} + +const char * +mm_auth_provider_get_authorization_for_id (MMAuthProvider *provider, guint32 reqid) +{ + MMAuthProviderPrivate *priv; + MMAuthRequest *req; + + g_return_val_if_fail (provider != NULL, NULL); + g_return_val_if_fail (MM_IS_AUTH_PROVIDER (provider), NULL); + g_return_val_if_fail (reqid > 0, NULL); + + priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); + req = (MMAuthRequest *) g_hash_table_lookup (priv->requests, GUINT_TO_POINTER (reqid)); + g_return_val_if_fail (req != NULL, NULL); + + return mm_auth_request_get_authorization (req); +} + +/*****************************************************************************/ + +static gboolean +real_request_auth (MMAuthProvider *provider, + MMAuthRequest *req, + GError **error) +{ + /* This class provides null authentication; all requests pass */ + mm_auth_provider_finish_request (provider, + mm_auth_request_get_id (req), + MM_AUTH_RESULT_AUTHORIZED); + return TRUE; +} + +guint32 +mm_auth_provider_request_auth (MMAuthProvider *provider, + const char *authorization, + GObject *instance, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify, + GError **error) +{ + MMAuthProviderPrivate *priv; + MMAuthRequest *req; + + g_return_val_if_fail (provider != NULL, 0); + g_return_val_if_fail (MM_IS_AUTH_PROVIDER (provider), 0); + g_return_val_if_fail (authorization != NULL, 0); + g_return_val_if_fail (callback != NULL, 0); + + priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); + + req = mm_auth_request_new (authorization, instance, callback, callback_data, notify); + g_assert (req); + + g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->id), req); + g_signal_emit (provider, signals[REQUEST_ADDED], 0, instance, req->id); + + if (!MM_AUTH_PROVIDER_GET_CLASS (provider)->request_auth (provider, req, error)) { + /* Error */ + g_signal_emit (provider, signals[REQUEST_REMOVED], 0, instance, req->id); + + /* Let the caller clean up the request's callback data */ + if (req->notify) + req->notify (req->callback_data); + + g_hash_table_remove (priv->requests, GUINT_TO_POINTER (req->id)); + return 0; + } + + return req->id; +} + +/*****************************************************************************/ + +static void +mm_auth_provider_init (MMAuthProvider *self) +{ + MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (self); + + priv->requests = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + (GDestroyNotify) mm_auth_request_unref); +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_NAME: + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +#define NULL_PROVIDER "open" + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, NULL_PROVIDER); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (object); + + if (priv->process_id) + g_source_remove (priv->process_id); + g_hash_table_destroy (priv->requests); + + G_OBJECT_CLASS (mm_auth_provider_parent_class)->finalize (object); +} + +static void +mm_auth_provider_class_init (MMAuthProviderClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + mm_auth_provider_parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (MMAuthProviderPrivate)); + + /* Virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + class->request_auth = real_request_auth; + + /* Properties */ + g_object_class_install_property (object_class, PROP_NAME, + g_param_spec_string (MM_AUTH_PROVIDER_NAME, + "Name", + "Provider name", + NULL_PROVIDER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* Signals */ + signals[REQUEST_ADDED] = + g_signal_new ("request-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + mm_marshal_VOID__POINTER_UINT, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); + + signals[REQUEST_REMOVED] = + g_signal_new ("request-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + mm_marshal_VOID__POINTER_UINT, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); +} + diff --git a/src/mm-auth-provider.h b/src/mm-auth-provider.h new file mode 100644 index 00000000..8d693f3e --- /dev/null +++ b/src/mm-auth-provider.h @@ -0,0 +1,99 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifndef MM_AUTH_PROVIDER_H +#define MM_AUTH_PROVIDER_H + +#include + +/* Authorizations */ +#define MM_AUTHORIZATION_DEVICE "org.freedesktop.ModemManager.Device" +#define MM_AUTHORIZATION_CONTACTS "org.freedesktop.ModemManager.Contacts" +#define MM_AUTHORIZATION_SMS "org.freedesktop.ModemManager.SMS" +/******************/ + + +#define MM_TYPE_AUTH_PROVIDER (mm_auth_provider_get_type ()) +#define MM_AUTH_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_AUTH_PROVIDER, MMAuthProvider)) +#define MM_AUTH_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_AUTH_PROVIDER, MMAuthProviderClass)) +#define MM_IS_AUTH_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_AUTH_PROVIDER)) +#define MM_IS_AUTH_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_AUTH_PROVIDER)) +#define MM_AUTH_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_AUTH_PROVIDER, MMAuthProviderClass)) + +#define MM_AUTH_PROVIDER_NAME "name" + +typedef enum MMAuthResult { + MM_AUTH_RESULT_UNKNOWN = 0, + MM_AUTH_RESULT_INTERNAL_FAILURE, + MM_AUTH_RESULT_NOT_AUTHORIZED, + MM_AUTH_RESULT_CHALLENGE, + MM_AUTH_RESULT_AUTHORIZED +} MMAuthResult; + +typedef struct MMAuthRequest MMAuthRequest; +typedef struct _MMAuthProvider MMAuthProvider; +typedef struct _MMAuthProviderClass MMAuthProviderClass; + +typedef void (*MMAuthRequestCb) (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data); + +struct _MMAuthProvider { + GObject parent; +}; + +struct _MMAuthProviderClass { + GObjectClass parent; + + gboolean (*request_auth) (MMAuthProvider *provider, + MMAuthRequest *req, + GError **error); +}; + +GType mm_auth_provider_get_type (void); + +guint32 mm_auth_provider_request_auth (MMAuthProvider *provider, + const char *authorization, + GObject *instance, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify, + GError **error); + +/* To get an auth provider instance, implemented in mm-auth-provider-factory.c */ +MMAuthProvider *mm_auth_provider_get (void); + +/* For subclasses only */ +MMAuthRequest *mm_auth_provider_get_request (MMAuthProvider *provider, guint32 reqid); +MMAuthRequest *mm_auth_request_ref (MMAuthRequest *req); +void mm_auth_request_unref (MMAuthRequest *req); +guint32 mm_auth_request_get_id (MMAuthRequest *req); +const char * mm_auth_request_get_authorization (MMAuthRequest *req); + +/* Normal API */ + +/* schedules the request's completion */ +void mm_auth_provider_finish_request (MMAuthProvider *provider, + guint32 reqid, + MMAuthResult result); + +void mm_auth_provider_cancel_request (MMAuthProvider *provider, guint32 reqid); + +const char *mm_auth_provider_get_authorization_for_id (MMAuthProvider *provider, + guint32 reqid); + +#endif /* MM_AUTH_PROVIDER_H */ + diff --git a/src/mm-errors.c b/src/mm-errors.c index 16b591cc..d0a71d65 100644 --- a/src/mm-errors.c +++ b/src/mm-errors.c @@ -76,6 +76,7 @@ mm_modem_error_get_type (void) ENUM_ENTRY (MM_MODEM_ERROR_DISCONNECTED, "Disconnected"), ENUM_ENTRY (MM_MODEM_ERROR_OPERATION_IN_PROGRESS, "OperationInProgress"), ENUM_ENTRY (MM_MODEM_ERROR_REMOVED, "Removed"), + ENUM_ENTRY (MM_MODEM_ERROR_AUTHORIZATION_REQUIRED, "AuthorizationRequired"), { 0, 0, 0 } }; diff --git a/src/mm-errors.h b/src/mm-errors.h index 2a6c565e..1b924d40 100644 --- a/src/mm-errors.h +++ b/src/mm-errors.h @@ -39,7 +39,8 @@ enum { MM_MODEM_ERROR_CONNECTED = 2, MM_MODEM_ERROR_DISCONNECTED = 3, MM_MODEM_ERROR_OPERATION_IN_PROGRESS = 4, - MM_MODEM_ERROR_REMOVED = 5 + MM_MODEM_ERROR_REMOVED = 5, + MM_MODEM_ERROR_AUTHORIZATION_REQUIRED = 6 }; #define MM_MODEM_ERROR (mm_modem_error_quark ()) diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c index 43ec6f84..83178874 100644 --- a/src/mm-modem-base.c +++ b/src/mm-modem-base.c @@ -44,6 +44,11 @@ typedef struct { gboolean valid; MMModemState state; + MMAuthProvider *authp; + guint authp_added_id; + guint authp_removed_id; + GSList *auth_reqs; + GHashTable *ports; } MMModemBasePrivate; @@ -213,11 +218,104 @@ mm_modem_base_set_unlock_required (MMModemBase *self, const char *unlock_require /*****************************************************************************/ +static gboolean +modem_auth_request (MMModem *modem, + const char *authorization, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify, + GError **error) +{ + MMModemBase *self = MM_MODEM_BASE (modem); + MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + + g_assert (priv->authp); + return !!mm_auth_provider_request_auth (priv->authp, + authorization, + G_OBJECT (self), + callback, + callback_data, + notify, + error); +} + +static gboolean +modem_auth_finish (MMModem *modem, + guint32 reqid, + MMAuthResult result, + GError **error) +{ + MMModemBase *self = MM_MODEM_BASE (modem); + MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + + if (result != MM_AUTH_RESULT_AUTHORIZED) { + const char *auth; + + auth = mm_auth_provider_get_authorization_for_id (priv->authp, reqid); + g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_AUTHORIZATION_REQUIRED, + "This request requires the '%s' authorization", + auth ? auth : "(unknown)"); + return FALSE; + } + + return TRUE; +} + +static void +authp_request_added (MMAuthProvider *provider, + gpointer parent, + guint32 reqid, + gpointer user_data) +{ + MMModemBase *self; + MMModemBasePrivate *priv; + + /* Make sure it's our auth request */ + if (parent != user_data) + return; + + self = MM_MODEM_BASE (user_data); + priv = MM_MODEM_BASE_GET_PRIVATE (self); + + /* Add this request to our table so we can cancel it when we die */ + priv->auth_reqs = g_slist_prepend (priv->auth_reqs, GUINT_TO_POINTER (reqid)); +} + +static void +authp_request_removed (MMAuthProvider *provider, + gpointer parent, + guint32 reqid, + gpointer user_data) +{ + MMModemBase *self; + MMModemBasePrivate *priv; + + /* Make sure it's our auth request */ + if (parent != user_data) + return; + + self = MM_MODEM_BASE (user_data); + priv = MM_MODEM_BASE_GET_PRIVATE (self); + + /* Request finished; remove cleanly */ + priv->auth_reqs = g_slist_remove (priv->auth_reqs, GUINT_TO_POINTER (reqid)); +} + +/*****************************************************************************/ + static void mm_modem_base_init (MMModemBase *self) { MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + priv->authp = mm_auth_provider_get (); + priv->authp_added_id = g_signal_connect (priv->authp, "request-added", + (GCallback) authp_request_added, + self); + priv->authp_removed_id = g_signal_connect (priv->authp, "request-removed", + (GCallback) authp_request_removed, + self); + priv->ports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); mm_properties_changed_signal_register_property (G_OBJECT (self), @@ -228,6 +326,8 @@ mm_modem_base_init (MMModemBase *self) static void modem_init (MMModem *modem_class) { + modem_class->auth_request = modem_auth_request; + modem_class->auth_finish = modem_auth_finish; } static gboolean @@ -325,6 +425,14 @@ finalize (GObject *object) { MMModemBase *self = MM_MODEM_BASE (object); MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); + GSList *iter; + + g_signal_handler_disconnect (priv->authp, priv->authp_added_id); + g_signal_handler_disconnect (priv->authp, priv->authp_removed_id); + + for (iter = priv->auth_reqs; iter; iter = g_slist_next (iter)) + mm_auth_provider_cancel_request (priv->authp, GPOINTER_TO_UINT (iter->data)); + g_slist_free (priv->auth_reqs); g_hash_table_destroy (priv->ports); g_free (priv->driver); diff --git a/src/mm-modem-cdma.c b/src/mm-modem-cdma.c index 112b93fa..0ba9f792 100644 --- a/src/mm-modem-cdma.c +++ b/src/mm-modem-cdma.c @@ -20,6 +20,7 @@ #include "mm-errors.h" #include "mm-callback-info.h" #include "mm-marshal.h" +#include "mm-auth-provider.h" static void impl_modem_cdma_get_signal_quality (MMModemCdma *modem, DBusGMethodInvocation *context); static void impl_modem_cdma_get_esn (MMModemCdma *modem, DBusGMethodInvocation *context); @@ -188,10 +189,38 @@ mm_modem_cdma_get_esn (MMModemCdma *self, } static void -impl_modem_cdma_get_esn (MMModemCdma *modem, - DBusGMethodInvocation *context) +esn_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) { - mm_modem_cdma_get_esn (modem, str_call_done, context); + MMModemCdma *self = MM_MODEM_CDMA (instance); + DBusGMethodInvocation *context = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise get the ESN */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + mm_modem_cdma_get_esn (self, str_call_done, context); +} + +static void +impl_modem_cdma_get_esn (MMModemCdma *self, DBusGMethodInvocation *context) +{ + GError *error = NULL; + + /* Make sure the caller is authorized to get the ESN */ + if (!mm_modem_auth_request (MM_MODEM (self), + MM_AUTHORIZATION_DEVICE, + esn_auth_cb, + context, + NULL, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } } void diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c index dea4590e..0e62779a 100644 --- a/src/mm-modem-gsm-card.c +++ b/src/mm-modem-gsm-card.c @@ -15,6 +15,7 @@ */ #include +#include #include "mm-modem-gsm-card.h" #include "mm-errors.h" @@ -201,26 +202,178 @@ mm_modem_gsm_card_change_pin (MMModemGsmCard *self, /*****************************************************************************/ static void -impl_gsm_modem_get_imei (MMModemGsmCard *modem, - DBusGMethodInvocation *context) +imei_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) { - mm_modem_gsm_card_get_imei (modem, str_call_done, context); + MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + DBusGMethodInvocation *context = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise get the IMEI */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + mm_modem_gsm_card_get_imei (self, str_call_done, context); +} + +static void +impl_gsm_modem_get_imei (MMModemGsmCard *modem, DBusGMethodInvocation *context) +{ + GError *error = NULL; + + /* Make sure the caller is authorized to get the IMEI */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_DEVICE, + imei_auth_cb, + context, + NULL, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + +static void +imsi_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + DBusGMethodInvocation *context = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise get the IMSI */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + mm_modem_gsm_card_get_imsi (self, str_call_done, context); } static void -impl_gsm_modem_get_imsi (MMModemGsmCard *modem, +impl_gsm_modem_get_imsi (MMModemGsmCard *modem, DBusGMethodInvocation *context) +{ + GError *error = NULL; + + /* Make sure the caller is authorized to get the IMSI */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_DEVICE, + imsi_auth_cb, + context, + NULL, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + +typedef struct { + char *puk; + char *pin; + char *pin2; + gboolean enabled; + DBusGMethodInvocation *context; +} SendPinPukInfo; + +static void +send_pin_puk_info_destroy (gpointer data) +{ + SendPinPukInfo *info = data; + + g_free (info->puk); + g_free (info->pin); + g_free (info->pin2); + memset (info, 0, sizeof (SendPinPukInfo)); + g_free (info); +} + +static SendPinPukInfo * +send_pin_puk_info_new (const char *puk, + const char *pin, + const char *pin2, + gboolean enabled, + DBusGMethodInvocation *context) +{ + SendPinPukInfo *info; + + info = g_malloc0 (sizeof (SendPinPukInfo)); + info->puk = g_strdup (puk); + info->pin = g_strdup (pin); + info->pin2 = g_strdup (pin2); + info->enabled = enabled; + info->context = context; + return info; +} + +/*****************************************************************************/ + +static void +send_puk_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + SendPinPukInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise send the PUK */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + mm_modem_gsm_card_send_puk (self, info->puk, info->pin, async_call_done, info->context); +} + +static void +impl_gsm_modem_send_puk (MMModemGsmCard *modem, + const char *puk, + const char *pin, DBusGMethodInvocation *context) { - mm_modem_gsm_card_get_imsi (modem, str_call_done, context); + GError *error = NULL; + SendPinPukInfo *info; + + info = send_pin_puk_info_new (puk, pin, NULL, FALSE, context); + + /* Make sure the caller is authorized to send the PUK */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_DEVICE, + send_puk_auth_cb, + info, + send_pin_puk_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } } +/*****************************************************************************/ + static void - impl_gsm_modem_send_puk (MMModemGsmCard *modem, - const char *puk, - const char *pin, - DBusGMethodInvocation *context) +send_pin_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) { - mm_modem_gsm_card_send_puk (modem, puk, pin, async_call_done, context); + MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + SendPinPukInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise unlock the modem */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + mm_modem_gsm_card_send_pin (self, info->pin, async_call_done, info->context); } static void @@ -228,7 +381,41 @@ impl_gsm_modem_send_pin (MMModemGsmCard *modem, const char *pin, DBusGMethodInvocation *context) { - mm_modem_gsm_card_send_pin (modem, pin, async_call_done, context); + GError *error = NULL; + SendPinPukInfo *info; + + info = send_pin_puk_info_new (NULL, pin, NULL, FALSE, context); + + /* Make sure the caller is authorized to unlock the modem */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_DEVICE, + send_pin_auth_cb, + info, + send_pin_puk_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + +static void +enable_pin_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + SendPinPukInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise enable the PIN */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + mm_modem_gsm_card_enable_pin (self, info->pin, info->enabled, async_call_done, info->context); } static void @@ -237,7 +424,41 @@ impl_gsm_modem_enable_pin (MMModemGsmCard *modem, gboolean enabled, DBusGMethodInvocation *context) { - mm_modem_gsm_card_enable_pin (modem, pin, enabled, async_call_done, context); + GError *error = NULL; + SendPinPukInfo *info; + + info = send_pin_puk_info_new (NULL, pin, NULL, enabled, context); + + /* Make sure the caller is authorized to enable a PIN */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_DEVICE, + enable_pin_auth_cb, + info, + send_pin_puk_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + +static void +change_pin_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + SendPinPukInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise change the PIN */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + mm_modem_gsm_card_change_pin (self, info->pin, info->pin2, async_call_done, info->context); } static void @@ -246,7 +467,21 @@ impl_gsm_modem_change_pin (MMModemGsmCard *modem, const char *new_pin, DBusGMethodInvocation *context) { - mm_modem_gsm_card_change_pin (modem, old_pin, new_pin, async_call_done, context); + GError *error = NULL; + SendPinPukInfo *info; + + info = send_pin_puk_info_new (NULL, old_pin, new_pin, FALSE, context); + + /* Make sure the caller is authorized to change the PIN */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_DEVICE, + change_pin_auth_cb, + info, + send_pin_puk_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } } /*****************************************************************************/ @@ -305,6 +540,7 @@ mm_modem_gsm_card_get_type (void) &card_info, 0); g_type_interface_add_prerequisite (card_type, G_TYPE_OBJECT); + g_type_interface_add_prerequisite (card_type, MM_TYPE_MODEM); dbus_g_object_type_install_info (card_type, &dbus_glib_mm_modem_gsm_card_object_info); } diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c index 26ff4229..bb84da12 100644 --- a/src/mm-modem-gsm-network.c +++ b/src/mm-modem-gsm-network.c @@ -397,11 +397,40 @@ impl_gsm_modem_register (MMModemGsmNetwork *modem, mm_modem_gsm_network_register (modem, id, async_call_done, context); } +static void +scan_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmNetwork *self = MM_MODEM_GSM_NETWORK (instance); + DBusGMethodInvocation *context = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise get the IMEI */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + mm_modem_gsm_network_scan (self, scan_call_done, context); +} + static void impl_gsm_modem_scan (MMModemGsmNetwork *modem, DBusGMethodInvocation *context) { - mm_modem_gsm_network_scan (modem, scan_call_done, context); + GError *error = NULL; + + /* Make sure the caller is authorized to request a scan */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_DEVICE, + scan_auth_cb, + context, + NULL, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } } static void @@ -562,6 +591,7 @@ mm_modem_gsm_network_get_type (void) &network_info, 0); g_type_interface_add_prerequisite (network_type, G_TYPE_OBJECT); + g_type_interface_add_prerequisite (network_type, MM_TYPE_MODEM); dbus_g_object_type_install_info (network_type, &dbus_glib_mm_modem_gsm_network_object_info); } diff --git a/src/mm-modem.c b/src/mm-modem.c index 5bb2ef6b..0c8e6b25 100644 --- a/src/mm-modem.c +++ b/src/mm-modem.c @@ -608,6 +608,52 @@ mm_modem_set_state (MMModem *self, /*****************************************************************************/ +gboolean +mm_modem_auth_request (MMModem *self, + const char *authorization, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify, + GError **error) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (MM_IS_MODEM (self), FALSE); + g_return_val_if_fail (authorization != NULL, FALSE); + g_return_val_if_fail (callback != NULL, FALSE); + + g_return_val_if_fail (MM_MODEM_GET_INTERFACE (self)->auth_request, FALSE); + return MM_MODEM_GET_INTERFACE (self)->auth_request (self, + authorization, + callback, + callback_data, + notify, + error); +} + +gboolean +mm_modem_auth_finish (MMModem *self, + guint32 reqid, + MMAuthResult result, + GError **error) +{ + gboolean success; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (MM_IS_MODEM (self), FALSE); + g_return_val_if_fail (reqid > 0, FALSE); + + g_return_val_if_fail (MM_MODEM_GET_INTERFACE (self)->auth_finish, FALSE); + success = MM_MODEM_GET_INTERFACE (self)->auth_finish (self, reqid, result, error); + + /* If the request failed, the implementor *should* return an error */ + if (!success && error) + g_warn_if_fail (*error != NULL); + + return success; +} + +/*****************************************************************************/ + static void mm_modem_init (gpointer g_iface) { diff --git a/src/mm-modem.h b/src/mm-modem.h index ead2cca5..531ca785 100644 --- a/src/mm-modem.h +++ b/src/mm-modem.h @@ -20,6 +20,7 @@ #include #include "mm-port.h" +#include "mm-auth-provider.h" typedef enum { MM_MODEM_STATE_UNKNOWN = 0, @@ -156,6 +157,21 @@ struct _MMModem { MMModemInfoFn callback, gpointer user_data); + /* Normally implemented by the modem base class; plugins should + * never need to implement this. + */ + gboolean (*auth_request) (MMModem *self, + const char *authorization, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify, + GError **error); + + gboolean (*auth_finish) (MMModem *self, + guint32 reqid, + MMAuthResult result, + GError **error); + /* Signals */ void (*state_changed) (MMModem *self, MMModemState new_state, @@ -217,5 +233,21 @@ void mm_modem_set_state (MMModem *self, GError *mm_modem_check_removed (MMModem *self, const GError *error); +/* Request authorization to perform an action. Used by D-Bus method + * handlers to ensure that the incoming request is authorized to perform + * the action it's requesting. + */ +gboolean mm_modem_auth_request (MMModem *self, + const char *authorization, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify, + GError **error); + +gboolean mm_modem_auth_finish (MMModem *self, + guint32 reqid, + MMAuthResult result, + GError **error); + #endif /* MM_MODEM_H */ -- cgit v1.2.3-70-g09d2 From 27ffa6b272132c6c92c07cb99e0f213521874475 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 27 Feb 2010 07:19:37 -0800 Subject: core: authenticate SMS operations --- org.freedesktop.ModemManager.conf.polkit | 8 + src/mm-modem-gsm-sms.c | 388 +++++++++++++++++++++++++++++-- 2 files changed, 376 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/org.freedesktop.ModemManager.conf.polkit b/org.freedesktop.ModemManager.conf.polkit index 7aeea8af..ecd95566 100644 --- a/org.freedesktop.ModemManager.conf.polkit +++ b/org.freedesktop.ModemManager.conf.polkit @@ -127,6 +127,14 @@ + + + + diff --git a/src/mm-modem-gsm-sms.c b/src/mm-modem-gsm-sms.c index e8ec0742..00cd953f 100644 --- a/src/mm-modem-gsm-sms.c +++ b/src/mm-modem-gsm-sms.c @@ -129,12 +129,141 @@ mm_modem_gsm_sms_send (MMModemGsmSms *self, /*****************************************************************************/ +typedef struct { + guint num1; + guint num2; + guint num3; + guint num4; + guint num5; + char *str; + GHashTable *hash; + DBusGMethodInvocation *context; +} SmsAuthInfo; + +static void +sms_auth_info_destroy (gpointer data) +{ + SmsAuthInfo *info = data; + + g_hash_table_destroy (info->hash); + g_free (info->str); + memset (info, 0, sizeof (SmsAuthInfo)); + g_free (info); +} + +static void +destroy_gvalue (gpointer data) +{ + GValue *value = (GValue *) data; + + g_value_unset (value); + g_slice_free (GValue, value); +} + +static SmsAuthInfo * +sms_auth_info_new (guint num1, + guint num2, + guint num3, + guint num4, + guint num5, + const char *str, + GHashTable *hash, + DBusGMethodInvocation *context) +{ + SmsAuthInfo *info; + + info = g_malloc0 (sizeof (SmsAuthInfo)); + info->num1 = num1; + info->num2 = num2; + info->num3 = num3; + info->num4 = num4; + info->num5 = num5; + info->str = g_strdup (str); + info->context = context; + + /* Copy the hash table if we're given one */ + if (hash) { + GHashTableIter iter; + gpointer key, value; + + info->hash = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, destroy_gvalue); + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, &key, &value)) { + const char *str_key = (const char *) key; + GValue *src = (GValue *) value; + GValue *dst; + + dst = g_slice_new0 (GValue); + g_value_init (dst, G_VALUE_TYPE (src)); + g_hash_table_insert (info->hash, g_strdup (str_key), dst); + } + } + + return info; +} + +/*****************************************************************************/ + +static void +sms_delete_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + SmsAuthInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise delete the SMS */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + async_call_not_supported (self, async_call_done, info->context); +} + static void impl_gsm_modem_sms_delete (MMModemGsmSms *modem, guint idx, DBusGMethodInvocation *context) { - async_call_not_supported (modem, async_call_done, context); + GError *error = NULL; + SmsAuthInfo *info; + + info = sms_auth_info_new (idx, 0, 0, 0, 0, NULL, NULL, context); + + /* Make sure the caller is authorized to send the PUK */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_SMS, + sms_delete_auth_cb, + info, + sms_auth_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + +static void +sms_get_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + SmsAuthInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise delete the SMS */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + async_call_not_supported (self, async_call_done, info->context); } static void @@ -142,9 +271,25 @@ impl_gsm_modem_sms_get (MMModemGsmSms *modem, guint idx, DBusGMethodInvocation *context) { - async_call_not_supported (modem, async_call_done, context); + GError *error = NULL; + SmsAuthInfo *info; + + info = sms_auth_info_new (idx, 0, 0, 0, 0, NULL, NULL, context); + + /* Make sure the caller is authorized to send the PUK */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_SMS, + sms_get_auth_cb, + info, + sms_auth_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } } +/*****************************************************************************/ + static void impl_gsm_modem_sms_get_format (MMModemGsmSms *modem, DBusGMethodInvocation *context) @@ -167,19 +312,107 @@ impl_gsm_modem_sms_get_smsc (MMModemGsmSms *modem, async_call_not_supported (modem, async_call_done, context); } +/*****************************************************************************/ + +static void +sms_set_smsc_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + SmsAuthInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise delete the SMS */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + async_call_not_supported (self, async_call_done, info->context); +} + static void impl_gsm_modem_sms_set_smsc (MMModemGsmSms *modem, const char *smsc, DBusGMethodInvocation *context) { - async_call_not_supported (modem, async_call_done, context); + GError *error = NULL; + SmsAuthInfo *info; + + info = sms_auth_info_new (0, 0, 0, 0, 0, smsc, NULL, context); + + /* Make sure the caller is authorized to send the PUK */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_SMS, + sms_set_smsc_auth_cb, + info, + sms_auth_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + +static void +sms_list_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + SmsAuthInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise delete the SMS */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + async_call_not_supported (self, async_call_done, info->context); } static void impl_gsm_modem_sms_list (MMModemGsmSms *modem, DBusGMethodInvocation *context) { - async_call_not_supported (modem, async_call_done, context); + GError *error = NULL; + SmsAuthInfo *info; + + info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, NULL, context); + + /* Make sure the caller is authorized to send the PUK */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_SMS, + sms_list_auth_cb, + info, + sms_auth_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + +static void +sms_save_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + SmsAuthInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise delete the SMS */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + async_call_not_supported (self, async_call_done, info->context); } static void @@ -187,54 +420,121 @@ impl_gsm_modem_sms_save (MMModemGsmSms *modem, GHashTable *properties, DBusGMethodInvocation *context) { - async_call_not_supported (modem, async_call_done, context); + GError *error = NULL; + SmsAuthInfo *info; + + info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, properties, context); + + /* Make sure the caller is authorized to send the PUK */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_SMS, + sms_save_auth_cb, + info, + sms_auth_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } } +/*****************************************************************************/ + static void -impl_gsm_modem_sms_send (MMModemGsmSms *modem, - GHashTable *properties, - DBusGMethodInvocation *context) +sms_send_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) { + MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + SmsAuthInfo *info = user_data; + GError *error = NULL; GValue *value; const char *number = NULL; const char *text = NULL ; const char *smsc = NULL; - GError *error = NULL; guint validity = 0; guint class = 0; - value = (GValue *) g_hash_table_lookup (properties, "number"); + /* Return any authorization error, otherwise delete the SMS */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) + goto done; + + value = (GValue *) g_hash_table_lookup (info->hash, "number"); if (value) number = g_value_get_string (value); - value = (GValue *) g_hash_table_lookup (properties, "text"); + value = (GValue *) g_hash_table_lookup (info->hash, "text"); if (value) text = g_value_get_string (value); - value = (GValue *) g_hash_table_lookup (properties, "smsc"); + value = (GValue *) g_hash_table_lookup (info->hash, "smsc"); if (value) smsc = g_value_get_string (value); - value = (GValue *) g_hash_table_lookup (properties, "validity"); + value = (GValue *) g_hash_table_lookup (info->hash, "validity"); if (value) validity = g_value_get_uint (value); - value = (GValue *) g_hash_table_lookup (properties, "class"); + value = (GValue *) g_hash_table_lookup (info->hash, "class"); if (value) class = g_value_get_uint (value); - if (!number) + if (!number) { error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Missing number"); - else if (!text) + } else if (!text) { error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Missing message text"); + } +done: if (error) { - async_call_done (MM_MODEM (modem), error, context); + async_call_done (MM_MODEM (self), error, info->context); g_error_free (error); } else - mm_modem_gsm_sms_send (modem, number, text, smsc, validity, class, async_call_done, context); + mm_modem_gsm_sms_send (self, number, text, smsc, validity, class, async_call_done, info->context); +} + +static void +impl_gsm_modem_sms_send (MMModemGsmSms *modem, + GHashTable *properties, + DBusGMethodInvocation *context) +{ + GError *error = NULL; + SmsAuthInfo *info; + + info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, properties, context); + + /* Make sure the caller is authorized to send the PUK */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_SMS, + sms_send_auth_cb, + info, + sms_auth_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + +static void +sms_send_from_storage_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + SmsAuthInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise delete the SMS */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + async_call_not_supported (self, async_call_done, info->context); } static void @@ -242,7 +542,41 @@ impl_gsm_modem_sms_send_from_storage (MMModemGsmSms *modem, guint idx, DBusGMethodInvocation *context) { - async_call_not_supported (modem, async_call_done, context); + GError *error = NULL; + SmsAuthInfo *info; + + info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, NULL, context); + + /* Make sure the caller is authorized to send the PUK */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_SMS, + sms_send_from_storage_auth_cb, + info, + sms_auth_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + +static void +sms_set_indication_auth_cb (GObject *instance, + guint32 reqid, + MMAuthResult result, + gpointer user_data) +{ + MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + SmsAuthInfo *info = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise delete the SMS */ + if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + dbus_g_method_return_error (info->context, error); + g_error_free (error); + } else + async_call_not_supported (self, async_call_done, info->context); } static void @@ -254,7 +588,21 @@ impl_gsm_modem_sms_set_indication (MMModemGsmSms *modem, guint bfr, DBusGMethodInvocation *context) { - async_call_not_supported (modem, async_call_done, context); + GError *error = NULL; + SmsAuthInfo *info; + + info = sms_auth_info_new (mode, mt, bm, ds, bfr, NULL, NULL, context); + + /* Make sure the caller is authorized to send the PUK */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_SMS, + sms_set_indication_auth_cb, + info, + sms_auth_info_destroy, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } } /*****************************************************************************/ -- cgit v1.2.3-70-g09d2 From 3b6a58145ff29d28bc026d4cec59aec076a99aba Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 27 Feb 2010 10:29:34 -0800 Subject: core: simply authentication request objects --- src/Makefile.am | 12 ++- src/mm-auth-provider.c | 254 +++++++++++++-------------------------------- src/mm-auth-provider.h | 65 +++++------- src/mm-modem-base.c | 72 +------------ src/mm-modem-cdma.c | 9 +- src/mm-modem-gsm-card.c | 54 ++++------ src/mm-modem-gsm-network.c | 9 +- src/mm-modem-gsm-sms.c | 72 +++++-------- src/mm-modem.c | 7 +- src/mm-modem.h | 6 +- 10 files changed, 159 insertions(+), 401 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 2ed7e603..70e143ac 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,6 +37,11 @@ modem_manager_SOURCES = \ main.c \ mm-callback-info.c \ mm-callback-info.h \ + mm-auth-request.c \ + mm-auth-request.h \ + mm-auth-provider.h \ + mm-auth-provider.c \ + mm-auth-provider-factory.c \ mm-manager.c \ mm-manager.h \ mm-modem.c \ @@ -71,13 +76,12 @@ modem_manager_SOURCES = \ mm-plugin-base.c \ mm-plugin-base.h \ mm-properties-changed-signal.c \ - mm-properties-changed-signal.h \ - mm-auth-provider.h \ - mm-auth-provider.c \ - mm-auth-provider-factory.c + mm-properties-changed-signal.h if WITH_POLKIT modem_manager_SOURCES += \ + mm-auth-request-polkit.c \ + mm-auth-request-polkit.h \ mm-auth-provider-polkit.c \ mm-auth-provider-polkit.h endif diff --git a/src/mm-auth-provider.c b/src/mm-auth-provider.c index 0ff4baff..5f0f04c4 100644 --- a/src/mm-auth-provider.c +++ b/src/mm-auth-provider.c @@ -35,14 +35,6 @@ enum { LAST_PROP }; -enum { - REQUEST_ADDED, - REQUEST_REMOVED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - - /*****************************************************************************/ GObject * @@ -53,101 +45,19 @@ mm_auth_provider_new (void) /*****************************************************************************/ -struct MMAuthRequest { - guint32 refcount; - guint32 id; - char *auth; - GObject *instance; - - MMAuthResult result; - - MMAuthRequestCb callback; - gpointer callback_data; - GDestroyNotify notify; -}; - -static MMAuthRequest * -mm_auth_request_new (const char *authorization, - GObject *instance, - MMAuthRequestCb callback, - gpointer callback_data, - GDestroyNotify notify) +static void +remove_requests (MMAuthProvider *self, GSList *remove) { - static guint32 id = 1; + MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (self); MMAuthRequest *req; - g_return_val_if_fail (authorization != NULL, NULL); - g_return_val_if_fail (callback != NULL, NULL); - - req = g_malloc0 (sizeof (MMAuthRequest)); - req->id = id++; - req->refcount = 1; - req->auth = g_strdup (authorization); - req->instance = instance; - req->callback = callback; - req->callback_data = callback_data; - req->notify = notify; - - return req; -} - -MMAuthRequest * -mm_auth_request_ref (MMAuthRequest *req) -{ - g_return_val_if_fail (req != NULL, NULL); - g_return_val_if_fail (req->refcount > 0, NULL); - - req->refcount++; - return req; -} - -void -mm_auth_request_unref (MMAuthRequest *req) -{ - g_return_if_fail (req != NULL); - g_return_if_fail (req->refcount > 0); - - req->refcount--; - if (req->refcount == 0) { - g_free (req->auth); - memset (req, 0, sizeof (MMAuthRequest)); - g_free (req); + while (remove) { + req = MM_AUTH_REQUEST (remove->data); + g_hash_table_remove (priv->requests, req); + remove = g_slist_remove (remove, req); } } -guint32 -mm_auth_request_get_id (MMAuthRequest *req) -{ - g_return_val_if_fail (req != NULL, 0); - g_return_val_if_fail (req->refcount > 0, 0); - - return req->id; -} - -const char * -mm_auth_request_get_authorization (MMAuthRequest *req) -{ - g_return_val_if_fail (req != NULL, 0); - g_return_val_if_fail (req->refcount > 0, 0); - - return req->auth; -} - -/*****************************************************************************/ - -MMAuthRequest * -mm_auth_provider_get_request (MMAuthProvider *provider, guint32 reqid) -{ - MMAuthProviderPrivate *priv; - - g_return_val_if_fail (provider != NULL, NULL); - g_return_val_if_fail (MM_IS_AUTH_PROVIDER (provider), NULL); - g_return_val_if_fail (reqid > 0, NULL); - - priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); - return (MMAuthRequest *) g_hash_table_lookup (priv->requests, GUINT_TO_POINTER (reqid)); -} - static gboolean process_complete_requests (gpointer user_data) { @@ -163,92 +73,78 @@ process_complete_requests (gpointer user_data) /* Call finished request's callbacks */ g_hash_table_iter_init (&iter, priv->requests); while (g_hash_table_iter_next (&iter, NULL, &value)) { - req = (MMAuthRequest *) value; - if (req->result != MM_AUTH_RESULT_UNKNOWN) { - req->callback (req->instance, req->id, req->result, req->callback_data); - - /* Let the caller clean up the request's callback data */ - if (req->notify) - req->notify (req->callback_data); + req = MM_AUTH_REQUEST (value); + if (mm_auth_request_get_authorization (req) != MM_AUTH_RESULT_UNKNOWN) { + mm_auth_request_complete (req); remove = g_slist_prepend (remove, req); } } /* And remove those requests from our pending request list */ - while (remove) { - req = (MMAuthRequest *) remove->data; - g_signal_emit (self, signals[REQUEST_REMOVED], 0, req->instance, req->id); - g_hash_table_remove (priv->requests, GUINT_TO_POINTER (req->id)); - remove = g_slist_remove (remove, req); - } + remove_requests (self, remove); return FALSE; } void mm_auth_provider_finish_request (MMAuthProvider *provider, - guint32 reqid, + MMAuthRequest *req, MMAuthResult result) { MMAuthProviderPrivate *priv; - MMAuthRequest *req; g_return_if_fail (provider != NULL); g_return_if_fail (MM_IS_AUTH_PROVIDER (provider)); - g_return_if_fail (reqid > 0); + g_return_if_fail (req != NULL); g_return_if_fail (result != MM_AUTH_RESULT_UNKNOWN); priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); - req = (MMAuthRequest *) g_hash_table_lookup (priv->requests, GUINT_TO_POINTER (reqid)); - g_return_if_fail (req != NULL); - - req->result = result; + g_return_if_fail (g_hash_table_lookup (priv->requests, req) != NULL); + mm_auth_request_set_result (req, result); if (priv->process_id == 0) priv->process_id = g_idle_add (process_complete_requests, provider); } void -mm_auth_provider_cancel_request (MMAuthProvider *provider, guint32 reqid) +mm_auth_provider_cancel_request (MMAuthProvider *provider, MMAuthRequest *req) { MMAuthProviderPrivate *priv; - MMAuthRequest *req; g_return_if_fail (provider != NULL); g_return_if_fail (MM_IS_AUTH_PROVIDER (provider)); - g_return_if_fail (reqid > 0); - - priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); - - req = (MMAuthRequest *) g_hash_table_lookup (priv->requests, GUINT_TO_POINTER (reqid)); g_return_if_fail (req != NULL); - /* Let the caller clean up the request's callback data */ - if (req->notify) - req->notify (req->callback_data); + priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); - /* We don't signal removal here as it's assumed the caller - * handles that itself instead of by the signal. - */ - g_hash_table_remove (priv->requests, GUINT_TO_POINTER (reqid)); + g_return_if_fail (g_hash_table_lookup (priv->requests, req) != NULL); + g_hash_table_remove (priv->requests, req); } -const char * -mm_auth_provider_get_authorization_for_id (MMAuthProvider *provider, guint32 reqid) +void +mm_auth_provider_cancel_for_owner (MMAuthProvider *self, GObject *owner) { MMAuthProviderPrivate *priv; + GHashTableIter iter; MMAuthRequest *req; + gpointer value; + GSList *remove = NULL; - g_return_val_if_fail (provider != NULL, NULL); - g_return_val_if_fail (MM_IS_AUTH_PROVIDER (provider), NULL); - g_return_val_if_fail (reqid > 0, NULL); + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_AUTH_PROVIDER (self)); - priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); - req = (MMAuthRequest *) g_hash_table_lookup (priv->requests, GUINT_TO_POINTER (reqid)); - g_return_val_if_fail (req != NULL, NULL); + /* Find all requests from this owner */ + priv = MM_AUTH_PROVIDER_GET_PRIVATE (self); + g_hash_table_iter_init (&iter, priv->requests); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + req = MM_AUTH_REQUEST (value); + if (mm_auth_request_get_owner (req) == owner) + remove = g_slist_prepend (remove, req); + } - return mm_auth_request_get_authorization (req); + /* And cancel/remove them */ + remove_requests (self, remove); } /*****************************************************************************/ @@ -259,16 +155,25 @@ real_request_auth (MMAuthProvider *provider, GError **error) { /* This class provides null authentication; all requests pass */ - mm_auth_provider_finish_request (provider, - mm_auth_request_get_id (req), - MM_AUTH_RESULT_AUTHORIZED); + mm_auth_provider_finish_request (provider, req, MM_AUTH_RESULT_AUTHORIZED); return TRUE; } -guint32 -mm_auth_provider_request_auth (MMAuthProvider *provider, +static MMAuthRequest * +real_create_request (MMAuthProvider *provider, + const char *authorization, + GObject *owner, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify) +{ + return (MMAuthRequest *) mm_auth_request_new (authorization, owner, callback, callback_data, notify); +} + +MMAuthRequest * +mm_auth_provider_request_auth (MMAuthProvider *self, const char *authorization, - GObject *instance, + GObject *owner, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify, @@ -277,32 +182,29 @@ mm_auth_provider_request_auth (MMAuthProvider *provider, MMAuthProviderPrivate *priv; MMAuthRequest *req; - g_return_val_if_fail (provider != NULL, 0); - g_return_val_if_fail (MM_IS_AUTH_PROVIDER (provider), 0); + g_return_val_if_fail (self != NULL, 0); + g_return_val_if_fail (MM_IS_AUTH_PROVIDER (self), 0); g_return_val_if_fail (authorization != NULL, 0); g_return_val_if_fail (callback != NULL, 0); - priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); + priv = MM_AUTH_PROVIDER_GET_PRIVATE (self); - req = mm_auth_request_new (authorization, instance, callback, callback_data, notify); + req = MM_AUTH_PROVIDER_GET_CLASS (self)->create_request (self, + authorization, + owner, + callback, + callback_data, + notify); g_assert (req); - g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->id), req); - g_signal_emit (provider, signals[REQUEST_ADDED], 0, instance, req->id); - - if (!MM_AUTH_PROVIDER_GET_CLASS (provider)->request_auth (provider, req, error)) { + g_hash_table_insert (priv->requests, req, req); + if (!MM_AUTH_PROVIDER_GET_CLASS (self)->request_auth (self, req, error)) { /* Error */ - g_signal_emit (provider, signals[REQUEST_REMOVED], 0, instance, req->id); - - /* Let the caller clean up the request's callback data */ - if (req->notify) - req->notify (req->callback_data); - - g_hash_table_remove (priv->requests, GUINT_TO_POINTER (req->id)); - return 0; + g_hash_table_remove (priv->requests, req); + return NULL; } - return req->id; + return req; } /*****************************************************************************/ @@ -315,7 +217,7 @@ mm_auth_provider_init (MMAuthProvider *self) priv->requests = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, - (GDestroyNotify) mm_auth_request_unref); + (GDestroyNotify) g_object_unref); } static void @@ -352,7 +254,7 @@ get_property (GObject *object, } static void -finalize (GObject *object) +dispose (GObject *object) { MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (object); @@ -360,7 +262,7 @@ finalize (GObject *object) g_source_remove (priv->process_id); g_hash_table_destroy (priv->requests); - G_OBJECT_CLASS (mm_auth_provider_parent_class)->finalize (object); + G_OBJECT_CLASS (mm_auth_provider_parent_class)->dispose (object); } static void @@ -374,8 +276,9 @@ mm_auth_provider_class_init (MMAuthProviderClass *class) /* Virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; + object_class->dispose = dispose; class->request_auth = real_request_auth; + class->create_request = real_create_request; /* Properties */ g_object_class_install_property (object_class, PROP_NAME, @@ -384,22 +287,5 @@ mm_auth_provider_class_init (MMAuthProviderClass *class) "Provider name", NULL_PROVIDER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /* Signals */ - signals[REQUEST_ADDED] = - g_signal_new ("request-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - mm_marshal_VOID__POINTER_UINT, - G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); - - signals[REQUEST_REMOVED] = - g_signal_new ("request-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - mm_marshal_VOID__POINTER_UINT, - G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); } diff --git a/src/mm-auth-provider.h b/src/mm-auth-provider.h index 8d693f3e..0bc6f100 100644 --- a/src/mm-auth-provider.h +++ b/src/mm-auth-provider.h @@ -18,6 +18,8 @@ #include +#include "mm-auth-request.h" + /* Authorizations */ #define MM_AUTHORIZATION_DEVICE "org.freedesktop.ModemManager.Device" #define MM_AUTHORIZATION_CONTACTS "org.freedesktop.ModemManager.Contacts" @@ -34,66 +36,47 @@ #define MM_AUTH_PROVIDER_NAME "name" -typedef enum MMAuthResult { - MM_AUTH_RESULT_UNKNOWN = 0, - MM_AUTH_RESULT_INTERNAL_FAILURE, - MM_AUTH_RESULT_NOT_AUTHORIZED, - MM_AUTH_RESULT_CHALLENGE, - MM_AUTH_RESULT_AUTHORIZED -} MMAuthResult; - -typedef struct MMAuthRequest MMAuthRequest; -typedef struct _MMAuthProvider MMAuthProvider; -typedef struct _MMAuthProviderClass MMAuthProviderClass; - -typedef void (*MMAuthRequestCb) (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data); - -struct _MMAuthProvider { +typedef struct { GObject parent; -}; +} MMAuthProvider; -struct _MMAuthProviderClass { +typedef struct { GObjectClass parent; gboolean (*request_auth) (MMAuthProvider *provider, MMAuthRequest *req, GError **error); -}; -GType mm_auth_provider_get_type (void); - -guint32 mm_auth_provider_request_auth (MMAuthProvider *provider, + MMAuthRequest * (*create_request) (MMAuthProvider *provider, const char *authorization, - GObject *instance, + GObject *owner, MMAuthRequestCb callback, gpointer callback_data, - GDestroyNotify notify, - GError **error); + GDestroyNotify notify); +} MMAuthProviderClass; -/* To get an auth provider instance, implemented in mm-auth-provider-factory.c */ -MMAuthProvider *mm_auth_provider_get (void); +GType mm_auth_provider_get_type (void); + +MMAuthRequest *mm_auth_provider_request_auth (MMAuthProvider *provider, + const char *authorization, + GObject *owner, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify, + GError **error); -/* For subclasses only */ -MMAuthRequest *mm_auth_provider_get_request (MMAuthProvider *provider, guint32 reqid); -MMAuthRequest *mm_auth_request_ref (MMAuthRequest *req); -void mm_auth_request_unref (MMAuthRequest *req); -guint32 mm_auth_request_get_id (MMAuthRequest *req); -const char * mm_auth_request_get_authorization (MMAuthRequest *req); +void mm_auth_provider_cancel_for_owner (MMAuthProvider *provider, + GObject *owner); -/* Normal API */ +/* To get an auth provider instance, implemented in mm-auth-provider-factory.c */ +MMAuthProvider *mm_auth_provider_get (void); /* schedules the request's completion */ void mm_auth_provider_finish_request (MMAuthProvider *provider, - guint32 reqid, + MMAuthRequest *req, MMAuthResult result); -void mm_auth_provider_cancel_request (MMAuthProvider *provider, guint32 reqid); - -const char *mm_auth_provider_get_authorization_for_id (MMAuthProvider *provider, - guint32 reqid); +void mm_auth_provider_cancel_request (MMAuthProvider *provider, MMAuthRequest *req); #endif /* MM_AUTH_PROVIDER_H */ diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c index 83178874..84dc1888 100644 --- a/src/mm-modem-base.c +++ b/src/mm-modem-base.c @@ -45,9 +45,6 @@ typedef struct { MMModemState state; MMAuthProvider *authp; - guint authp_added_id; - guint authp_removed_id; - GSList *auth_reqs; GHashTable *ports; } MMModemBasePrivate; @@ -240,67 +237,18 @@ modem_auth_request (MMModem *modem, } static gboolean -modem_auth_finish (MMModem *modem, - guint32 reqid, - MMAuthResult result, - GError **error) +modem_auth_finish (MMModem *modem, MMAuthRequest *req, GError **error) { - MMModemBase *self = MM_MODEM_BASE (modem); - MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); - - if (result != MM_AUTH_RESULT_AUTHORIZED) { - const char *auth; - - auth = mm_auth_provider_get_authorization_for_id (priv->authp, reqid); + if (mm_auth_request_get_result (req) != MM_AUTH_RESULT_AUTHORIZED) { g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_AUTHORIZATION_REQUIRED, "This request requires the '%s' authorization", - auth ? auth : "(unknown)"); + mm_auth_request_get_authorization (req)); return FALSE; } return TRUE; } -static void -authp_request_added (MMAuthProvider *provider, - gpointer parent, - guint32 reqid, - gpointer user_data) -{ - MMModemBase *self; - MMModemBasePrivate *priv; - - /* Make sure it's our auth request */ - if (parent != user_data) - return; - - self = MM_MODEM_BASE (user_data); - priv = MM_MODEM_BASE_GET_PRIVATE (self); - - /* Add this request to our table so we can cancel it when we die */ - priv->auth_reqs = g_slist_prepend (priv->auth_reqs, GUINT_TO_POINTER (reqid)); -} - -static void -authp_request_removed (MMAuthProvider *provider, - gpointer parent, - guint32 reqid, - gpointer user_data) -{ - MMModemBase *self; - MMModemBasePrivate *priv; - - /* Make sure it's our auth request */ - if (parent != user_data) - return; - - self = MM_MODEM_BASE (user_data); - priv = MM_MODEM_BASE_GET_PRIVATE (self); - - /* Request finished; remove cleanly */ - priv->auth_reqs = g_slist_remove (priv->auth_reqs, GUINT_TO_POINTER (reqid)); -} - /*****************************************************************************/ static void @@ -309,12 +257,6 @@ mm_modem_base_init (MMModemBase *self) MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); priv->authp = mm_auth_provider_get (); - priv->authp_added_id = g_signal_connect (priv->authp, "request-added", - (GCallback) authp_request_added, - self); - priv->authp_removed_id = g_signal_connect (priv->authp, "request-removed", - (GCallback) authp_request_removed, - self); priv->ports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); @@ -425,14 +367,8 @@ finalize (GObject *object) { MMModemBase *self = MM_MODEM_BASE (object); MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self); - GSList *iter; - - g_signal_handler_disconnect (priv->authp, priv->authp_added_id); - g_signal_handler_disconnect (priv->authp, priv->authp_removed_id); - for (iter = priv->auth_reqs; iter; iter = g_slist_next (iter)) - mm_auth_provider_cancel_request (priv->authp, GPOINTER_TO_UINT (iter->data)); - g_slist_free (priv->auth_reqs); + mm_auth_provider_cancel_for_owner (priv->authp, object); g_hash_table_destroy (priv->ports); g_free (priv->driver); diff --git a/src/mm-modem-cdma.c b/src/mm-modem-cdma.c index 0ba9f792..e57203ae 100644 --- a/src/mm-modem-cdma.c +++ b/src/mm-modem-cdma.c @@ -189,17 +189,14 @@ mm_modem_cdma_get_esn (MMModemCdma *self, } static void -esn_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +esn_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemCdma *self = MM_MODEM_CDMA (instance); + MMModemCdma *self = MM_MODEM_CDMA (owner); DBusGMethodInvocation *context = user_data; GError *error = NULL; /* Return any authorization error, otherwise get the ESN */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); } else diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c index 0e62779a..f16374e7 100644 --- a/src/mm-modem-gsm-card.c +++ b/src/mm-modem-gsm-card.c @@ -202,17 +202,14 @@ mm_modem_gsm_card_change_pin (MMModemGsmCard *self, /*****************************************************************************/ static void -imei_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +imei_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); DBusGMethodInvocation *context = user_data; GError *error = NULL; /* Return any authorization error, otherwise get the IMEI */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); } else @@ -239,17 +236,14 @@ impl_gsm_modem_get_imei (MMModemGsmCard *modem, DBusGMethodInvocation *context) /*****************************************************************************/ static void -imsi_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +imsi_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); DBusGMethodInvocation *context = user_data; GError *error = NULL; /* Return any authorization error, otherwise get the IMSI */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); } else @@ -316,17 +310,14 @@ send_pin_puk_info_new (const char *puk, /*****************************************************************************/ static void -send_puk_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +send_puk_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); SendPinPukInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise send the PUK */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else @@ -359,17 +350,14 @@ impl_gsm_modem_send_puk (MMModemGsmCard *modem, /*****************************************************************************/ static void -send_pin_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +send_pin_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); SendPinPukInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise unlock the modem */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else @@ -401,17 +389,14 @@ impl_gsm_modem_send_pin (MMModemGsmCard *modem, /*****************************************************************************/ static void -enable_pin_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +enable_pin_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); SendPinPukInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise enable the PIN */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else @@ -444,17 +429,14 @@ impl_gsm_modem_enable_pin (MMModemGsmCard *modem, /*****************************************************************************/ static void -change_pin_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +change_pin_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmCard *self = MM_MODEM_GSM_CARD (instance); + MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); SendPinPukInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise change the PIN */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c index bb84da12..ab50aed9 100644 --- a/src/mm-modem-gsm-network.c +++ b/src/mm-modem-gsm-network.c @@ -398,17 +398,14 @@ impl_gsm_modem_register (MMModemGsmNetwork *modem, } static void -scan_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +scan_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmNetwork *self = MM_MODEM_GSM_NETWORK (instance); + MMModemGsmNetwork *self = MM_MODEM_GSM_NETWORK (owner); DBusGMethodInvocation *context = user_data; GError *error = NULL; /* Return any authorization error, otherwise get the IMEI */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); } else diff --git a/src/mm-modem-gsm-sms.c b/src/mm-modem-gsm-sms.c index 00cd953f..27fe55ce 100644 --- a/src/mm-modem-gsm-sms.c +++ b/src/mm-modem-gsm-sms.c @@ -207,17 +207,14 @@ sms_auth_info_new (guint num1, /*****************************************************************************/ static void -sms_delete_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +sms_delete_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else @@ -249,17 +246,14 @@ impl_gsm_modem_sms_delete (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_get_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +sms_get_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else @@ -315,17 +309,14 @@ impl_gsm_modem_sms_get_smsc (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_set_smsc_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +sms_set_smsc_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else @@ -357,17 +348,14 @@ impl_gsm_modem_sms_set_smsc (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_list_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +sms_list_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else @@ -398,17 +386,14 @@ impl_gsm_modem_sms_list (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_save_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +sms_save_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else @@ -440,12 +425,9 @@ impl_gsm_modem_sms_save (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_send_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +sms_send_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); SmsAuthInfo *info = user_data; GError *error = NULL; GValue *value; @@ -456,7 +438,7 @@ sms_send_auth_cb (GObject *instance, guint class = 0; /* Return any authorization error, otherwise delete the SMS */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) goto done; value = (GValue *) g_hash_table_lookup (info->hash, "number"); @@ -520,17 +502,14 @@ impl_gsm_modem_sms_send (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_send_from_storage_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +sms_send_from_storage_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else @@ -562,17 +541,14 @@ impl_gsm_modem_sms_send_from_storage (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_set_indication_auth_cb (GObject *instance, - guint32 reqid, - MMAuthResult result, - gpointer user_data) +sms_set_indication_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) { - MMModemGsmSms *self = MM_MODEM_GSM_SMS (instance); + MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ - if (!mm_modem_auth_finish (MM_MODEM (self), reqid, result, &error)) { + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { dbus_g_method_return_error (info->context, error); g_error_free (error); } else diff --git a/src/mm-modem.c b/src/mm-modem.c index 0c8e6b25..21375db0 100644 --- a/src/mm-modem.c +++ b/src/mm-modem.c @@ -632,18 +632,17 @@ mm_modem_auth_request (MMModem *self, gboolean mm_modem_auth_finish (MMModem *self, - guint32 reqid, - MMAuthResult result, + MMAuthRequest *req, GError **error) { gboolean success; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (MM_IS_MODEM (self), FALSE); - g_return_val_if_fail (reqid > 0, FALSE); + g_return_val_if_fail (req != NULL, FALSE); g_return_val_if_fail (MM_MODEM_GET_INTERFACE (self)->auth_finish, FALSE); - success = MM_MODEM_GET_INTERFACE (self)->auth_finish (self, reqid, result, error); + success = MM_MODEM_GET_INTERFACE (self)->auth_finish (self, req, error); /* If the request failed, the implementor *should* return an error */ if (!success && error) diff --git a/src/mm-modem.h b/src/mm-modem.h index 531ca785..fb28b322 100644 --- a/src/mm-modem.h +++ b/src/mm-modem.h @@ -168,8 +168,7 @@ struct _MMModem { GError **error); gboolean (*auth_finish) (MMModem *self, - guint32 reqid, - MMAuthResult result, + MMAuthRequest *req, GError **error); /* Signals */ @@ -245,8 +244,7 @@ gboolean mm_modem_auth_request (MMModem *self, GError **error); gboolean mm_modem_auth_finish (MMModem *self, - guint32 reqid, - MMAuthResult result, + MMAuthRequest *req, GError **error); #endif /* MM_MODEM_H */ -- cgit v1.2.3-70-g09d2 From aed5f3765d4b8e421888f6cc87800d76853b67d4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 27 Feb 2010 12:51:03 -0800 Subject: core: add missing MMAuthRequest class --- src/mm-auth-request.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/mm-auth-request.h | 72 ++++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 src/mm-auth-request.c create mode 100644 src/mm-auth-request.h (limited to 'src') diff --git a/src/mm-auth-request.c b/src/mm-auth-request.c new file mode 100644 index 00000000..79f0d421 --- /dev/null +++ b/src/mm-auth-request.c @@ -0,0 +1,182 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#include "mm-auth-request.h" + +G_DEFINE_TYPE (MMAuthRequest, mm_auth_request, G_TYPE_OBJECT) + +#define MM_AUTH_REQUEST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_AUTH_REQUEST, MMAuthRequestPrivate)) + +typedef struct { + GObject *owner; + char *auth; + DBusGMethodInvocation *context; + MMAuthRequestCb callback; + gpointer callback_data; + + MMAuthResult result; +} MMAuthRequestPrivate; + +/*****************************************************************************/ + +GObject * +mm_auth_request_new (GType atype, + const char *authorization, + GObject *owner, + DBusGMethodInvocation *context, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify) +{ + GObject *obj; + MMAuthRequestPrivate *priv; + + g_return_val_if_fail (authorization != NULL, NULL); + g_return_val_if_fail (owner != NULL, NULL); + g_return_val_if_fail (callback != NULL, NULL); + + obj = g_object_new (atype ? atype : MM_TYPE_AUTH_REQUEST, NULL); + if (obj) { + priv = MM_AUTH_REQUEST_GET_PRIVATE (obj); + priv->owner = owner; /* not reffed */ + priv->context = context; + priv->auth = g_strdup (authorization); + priv->callback = callback; + priv->callback_data = callback_data; + + g_object_set_data_full (obj, "caller-data", callback_data, notify); + } + + return obj; +} + +/*****************************************************************************/ + +const char * +mm_auth_request_get_authorization (MMAuthRequest *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (MM_IS_AUTH_REQUEST (self), NULL); + + return MM_AUTH_REQUEST_GET_PRIVATE (self)->auth; +} + +GObject * +mm_auth_request_get_owner (MMAuthRequest *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (MM_IS_AUTH_REQUEST (self), NULL); + + return MM_AUTH_REQUEST_GET_PRIVATE (self)->owner; +} + +MMAuthResult +mm_auth_request_get_result (MMAuthRequest *self) +{ + g_return_val_if_fail (self != NULL, MM_AUTH_RESULT_UNKNOWN); + g_return_val_if_fail (MM_IS_AUTH_REQUEST (self), MM_AUTH_RESULT_UNKNOWN); + + return MM_AUTH_REQUEST_GET_PRIVATE (self)->result; +} + +void +mm_auth_request_set_result (MMAuthRequest *self, MMAuthResult result) +{ + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_AUTH_REQUEST (self)); + g_return_if_fail (result != MM_AUTH_RESULT_UNKNOWN); + + MM_AUTH_REQUEST_GET_PRIVATE (self)->result = result; +} + +gboolean +mm_auth_request_authenticate (MMAuthRequest *self, GError **error) +{ + return MM_AUTH_REQUEST_GET_CLASS (self)->authenticate (self, error); +} + +void +mm_auth_request_callback (MMAuthRequest *self) +{ + MMAuthRequestPrivate *priv; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_AUTH_REQUEST (self)); + + priv = MM_AUTH_REQUEST_GET_PRIVATE (self); + g_warn_if_fail (priv->result != MM_AUTH_RESULT_UNKNOWN); + + if (priv->callback) + priv->callback (self, priv->owner, priv->context, priv->callback_data); +} + +void +mm_auth_request_dispose (MMAuthRequest *self) +{ + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_AUTH_REQUEST (self)); + + if (MM_AUTH_REQUEST_GET_CLASS (self)->dispose) + MM_AUTH_REQUEST_GET_CLASS (self)->dispose (self); +} + +/*****************************************************************************/ + +static gboolean +real_authenticate (MMAuthRequest *self, GError **error) +{ + /* Null auth; everything passes */ + mm_auth_request_set_result (self, MM_AUTH_RESULT_AUTHORIZED); + g_signal_emit_by_name (self, "result"); + return TRUE; +} + +/*****************************************************************************/ + +static void +mm_auth_request_init (MMAuthRequest *self) +{ +} + +static void +dispose (GObject *object) +{ + MMAuthRequestPrivate *priv = MM_AUTH_REQUEST_GET_PRIVATE (object); + + g_free (priv->auth); + + G_OBJECT_CLASS (mm_auth_request_parent_class)->dispose (object); +} + +static void +mm_auth_request_class_init (MMAuthRequestClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + mm_auth_request_parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (MMAuthRequestPrivate)); + + /* Virtual methods */ + object_class->dispose = dispose; + class->authenticate = real_authenticate; + + g_signal_new ("result", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, G_TYPE_NONE); +} + diff --git a/src/mm-auth-request.h b/src/mm-auth-request.h new file mode 100644 index 00000000..e22f0a23 --- /dev/null +++ b/src/mm-auth-request.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifndef MM_AUTH_REQUEST_H +#define MM_AUTH_REQUEST_H + +#include +#include + +#define MM_TYPE_AUTH_REQUEST (mm_auth_request_get_type ()) +#define MM_AUTH_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_AUTH_REQUEST, MMAuthRequest)) +#define MM_AUTH_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_AUTH_REQUEST, MMAuthRequestClass)) +#define MM_IS_AUTH_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_AUTH_REQUEST)) +#define MM_IS_AUTH_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_AUTH_REQUEST)) +#define MM_AUTH_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_AUTH_REQUEST, MMAuthRequestClass)) + +typedef enum MMAuthResult { + MM_AUTH_RESULT_UNKNOWN = 0, + MM_AUTH_RESULT_INTERNAL_FAILURE, + MM_AUTH_RESULT_NOT_AUTHORIZED, + MM_AUTH_RESULT_CHALLENGE, + MM_AUTH_RESULT_AUTHORIZED +} MMAuthResult; + +typedef struct { + GObject parent; +} MMAuthRequest; + +typedef struct { + GObjectClass parent; + + gboolean (*authenticate) (MMAuthRequest *self, GError **error); + void (*dispose) (MMAuthRequest *self); +} MMAuthRequestClass; + +GType mm_auth_request_get_type (void); + +typedef void (*MMAuthRequestCb) (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data); + +GObject *mm_auth_request_new (GType atype, + const char *authorization, + GObject *owner, + DBusGMethodInvocation *context, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify); + +const char * mm_auth_request_get_authorization (MMAuthRequest *req); +GObject * mm_auth_request_get_owner (MMAuthRequest *req); +MMAuthResult mm_auth_request_get_result (MMAuthRequest *req); +void mm_auth_request_set_result (MMAuthRequest *req, MMAuthResult result); +gboolean mm_auth_request_authenticate (MMAuthRequest *req, GError **error); +void mm_auth_request_callback (MMAuthRequest *req); +void mm_auth_request_dispose (MMAuthRequest *req); + +#endif /* MM_AUTH_REQUEST_H */ + -- cgit v1.2.3-70-g09d2 From 28d065c1f15a7ebf9109abbdca2ba8e831291f13 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 27 Feb 2010 12:51:13 -0800 Subject: core: implement optional PolicyKit-based authentication --- org.freedesktop.ModemManager.conf.polkit | 7 ++ src/Makefile.am | 29 ++--- src/mm-auth-provider-polkit.c | 153 +++++++++++++++++++++++++++ src/mm-auth-provider-polkit.h | 43 ++++++++ src/mm-auth-provider.c | 133 ++++++++++++----------- src/mm-auth-provider.h | 10 +- src/mm-auth-request-polkit.c | 175 +++++++++++++++++++++++++++++++ src/mm-auth-request-polkit.h | 53 ++++++++++ src/mm-modem-base.c | 2 + src/mm-modem-cdma.c | 9 +- src/mm-modem-gsm-card.c | 71 ++++++++----- src/mm-modem-gsm-network.c | 9 +- src/mm-modem-gsm-sms.c | 131 +++++++++++++---------- src/mm-modem.c | 3 + src/mm-modem.h | 3 + 15 files changed, 664 insertions(+), 167 deletions(-) create mode 100644 src/mm-auth-provider-polkit.c create mode 100644 src/mm-auth-provider-polkit.h create mode 100644 src/mm-auth-request-polkit.c create mode 100644 src/mm-auth-request-polkit.h (limited to 'src') diff --git a/org.freedesktop.ModemManager.conf.polkit b/org.freedesktop.ModemManager.conf.polkit index ecd95566..25490e33 100644 --- a/org.freedesktop.ModemManager.conf.polkit +++ b/org.freedesktop.ModemManager.conf.polkit @@ -12,6 +12,13 @@ The rest are restricted to root for security. --> + + + + diff --git a/src/Makefile.am b/src/Makefile.am index 70e143ac..a695f374 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,15 +33,26 @@ if WITH_POLKIT modem_manager_LDADD += $(POLKIT_LIBS) endif -modem_manager_SOURCES = \ - main.c \ - mm-callback-info.c \ - mm-callback-info.h \ +auth_sources = \ mm-auth-request.c \ mm-auth-request.h \ mm-auth-provider.h \ mm-auth-provider.c \ - mm-auth-provider-factory.c \ + mm-auth-provider-factory.c + +if WITH_POLKIT +auth_sources += \ + mm-auth-request-polkit.c \ + mm-auth-request-polkit.h \ + mm-auth-provider-polkit.c \ + mm-auth-provider-polkit.h +endif + +modem_manager_SOURCES = \ + main.c \ + mm-callback-info.c \ + mm-callback-info.h \ + $(auth_sources) \ mm-manager.c \ mm-manager.h \ mm-modem.c \ @@ -78,14 +89,6 @@ modem_manager_SOURCES = \ mm-properties-changed-signal.c \ mm-properties-changed-signal.h -if WITH_POLKIT -modem_manager_SOURCES += \ - mm-auth-request-polkit.c \ - mm-auth-request-polkit.h \ - mm-auth-provider-polkit.c \ - mm-auth-provider-polkit.h -endif - mm-manager-glue.h: $(top_srcdir)/introspection/mm-manager.xml dbus-binding-tool --prefix=mm_manager --mode=glib-server --output=$@ $< diff --git a/src/mm-auth-provider-polkit.c b/src/mm-auth-provider-polkit.c new file mode 100644 index 00000000..c457eaf4 --- /dev/null +++ b/src/mm-auth-provider-polkit.c @@ -0,0 +1,153 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#include + +#include "mm-auth-request-polkit.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 { + PolkitAuthority *authority; + guint auth_changed_id; +} MMAuthProviderPolkitPrivate; + +enum { + PROP_NAME = 1000, +}; + +/*****************************************************************************/ + +GObject * +mm_auth_provider_polkit_new (void) +{ + return g_object_new (MM_TYPE_AUTH_PROVIDER_POLKIT, NULL); +} + +/*****************************************************************************/ + +static void +pk_authority_changed_cb (GObject *object, gpointer user_data) +{ + /* Let clients know they should re-check their authorization */ +} + +/*****************************************************************************/ + +static MMAuthRequest * +real_create_request (MMAuthProvider *provider, + const char *authorization, + GObject *owner, + DBusGMethodInvocation *context, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify) +{ + 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); +} + +/*****************************************************************************/ + +static void +mm_auth_provider_polkit_init (MMAuthProviderPolkit *self) +{ + MMAuthProviderPolkitPrivate *priv = MM_AUTH_PROVIDER_POLKIT_GET_PRIVATE (self); + + priv->authority = polkit_authority_get (); + if (priv->authority) { + priv->auth_changed_id = g_signal_connect (priv->authority, + "changed", + G_CALLBACK (pk_authority_changed_cb), + self); + } else + g_warning ("%s: failed to create PolicyKit authority.", __func__); +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_NAME: + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + 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; + } +} + +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_OBJECT_CLASS (mm_auth_provider_polkit_parent_class)->dispose (object); +} + +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); + + 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); +} + diff --git a/src/mm-auth-provider-polkit.h b/src/mm-auth-provider-polkit.h new file mode 100644 index 00000000..a52c56df --- /dev/null +++ b/src/mm-auth-provider-polkit.h @@ -0,0 +1,43 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifndef MM_AUTH_PROVIDER_POLKIT_H +#define MM_AUTH_PROVIDER_POLKIT_H + +#include + +#include "mm-auth-provider.h" + +#define MM_TYPE_AUTH_PROVIDER_POLKIT (mm_auth_provider_polkit_get_type ()) +#define MM_AUTH_PROVIDER_POLKIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_AUTH_PROVIDER_POLKIT, MMAuthProviderPolkit)) +#define MM_AUTH_PROVIDER_POLKIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_AUTH_PROVIDER_POLKIT, MMAuthProviderPolkitClass)) +#define MM_IS_AUTH_PROVIDER_POLKIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_AUTH_PROVIDER_POLKIT)) +#define MM_IS_AUTH_PROVIDER_POLKIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_AUTH_PROVIDER_POLKIT)) +#define MM_AUTH_PROVIDER_POLKIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_AUTH_PROVIDER_POLKIT, MMAuthProviderPolkitClass)) + +typedef struct { + MMAuthProvider parent; +} MMAuthProviderPolkit; + +typedef struct { + MMAuthProviderClass parent; +} MMAuthProviderPolkitClass; + +GType mm_auth_provider_polkit_get_type (void); + +GObject *mm_auth_provider_polkit_new (void); + +#endif /* MM_AUTH_PROVIDER_POLKIT_H */ + diff --git a/src/mm-auth-provider.c b/src/mm-auth-provider.c index 5f0f04c4..ceff9adf 100644 --- a/src/mm-auth-provider.c +++ b/src/mm-auth-provider.c @@ -58,55 +58,6 @@ remove_requests (MMAuthProvider *self, GSList *remove) } } -static gboolean -process_complete_requests (gpointer user_data) -{ - MMAuthProvider *self = MM_AUTH_PROVIDER (user_data); - MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (self); - GHashTableIter iter; - gpointer value; - GSList *remove = NULL; - MMAuthRequest *req; - - priv->process_id = 0; - - /* Call finished request's callbacks */ - g_hash_table_iter_init (&iter, priv->requests); - while (g_hash_table_iter_next (&iter, NULL, &value)) { - req = MM_AUTH_REQUEST (value); - - if (mm_auth_request_get_authorization (req) != MM_AUTH_RESULT_UNKNOWN) { - mm_auth_request_complete (req); - remove = g_slist_prepend (remove, req); - } - } - - /* And remove those requests from our pending request list */ - remove_requests (self, remove); - - return FALSE; -} - -void -mm_auth_provider_finish_request (MMAuthProvider *provider, - MMAuthRequest *req, - MMAuthResult result) -{ - MMAuthProviderPrivate *priv; - - g_return_if_fail (provider != NULL); - g_return_if_fail (MM_IS_AUTH_PROVIDER (provider)); - g_return_if_fail (req != NULL); - g_return_if_fail (result != MM_AUTH_RESULT_UNKNOWN); - - priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider); - g_return_if_fail (g_hash_table_lookup (priv->requests, req) != NULL); - - mm_auth_request_set_result (req, result); - if (priv->process_id == 0) - priv->process_id = g_idle_add (process_complete_requests, provider); -} - void mm_auth_provider_cancel_request (MMAuthProvider *provider, MMAuthRequest *req) { @@ -149,31 +100,72 @@ mm_auth_provider_cancel_for_owner (MMAuthProvider *self, GObject *owner) /*****************************************************************************/ -static gboolean -real_request_auth (MMAuthProvider *provider, - MMAuthRequest *req, - GError **error) -{ - /* This class provides null authentication; all requests pass */ - mm_auth_provider_finish_request (provider, req, MM_AUTH_RESULT_AUTHORIZED); - return TRUE; -} static MMAuthRequest * real_create_request (MMAuthProvider *provider, const char *authorization, GObject *owner, + DBusGMethodInvocation *context, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify) { - return (MMAuthRequest *) mm_auth_request_new (authorization, owner, callback, callback_data, notify); + return (MMAuthRequest *) mm_auth_request_new (0, + authorization, + owner, + context, + callback, + callback_data, + notify); } +static gboolean +process_complete_requests (gpointer user_data) +{ + MMAuthProvider *self = MM_AUTH_PROVIDER (user_data); + MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (self); + GHashTableIter iter; + gpointer value; + GSList *remove = NULL; + MMAuthRequest *req; + + priv->process_id = 0; + + /* Call finished request's callbacks */ + g_hash_table_iter_init (&iter, priv->requests); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + req = MM_AUTH_REQUEST (value); + + if (mm_auth_request_get_authorization (req) != MM_AUTH_RESULT_UNKNOWN) { + mm_auth_request_callback (req); + remove = g_slist_prepend (remove, req); + } + } + + /* And remove those requests from our pending request list */ + remove_requests (self, remove); + + return FALSE; +} + +static void +auth_result_cb (MMAuthRequest *req, gpointer user_data) +{ + MMAuthProvider *self = MM_AUTH_PROVIDER (user_data); + MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (self); + + /* Process results from an idle handler */ + if (priv->process_id == 0) + priv->process_id = g_idle_add (process_complete_requests, self); +} + +#define RESULT_SIGID_TAG "result-sigid" + MMAuthRequest * mm_auth_provider_request_auth (MMAuthProvider *self, const char *authorization, GObject *owner, + DBusGMethodInvocation *context, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify, @@ -181,6 +173,7 @@ mm_auth_provider_request_auth (MMAuthProvider *self, { MMAuthProviderPrivate *priv; MMAuthRequest *req; + guint32 sigid; g_return_val_if_fail (self != NULL, 0); g_return_val_if_fail (MM_IS_AUTH_PROVIDER (self), 0); @@ -192,13 +185,17 @@ mm_auth_provider_request_auth (MMAuthProvider *self, req = MM_AUTH_PROVIDER_GET_CLASS (self)->create_request (self, authorization, owner, + context, callback, callback_data, notify); g_assert (req); + sigid = g_signal_connect (req, "result", G_CALLBACK (auth_result_cb), self); + g_object_set_data (G_OBJECT (req), RESULT_SIGID_TAG, GUINT_TO_POINTER (sigid)); + g_hash_table_insert (priv->requests, req, req); - if (!MM_AUTH_PROVIDER_GET_CLASS (self)->request_auth (self, req, error)) { + if (!mm_auth_request_authenticate (req, error)) { /* Error */ g_hash_table_remove (priv->requests, req); return NULL; @@ -209,6 +206,19 @@ mm_auth_provider_request_auth (MMAuthProvider *self, /*****************************************************************************/ +static void +dispose_auth_request (gpointer data) +{ + MMAuthRequest *req = MM_AUTH_REQUEST (data); + guint sigid; + + sigid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), RESULT_SIGID_TAG)); + if (sigid) + g_signal_handler_disconnect (req, sigid); + mm_auth_request_dispose (req); + g_object_unref (req); +} + static void mm_auth_provider_init (MMAuthProvider *self) { @@ -217,7 +227,7 @@ mm_auth_provider_init (MMAuthProvider *self) priv->requests = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, - (GDestroyNotify) g_object_unref); + dispose_auth_request); } static void @@ -277,7 +287,6 @@ mm_auth_provider_class_init (MMAuthProviderClass *class) object_class->set_property = set_property; object_class->get_property = get_property; object_class->dispose = dispose; - class->request_auth = real_request_auth; class->create_request = real_create_request; /* Properties */ diff --git a/src/mm-auth-provider.h b/src/mm-auth-provider.h index 0bc6f100..94edc44d 100644 --- a/src/mm-auth-provider.h +++ b/src/mm-auth-provider.h @@ -17,6 +17,7 @@ #define MM_AUTH_PROVIDER_H #include +#include #include "mm-auth-request.h" @@ -43,13 +44,10 @@ typedef struct { typedef struct { GObjectClass parent; - gboolean (*request_auth) (MMAuthProvider *provider, - MMAuthRequest *req, - GError **error); - MMAuthRequest * (*create_request) (MMAuthProvider *provider, const char *authorization, GObject *owner, + DBusGMethodInvocation *context, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify); @@ -57,9 +55,11 @@ typedef struct { GType mm_auth_provider_get_type (void); +/* Don't do anything clever from the notify callback... */ MMAuthRequest *mm_auth_provider_request_auth (MMAuthProvider *provider, const char *authorization, GObject *owner, + DBusGMethodInvocation *context, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify, @@ -68,6 +68,8 @@ MMAuthRequest *mm_auth_provider_request_auth (MMAuthProvider *provider, void mm_auth_provider_cancel_for_owner (MMAuthProvider *provider, GObject *owner); +/* Subclass API */ + /* To get an auth provider instance, implemented in mm-auth-provider-factory.c */ MMAuthProvider *mm_auth_provider_get (void); diff --git a/src/mm-auth-request-polkit.c b/src/mm-auth-request-polkit.c new file mode 100644 index 00000000..2a96bfec --- /dev/null +++ b/src/mm-auth-request-polkit.c @@ -0,0 +1,175 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#include +#include + +#include "mm-auth-request-polkit.h" + +G_DEFINE_TYPE (MMAuthRequestPolkit, mm_auth_request_polkit, MM_TYPE_AUTH_REQUEST) + +#define MM_AUTH_REQUEST_POLKIT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_AUTH_REQUEST_POLKIT, MMAuthRequestPolkitPrivate)) + +typedef struct { + PolkitAuthority *authority; + GCancellable *cancellable; + PolkitSubject *subject; +} MMAuthRequestPolkitPrivate; + +/*****************************************************************************/ + +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; +} + +/*****************************************************************************/ + +static void +pk_auth_cb (GObject *object, GAsyncResult *result, gpointer user_data) +{ + MMAuthRequestPolkit *self = user_data; + MMAuthRequestPolkitPrivate *priv; + PolkitAuthorizationResult *pk_result; + GError *error = NULL; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_AUTH_REQUEST_POLKIT (self)); + + priv = MM_AUTH_REQUEST_POLKIT_GET_PRIVATE (self); + if (!g_cancellable_is_cancelled (priv->cancellable)) { + pk_result = polkit_authority_check_authorization_finish (priv->authority, + result, + &error); + if (error) { + mm_auth_request_set_result (MM_AUTH_REQUEST (self), MM_AUTH_RESULT_INTERNAL_FAILURE); + g_warning ("%s: PolicyKit authentication error: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } else if (polkit_authorization_result_get_is_authorized (pk_result)) + mm_auth_request_set_result (MM_AUTH_REQUEST (self), MM_AUTH_RESULT_AUTHORIZED); + else if (polkit_authorization_result_get_is_challenge (pk_result)) + mm_auth_request_set_result (MM_AUTH_REQUEST (self), MM_AUTH_RESULT_CHALLENGE); + else + mm_auth_request_set_result (MM_AUTH_REQUEST (self), MM_AUTH_RESULT_NOT_AUTHORIZED); + + g_signal_emit_by_name (self, "result"); + } + + g_object_unref (self); +} + +static gboolean +real_authenticate (MMAuthRequest *self, GError **error) +{ + MMAuthRequestPolkitPrivate *priv; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (MM_IS_AUTH_REQUEST_POLKIT (self), FALSE); + + /* We ref ourselves across the polkit call, because we can't get + * disposed of while the call is still in-progress, and even if we + * cancel ourselves we'll still get the callback. + */ + g_object_ref (self); + + priv = MM_AUTH_REQUEST_POLKIT_GET_PRIVATE (self); + polkit_authority_check_authorization (priv->authority, + priv->subject, + mm_auth_request_get_authorization (MM_AUTH_REQUEST (self)), + NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + priv->cancellable, + pk_auth_cb, + self); + return TRUE; +} + +static void +real_dispose (MMAuthRequest *req) +{ + g_return_if_fail (req != NULL); + g_return_if_fail (MM_IS_AUTH_REQUEST_POLKIT (req)); + + g_cancellable_cancel (MM_AUTH_REQUEST_POLKIT_GET_PRIVATE (req)->cancellable); +} + +/*****************************************************************************/ + +static void +mm_auth_request_polkit_init (MMAuthRequestPolkit *self) +{ +} + +static void +dispose (GObject *object) +{ + MMAuthRequestPolkitPrivate *priv = MM_AUTH_REQUEST_POLKIT_GET_PRIVATE (object); + + g_object_unref (priv->cancellable); + g_object_unref (priv->subject); + + G_OBJECT_CLASS (mm_auth_request_polkit_parent_class)->dispose (object); +} + +static void +mm_auth_request_polkit_class_init (MMAuthRequestPolkitClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + MMAuthRequestClass *ar_class = MM_AUTH_REQUEST_CLASS (class); + + mm_auth_request_polkit_parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (MMAuthRequestPolkitPrivate)); + + /* Virtual methods */ + object_class->dispose = dispose; + ar_class->authenticate = real_authenticate; + ar_class->dispose = real_dispose; +} + diff --git a/src/mm-auth-request-polkit.h b/src/mm-auth-request-polkit.h new file mode 100644 index 00000000..384ace85 --- /dev/null +++ b/src/mm-auth-request-polkit.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifndef MM_AUTH_REQUEST_POLKIT_H +#define MM_AUTH_REQUEST_POLKIT_H + +#include +#include +#include + +#include "mm-auth-request.h" + +#define MM_TYPE_AUTH_REQUEST_POLKIT (mm_auth_request_polkit_get_type ()) +#define MM_AUTH_REQUEST_POLKIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_AUTH_REQUEST_POLKIT, MMAuthRequestPolkit)) +#define MM_AUTH_REQUEST_POLKIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_AUTH_REQUEST_POLKIT, MMAuthRequestPolkitClass)) +#define MM_IS_AUTH_REQUEST_POLKIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_AUTH_REQUEST_POLKIT)) +#define MM_IS_AUTH_REQUEST_POLKIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_AUTH_REQUEST_POLKIT)) +#define MM_AUTH_REQUEST_POLKIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_AUTH_REQUEST_POLKIT, MMAuthRequestPolkitClass)) + +typedef struct { + MMAuthRequest parent; +} MMAuthRequestPolkit; + +typedef struct { + MMAuthRequestClass parent; +} MMAuthRequestPolkitClass; + +GType mm_auth_request_polkit_get_type (void); + +GObject *mm_auth_request_polkit_new (PolkitAuthority *authority, + const char *authorization, + GObject *owner, + DBusGMethodInvocation *context, + MMAuthRequestCb callback, + gpointer callback_data, + GDestroyNotify notify); + +void mm_auth_request_polkit_cancel (MMAuthRequestPolkit *self); + +#endif /* MM_AUTH_REQUEST_POLKIT_H */ + diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c index 84dc1888..af1c6258 100644 --- a/src/mm-modem-base.c +++ b/src/mm-modem-base.c @@ -218,6 +218,7 @@ mm_modem_base_set_unlock_required (MMModemBase *self, const char *unlock_require static gboolean modem_auth_request (MMModem *modem, const char *authorization, + DBusGMethodInvocation *context, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify, @@ -230,6 +231,7 @@ modem_auth_request (MMModem *modem, return !!mm_auth_provider_request_auth (priv->authp, authorization, G_OBJECT (self), + context, callback, callback_data, notify, diff --git a/src/mm-modem-cdma.c b/src/mm-modem-cdma.c index e57203ae..1a4fe6a2 100644 --- a/src/mm-modem-cdma.c +++ b/src/mm-modem-cdma.c @@ -189,10 +189,12 @@ mm_modem_cdma_get_esn (MMModemCdma *self, } static void -esn_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +esn_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemCdma *self = MM_MODEM_CDMA (owner); - DBusGMethodInvocation *context = user_data; GError *error = NULL; /* Return any authorization error, otherwise get the ESN */ @@ -211,8 +213,9 @@ impl_modem_cdma_get_esn (MMModemCdma *self, DBusGMethodInvocation *context) /* Make sure the caller is authorized to get the ESN */ if (!mm_modem_auth_request (MM_MODEM (self), MM_AUTHORIZATION_DEVICE, - esn_auth_cb, context, + esn_auth_cb, + NULL, NULL, &error)) { dbus_g_method_return_error (context, error); diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c index f16374e7..9881871c 100644 --- a/src/mm-modem-gsm-card.c +++ b/src/mm-modem-gsm-card.c @@ -202,10 +202,12 @@ mm_modem_gsm_card_change_pin (MMModemGsmCard *self, /*****************************************************************************/ static void -imei_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +imei_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); - DBusGMethodInvocation *context = user_data; GError *error = NULL; /* Return any authorization error, otherwise get the IMEI */ @@ -224,8 +226,9 @@ impl_gsm_modem_get_imei (MMModemGsmCard *modem, DBusGMethodInvocation *context) /* Make sure the caller is authorized to get the IMEI */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_DEVICE, - imei_auth_cb, context, + imei_auth_cb, + NULL, NULL, &error)) { dbus_g_method_return_error (context, error); @@ -236,10 +239,12 @@ impl_gsm_modem_get_imei (MMModemGsmCard *modem, DBusGMethodInvocation *context) /*****************************************************************************/ static void -imsi_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +imsi_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); - DBusGMethodInvocation *context = user_data; GError *error = NULL; /* Return any authorization error, otherwise get the IMSI */ @@ -258,8 +263,9 @@ impl_gsm_modem_get_imsi (MMModemGsmCard *modem, DBusGMethodInvocation *context) /* Make sure the caller is authorized to get the IMSI */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_DEVICE, - imsi_auth_cb, context, + imsi_auth_cb, + NULL, NULL, &error)) { dbus_g_method_return_error (context, error); @@ -274,7 +280,6 @@ typedef struct { char *pin; char *pin2; gboolean enabled; - DBusGMethodInvocation *context; } SendPinPukInfo; static void @@ -293,8 +298,7 @@ static SendPinPukInfo * send_pin_puk_info_new (const char *puk, const char *pin, const char *pin2, - gboolean enabled, - DBusGMethodInvocation *context) + gboolean enabled) { SendPinPukInfo *info; @@ -303,14 +307,16 @@ send_pin_puk_info_new (const char *puk, info->pin = g_strdup (pin); info->pin2 = g_strdup (pin2); info->enabled = enabled; - info->context = context; return info; } /*****************************************************************************/ static void -send_puk_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +send_puk_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); SendPinPukInfo *info = user_data; @@ -318,10 +324,10 @@ send_puk_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) /* Return any authorization error, otherwise send the PUK */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - mm_modem_gsm_card_send_puk (self, info->puk, info->pin, async_call_done, info->context); + mm_modem_gsm_card_send_puk (self, info->puk, info->pin, async_call_done, context); } static void @@ -333,11 +339,12 @@ impl_gsm_modem_send_puk (MMModemGsmCard *modem, GError *error = NULL; SendPinPukInfo *info; - info = send_pin_puk_info_new (puk, pin, NULL, FALSE, context); + info = send_pin_puk_info_new (puk, pin, NULL, FALSE); /* Make sure the caller is authorized to send the PUK */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_DEVICE, + context, send_puk_auth_cb, info, send_pin_puk_info_destroy, @@ -350,7 +357,10 @@ impl_gsm_modem_send_puk (MMModemGsmCard *modem, /*****************************************************************************/ static void -send_pin_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +send_pin_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); SendPinPukInfo *info = user_data; @@ -358,10 +368,10 @@ send_pin_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) /* Return any authorization error, otherwise unlock the modem */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - mm_modem_gsm_card_send_pin (self, info->pin, async_call_done, info->context); + mm_modem_gsm_card_send_pin (self, info->pin, async_call_done, context); } static void @@ -372,11 +382,12 @@ impl_gsm_modem_send_pin (MMModemGsmCard *modem, GError *error = NULL; SendPinPukInfo *info; - info = send_pin_puk_info_new (NULL, pin, NULL, FALSE, context); + info = send_pin_puk_info_new (NULL, pin, NULL, FALSE); /* Make sure the caller is authorized to unlock the modem */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_DEVICE, + context, send_pin_auth_cb, info, send_pin_puk_info_destroy, @@ -389,7 +400,10 @@ impl_gsm_modem_send_pin (MMModemGsmCard *modem, /*****************************************************************************/ static void -enable_pin_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +enable_pin_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); SendPinPukInfo *info = user_data; @@ -397,10 +411,10 @@ enable_pin_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) /* Return any authorization error, otherwise enable the PIN */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - mm_modem_gsm_card_enable_pin (self, info->pin, info->enabled, async_call_done, info->context); + mm_modem_gsm_card_enable_pin (self, info->pin, info->enabled, async_call_done, context); } static void @@ -412,11 +426,12 @@ impl_gsm_modem_enable_pin (MMModemGsmCard *modem, GError *error = NULL; SendPinPukInfo *info; - info = send_pin_puk_info_new (NULL, pin, NULL, enabled, context); + info = send_pin_puk_info_new (NULL, pin, NULL, enabled); /* Make sure the caller is authorized to enable a PIN */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_DEVICE, + context, enable_pin_auth_cb, info, send_pin_puk_info_destroy, @@ -429,7 +444,10 @@ impl_gsm_modem_enable_pin (MMModemGsmCard *modem, /*****************************************************************************/ static void -change_pin_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +change_pin_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); SendPinPukInfo *info = user_data; @@ -437,10 +455,10 @@ change_pin_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) /* Return any authorization error, otherwise change the PIN */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - mm_modem_gsm_card_change_pin (self, info->pin, info->pin2, async_call_done, info->context); + mm_modem_gsm_card_change_pin (self, info->pin, info->pin2, async_call_done, context); } static void @@ -452,11 +470,12 @@ impl_gsm_modem_change_pin (MMModemGsmCard *modem, GError *error = NULL; SendPinPukInfo *info; - info = send_pin_puk_info_new (NULL, old_pin, new_pin, FALSE, context); + info = send_pin_puk_info_new (NULL, old_pin, new_pin, FALSE); /* Make sure the caller is authorized to change the PIN */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_DEVICE, + context, change_pin_auth_cb, info, send_pin_puk_info_destroy, diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c index ab50aed9..bf52b942 100644 --- a/src/mm-modem-gsm-network.c +++ b/src/mm-modem-gsm-network.c @@ -398,10 +398,12 @@ impl_gsm_modem_register (MMModemGsmNetwork *modem, } static void -scan_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +scan_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmNetwork *self = MM_MODEM_GSM_NETWORK (owner); - DBusGMethodInvocation *context = user_data; GError *error = NULL; /* Return any authorization error, otherwise get the IMEI */ @@ -421,8 +423,9 @@ impl_gsm_modem_scan (MMModemGsmNetwork *modem, /* Make sure the caller is authorized to request a scan */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_DEVICE, - scan_auth_cb, context, + scan_auth_cb, + NULL, NULL, &error)) { dbus_g_method_return_error (context, error); diff --git a/src/mm-modem-gsm-sms.c b/src/mm-modem-gsm-sms.c index 27fe55ce..083ce8ae 100644 --- a/src/mm-modem-gsm-sms.c +++ b/src/mm-modem-gsm-sms.c @@ -137,7 +137,6 @@ typedef struct { guint num5; char *str; GHashTable *hash; - DBusGMethodInvocation *context; } SmsAuthInfo; static void @@ -167,8 +166,7 @@ sms_auth_info_new (guint num1, guint num4, guint num5, const char *str, - GHashTable *hash, - DBusGMethodInvocation *context) + GHashTable *hash) { SmsAuthInfo *info; @@ -179,7 +177,6 @@ sms_auth_info_new (guint num1, info->num4 = num4; info->num5 = num5; info->str = g_strdup (str); - info->context = context; /* Copy the hash table if we're given one */ if (hash) { @@ -207,18 +204,20 @@ sms_auth_info_new (guint num1, /*****************************************************************************/ static void -sms_delete_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +sms_delete_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); - SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - async_call_not_supported (self, async_call_done, info->context); + async_call_not_supported (self, async_call_done, context); } static void @@ -229,11 +228,12 @@ impl_gsm_modem_sms_delete (MMModemGsmSms *modem, GError *error = NULL; SmsAuthInfo *info; - info = sms_auth_info_new (idx, 0, 0, 0, 0, NULL, NULL, context); + info = sms_auth_info_new (idx, 0, 0, 0, 0, NULL, NULL); - /* Make sure the caller is authorized to send the PUK */ + /* Make sure the caller is authorized to delete an SMS */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_SMS, + context, sms_delete_auth_cb, info, sms_auth_info_destroy, @@ -246,18 +246,20 @@ impl_gsm_modem_sms_delete (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_get_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +sms_get_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); - SmsAuthInfo *info = user_data; GError *error = NULL; - /* Return any authorization error, otherwise delete the SMS */ + /* Return any authorization error, otherwise get the SMS */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - async_call_not_supported (self, async_call_done, info->context); + async_call_not_supported (self, async_call_done, context); } static void @@ -268,11 +270,12 @@ impl_gsm_modem_sms_get (MMModemGsmSms *modem, GError *error = NULL; SmsAuthInfo *info; - info = sms_auth_info_new (idx, 0, 0, 0, 0, NULL, NULL, context); + info = sms_auth_info_new (idx, 0, 0, 0, 0, NULL, NULL); - /* Make sure the caller is authorized to send the PUK */ + /* Make sure the caller is authorized to get an SMS */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_SMS, + context, sms_get_auth_cb, info, sms_auth_info_destroy, @@ -309,18 +312,20 @@ impl_gsm_modem_sms_get_smsc (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_set_smsc_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +sms_set_smsc_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); - SmsAuthInfo *info = user_data; GError *error = NULL; - /* Return any authorization error, otherwise delete the SMS */ + /* Return any authorization error, otherwise set the SMS service center */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - async_call_not_supported (self, async_call_done, info->context); + async_call_not_supported (self, async_call_done, context); } static void @@ -331,11 +336,12 @@ impl_gsm_modem_sms_set_smsc (MMModemGsmSms *modem, GError *error = NULL; SmsAuthInfo *info; - info = sms_auth_info_new (0, 0, 0, 0, 0, smsc, NULL, context); + info = sms_auth_info_new (0, 0, 0, 0, 0, smsc, NULL); - /* Make sure the caller is authorized to send the PUK */ + /* Make sure the caller is authorized to set the SMS service center */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_SMS, + context, sms_set_smsc_auth_cb, info, sms_auth_info_destroy, @@ -348,18 +354,20 @@ impl_gsm_modem_sms_set_smsc (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_list_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +sms_list_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); - SmsAuthInfo *info = user_data; GError *error = NULL; - /* Return any authorization error, otherwise delete the SMS */ + /* Return any authorization error, otherwise list SMSs */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - async_call_not_supported (self, async_call_done, info->context); + async_call_not_supported (self, async_call_done, context); } static void @@ -367,16 +375,14 @@ impl_gsm_modem_sms_list (MMModemGsmSms *modem, DBusGMethodInvocation *context) { GError *error = NULL; - SmsAuthInfo *info; - - info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, NULL, context); - /* Make sure the caller is authorized to send the PUK */ + /* Make sure the caller is authorized to list SMSs */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_SMS, + context, sms_list_auth_cb, - info, - sms_auth_info_destroy, + NULL, + NULL, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); @@ -386,18 +392,20 @@ impl_gsm_modem_sms_list (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_save_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +sms_save_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); - SmsAuthInfo *info = user_data; GError *error = NULL; - /* Return any authorization error, otherwise delete the SMS */ + /* Return any authorization error, otherwise save the SMS */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - async_call_not_supported (self, async_call_done, info->context); + async_call_not_supported (self, async_call_done, context); } static void @@ -408,11 +416,12 @@ impl_gsm_modem_sms_save (MMModemGsmSms *modem, GError *error = NULL; SmsAuthInfo *info; - info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, properties, context); + info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, properties); - /* Make sure the caller is authorized to send the PUK */ + /* Make sure the caller is authorized to save the SMS */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_SMS, + context, sms_save_auth_cb, info, sms_auth_info_destroy, @@ -425,7 +434,10 @@ impl_gsm_modem_sms_save (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_send_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +sms_send_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); SmsAuthInfo *info = user_data; @@ -471,10 +483,10 @@ sms_send_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) done: if (error) { - async_call_done (MM_MODEM (self), error, info->context); + async_call_done (MM_MODEM (self), error, context); g_error_free (error); } else - mm_modem_gsm_sms_send (self, number, text, smsc, validity, class, async_call_done, info->context); + mm_modem_gsm_sms_send (self, number, text, smsc, validity, class, async_call_done, context); } static void @@ -485,11 +497,12 @@ impl_gsm_modem_sms_send (MMModemGsmSms *modem, GError *error = NULL; SmsAuthInfo *info; - info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, properties, context); + info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, properties); /* Make sure the caller is authorized to send the PUK */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_SMS, + context, sms_send_auth_cb, info, sms_auth_info_destroy, @@ -502,18 +515,20 @@ impl_gsm_modem_sms_send (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_send_from_storage_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +sms_send_from_storage_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); - SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - async_call_not_supported (self, async_call_done, info->context); + async_call_not_supported (self, async_call_done, context); } static void @@ -524,11 +539,12 @@ impl_gsm_modem_sms_send_from_storage (MMModemGsmSms *modem, GError *error = NULL; SmsAuthInfo *info; - info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, NULL, context); + info = sms_auth_info_new (idx, 0, 0, 0, 0, NULL, NULL); /* Make sure the caller is authorized to send the PUK */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_SMS, + context, sms_send_from_storage_auth_cb, info, sms_auth_info_destroy, @@ -541,18 +557,20 @@ impl_gsm_modem_sms_send_from_storage (MMModemGsmSms *modem, /*****************************************************************************/ static void -sms_set_indication_auth_cb (MMAuthRequest *req, GObject *owner, gpointer user_data) +sms_set_indication_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) { MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner); - SmsAuthInfo *info = user_data; GError *error = NULL; /* Return any authorization error, otherwise delete the SMS */ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { - dbus_g_method_return_error (info->context, error); + dbus_g_method_return_error (context, error); g_error_free (error); } else - async_call_not_supported (self, async_call_done, info->context); + async_call_not_supported (self, async_call_done, context); } static void @@ -567,11 +585,12 @@ impl_gsm_modem_sms_set_indication (MMModemGsmSms *modem, GError *error = NULL; SmsAuthInfo *info; - info = sms_auth_info_new (mode, mt, bm, ds, bfr, NULL, NULL, context); + info = sms_auth_info_new (mode, mt, bm, ds, bfr, NULL, NULL); /* Make sure the caller is authorized to send the PUK */ if (!mm_modem_auth_request (MM_MODEM (modem), MM_AUTHORIZATION_SMS, + context, sms_set_indication_auth_cb, info, sms_auth_info_destroy, diff --git a/src/mm-modem.c b/src/mm-modem.c index 21375db0..8e2d8a48 100644 --- a/src/mm-modem.c +++ b/src/mm-modem.c @@ -611,6 +611,7 @@ mm_modem_set_state (MMModem *self, gboolean mm_modem_auth_request (MMModem *self, const char *authorization, + DBusGMethodInvocation *context, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify, @@ -619,11 +620,13 @@ mm_modem_auth_request (MMModem *self, g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (MM_IS_MODEM (self), FALSE); g_return_val_if_fail (authorization != NULL, FALSE); + g_return_val_if_fail (context != NULL, FALSE); g_return_val_if_fail (callback != NULL, FALSE); g_return_val_if_fail (MM_MODEM_GET_INTERFACE (self)->auth_request, FALSE); return MM_MODEM_GET_INTERFACE (self)->auth_request (self, authorization, + context, callback, callback_data, notify, diff --git a/src/mm-modem.h b/src/mm-modem.h index fb28b322..93915eb0 100644 --- a/src/mm-modem.h +++ b/src/mm-modem.h @@ -18,6 +18,7 @@ #define MM_MODEM_H #include +#include #include "mm-port.h" #include "mm-auth-provider.h" @@ -162,6 +163,7 @@ struct _MMModem { */ gboolean (*auth_request) (MMModem *self, const char *authorization, + DBusGMethodInvocation *context, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify, @@ -238,6 +240,7 @@ GError *mm_modem_check_removed (MMModem *self, const GError *error); */ gboolean mm_modem_auth_request (MMModem *self, const char *authorization, + DBusGMethodInvocation *context, MMAuthRequestCb callback, gpointer callback_data, GDestroyNotify notify, -- cgit v1.2.3-70-g09d2 From 27ede83bd33f570504d25d370422e23034c8f529 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 28 Feb 2010 21:15:22 -0800 Subject: trivial: rearrange some code --- src/mm-generic-gsm.c | 67 ++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index d26f1171..58f0f9a0 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -135,39 +135,6 @@ got_signal_quality (MMModem *modem, { } -void -mm_generic_gsm_set_reg_status (MMGenericGsm *modem, - MMModemGsmNetworkRegStatus status) -{ - MMGenericGsmPrivate *priv; - - g_return_if_fail (MM_IS_GENERIC_GSM (modem)); - - priv = MM_GENERIC_GSM_GET_PRIVATE (modem); - - if (priv->reg_status != status) { - priv->reg_status = status; - - g_debug ("Registration state changed: %d", status); - - if (status == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME || - status == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) { - mm_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem); - mm_serial_port_queue_command (priv->primary, "+COPS=3,0;+COPS?", 3, read_operator_name_done, modem); - mm_modem_gsm_network_get_signal_quality (MM_MODEM_GSM_NETWORK (modem), got_signal_quality, NULL); - } else { - g_free (priv->oper_code); - g_free (priv->oper_name); - priv->oper_code = priv->oper_name = NULL; - - mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (modem), priv->reg_status, - priv->oper_code, priv->oper_name); - } - - mm_generic_gsm_update_enabled_state (modem, TRUE, MM_MODEM_STATE_REASON_NONE); - } -} - typedef struct { const char *result; const char *normalized; @@ -1124,6 +1091,40 @@ mm_generic_gsm_pending_registration_stop (MMGenericGsm *modem) } } +void +mm_generic_gsm_set_reg_status (MMGenericGsm *modem, + MMModemGsmNetworkRegStatus status) +{ + MMGenericGsmPrivate *priv; + + g_return_if_fail (MM_IS_GENERIC_GSM (modem)); + + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + + if (priv->reg_status != status) { + priv->reg_status = status; + + g_debug ("Registration state changed: %d", status); + + if (status == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME || + status == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) { + mm_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem); + mm_serial_port_queue_command (priv->primary, "+COPS=3,0;+COPS?", 3, read_operator_name_done, modem); + mm_modem_gsm_network_get_signal_quality (MM_MODEM_GSM_NETWORK (modem), got_signal_quality, NULL); + } else { + g_free (priv->oper_code); + g_free (priv->oper_name); + priv->oper_code = priv->oper_name = NULL; + + mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (modem), priv->reg_status, + priv->oper_code, priv->oper_name); + } + + mm_generic_gsm_update_enabled_state (modem, TRUE, MM_MODEM_STATE_REASON_NONE); + } +} + +/* Returns TRUE if the modem is "done", ie has registered or been denied */ static gboolean reg_status_updated (MMGenericGsm *self, int new_value, GError **error) { -- cgit v1.2.3-70-g09d2 From 9d7cb0ddcf69993903c5bc51bbbfbd3a57f55413 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 28 Feb 2010 22:11:47 -0800 Subject: gsm: fix direct registration info requests --- src/mm-generic-gsm.c | 58 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 58f0f9a0..6f88a031 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -1250,8 +1250,7 @@ get_reg_status_done (MMSerialPort *port, GMatchInfo *match_info; char *tmp; guint id; - - g_warn_if_fail (info == priv->pending_reg_info); + gboolean status_done; if (error) { info->error = g_error_copy (error); @@ -1285,31 +1284,38 @@ get_reg_status_done (MMSerialPort *port, g_regex_unref (r); } - if ( reg_status >= 0 - && !reg_status_updated (self, reg_status, &info->error) - && priv->pending_reg_info) { - g_clear_error (&info->error); + if (reg_status >= 0) { + /* Update cached registration status */ + status_done = reg_status_updated (self, reg_status, &info->error); - /* Not registered yet; poll registration status again */ - id = g_timeout_add_seconds (1, reg_status_again, info); - mm_callback_info_set_data (info, REG_STATUS_AGAIN_TAG, - GUINT_TO_POINTER (id), - reg_status_again_remove); - return; + /* If we're waiting for automatic registration to complete and it's + * not done yet, check again in a few seconds. + */ + if ((info == priv->pending_reg_info) && !status_done) { + g_clear_error (&info->error); + + /* Not registered yet; poll registration status again */ + id = g_timeout_add_seconds (1, reg_status_again, info); + mm_callback_info_set_data (info, REG_STATUS_AGAIN_TAG, + GUINT_TO_POINTER (id), + reg_status_again_remove); + return; + } } reg_done: - /* This will schedule the callback for us */ - mm_generic_gsm_pending_registration_stop (self); + if (info == priv->pending_reg_info) { + /* For pending registration, this will schedule the callback for us */ + mm_generic_gsm_pending_registration_stop (self); + } else { + /* Otherwise for a direct registration request, schedule the callback now */ + mm_callback_info_schedule (info); + } } static void get_registration_status (MMSerialPort *port, MMCallbackInfo *info) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); - - g_warn_if_fail (info == priv->pending_reg_info); - mm_serial_port_queue_command (port, "+CREG?", 10, get_reg_status_done, info); } @@ -1418,14 +1424,28 @@ get_registration_info (MMModemGsmNetwork *self, MMModemGsmNetworkRegInfoFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); MMCallbackInfo *info; + MMSerialPort *port = priv->primary; info = mm_callback_info_new_full (MM_MODEM (self), gsm_network_reg_info_invoke, G_CALLBACK (callback), user_data); - mm_callback_info_schedule (info); + if (mm_port_get_connected (MM_PORT (priv->primary))) { + if (!priv->secondary) { + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_CONNECTED, + "Cannot get registration info while connected"); + mm_callback_info_schedule (info); + return; + } + + /* Use secondary port if primary is connected */ + port = priv->secondary; + } + + get_registration_status (port, info); } void -- cgit v1.2.3-70-g09d2