aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am19
-rw-r--r--configure.ac18
-rw-r--r--marshallers/mm-marshal.list1
-rw-r--r--org.freedesktop.ModemManager.conf.nopolkit (renamed from org.freedesktop.ModemManager.conf)3
-rw-r--r--org.freedesktop.ModemManager.conf.polkit154
-rw-r--r--src/Makefile.am24
-rw-r--r--src/mm-auth-provider-factory.c45
-rw-r--r--src/mm-auth-provider-polkit.c153
-rw-r--r--src/mm-auth-provider-polkit.h43
-rw-r--r--src/mm-auth-provider.c300
-rw-r--r--src/mm-auth-provider.h84
-rw-r--r--src/mm-auth-request-polkit.c175
-rw-r--r--src/mm-auth-request-polkit.h53
-rw-r--r--src/mm-auth-request.c182
-rw-r--r--src/mm-auth-request.h72
-rw-r--r--src/mm-errors.c1
-rw-r--r--src/mm-errors.h3
-rw-r--r--src/mm-generic-gsm.c125
-rw-r--r--src/mm-modem-base.c46
-rw-r--r--src/mm-modem-cdma.c35
-rw-r--r--src/mm-modem-gsm-card.c263
-rw-r--r--src/mm-modem-gsm-network.c32
-rw-r--r--src/mm-modem-gsm-sms.c383
-rw-r--r--src/mm-modem.c48
-rw-r--r--src/mm-modem.h33
26 files changed, 2205 insertions, 92 deletions
diff --git a/.gitignore b/.gitignore
index 9b8ee463..e7db0a8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,7 @@ libtool
*-glue.h
*.tar.bz2
org.freedesktop.ModemManager.service
+org.freedesktop.ModemManager.conf
ModemManager.pc
marshallers/mm-marshal.[ch]
src/modem-manager
@@ -30,6 +31,7 @@ docs/spec.html
callouts/mm-modem-probe
test/lsudev
src/tests/test-modem-helpers
+policy/org.freedesktop.modem-manager.policy
libqcdm/tests/test-qcdm
diff --git a/Makefile.am b/Makefile.am
index 0153b10e..c2639508 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,9 +21,23 @@ endif
SUBDIRS = marshallers libqcdm src plugins introspection po policy test
+if WITH_POLKIT
+SUBDIRS += policy
+endif
+
dbusservicedir = $(DBUS_SYS_DIR)
dbusservice_DATA = org.freedesktop.ModemManager.conf
+dbusservice_file_polkit = org.freedesktop.ModemManager.conf.polkit
+dbusservice_file_nopolkit = org.freedesktop.ModemManager.conf.nopolkit
+
+org.freedesktop.ModemManager.conf:
+if WITH_POLKIT
+ cp -f $(top_srcdir)/$(dbusservice_file_polkit) $(dbusservice_DATA)
+else
+ cp -f $(top_srcdir)/$(dbusservice_file_nopolkit) $(dbusservice_DATA)
+endif
+
dbusactivationdir = $(datadir)/dbus-1/system-services
dbusactivation_in_files = org.freedesktop.ModemManager.service.in
dbusactivation_DATA = $(dbusactivation_in_files:.service.in=.service)
@@ -53,8 +67,9 @@ DISTCLEANFILES = \
EXTRA_DIST = \
doc-generator.xsl \
- $(dbusservice_DATA) \
$(dbusactivation_in_files) \
- $(INTLTOOL_FILES)
+ $(INTLTOOL_FILES) \
+ $(dbusservice_file_polkit) \
+ $(dbusservice_file_nopolkit)
ACLOCAL_AMFLAGS = -I m4
diff --git a/configure.ac b/configure.ac
index cc2f2f62..6f6621d7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,6 +50,22 @@ AC_SUBST(UDEV_BASE_DIR)
GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
AC_SUBST(GLIB_GENMARSHAL)
+# PolicyKit
+AC_ARG_WITH(polkit, AS_HELP_STRING([--with-polkit], [Build with PolicyKit support]))
+AM_CONDITIONAL(WITH_POLKIT, test "x$with_polkit" = "xyes")
+case $with_polkit in
+ yes)
+ with_polkit=yes
+ PKG_CHECK_MODULES(POLKIT, polkit-gobject-1 >= 0.95)
+ AC_DEFINE(WITH_POLKIT, 1, [Define if you want to use PolicyKit])
+ AC_SUBST(POLKIT_CFLAGS)
+ AC_SUBST(POLKIT_LIBS)
+ ;;
+ *)
+ with_polkit=no
+ ;;
+esac
+
# PPPD
AC_CHECK_HEADERS(pppd/pppd.h, have_pppd_headers="yes", have_pppd_headers="no")
AM_CONDITIONAL(HAVE_PPPD_H, test "x$have_pppd_headers" = "xyes")
@@ -119,4 +135,6 @@ echo Building documentation: ${with_docs}
echo
echo Building PPP-enabled tests: ${have_pppd_headers}
echo
+echo Building with PolicyKit support: ${with_polkit}
+echo
diff --git a/marshallers/mm-marshal.list b/marshallers/mm-marshal.list
index 474d704d..c209bbbf 100644
--- a/marshallers/mm-marshal.list
+++ b/marshallers/mm-marshal.list
@@ -5,4 +5,5 @@ VOID:UINT,BOOLEAN
VOID:UINT,UINT
VOID:UINT,UINT,UINT
VOID:STRING,BOXED
+VOID:POINTER,UINT
diff --git a/org.freedesktop.ModemManager.conf b/org.freedesktop.ModemManager.conf.nopolkit
index 5d62d7a9..2f331613 100644
--- a/org.freedesktop.ModemManager.conf
+++ b/org.freedesktop.ModemManager.conf.nopolkit
@@ -2,6 +2,8 @@
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
+ <!-- This config allows anyone to control ModemManager -->
+
<policy context="default">
<allow send_destination="org.freedesktop.ModemManager"/>
</policy>
@@ -12,3 +14,4 @@
<limit name="max_replies_per_connection">512</limit>
</busconfig>
+
diff --git a/org.freedesktop.ModemManager.conf.polkit b/org.freedesktop.ModemManager.conf.polkit
new file mode 100644
index 00000000..25490e33
--- /dev/null
+++ b/org.freedesktop.ModemManager.conf.polkit
@@ -0,0 +1,154 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <policy context="default">
+ <deny send_destination="org.freedesktop.ModemManager"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.DBus.Introspectable"/>
+
+ <!-- Methods listed here are explicitly allowed or PolicyKit protected.
+ The rest are restricted to root for security.
+ -->
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager"
+ send_member="EnumerateDevices"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.DBus.Properties"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem"
+ send_member="GetInfo"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Cdma"
+ send_member="GetSignalQuality"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Cdma"
+ send_member="GetServingSystem"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Cdma"
+ send_member="GetRegistrationState"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Cdma"
+ send_member="GetEsn"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Network"
+ send_member="GetSignalQuality"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Network"
+ send_member="GetBand"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Network"
+ send_member="GetNetworkMode"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Network"
+ send_member="GetRegistrationInfo"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Network"
+ send_member="Scan"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Card"
+ send_member="GetImei"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Card"
+ send_member="GetImsi"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Card"
+ send_member="SendPuk"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Card"
+ send_member="SendPin"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Card"
+ send_member="EnablePin"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Card"
+ send_member="ChangePin"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Contacts"
+ send_member="Add"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Contacts"
+ send_member="Delete"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Contacts"
+ send_member="Get"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Contacts"
+ send_member="List"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Contacts"
+ send_member="Find"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.Contacts"
+ send_member="GetCount"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.SMS"
+ send_member="Delete"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.SMS"
+ send_member="Get"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.SMS"
+ send_member="List"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.SMS"
+ send_member="Save"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.SMS"
+ send_member="Send"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.SMS"
+ send_member="SendFromStorage"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.SMS"
+ send_member="SetIndication"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.SMS"
+ send_member="GetSmsc"/>
+
+ <allow send_destination="org.freedesktop.ModemManager"
+ send_interface="org.freedesktop.ModemManager.Modem.Gsm.SMS"
+ send_member="SetSmsc"/>
+ </policy>
+
+ <policy user="root">
+ <allow own="org.freedesktop.ModemManager"/>
+ <allow send_destination="org.freedesktop.ModemManager"/>
+ </policy>
+
+ <limit name="max_replies_per_connection">512</limit>
+</busconfig>
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 15b91bd5..3d938063 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,6 +20,10 @@ 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) \
@@ -27,10 +31,30 @@ modem_manager_LDADD = \
$(top_builddir)/libqcdm/src/libqcdm.la \
$(builddir)/libmodem-helpers.la
+if WITH_POLKIT
+modem_manager_LDADD += $(POLKIT_LIBS)
+endif
+
+auth_sources = \
+ mm-auth-request.c \
+ mm-auth-request.h \
+ mm-auth-provider.h \
+ mm-auth-provider.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 \
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-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 <polkit/polkit.h>
+
+#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 <glib-object.h>
+
+#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
new file mode 100644
index 00000000..ceff9adf
--- /dev/null
+++ b/src/mm-auth-provider.c
@@ -0,0 +1,300 @@
+/* -*- 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
+};
+
+/*****************************************************************************/
+
+GObject *
+mm_auth_provider_new (void)
+{
+ return g_object_new (MM_TYPE_AUTH_PROVIDER, NULL);
+}
+
+/*****************************************************************************/
+
+static void
+remove_requests (MMAuthProvider *self, GSList *remove)
+{
+ MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (self);
+ MMAuthRequest *req;
+
+ while (remove) {
+ req = MM_AUTH_REQUEST (remove->data);
+ g_hash_table_remove (priv->requests, req);
+ remove = g_slist_remove (remove, req);
+ }
+}
+
+void
+mm_auth_provider_cancel_request (MMAuthProvider *provider, MMAuthRequest *req)
+{
+ MMAuthProviderPrivate *priv;
+
+ g_return_if_fail (provider != NULL);
+ g_return_if_fail (MM_IS_AUTH_PROVIDER (provider));
+ g_return_if_fail (req != NULL);
+
+ priv = MM_AUTH_PROVIDER_GET_PRIVATE (provider);
+
+ g_return_if_fail (g_hash_table_lookup (priv->requests, req) != NULL);
+ g_hash_table_remove (priv->requests, req);
+}
+
+void
+mm_auth_provider_cancel_for_owner (MMAuthProvider *self, GObject *owner)
+{
+ MMAuthProviderPrivate *priv;
+ GHashTableIter iter;
+ MMAuthRequest *req;
+ gpointer value;
+ GSList *remove = NULL;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (MM_IS_AUTH_PROVIDER (self));
+
+ /* 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);
+ }
+
+ /* And cancel/remove them */
+ remove_requests (self, remove);
+}
+
+/*****************************************************************************/
+
+
+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 (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,
+ GError **error)
+{
+ 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);
+ g_return_val_if_fail (authorization != NULL, 0);
+ g_return_val_if_fail (callback != NULL, 0);
+
+ priv = MM_AUTH_PROVIDER_GET_PRIVATE (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_request_authenticate (req, error)) {
+ /* Error */
+ g_hash_table_remove (priv->requests, req);
+ return NULL;
+ }
+
+ return req;
+}
+
+/*****************************************************************************/
+
+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)
+{
+ MMAuthProviderPrivate *priv = MM_AUTH_PROVIDER_GET_PRIVATE (self);
+
+ priv->requests = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ dispose_auth_request);
+}
+
+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
+dispose (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)->dispose (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->dispose = dispose;
+ class->create_request = real_create_request;
+
+ /* 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));
+}
+
diff --git a/src/mm-auth-provider.h b/src/mm-auth-provider.h
new file mode 100644
index 00000000..94edc44d
--- /dev/null
+++ b/src/mm-auth-provider.h
@@ -0,0 +1,84 @@
+/* -*- 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>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "mm-auth-request.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 struct {
+ GObject parent;
+} MMAuthProvider;
+
+typedef struct {
+ GObjectClass parent;
+
+ MMAuthRequest * (*create_request) (MMAuthProvider *provider,
+ const char *authorization,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ MMAuthRequestCb callback,
+ gpointer callback_data,
+ GDestroyNotify notify);
+} MMAuthProviderClass;
+
+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,
+ GError **error);
+
+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);
+
+/* schedules the request's completion */
+void mm_auth_provider_finish_request (MMAuthProvider *provider,
+ MMAuthRequest *req,
+ MMAuthResult result);
+
+void mm_auth_provider_cancel_request (MMAuthProvider *provider, MMAuthRequest *req);
+
+#endif /* MM_AUTH_PROVIDER_H */
+
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 <glib.h>
+#include <gio/gio.h>
+
+#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 <glib-object.h>
+#include <polkit/polkit.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#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-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 <glib-object.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#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 */
+
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-generic-gsm.c b/src/mm-generic-gsm.c
index 7e121f20..425a92f7 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -136,39 +136,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_at_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem);
- mm_at_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;
@@ -1130,6 +1097,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_at_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem);
+ mm_at_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)
{
@@ -1255,8 +1256,7 @@ get_reg_status_done (MMAtSerialPort *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);
@@ -1290,31 +1290,38 @@ get_reg_status_done (MMAtSerialPort *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 (MMAtSerialPort *port, MMCallbackInfo *info)
{
- MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
-
- g_warn_if_fail (info == priv->pending_reg_info);
-
mm_at_serial_port_queue_command (port, "+CREG?", 10, get_reg_status_done, info);
}
@@ -1423,14 +1430,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
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c
index b9d07060..20ba2a4c 100644
--- a/src/mm-modem-base.c
+++ b/src/mm-modem-base.c
@@ -44,6 +44,8 @@ typedef struct {
gboolean valid;
MMModemState state;
+ MMAuthProvider *authp;
+
GHashTable *ports;
} MMModemBasePrivate;
@@ -213,11 +215,51 @@ 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,
+ 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),
+ context,
+ callback,
+ callback_data,
+ notify,
+ error);
+}
+
+static gboolean
+modem_auth_finish (MMModem *modem, MMAuthRequest *req, GError **error)
+{
+ 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",
+ mm_auth_request_get_authorization (req));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+
static void
mm_modem_base_init (MMModemBase *self)
{
MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self);
+ priv->authp = mm_auth_provider_get ();
+
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 +270,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
@@ -326,6 +370,8 @@ finalize (GObject *object)
MMModemBase *self = MM_MODEM_BASE (object);
MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self);
+ mm_auth_provider_cancel_for_owner (priv->authp, object);
+
g_hash_table_destroy (priv->ports);
g_free (priv->driver);
g_free (priv->plugin);
diff --git a/src/mm-modem-cdma.c b/src/mm-modem-cdma.c
index 112b93fa..1a4fe6a2 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 (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
{
- mm_modem_cdma_get_esn (modem, str_call_done, context);
+ MMModemCdma *self = MM_MODEM_CDMA (owner);
+ GError *error = NULL;
+
+ /* Return any authorization error, otherwise get the ESN */
+ if (!mm_modem_auth_finish (MM_MODEM (self), req, &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,
+ context,
+ esn_auth_cb,
+ NULL,
+ 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..9881871c 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,176 @@ mm_modem_gsm_card_change_pin (MMModemGsmCard *self,
/*****************************************************************************/
static void
-impl_gsm_modem_get_imei (MMModemGsmCard *modem,
- DBusGMethodInvocation *context)
+imei_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
{
- mm_modem_gsm_card_get_imei (modem, str_call_done, context);
+ MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner);
+ GError *error = NULL;
+
+ /* Return any authorization error, otherwise get the IMEI */
+ if (!mm_modem_auth_finish (MM_MODEM (self), req, &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_imsi (MMModemGsmCard *modem,
+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,
+ context,
+ imei_auth_cb,
+ NULL,
+ NULL,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+imsi_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner);
+ GError *error = NULL;
+
+ /* Return any authorization error, otherwise get the IMSI */
+ if (!mm_modem_auth_finish (MM_MODEM (self), req, &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, 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,
+ context,
+ imsi_auth_cb,
+ NULL,
+ NULL,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+/*****************************************************************************/
+
+typedef struct {
+ char *puk;
+ char *pin;
+ char *pin2;
+ gboolean enabled;
+} 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)
+{
+ 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;
+ return info;
+}
+
+/*****************************************************************************/
+
+static void
+send_puk_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ 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), req, &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, 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);
+
+ /* 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,
+ &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 (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
{
- mm_modem_gsm_card_send_puk (modem, puk, pin, async_call_done, context);
+ 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), req, &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, context);
}
static void
@@ -228,7 +379,42 @@ 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);
+
+ /* 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,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+enable_pin_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ 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), req, &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, context);
}
static void
@@ -237,7 +423,42 @@ 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);
+
+ /* 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,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+change_pin_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ 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), req, &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, context);
}
static void
@@ -246,7 +467,22 @@ 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);
+
+ /* 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,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
}
/*****************************************************************************/
@@ -305,6 +541,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..bf52b942 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 (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmNetwork *self = MM_MODEM_GSM_NETWORK (owner);
+ GError *error = NULL;
+
+ /* Return any authorization error, otherwise get the IMEI */
+ if (!mm_modem_auth_finish (MM_MODEM (self), req, &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,
+ context,
+ scan_auth_cb,
+ NULL,
+ 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-gsm-sms.c b/src/mm-modem-gsm-sms.c
index e8ec0742..083ce8ae 100644
--- a/src/mm-modem-gsm-sms.c
+++ b/src/mm-modem-gsm-sms.c
@@ -129,12 +129,137 @@ mm_modem_gsm_sms_send (MMModemGsmSms *self,
/*****************************************************************************/
+typedef struct {
+ guint num1;
+ guint num2;
+ guint num3;
+ guint num4;
+ guint num5;
+ char *str;
+ GHashTable *hash;
+} 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)
+{
+ 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);
+
+ /* 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 (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner);
+ 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 (context, error);
+ g_error_free (error);
+ } else
+ async_call_not_supported (self, async_call_done, 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);
+
+ /* 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,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+sms_get_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner);
+ GError *error = NULL;
+
+ /* Return any authorization error, otherwise get the SMS */
+ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ } else
+ async_call_not_supported (self, async_call_done, context);
}
static void
@@ -142,9 +267,26 @@ 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);
+
+ /* 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,
+ &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 +309,103 @@ impl_gsm_modem_sms_get_smsc (MMModemGsmSms *modem,
async_call_not_supported (modem, async_call_done, context);
}
+/*****************************************************************************/
+
+static void
+sms_set_smsc_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner);
+ GError *error = NULL;
+
+ /* 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 (context, error);
+ g_error_free (error);
+ } else
+ async_call_not_supported (self, async_call_done, 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);
+
+ /* 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,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+sms_list_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner);
+ GError *error = NULL;
+
+ /* Return any authorization error, otherwise list SMSs */
+ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ } else
+ async_call_not_supported (self, async_call_done, context);
}
static void
impl_gsm_modem_sms_list (MMModemGsmSms *modem,
DBusGMethodInvocation *context)
{
- async_call_not_supported (modem, async_call_done, context);
+ GError *error = NULL;
+
+ /* 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,
+ NULL,
+ NULL,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+sms_save_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner);
+ GError *error = NULL;
+
+ /* Return any authorization error, otherwise save the SMS */
+ if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ } else
+ async_call_not_supported (self, async_call_done, context);
}
static void
@@ -187,54 +413,122 @@ 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);
+
+ /* 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,
+ &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 (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
{
+ MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner);
+ 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), req, &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, 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, 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);
+
+ /* 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,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+sms_send_from_storage_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner);
+ 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 (context, error);
+ g_error_free (error);
+ } else
+ async_call_not_supported (self, async_call_done, context);
}
static void
@@ -242,7 +536,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 (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,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+sms_set_indication_auth_cb (MMAuthRequest *req,
+ GObject *owner,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ MMModemGsmSms *self = MM_MODEM_GSM_SMS (owner);
+ 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 (context, error);
+ g_error_free (error);
+ } else
+ async_call_not_supported (self, async_call_done, context);
}
static void
@@ -254,7 +582,22 @@ 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);
+
+ /* 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,
+ &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ }
}
/*****************************************************************************/
diff --git a/src/mm-modem.c b/src/mm-modem.c
index 5bb2ef6b..8e2d8a48 100644
--- a/src/mm-modem.c
+++ b/src/mm-modem.c
@@ -608,6 +608,54 @@ 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,
+ 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 (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,
+ error);
+}
+
+gboolean
+mm_modem_auth_finish (MMModem *self,
+ 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 (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, req, 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..93915eb0 100644
--- a/src/mm-modem.h
+++ b/src/mm-modem.h
@@ -18,8 +18,10 @@
#define MM_MODEM_H
#include <glib-object.h>
+#include <dbus/dbus-glib-lowlevel.h>
#include "mm-port.h"
+#include "mm-auth-provider.h"
typedef enum {
MM_MODEM_STATE_UNKNOWN = 0,
@@ -156,6 +158,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,
+ DBusGMethodInvocation *context,
+ MMAuthRequestCb callback,
+ gpointer callback_data,
+ GDestroyNotify notify,
+ GError **error);
+
+ gboolean (*auth_finish) (MMModem *self,
+ MMAuthRequest *req,
+ GError **error);
+
/* Signals */
void (*state_changed) (MMModem *self,
MMModemState new_state,
@@ -217,5 +234,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,
+ DBusGMethodInvocation *context,
+ MMAuthRequestCb callback,
+ gpointer callback_data,
+ GDestroyNotify notify,
+ GError **error);
+
+gboolean mm_modem_auth_finish (MMModem *self,
+ MMAuthRequest *req,
+ GError **error);
+
#endif /* MM_MODEM_H */