Merge remote branch 'origin/master' into qcdm

This commit is contained in:
Dan Williams
2010-03-01 09:07:05 -08:00
26 changed files with 2225 additions and 112 deletions

2
.gitignore vendored
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -5,4 +5,5 @@ VOID:UINT,BOOLEAN
VOID:UINT,UINT
VOID:UINT,UINT,UINT
VOID:STRING,BOXED
VOID:POINTER,UINT

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 \

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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 */

300
src/mm-auth-provider.c Normal file
View File

@@ -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));
}

84
src/mm-auth-provider.h Normal file
View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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 */

182
src/mm-auth-request.c Normal file
View File

@@ -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);
}

72
src/mm-auth-request.h Normal file
View File

@@ -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 */

View File

@@ -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 }
};

View File

@@ -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 ())

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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,
DBusGMethodInvocation *context)
impl_gsm_modem_get_imei (MMModemGsmCard *modem, DBusGMethodInvocation *context)
{
mm_modem_gsm_card_get_imsi (modem, str_call_done, 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_send_puk (MMModemGsmCard *modem,
const char *puk,
const char *pin,
DBusGMethodInvocation *context)
impl_gsm_modem_get_imsi (MMModemGsmCard *modem, DBusGMethodInvocation *context)
{
mm_modem_gsm_card_send_puk (modem, puk, pin, async_call_done, 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)
{
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
send_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 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);
}

View File

@@ -397,11 +397,40 @@ impl_gsm_modem_register (MMModemGsmNetwork *modem,
mm_modem_gsm_network_register (modem, id, async_call_done, context);
}
static void
scan_auth_cb (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);
}

View File

@@ -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,7 +413,80 @@ 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
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;
guint validity = 0;
guint class = 0;
/* 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 (info->hash, "text");
if (value)
text = g_value_get_string (value);
value = (GValue *) g_hash_table_lookup (info->hash, "smsc");
if (value)
smsc = g_value_get_string (value);
value = (GValue *) g_hash_table_lookup (info->hash, "validity");
if (value)
validity = g_value_get_uint (value);
value = (GValue *) g_hash_table_lookup (info->hash, "class");
if (value)
class = g_value_get_uint (value);
if (!number) {
error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Missing number");
} 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 (self), error, context);
g_error_free (error);
} else
mm_modem_gsm_sms_send (self, number, text, smsc, validity, class, async_call_done, context);
}
static void
@@ -195,46 +494,41 @@ impl_gsm_modem_sms_send (MMModemGsmSms *modem,
GHashTable *properties,
DBusGMethodInvocation *context)
{
GValue *value;
const char *number = NULL;
const char *text = NULL ;
const char *smsc = NULL;
GError *error = NULL;
guint validity = 0;
guint class = 0;
SmsAuthInfo *info;
value = (GValue *) g_hash_table_lookup (properties, "number");
if (value)
number = g_value_get_string (value);
info = sms_auth_info_new (0, 0, 0, 0, 0, NULL, properties);
value = (GValue *) g_hash_table_lookup (properties, "text");
if (value)
text = g_value_get_string (value);
/* 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);
}
}
value = (GValue *) g_hash_table_lookup (properties, "smsc");
if (value)
smsc = g_value_get_string (value);
/*****************************************************************************/
value = (GValue *) g_hash_table_lookup (properties, "validity");
if (value)
validity = g_value_get_uint (value);
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;
value = (GValue *) g_hash_table_lookup (properties, "class");
if (value)
class = g_value_get_uint (value);
if (!number)
error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Missing number");
else if (!text)
error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
"Missing message text");
if (error) {
async_call_done (MM_MODEM (modem), error, context);
/* 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
mm_modem_gsm_sms_send (modem, number, text, smsc, validity, class, async_call_done, context);
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);
}
}
/*****************************************************************************/

View File

@@ -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)
{

View File

@@ -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 */