aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am19
-rw-r--r--src/mm-auth-provider-factory.c45
-rw-r--r--src/mm-auth-provider.c405
-rw-r--r--src/mm-auth-provider.h99
-rw-r--r--src/mm-errors.c1
-rw-r--r--src/mm-errors.h3
-rw-r--r--src/mm-modem-base.c108
-rw-r--r--src/mm-modem-cdma.c35
-rw-r--r--src/mm-modem-gsm-card.c262
-rw-r--r--src/mm-modem-gsm-network.c32
-rw-r--r--src/mm-modem.c46
-rw-r--r--src/mm-modem.h32
12 files changed, 1068 insertions, 19 deletions
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 <string.h>
+
+#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 <string.h>
+
+#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 <glib-object.h>
+
+/* 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 <dbus/dbus-glib.h>
+#include <string.h>
#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
@@ -398,10 +398,39 @@ impl_gsm_modem_register (MMModemGsmNetwork *modem,
}
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 <glib-object.h>
#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 */