Compare commits

...

11 Commits

Author SHA1 Message Date
Ray Strode
0062544c09 update for latest changes
I'm planning on scrapping a lot of the account dialog changes soon
though.

i'm just doing an unorganized push since code hoarding considered
harmful.
2012-06-21 22:47:15 -04:00
Stef Walter
d9785198a8 user-accounts: Update the realmd dbus interface to latest
The changes in the realmd dbus interface are futureproofing to
support cancellation.

In addition during this time of interface flux, check the
daemon version number to make sure we can talk to it.

https://bugzilla.gnome.org/show_bug.cgi?id=678105
2012-06-20 14:58:22 -04:00
Bastien Nocera
56d6308342 build: Enable Kerberos by default if present
https://bugzilla.gnome.org/show_bug.cgi?id=671156
2012-06-20 14:48:23 -04:00
Bastien Nocera
112e0cd399 build: Print out status of kerberos support
https://bugzilla.gnome.org/show_bug.cgi?id=671156
2012-06-20 14:48:23 -04:00
Ray Strode
53f91662b2 user-accounts: Use identity manager in user panel
This commit hooks up the identity manager to the actual
UI.  It creates a list of currently "accessible realms"
and provides buttons for signing out of those realms.

This is outlined here:

https://live.gnome.org/Design/Proposals/UserIdentities

https://bugzilla.gnome.org/show_bug.cgi?id=671156
2012-06-20 14:48:23 -04:00
Ray Strode
93cb3a470c user-accounts: add kerberos implemention of identity manager interface
This commits adds a concrete implementation of the identity manager
inteface using the krb5 libraries.

In the future we may add a different interface that leverages SSSD.

https://bugzilla.gnome.org/show_bug.cgi?id=671156
2012-06-20 14:48:23 -04:00
Ray Strode
c0e63417f9 user-accounts: add alarm class
When we support showing kerberos realms in the UI,
we're going to need some way to get notified when
the users credentials are no longer valid for
those realms.

This commit adds an alarm class that abstracts
timerfd so we can get proper notification when
kerberos credentials expire.

https://bugzilla.gnome.org/show_bug.cgi?id=671156
2012-06-20 14:48:23 -04:00
Ray Strode
8c2329e409 user-accounts: Add identity manager interface
The page here:

https://live.gnome.org/Design/Proposals/UserIdentities

proposes adding a list of "accessible realms" to the user
panel. To implement that we'll need to get a list of realms
to show.

This commit adds the basics of the required interface.  A
subsequent commit will had a concrete implementation based
on kerberos.  At some point, we may add an SSSD based
implementation, too, which is why there's the abstraction.

https://bugzilla.gnome.org/show_bug.cgi?id=671156
2012-06-20 14:48:23 -04:00
Ray Strode
83f7135a03 user-accounts: hide admin tasks from non-administrators
If the user isn't an administrator (either by account type,
or through polkit escalation), then don't show administrative
tasks in the panel like editing other users, setting up autologin,
etc.

https://bugzilla.gnome.org/show_bug.cgi?id=671156
2012-06-20 14:48:23 -04:00
Ray Strode
f87057b4c4 user-accounts: add "Other Passwords" button
Since the user can change the login password from
the user panel, it stands to reason the user may want
to be able to adjust other passwords from there as well.

This commit adds an "Other Passwords" button which runs
seahorse when clicked.

See:

https://live.gnome.org/Design/Proposals/UserIdentities

for more information.

https://bugzilla.gnome.org/show_bug.cgi?id=671156
2012-06-20 14:48:23 -04:00
Ray Strode
24afc5e651 user-accounts: port from GtkTable to GtkGrid
GtkTable is deprecated and no longer encouraged.

This commit changes the user panel over to gtkgrid
instead.

https://bugzilla.gnome.org/show_bug.cgi?id=671156
2012-06-20 14:48:23 -04:00
26 changed files with 6426 additions and 71 deletions

View File

@@ -62,6 +62,11 @@ else
SYSTEMD=
fi
AC_ARG_ENABLE([kerberos],
AS_HELP_STRING([--enable-kerberos], [Use Kerberos]),
[with_kerberos=$enableval],
[with_kerberos=auto])
dnl ==============================================
dnl Check that we meet the dependencies
dnl ==============================================
@@ -200,6 +205,31 @@ else
fi
AM_CONDITIONAL(BUILD_CHEESE, test x${have_cheese} = xyes)
AC_PATH_PROG([KRB5_CONFIG], krb5-config, none, $PATH:/usr/kerberos/bin)
if test "x$KRB5_CONFIG" != "xnone"; then
KRB5_LIBS="`${KRB5_CONFIG} --libs krb5`"
KRB5_CFLAGS="`${KRB5_CONFIG} --cflags krb5`"
have_kerberos=yes
else
KRB5_LIBS=""
KRB5_CFLAGS=""
have_kerberos=no
fi
AC_SUBST(KRB5_CFLAGS)
AC_SUBST(KRB5_LIBS)
if test "$with_kerberos" != "no" ; then
if test "$have_kerberos" = "no" ; then
AC_MSG_ERROR([kerberos support requested, but not available])
fi
AC_DEFINE(HAVE_KERBEROS, 1, [Define to 1 if kerberos is available])
fi
AM_CONDITIONAL(BUILD_KERBEROS, [test x$with_kerberos != xno])
USER_ACCOUNTS_PANEL_CFLAGS="$USER_ACCOUNTS_PANEL_CFLAGS $KRB5_CFLAGS"
USER_ACCOUNTS_PANEL_LIBS="$USER_ACCOUNTS_PANEL_LIBS $KRB5_LIBS"
# wacom is disabled for s390/s390x and non Linux platforms (needs udev)
case $host_os in
linux*)
@@ -270,6 +300,59 @@ AC_SUBST(PANEL_LIBS)
PANEL_LDFLAGS="-export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload)'"
AC_SUBST(PANEL_LDFLAGS)
dnl ==================================================
dnl timerfd support
dnl ==================================================
AC_MSG_CHECKING([for timerfd support])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
#include <sys/timerfd.h>
#include <unistd.h>
],[
int
main (void)
{
struct itimerspec timer_spec = { 0 };
timerfd_settime (timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC),
TFD_TIMER_ABSTIME,
&timer_spec,
NULL);
return 0;
}
])],
[have_timerfd=yes],
[have_timerfd=no])
AC_MSG_RESULT($have_timerfd)
if test x"$have_timerfd" = x"yes"; then
AC_DEFINE(HAVE_TIMERFD, 1, [have timerfd support])
dnl libc headers tend to trail kernel support
dnl so compensate if necessary
AC_MSG_CHECKING([for timerfd cancel-on-set support])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
#include <sys/timerfd.h>
#include <unistd.h>
],[
int
main (void)
{
struct itimerspec timer_spec = { 0 };
timerfd_settime (timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC),
TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
&timer_spec,
NULL);
return 0;
}
])],
[have_tfd_timer_cancel_on_set=yes],
[have_tfd_timer_cancel_on_set=no])
AC_MSG_RESULT($have_tfd_timer_cancel_on_set)
if test x"$have_tfd_timer_cancel_on_set" = x"no"; then
AC_DEFINE(TFD_TIMER_CANCEL_ON_SET, [(1 << 1)], [have timerfd support])
fi
fi
dnl ==============================================
dnl libsocialweb
dnl ==============================================
@@ -487,6 +570,12 @@ if test "x$have_cheese" = "xyes"; then
else
AC_MSG_NOTICE([ Users panel webcam support disabled])
fi
if test "x$with_kerberos" != "xno"; then
AC_MSG_NOTICE([** Kerberos (Users panel Kerberos support)])
else
AC_MSG_NOTICE([ Users panel Kerberos support disabled])
fi
if test "x$with_libsocialweb" = "xyes"; then
AC_MSG_NOTICE([** libsocialweb (Background panel Flickr support)])
else

View File

@@ -30,6 +30,13 @@ BUILT_SOURCES = \
libuser_accounts_la_SOURCES = \
um-account-type.h \
um-account-type.c \
gsd-alarm.h \
gsd-alarm.c \
gsd-identity-manager.h \
gsd-identity-manager.c \
gsd-identity.h \
gsd-identity.c \
$(kerberos_sources) \
um-user.h \
um-user.c \
um-user-manager.h \
@@ -62,6 +69,15 @@ libuser_accounts_la_SOURCES = \
um-realm-manager.h \
$(BUILT_SOURCES)
if BUILD_KERBEROS
libuser_accounts_la_SOURCES += \
gsd-kerberos-identity-manager.h \
gsd-kerberos-identity-manager.c \
gsd-kerberos-identity.h \
gsd-kerberos-identity.c
endif
libuser_accounts_la_LIBADD = \
$(PANEL_LIBS) \
$(USER_ACCOUNTS_PANEL_LIBS) \

View File

@@ -12,6 +12,16 @@
-->
<interface name="org.freedesktop.realmd.Provider">
<!--
* The name of the provider
-->
<property name="Name" type="s" access="read"/>
<!--
* A version number for the provider
-->
<property name="Version" type="s" access="read"/>
<!--
* A list of known, enrolled or discovered realms.
* Each realm is a DBus object and is represeted by a:
@@ -29,6 +39,8 @@
<!-- The input string -->
<arg name="string" type="s" direction="in"/>
<arg name="operation_id" type="s" direction="in"/>
<!-- Returned match relevance -->
<arg name="relevance" type="i" direction="out"/>
@@ -47,6 +59,7 @@
<interface name="org.freedesktop.realmd.Diagnostics">
<signal name="Diagnostics">
<arg name="data" type="s"/>
<arg name="operation_id" type="s"/>
</signal>
</interface>
@@ -65,6 +78,11 @@
-->
<property name="Domain" type="s" access="read"/>
<!--
* The server software, for information only. eg: active-directory
-->
<property name="Details" type="a{ss}" access="read"/>
<!--
* The suggested Administrator login name for this realm
-->
@@ -83,6 +101,7 @@
<arg name="principal" type="s" direction="in"/>
<arg name="password" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="operation_id" type="s" direction="in"/>
</method>
<!--
@@ -95,6 +114,7 @@
<annotation name="org.gtk.GDBus.C.ForceGVariant" value="yup"/>
</arg>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="operation_id" type="s" direction="in"/>
</method>
<!--
@@ -105,6 +125,7 @@
<arg name="principal" type="s" direction="in"/>
<arg name="password" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="operation_id" type="s" direction="in"/>
</method>
<!--
@@ -117,6 +138,7 @@
<annotation name="org.gtk.GDBus.C.ForceGVariant" value="yup"/>
</arg>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="operation_id" type="s" direction="in"/>
</method>
<!--
@@ -139,6 +161,7 @@
<method name="ChangePermittedLogins">
<arg name="add" type="as" direction="in"/>
<arg name="remove" type="as" direction="in"/>
<arg name="operation_id" type="s" direction="in"/>
</method>
</interface>

View File

@@ -131,11 +131,10 @@
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkTable" id="table1">
<object class="GtkGrid" id="user-grid">
<property name="visible">True</property>
<property name="n_rows">7</property>
<property name="n_columns">2</property>
<property name="column_spacing">10</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkNotebook" id="account-fingerprint-notebook">
<property name="visible">True</property>
@@ -167,10 +166,9 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="width">1</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="y_options">0</property>
<property name="height">1</property>
</packing>
</child>
<child>
@@ -180,17 +178,18 @@
<property name="text-column">0</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options">0</property>
<property name="left_attach">2</property>
<property name="width">1</property>
<property name="top_attach">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="account-type-label">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="halign">GTK_ALIGN_END</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Account _type</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">account-type-combo</property>
@@ -199,10 +198,10 @@
</style>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">0</property>
<property name="left_attach">1</property>
<property name="width">1</property>
<property name="top_attach">2</property>
<property name="height">1</property>
</packing>
</child>
<child>
@@ -223,15 +222,18 @@
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options">0</property>
<property name="left_attach">2</property>
<property name="width">1</property>
<property name="top_attach">0</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="login-options-label">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="halign">GTK_ALIGN_END</property>
<property name="hexpand">True</property>
<property name="ypad">5</property>
<property name="label" translatable="yes">Login Options</property>
<attributes>
@@ -239,16 +241,18 @@
</attributes>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">0</property>
<property name="left_attach">1</property>
<property name="width">1</property>
<property name="top_attach">4</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="password-label">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="halign">GTK_ALIGN_END</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">_Password</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">account-password-button</property>
@@ -257,28 +261,66 @@
</style>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">0</property>
<property name="left_attach">1</property>
<property name="width">1</property>
<property name="top_attach">5</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="UmEditableButton" id="account-password-button">
<property name="visible">True</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="width">1</property>
<property name="top_attach">5</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="other-passwords-button">
<property name="visible">True</property>
<property name="halign">GTK_ALIGN_START</property>
<property name="hexpand">TRUE</property>
<child>
<object class="GtkLabel" id="other-passwords-label">
<property name="visible">True</property>
<property name="label" translatable="yes">Other Passwords…</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="width">1</property>
<property name="top_attach">6</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="accessible-realms-label">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="halign">GTK_ALIGN_END</property>
<property name="hexpand">TRUE</property>
<property name="label" translatable="yes">Accessible Realms</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options">0</property>
<property name="width">1</property>
<property name="top_attach">7</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="autologin-label">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="halign">GTK_ALIGN_END</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">A_utomatic Login</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">autologin-switch</property>
@@ -287,10 +329,10 @@
</style>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">0</property>
<property name="left_attach">1</property>
<property name="width">1</property>
<property name="top_attach">8</property>
<property name="height">1</property>
</packing>
</child>
<child>
@@ -311,17 +353,18 @@
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options">0</property>
<property name="left_attach">2</property>
<property name="width">1</property>
<property name="top_attach">8</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="account-fingerprint-label">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="halign">GTK_ALIGN_END</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">_Fingerprint Login</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">account-fingerprint-button</property>
@@ -330,15 +373,17 @@
</style>
</object>
<packing>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">0</property>
<property name="left_attach">1</property>
<property name="width">1</property>
<property name="top_attach">9</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox5">
<property name="visible">True</property>
<property name="halign">GTK_ALIGN_END</property>
<property name="hexpand">True</property>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
@@ -399,14 +444,18 @@
</child>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options">0</property>
<property name="left_attach">1</property>
<property name="width">1</property>
<property name="top_attach">0</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="language-label">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="halign">GTK_ALIGN_END</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">_Language</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">account-language-combo</property>
@@ -415,10 +464,10 @@
</style>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">0</property>
<property name="left_attach">1</property>
<property name="width">1</property>
<property name="top_attach">3</property>
<property name="height">1</property>
</packing>
</child>
<child>
@@ -428,12 +477,10 @@
<property name="text-column">1</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">0</property>
<property name="left_attach">2</property>
<property name="width">1</property>
<property name="top_attach">3</property>
<property name="height">1</property>
</packing>
</child>
</object>

View File

@@ -0,0 +1,549 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Ray Strode
* Based on work by Colin Walters
*/
#include "config.h"
#include "gsd-alarm.h"
#ifdef HAVE_TIMERFD
#include <sys/timerfd.h>
#endif
#include <unistd.h>
#include <string.h>
#include <glib.h>
#include <gio/gio.h>
#include <gio/gunixinputstream.h>
typedef struct {
GSource *source;
GInputStream *stream;
} Timer;
typedef struct {
GSource *source;
} Timeout;
#define MAX_TIMEOUT_INTERVAL (10 * 1000)
typedef enum {
GSD_ALARM_TYPE_UNSCHEDULED,
GSD_ALARM_TYPE_TIMER,
GSD_ALARM_TYPE_TIMEOUT,
} GsdAlarmType;
struct _GsdAlarmPrivate
{
GCancellable *cancellable;
GDateTime *time;
GDateTime *previous_wakeup_time;
GMainContext *context;
GSource *immediate_wakeup_source;
GRecMutex lock;
GsdAlarmType type;
union {
Timer timer;
Timeout timeout;
};
};
enum {
FIRED,
REARMED,
NUMBER_OF_SIGNALS,
};
static void schedule_wakeups (GsdAlarm *self);
static void schedule_wakeups_with_timeout_source (GsdAlarm *self);
static guint signals[NUMBER_OF_SIGNALS] = { 0 };
G_DEFINE_TYPE (GsdAlarm, gsd_alarm, G_TYPE_OBJECT);
static void
clear_scheduled_immediate_wakeup (GsdAlarm *self)
{
g_clear_pointer (&self->priv->immediate_wakeup_source,
(GDestroyNotify)
g_source_destroy);
}
static void
clear_scheduled_timer_wakeups (GsdAlarm *self)
{
#ifdef HAVE_TIMERFD
GError *error;
gboolean is_closed;
g_clear_pointer (&self->priv->timer.source,
(GDestroyNotify)
g_source_destroy);
error = NULL;
is_closed = g_input_stream_close (self->priv->timer.stream,
NULL,
&error);
if (!is_closed) {
g_warning ("GsdAlarm: could not close timer stream: %s",
error->message);
g_error_free (error);
}
g_clear_object (&self->priv->timer.stream);
#endif
}
static void
clear_scheduled_timeout_wakeups (GsdAlarm *self)
{
g_clear_pointer (&self->priv->timeout.source,
(GDestroyNotify)
g_source_destroy);
}
static void
clear_scheduled_wakeups (GsdAlarm *self)
{
g_rec_mutex_lock (&self->priv->lock);
clear_scheduled_immediate_wakeup (self);
switch (self->priv->type) {
case GSD_ALARM_TYPE_TIMER:
clear_scheduled_timer_wakeups (self);
break;
case GSD_ALARM_TYPE_TIMEOUT:
clear_scheduled_timeout_wakeups (self);
break;
default:
break;
}
g_clear_object (&self->priv->cancellable);
g_clear_pointer (&self->priv->context,
(GDestroyNotify)
g_main_context_unref);
g_clear_pointer (&self->priv->previous_wakeup_time,
(GDestroyNotify)
g_date_time_unref);
g_clear_pointer (&self->priv->time,
(GDestroyNotify)
g_date_time_unref);
g_assert (self->priv->timeout.source == NULL);
self->priv->type = GSD_ALARM_TYPE_UNSCHEDULED;
g_rec_mutex_unlock (&self->priv->lock);
}
static void
gsd_alarm_finalize (GObject *object)
{
GsdAlarm *self = GSD_ALARM (object);
clear_scheduled_wakeups (self);
G_OBJECT_CLASS (gsd_alarm_parent_class)->finalize (object);
}
static void
gsd_alarm_class_init (GsdAlarmClass *klass)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gsd_alarm_finalize;
g_type_class_add_private (klass, sizeof (GsdAlarmPrivate));
signals[FIRED] = g_signal_new ("fired",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
signals[REARMED] = g_signal_new ("rearmed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
static void
gsd_alarm_init (GsdAlarm *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GSD_TYPE_ALARM,
GsdAlarmPrivate);
self->priv->type = GSD_ALARM_TYPE_UNSCHEDULED;
g_rec_mutex_init (&self->priv->lock);
}
static void
on_cancelled (GCancellable *cancellable,
gpointer user_data)
{
GsdAlarm *self = GSD_ALARM (user_data);
clear_scheduled_wakeups (self);
}
static void
fire_alarm (GsdAlarm *self)
{
g_signal_emit (G_OBJECT (self), signals[FIRED], 0);
}
static void
rearm_alarm (GsdAlarm *self)
{
g_signal_emit (G_OBJECT (self), signals[REARMED], 0);
}
static void
fire_or_rearm_alarm (GsdAlarm *self)
{
GTimeSpan time_until_fire;
GTimeSpan previous_time_until_fire;
GDateTime *now;
now = g_date_time_new_now_local ();
time_until_fire = g_date_time_difference (self->priv->time, now);
if (self->priv->previous_wakeup_time == NULL) {
self->priv->previous_wakeup_time = now;
/* If, according to the time, we're past when we should have fired,
* then fire the alarm.
*/
if (time_until_fire <= 0) {
fire_alarm (self);
}
} else {
previous_time_until_fire = g_date_time_difference (self->priv->time,
self->priv->previous_wakeup_time);
g_date_time_unref (self->priv->previous_wakeup_time);
self->priv->previous_wakeup_time = now;
/* If, according to the time, we're past when we should have fired,
* and this is the first wakeup where that's been true then fire
* the alarm. The first check makes sure we don't fire prematurely,
* and the second check makes sure we don't fire more than once
*/
if (time_until_fire <= 0 && previous_time_until_fire > 0) {
fire_alarm (self);
/* If, according to the time, we're before when we should fire,
* and we previously fired the alarm, then we've jumped back in
* time and need to rearm the alarm.
*/
} else if (time_until_fire > 0 && previous_time_until_fire <= 0) {
rearm_alarm (self);
}
}
}
static gboolean
on_immediate_wakeup_source_ready (GsdAlarm *self)
{
g_return_val_if_fail (self->priv->type != GSD_ALARM_TYPE_UNSCHEDULED, FALSE);
g_rec_mutex_lock (&self->priv->lock);
if (g_cancellable_is_cancelled (self->priv->cancellable)) {
goto out;
}
fire_or_rearm_alarm (self);
out:
g_rec_mutex_unlock (&self->priv->lock);
return FALSE;
}
#ifdef HAVE_TIMERFD
static gboolean
on_timer_source_ready (GObject *stream,
GsdAlarm *self)
{
gint64 number_of_fires;
gssize bytes_read;
gboolean run_again = FALSE;
g_return_val_if_fail (GSD_IS_ALARM (self), FALSE);
g_return_val_if_fail (self->priv->type == GSD_ALARM_TYPE_TIMER, FALSE);
g_rec_mutex_lock (&self->priv->lock);
if (g_cancellable_is_cancelled (self->priv->cancellable)) {
goto out;
}
bytes_read = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (stream),
&number_of_fires,
sizeof (gint64),
NULL,
NULL);
if (bytes_read == sizeof (gint64)) {
if (number_of_fires < 0 || number_of_fires > 1) {
g_warning ("GsdAlarm: expected timerfd to report firing once,"
"but it reported firing %ld times\n",
(long) number_of_fires);
}
}
fire_or_rearm_alarm (self);
run_again = TRUE;
out:
g_rec_mutex_unlock (&self->priv->lock);
return run_again;
}
static void
clear_timer_source_pointer (GsdAlarm *self)
{
self->priv->timer.source = NULL;
}
#endif
static gboolean
schedule_wakeups_with_timerfd (GsdAlarm *self)
{
#ifdef HAVE_TIMERFD
struct itimerspec timer_spec;
int fd;
int result;
static gboolean seen_before = FALSE;
if (!seen_before) {
g_debug ("GsdAlarm: trying to use kernel timer");
seen_before = TRUE;
}
fd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC | TFD_NONBLOCK);
if (fd < 0) {
g_debug ("GsdAlarm: could not create timer fd: %m");
return FALSE;
}
memset (&timer_spec, 0, sizeof (timer_spec));
timer_spec.it_value.tv_sec = g_date_time_to_unix (self->priv->time) + 1;
result = timerfd_settime (fd,
TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
&timer_spec,
NULL);
if (result < 0) {
g_debug ("GsdAlarm: could not set timer: %m");
return FALSE;
}
self->priv->type = GSD_ALARM_TYPE_TIMER;
self->priv->timer.stream = g_unix_input_stream_new (fd, TRUE);
self->priv->timer.source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (self->priv->timer.stream),
self->priv->cancellable);
g_source_set_callback (self->priv->timer.source,
(GSourceFunc)
on_timer_source_ready,
self,
(GDestroyNotify)
clear_timer_source_pointer);
g_source_attach (self->priv->timer.source,
self->priv->context);
g_source_unref (self->priv->timer.source);
return TRUE;
#endif /* HAVE_TIMERFD */
return FALSE;
}
static gboolean
on_timeout_source_ready (GsdAlarm *self)
{
g_return_val_if_fail (GSD_IS_ALARM (self), FALSE);
g_rec_mutex_lock (&self->priv->lock);
if (g_cancellable_is_cancelled (self->priv->cancellable) ||
self->priv->type == GSD_ALARM_TYPE_UNSCHEDULED) {
goto out;
}
fire_or_rearm_alarm (self);
if (g_cancellable_is_cancelled (self->priv->cancellable)) {
goto out;
}
schedule_wakeups_with_timeout_source (self);
out:
g_rec_mutex_unlock (&self->priv->lock);
return FALSE;
}
static void
clear_timeout_source_pointer (GsdAlarm *self)
{
self->priv->timeout.source = NULL;
}
static void
schedule_wakeups_with_timeout_source (GsdAlarm *self)
{
GDateTime *now;
GTimeSpan time_span;
guint interval;
self->priv->type = GSD_ALARM_TYPE_TIMEOUT;
now = g_date_time_new_now_local ();
time_span = g_date_time_difference (self->priv->time, now);
g_date_time_unref (now);
time_span = CLAMP (time_span, 1000 * G_TIME_SPAN_MILLISECOND, G_MAXUINT * G_TIME_SPAN_MILLISECOND);
interval = (guint) time_span / G_TIME_SPAN_MILLISECOND;
/* We poll every 10 seconds or so because we want to catch time skew
*/
interval = MIN (interval, MAX_TIMEOUT_INTERVAL);
self->priv->timeout.source = g_timeout_source_new (interval);
g_source_set_callback (self->priv->timeout.source,
(GSourceFunc)
on_timeout_source_ready,
self,
(GDestroyNotify)
clear_timeout_source_pointer);
g_source_attach (self->priv->timeout.source,
self->priv->context);
g_source_unref (self->priv->timeout.source);
}
static void
schedule_wakeups (GsdAlarm *self)
{
gboolean wakeup_scheduled;
wakeup_scheduled = schedule_wakeups_with_timerfd (self);
if (!wakeup_scheduled) {
static gboolean seen_before = FALSE;
if (!seen_before) {
g_debug ("GsdAlarm: falling back to polling timeout");
seen_before = TRUE;
}
schedule_wakeups_with_timeout_source (self);
}
}
static void
clear_immediate_wakeup_source_pointer (GsdAlarm *self)
{
self->priv->immediate_wakeup_source = NULL;
}
static void
schedule_immediate_wakeup (GsdAlarm *self)
{
self->priv->immediate_wakeup_source = g_idle_source_new ();
g_source_set_callback (self->priv->immediate_wakeup_source,
(GSourceFunc)
on_immediate_wakeup_source_ready,
self,
(GDestroyNotify)
clear_immediate_wakeup_source_pointer);
g_source_attach (self->priv->immediate_wakeup_source,
self->priv->context);
g_source_unref (self->priv->immediate_wakeup_source);
}
void
gsd_alarm_set_time (GsdAlarm *self,
GDateTime *time,
GCancellable *cancellable)
{
if (g_cancellable_is_cancelled (cancellable)) {
return;
}
if (self->priv->cancellable != NULL) {
if (!g_cancellable_is_cancelled (self->priv->cancellable)) {
g_cancellable_cancel (cancellable);
}
g_object_unref (self->priv->cancellable);
self->priv->cancellable = NULL;
}
if (cancellable == NULL) {
self->priv->cancellable = g_cancellable_new ();
} else {
self->priv->cancellable = g_object_ref (cancellable);
}
g_cancellable_connect (self->priv->cancellable,
G_CALLBACK (on_cancelled),
self,
NULL);
self->priv->time = g_date_time_ref (time);
self->priv->context = g_main_context_ref (g_main_context_default ());
schedule_wakeups (self);
/* Wake up right away, in case it's already expired leaving the gate */
schedule_immediate_wakeup (self);
}
GDateTime *
gsd_alarm_get_time (GsdAlarm *self)
{
return self->priv->time;
}
GsdAlarm *
gsd_alarm_new (void)
{
GsdAlarm *self;
self = GSD_ALARM (g_object_new (GSD_TYPE_ALARM, NULL));
return GSD_ALARM (self);
}

View File

@@ -0,0 +1,67 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Ray Strode
*/
#ifndef __GSD_ALARM_H__
#define __GSD_ALARM_H__
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
G_BEGIN_DECLS
#define GSD_TYPE_ALARM (gsd_alarm_get_type ())
#define GSD_ALARM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_ALARM, GsdAlarm))
#define GSD_ALARM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_ALARM, GsdAlarmClass))
#define GSD_IS_ALARM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_ALARM))
#define GSD_IS_ALARM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_ALARM))
#define GSD_ALARM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSD_TYPE_ALARM, GsdAlarmClass))
typedef struct _GsdAlarm GsdAlarm;
typedef struct _GsdAlarmClass GsdAlarmClass;
typedef struct _GsdAlarmPrivate GsdAlarmPrivate;
struct _GsdAlarm
{
GObject parent;
GsdAlarmPrivate *priv;
};
struct _GsdAlarmClass
{
GObjectClass parent_class;
void (* fired) (GsdAlarm *alarm);
void (* rearmed) (GsdAlarm *alarm);
};
GType gsd_alarm_get_type (void);
GsdAlarm *gsd_alarm_new (void);
void gsd_alarm_set_time (GsdAlarm *alarm,
GDateTime *time,
GCancellable *cancellable);
GDateTime *gsd_alarm_get_time (GsdAlarm *alarm);
G_END_DECLS
#endif /* __GSD_ALARM_H__ */

View File

@@ -0,0 +1,36 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Ray Strode
*/
#ifndef __GSD_IDENTITY_INQUIRY_PRIVATE_H__
#define __GSD_IDENTITY_INQUIRY_PRIVATE_H__
#include <glib.h>
#include <glib-object.h>
#include "gsd-identity-inquiry.h"
G_BEGIN_DECLS
void _gsd_identity_inquiry_emit_complete (GsdIdentityInquiry *inquiry);
G_END_DECLS
#endif /* __GSD_IDENTITY_INQUIRY_PRIVATE_H__ */

View File

@@ -0,0 +1,146 @@
/* -*- Mode: C; tab-width: 8; ident-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Ray Strode
*/
#include "config.h"
#include "gsd-identity-inquiry.h"
#include "gsd-identity-inquiry-private.h"
#include <string.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
enum {
COMPLETE,
NUMBER_OF_SIGNALS,
};
static guint signals[NUMBER_OF_SIGNALS] = { 0 };
G_DEFINE_INTERFACE (GsdIdentityInquiry,
gsd_identity_inquiry,
G_TYPE_OBJECT);
static void
gsd_identity_inquiry_default_init (GsdIdentityInquiryInterface *interface)
{
signals[COMPLETE] = g_signal_new ("complete",
G_TYPE_FROM_INTERFACE (interface),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
void
_gsd_identity_inquiry_emit_complete (GsdIdentityInquiry *self)
{
g_signal_emit (G_OBJECT (self), signals[COMPLETE], 0);
}
char *
gsd_identity_inquiry_get_name (GsdIdentityInquiry *self)
{
g_return_val_if_fail (GSD_IS_IDENTITY_INQUIRY (self), NULL);
return GSD_IDENTITY_INQUIRY_GET_IFACE (self)->get_name (self);
}
char *
gsd_identity_inquiry_get_banner (GsdIdentityInquiry *self)
{
g_return_val_if_fail (GSD_IS_IDENTITY_INQUIRY (self), NULL);
return GSD_IDENTITY_INQUIRY_GET_IFACE (self)->get_banner (self);
}
gboolean
gsd_identity_inquiry_is_complete (GsdIdentityInquiry *self)
{
g_return_val_if_fail (GSD_IS_IDENTITY_INQUIRY (self), TRUE);
return GSD_IDENTITY_INQUIRY_GET_IFACE (self)->is_complete (self);
}
void
gsd_identity_inquiry_iter_init (GsdIdentityInquiryIter *iter,
GsdIdentityInquiry *inquiry)
{
g_return_if_fail (GSD_IS_IDENTITY_INQUIRY (inquiry));
GSD_IDENTITY_INQUIRY_GET_IFACE (inquiry)->iter_init (iter, inquiry);
}
GsdIdentityQuery *
gsd_identity_inquiry_iter_next (GsdIdentityInquiryIter *iter,
GsdIdentityInquiry *inquiry)
{
g_return_val_if_fail (GSD_IS_IDENTITY_INQUIRY (inquiry), NULL);
return GSD_IDENTITY_INQUIRY_GET_IFACE (inquiry)->iter_next (iter, inquiry);
}
GsdIdentity *
gsd_identity_inquiry_get_identity (GsdIdentityInquiry *self)
{
g_return_val_if_fail (GSD_IS_IDENTITY_INQUIRY (self), NULL);
return GSD_IDENTITY_INQUIRY_GET_IFACE (self)->get_identity (self);
}
GsdIdentityQueryMode
gsd_identity_query_get_mode (GsdIdentityInquiry *self,
GsdIdentityQuery *query)
{
g_return_val_if_fail (GSD_IS_IDENTITY_INQUIRY (self),
GSD_IDENTITY_QUERY_MODE_INVISIBLE);
return GSD_IDENTITY_INQUIRY_GET_IFACE (self)->get_mode (self, query);
}
char *
gsd_identity_query_get_prompt (GsdIdentityInquiry *self,
GsdIdentityQuery *query)
{
g_return_val_if_fail (GSD_IS_IDENTITY_INQUIRY (self), NULL);
return GSD_IDENTITY_INQUIRY_GET_IFACE (self)->get_prompt (self, query);
}
void
gsd_identity_inquiry_answer_query (GsdIdentityInquiry *self,
GsdIdentityQuery *query,
const char *answer)
{
g_return_if_fail (GSD_IS_IDENTITY_INQUIRY (self));
GSD_IDENTITY_INQUIRY_GET_IFACE (self)->answer_query (self, query, answer);
}
gboolean
gsd_identity_query_is_answered (GsdIdentityInquiry *self,
GsdIdentityQuery *query)
{
g_return_val_if_fail (GSD_IS_IDENTITY_INQUIRY (self), FALSE);
return GSD_IDENTITY_INQUIRY_GET_IFACE (self)->is_answered (self, query);
}

View File

@@ -0,0 +1,108 @@
/* -*- Mode: C; tab-width: 8; ident-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Ray Strode
*/
#ifndef __GSD_IDENTITY_INQUIRY_H__
#define __GSD_IDENTITY_INQUIRY_H__
#include <stdint.h>
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include "gsd-identity.h"
G_BEGIN_DECLS
#define GSD_TYPE_IDENTITY_INQUIRY (gsd_identity_inquiry_get_type ())
#define GSD_IDENTITY_INQUIRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_IDENTITY_INQUIRY, GsdIdentityInquiry))
#define GSD_IDENTITY_INQUIRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_IDENTITY_INQUIRY, GsdIdentityInquiryClass))
#define GSD_IS_IDENTITY_INQUIRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_IDENTITY_INQUIRY))
#define GSD_IDENTITY_INQUIRY_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), GSD_TYPE_IDENTITY_INQUIRY, GsdIdentityInquiryInterface))
typedef struct _GsdIdentityInquiry GsdIdentityInquiry;
typedef struct _GsdIdentityInquiryInterface GsdIdentityInquiryInterface;
typedef struct _GsdIdentityInquiryIter GsdIdentityInquiryIter;
typedef struct _GsdIdentityQuery GsdIdentityQuery;
typedef void (* GsdIdentityInquiryFunc) (GsdIdentityInquiry *inquiry,
GCancellable *cancellable,
gpointer user_data);
typedef enum
{
GSD_IDENTITY_QUERY_MODE_INVISIBLE,
GSD_IDENTITY_QUERY_MODE_VISIBLE
} GsdIdentityQueryMode;
struct _GsdIdentityInquiryIter
{
gpointer data;
};
struct _GsdIdentityInquiryInterface
{
GTypeInterface base_interface;
GsdIdentity * (* get_identity) (GsdIdentityInquiry *inquiry);
char * (* get_name) (GsdIdentityInquiry *inquiry);
char * (* get_banner) (GsdIdentityInquiry *inquiry);
gboolean (* is_complete) (GsdIdentityInquiry *inquiry);
void (* answer_query) (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query,
const char *answer);
void (* iter_init) (GsdIdentityInquiryIter *iter,
GsdIdentityInquiry *inquiry);
GsdIdentityQuery * (* iter_next) (GsdIdentityInquiryIter *iter,
GsdIdentityInquiry *inquiry);
GsdIdentityQueryMode (* get_mode) (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query);
char * (* get_prompt) (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query);
gboolean (* is_answered) (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query);
};
GType gsd_identity_inquiry_get_type (void);
GsdIdentity *gsd_identity_inquiry_get_identity (GsdIdentityInquiry *inquiry);
char *gsd_identity_inquiry_get_name (GsdIdentityInquiry *inquiry);
char *gsd_identity_inquiry_get_banner (GsdIdentityInquiry *inquiry);
gboolean gsd_identity_inquiry_is_complete (GsdIdentityInquiry *inquiry);
void gsd_identity_inquiry_answer_query (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query,
const char *answer);
void gsd_identity_inquiry_iter_init (GsdIdentityInquiryIter *iter,
GsdIdentityInquiry *inquiry);
GsdIdentityQuery *gsd_identity_inquiry_iter_next (GsdIdentityInquiryIter *iter, GsdIdentityInquiry *inquiry);
GsdIdentityQueryMode gsd_identity_query_get_mode (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query);
char *gsd_identity_query_get_prompt (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query);
gboolean gsd_identity_query_is_answered (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query);
#endif /* __GSD_IDENTITY_INQUIRY_H__ */

View File

@@ -0,0 +1,51 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Ray Strode
*/
#ifndef __GSD_IDENTITY_MANAGER_PRIVATE_H__
#define __GSD_IDENTITY_MANAGER_PRIVATE_H__
#include <glib.h>
#include <glib-object.h>
#include "gsd-identity-manager.h"
G_BEGIN_DECLS
void _gsd_identity_manager_emit_identity_added (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void _gsd_identity_manager_emit_identity_removed (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void _gsd_identity_manager_emit_identity_refreshed (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void _gsd_identity_manager_emit_identity_renamed (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void _gsd_identity_manager_emit_identity_expiring (GsdIdentityManager *self,
GsdIdentity *identity);
void _gsd_identity_manager_emit_identity_needs_renewal (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void _gsd_identity_manager_emit_identity_expired (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
G_END_DECLS
#endif /* __GSD_IDENTITY_MANAGER_PRIVATE_H__ */

View File

@@ -0,0 +1,238 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include <glib-object.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include "gsd-identity-manager.h"
#include "gsd-identity-manager-private.h"
enum {
IDENTITY_ADDED,
IDENTITY_REMOVED,
IDENTITY_RENAMED,
IDENTITY_REFRESHED,
IDENTITY_NEEDS_RENEWAL,
IDENTITY_EXPIRING,
IDENTITY_EXPIRED,
NUMBER_OF_SIGNALS,
};
static guint signals[NUMBER_OF_SIGNALS] = { 0 };
G_DEFINE_INTERFACE (GsdIdentityManager, gsd_identity_manager, G_TYPE_OBJECT);
static void
gsd_identity_manager_default_init (GsdIdentityManagerInterface *interface)
{
signals[IDENTITY_ADDED] = g_signal_new ("identity-added",
G_TYPE_FROM_INTERFACE (interface),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GsdIdentityManagerInterface, identity_added),
NULL, NULL, NULL,
G_TYPE_NONE, 1, GSD_TYPE_IDENTITY);
signals[IDENTITY_REMOVED] = g_signal_new ("identity-removed",
G_TYPE_FROM_INTERFACE (interface),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GsdIdentityManagerInterface, identity_removed),
NULL, NULL, NULL,
G_TYPE_NONE, 1, GSD_TYPE_IDENTITY);
signals[IDENTITY_REFRESHED] = g_signal_new ("identity-refreshed",
G_TYPE_FROM_INTERFACE (interface),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GsdIdentityManagerInterface, identity_refreshed),
NULL, NULL, NULL,
G_TYPE_NONE, 1, GSD_TYPE_IDENTITY);
signals[IDENTITY_RENAMED] = g_signal_new ("identity-renamed",
G_TYPE_FROM_INTERFACE (interface),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GsdIdentityManagerInterface, identity_renamed),
NULL, NULL, NULL,
G_TYPE_NONE, 1, GSD_TYPE_IDENTITY);
signals[IDENTITY_NEEDS_RENEWAL] = g_signal_new ("identity-needs-renewal",
G_TYPE_FROM_INTERFACE (interface),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GsdIdentityManagerInterface, identity_needs_renewal),
NULL, NULL, NULL,
G_TYPE_NONE, 1, GSD_TYPE_IDENTITY);
signals[IDENTITY_EXPIRING] = g_signal_new ("identity-expiring",
G_TYPE_FROM_INTERFACE (interface),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GsdIdentityManagerInterface, identity_expiring),
NULL, NULL, NULL,
G_TYPE_NONE, 1, GSD_TYPE_IDENTITY);
signals[IDENTITY_EXPIRED] = g_signal_new ("identity-expired",
G_TYPE_FROM_INTERFACE (interface),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GsdIdentityManagerInterface, identity_expired),
NULL, NULL, NULL,
G_TYPE_NONE, 1, GSD_TYPE_IDENTITY);
}
GQuark
gsd_identity_manager_error_quark (void)
{
static GQuark error_quark = 0;
if (error_quark == 0) {
error_quark = g_quark_from_static_string ("gsd-identity-manager-error");
}
return error_quark;
}
void
gsd_identity_manager_list_identities (GsdIdentityManager *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSD_IDENTITY_MANAGER_GET_IFACE (self)->list_identities (self,
cancellable,
callback,
user_data);
}
GList *
gsd_identity_manager_list_identities_finish (GsdIdentityManager *self,
GAsyncResult *result,
GError **error)
{
return GSD_IDENTITY_MANAGER_GET_IFACE (self)->list_identities_finish (self,
result,
error);
}
void
gsd_identity_manager_renew_identity (GsdIdentityManager *self,
GsdIdentity *identity,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSD_IDENTITY_MANAGER_GET_IFACE (self)->renew_identity (self, identity, cancellable, callback, user_data);
}
void
gsd_identity_manager_renew_identity_finish (GsdIdentityManager *self,
GAsyncResult *result,
GError **error)
{
GSD_IDENTITY_MANAGER_GET_IFACE (self)->renew_identity_finish (self, result, error);
}
void
gsd_identity_manager_sign_identity_in (GsdIdentityManager *self,
const char *identifier,
GsdIdentityInquiryFunc inquiry_func,
gpointer inquiry_data,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSD_IDENTITY_MANAGER_GET_IFACE (self)->sign_identity_in (self, identifier, inquiry_func, inquiry_data, cancellable, callback, user_data);
}
GsdIdentity *
gsd_identity_manager_sign_identity_in_finish (GsdIdentityManager *self,
GAsyncResult *result,
GError **error)
{
return GSD_IDENTITY_MANAGER_GET_IFACE (self)->sign_identity_in_finish (self, result, error);
}
void
gsd_identity_manager_sign_identity_out (GsdIdentityManager *self,
GsdIdentity *identity,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSD_IDENTITY_MANAGER_GET_IFACE (self)->sign_identity_out (self, identity, cancellable, callback, user_data);
}
void
gsd_identity_manager_sign_identity_out_finish (GsdIdentityManager *self,
GAsyncResult *result,
GError **error)
{
GSD_IDENTITY_MANAGER_GET_IFACE (self)->sign_identity_out_finish (self, result, error);
}
char *
gsd_identity_manager_name_identity (GsdIdentityManager *self,
GsdIdentity *identity)
{
return GSD_IDENTITY_MANAGER_GET_IFACE (self)->name_identity (self,
identity);
}
void
_gsd_identity_manager_emit_identity_added (GsdIdentityManager *self,
GsdIdentity *identity)
{
g_signal_emit (G_OBJECT (self), signals[IDENTITY_ADDED], 0, identity);
}
void
_gsd_identity_manager_emit_identity_removed (GsdIdentityManager *self,
GsdIdentity *identity)
{
g_signal_emit (G_OBJECT (self), signals[IDENTITY_REMOVED], 0, identity);
}
void
_gsd_identity_manager_emit_identity_renamed (GsdIdentityManager *self,
GsdIdentity *identity)
{
g_signal_emit (G_OBJECT (self), signals[IDENTITY_RENAMED], 0, identity);
}
void
_gsd_identity_manager_emit_identity_refreshed (GsdIdentityManager *self,
GsdIdentity *identity)
{
g_signal_emit (G_OBJECT (self), signals[IDENTITY_REFRESHED], 0, identity);
}
void
_gsd_identity_manager_emit_identity_needs_renewal (GsdIdentityManager *self,
GsdIdentity *identity)
{
g_signal_emit (G_OBJECT (self), signals[IDENTITY_NEEDS_RENEWAL], 0, identity);
}
void
_gsd_identity_manager_emit_identity_expiring (GsdIdentityManager *self,
GsdIdentity *identity)
{
g_signal_emit (G_OBJECT (self), signals[IDENTITY_EXPIRING], 0, identity);
}
void
_gsd_identity_manager_emit_identity_expired (GsdIdentityManager *self,
GsdIdentity *identity)
{
g_signal_emit (G_OBJECT (self), signals[IDENTITY_EXPIRED], 0, identity);
}

View File

@@ -0,0 +1,162 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Ray Strode
*/
#ifndef __GSD_IDENTITY_MANAGER_H__
#define __GSD_IDENTITY_MANAGER_H__
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include "gsd-identity.h"
#include "gsd-identity-inquiry.h"
G_BEGIN_DECLS
#define GSD_TYPE_IDENTITY_MANAGER (gsd_identity_manager_get_type ())
#define GSD_IDENTITY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_IDENTITY_MANAGER, GsdIdentityManager))
#define GSD_IDENTITY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_IDENTITY_MANAGER, GsdIdentityManagerInterface))
#define GSD_IS_IDENTITY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_IDENTITY_MANAGER))
#define GSD_IDENTITY_MANAGER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), GSD_TYPE_IDENTITY_MANAGER, GsdIdentityManagerInterface))
#define GSD_IDENTITY_MANAGER_ERROR (gsd_identity_manager_error_quark ())
typedef struct _GsdIdentityManager GsdIdentityManager;
typedef struct _GsdIdentityManagerInterface GsdIdentityManagerInterface;
typedef enum _GsdIdentityManagerError GsdIdentityManagerError;
struct _GsdIdentityManagerInterface
{
GTypeInterface base_interface;
/* Signals */
void (* identity_added) (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void (* identity_removed) (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void (* identity_renamed) (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void (* identity_refreshed) (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void (* identity_needs_renewal) (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void (* identity_expiring) (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
void (* identity_expired) (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
/* Virtual Functions */
void (* list_identities) (GsdIdentityManager *identity_manager,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GList * (* list_identities_finish) (GsdIdentityManager *identity_manager,
GAsyncResult *result,
GError **error);
void (* sign_identity_in) (GsdIdentityManager *identity_manager,
const char *identifier,
GsdIdentityInquiryFunc inquiry_func,
gpointer inquiry_data,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GsdIdentity * (* sign_identity_in_finish) (GsdIdentityManager *identity_manager,
GAsyncResult *result,
GError **error);
void (* sign_identity_out) (GsdIdentityManager *identity_manager,
GsdIdentity *identity,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void (* sign_identity_out_finish) (GsdIdentityManager *identity_manager,
GAsyncResult *result,
GError **error);
void (* renew_identity) (GsdIdentityManager *identity_manager,
GsdIdentity *identity,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void (* renew_identity_finish) (GsdIdentityManager *identity_manager,
GAsyncResult *result,
GError **error);
char * (* name_identity) (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
};
enum _GsdIdentityManagerError
{
GSD_IDENTITY_MANAGER_ERROR_INITIALIZING,
GSD_IDENTITY_MANAGER_ERROR_MONITORING,
GSD_IDENTITY_MANAGER_ERROR_SIGNING_IN,
GSD_IDENTITY_MANAGER_ERROR_SIGNING_OUT
};
GType gsd_identity_manager_get_type (void);
GQuark gsd_identity_manager_error_quark (void);
void gsd_identity_manager_list_identities (GsdIdentityManager *identity_manager,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GList * gsd_identity_manager_list_identities_finish (GsdIdentityManager *identity_manager,
GAsyncResult *result,
GError **error);
void gsd_identity_manager_sign_identity_in (GsdIdentityManager *identity_manager,
const char *identifier,
GsdIdentityInquiryFunc inquiry_func,
gpointer inquiry_data,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GsdIdentity * gsd_identity_manager_sign_identity_in_finish (GsdIdentityManager *identity_manager,
GAsyncResult *result,
GError **error);
void gsd_identity_manager_sign_identity_out (GsdIdentityManager *identity_manager,
GsdIdentity *identity,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void gsd_identity_manager_sign_identity_out_finish (GsdIdentityManager *identity_manager,
GAsyncResult *result,
GError **error);
void gsd_identity_manager_renew_identity (GsdIdentityManager *identity_manager,
GsdIdentity *identity,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void gsd_identity_manager_renew_identity_finish (GsdIdentityManager *identity_manager,
GAsyncResult *result,
GError **error);
char *gsd_identity_manager_name_identity (GsdIdentityManager *identity_manager,
GsdIdentity *identity);
G_END_DECLS
#endif /* __GSD_IDENTITY_MANAGER_H__ */

View File

@@ -0,0 +1,607 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <glib/gi18n-lib.h>
#include <gmodule.h>
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include <libnotify/notify.h>
#include <gcr/gcr.h>
#include "gnome-settings-plugin.h"
#include "gsd-identity-plugin.h"
#include "gsd-identity-manager.h"
#include "gsd-kerberos-identity-manager.h"
#include "gsd-kerberos-identity.h"
struct GsdIdentityPluginPrivate {
GsdIdentityManager *identity_manager;
};
#define GSD_IDENTITY_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), GSD_TYPE_IDENTITY_PLUGIN, GsdIdentityPluginPrivate))
GNOME_SETTINGS_PLUGIN_REGISTER (GsdIdentityPlugin, gsd_identity_plugin);
static void
gsd_identity_plugin_init (GsdIdentityPlugin *self)
{
self->priv = GSD_IDENTITY_PLUGIN_GET_PRIVATE (self);
g_debug ("GsdIdentityPlugin initializing");
}
static void
gsd_identity_plugin_finalize (GObject *object)
{
GsdIdentityPlugin *self;
g_return_if_fail (object != NULL);
g_return_if_fail (GSD_IS_IDENTITY_PLUGIN (object));
g_debug ("GsdIdentityPlugin: finalizing");
self = GSD_IDENTITY_PLUGIN (object);
g_return_if_fail (self->priv != NULL);
g_clear_object (&self->priv->identity_manager);
G_OBJECT_CLASS (gsd_identity_plugin_parent_class)->finalize (object);
}
static void
on_identity_renewed (GsdIdentityManager *manager,
GAsyncResult *result,
GnomeSettingsPlugin *self)
{
GError *error;
error = NULL;
gsd_identity_manager_renew_identity_finish (manager,
result,
&error);
if (error != NULL) {
g_debug ("GsdIdentityPlugin: could not renew identity: %s",
error->message);
g_error_free (error);
return;
}
g_debug ("GsdIdentityPlugin: identity renewed");
}
static void
on_identity_needs_renewal (GsdIdentityManager *identity_manager,
GsdIdentity *identity,
GsdIdentityPlugin *self)
{
g_debug ("GsdIdentityPlugin: identity needs renewal");
gsd_identity_manager_renew_identity (GSD_IDENTITY_MANAGER (self->priv->identity_manager),
identity,
NULL,
(GAsyncReadyCallback)
on_identity_renewed,
self);
}
static void
on_identity_signed_in (GsdIdentityManager *manager,
GAsyncResult *result,
GnomeSettingsPlugin *self)
{
GError *error;
error = NULL;
gsd_identity_manager_sign_identity_in_finish (manager,
result,
&error);
if (error != NULL) {
g_debug ("GsdIdentityPlugin: could not sign in identity: %s",
error->message);
g_error_free (error);
return;
}
g_debug ("GsdIdentityPlugin: identity signed in");
}
typedef struct {
GsdIdentityPlugin *plugin;
GsdIdentity *identity;
NotifyNotification *notification;
GCancellable *cancellable;
gulong refreshed_signal_id;
} SignInRequest;
static SignInRequest *
sign_in_request_new (GsdIdentityPlugin *plugin,
GsdIdentity *identity,
NotifyNotification *notification,
GCancellable *cancellable)
{
SignInRequest *request;
request = g_slice_new0 (SignInRequest);
request->plugin = plugin;
request->identity = g_object_ref (identity);
request->notification = notification;
request->cancellable = g_object_ref (cancellable);
return request;
}
static void
sign_in_request_free (SignInRequest *data)
{
GsdIdentityPlugin *plugin = data->plugin;
g_signal_handler_disconnect (plugin->priv->identity_manager,
data->refreshed_signal_id);
g_object_set_data (G_OBJECT (data->identity), "sign-in-request", NULL);
g_clear_object (&data->identity);
g_clear_object (&data->cancellable);
g_slice_free (SignInRequest, data);
}
typedef struct {
GsdIdentityPlugin *plugin;
GsdIdentity *identity;
GsdIdentityInquiry *inquiry;
GsdIdentityQuery *query;
GcrSystemPrompt *prompt;
GCancellable *cancellable;
} SystemPromptRequest;
static SystemPromptRequest *
system_prompt_request_new (GsdIdentityPlugin *plugin,
GcrSystemPrompt *prompt,
GsdIdentity *identity,
GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query,
GCancellable *cancellable)
{
SystemPromptRequest *data;
data = g_slice_new0 (SystemPromptRequest);
data->plugin = plugin;
data->prompt = prompt;
data->identity = g_object_ref (identity);
data->inquiry = g_object_ref (inquiry);
data->query = query;
data->cancellable = g_object_ref (cancellable);
return data;
}
static void
system_prompt_request_free (SystemPromptRequest *data)
{
g_clear_object (&data->identity);
g_clear_object (&data->inquiry);
g_clear_object (&data->cancellable);
g_slice_free (SystemPromptRequest, data);
}
static void
close_system_prompt (GsdIdentityManager *manager,
GsdIdentity *identity,
SystemPromptRequest *data)
{
GError *error;
/* Only close the prompt if the identity we're
* waiting on got refreshed
*/
if (data->identity != identity) {
return;
}
g_signal_handlers_disconnect_by_func (G_OBJECT (manager),
G_CALLBACK (close_system_prompt),
data);
error = NULL;
if (!gcr_system_prompt_close (data->prompt,
NULL,
&error)) {
if (error != NULL) {
g_debug ("GsdIdentityPlugin: could not close system prompt: %s",
error->message);
g_error_free (error);
}
}
}
static void
on_password_system_prompt_answered (GcrPrompt *prompt,
GAsyncResult *result,
SystemPromptRequest *request)
{
GsdIdentityPlugin *self = request->plugin;
GsdIdentityInquiry *inquiry = request->inquiry;
GsdIdentity *identity = request->identity;
GsdIdentityQuery *query = request->query;
GCancellable *cancellable = request->cancellable;
GError *error;
const char *password;
error = NULL;
password = gcr_prompt_password_finish (prompt, result, &error);
if (password == NULL) {
if (error != NULL) {
g_debug ("GsdIdentityPlugin: could not get password from user: %s",
error->message);
g_error_free (error);
} else {
g_cancellable_cancel (cancellable);
}
} else if (!g_cancellable_is_cancelled (cancellable)) {
gsd_identity_inquiry_answer_query (inquiry,
query,
password);
}
close_system_prompt (self->priv->identity_manager, identity, request);
system_prompt_request_free (request);
}
static void
query_user (GsdIdentityPlugin *self,
GsdIdentity *identity,
GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query,
GcrPrompt *prompt,
GCancellable *cancellable)
{
SystemPromptRequest *request;
char *prompt_text;
GsdIdentityQueryMode query_mode;
char *description;
char *name;
g_assert (GSD_IS_KERBEROS_IDENTITY (identity));
gcr_prompt_set_title (prompt, _("Sign In to Realm"));
name = gsd_identity_manager_name_identity (self->priv->identity_manager,
identity);
description = g_strdup_printf (_("The network realm %s needs some information to sign you in."), name);
g_free (name);
gcr_prompt_set_description (prompt, description);
g_free (description);
prompt_text = gsd_identity_query_get_prompt (inquiry, query);
gcr_prompt_set_message (prompt, prompt_text);
g_free (prompt_text);
request = system_prompt_request_new (self,
GCR_SYSTEM_PROMPT (prompt),
identity,
inquiry,
query,
cancellable);
g_signal_connect (G_OBJECT (self->priv->identity_manager),
"identity-refreshed",
G_CALLBACK (close_system_prompt),
request);
query_mode = gsd_identity_query_get_mode (inquiry, query);
switch (query_mode) {
case GSD_IDENTITY_QUERY_MODE_INVISIBLE:
gcr_prompt_password_async (prompt,
cancellable,
(GAsyncReadyCallback)
on_password_system_prompt_answered,
request);
break;
case GSD_IDENTITY_QUERY_MODE_VISIBLE:
gcr_prompt_password_async (prompt,
cancellable,
(GAsyncReadyCallback)
on_password_system_prompt_answered,
request);
break;
}
}
typedef struct {
GsdIdentityPlugin *plugin;
GsdIdentityInquiry *inquiry;
GCancellable *cancellable;
} SystemPromptOpenRequest;
static SystemPromptOpenRequest *
system_prompt_open_request_new (GsdIdentityPlugin *plugin,
GsdIdentityInquiry *inquiry,
GCancellable *cancellable)
{
SystemPromptOpenRequest *data;
data = g_slice_new0 (SystemPromptOpenRequest);
data->plugin = plugin;
data->inquiry = g_object_ref (inquiry);
data->cancellable = g_object_ref (cancellable);
return data;
}
static void
system_prompt_open_request_free (SystemPromptOpenRequest *data)
{
g_clear_object (&data->inquiry);
g_clear_object (&data->cancellable);
g_slice_free (SystemPromptOpenRequest, data);
}
static void
on_system_prompt_open (GcrSystemPrompt *system_prompt,
GAsyncResult *result,
SystemPromptOpenRequest *request)
{
GsdIdentityPlugin *self = request->plugin;
GsdIdentityInquiry *inquiry = request->inquiry;
GCancellable *cancellable = request->cancellable;
GsdIdentity *identity;
GsdIdentityQuery *query;
GcrPrompt *prompt;
GError *error;
GsdIdentityInquiryIter iter;
error = NULL;
prompt = gcr_system_prompt_open_finish (result, &error);
if (prompt == NULL) {
if (error != NULL) {
g_debug ("GsdIdentityPlugin: could not open system prompt: %s",
error->message);
g_error_free (error);
}
return;
}
identity = gsd_identity_inquiry_get_identity (inquiry);
gsd_identity_inquiry_iter_init (&iter, inquiry);
while ((query = gsd_identity_inquiry_iter_next (&iter, inquiry)) != NULL) {
query_user (self, identity, inquiry, query, prompt, cancellable);
}
system_prompt_open_request_free (request);
}
static void
on_identity_inquiry (GsdIdentityInquiry *inquiry,
GCancellable *cancellable,
GsdIdentityPlugin *self)
{
SystemPromptOpenRequest *request;
request = system_prompt_open_request_new (self, inquiry, cancellable);
gcr_system_prompt_open_async (-1,
cancellable,
(GAsyncReadyCallback)
on_system_prompt_open,
request);
}
static void
on_sign_in_clicked (NotifyNotification *notification,
const char *acition_id,
SignInRequest *request)
{
GsdIdentityPlugin *self = request->plugin;
GsdIdentity *identity = request->identity;
const char *identifier;
identifier = gsd_identity_get_identifier (identity);
gsd_identity_manager_sign_identity_in (self->priv->identity_manager,
identifier,
(GsdIdentityInquiryFunc)
on_identity_inquiry,
self,
request->cancellable,
(GAsyncReadyCallback)
on_identity_signed_in,
self);
}
static void
close_notification (GCancellable *cancellable,
NotifyNotification *notification)
{
notify_notification_close (notification, NULL);
}
static void
cancel_sign_in (GsdIdentityManager *identity_manager,
GsdIdentity *identity,
SignInRequest *data)
{
if (data->cancellable == NULL) {
return;
}
if (!g_cancellable_is_cancelled (data->cancellable)) {
g_cancellable_cancel (data->cancellable);
}
g_clear_object (&data->cancellable);
}
static void
ask_to_sign_in (GsdIdentityPlugin *self,
GsdIdentity *identity)
{
NotifyNotification *notification;
char *name;
char *description;
SignInRequest *request;
GCancellable *cancellable;
request = g_object_get_data (G_OBJECT (identity), "sign-in-request");
if (request != NULL) {
if (!g_cancellable_is_cancelled (request->cancellable)) {
g_cancellable_cancel (request->cancellable);
}
}
g_debug ("GsdIdentityPlugin: asking to sign back in");
name = gsd_identity_manager_name_identity (self->priv->identity_manager,
identity);
if (gsd_identity_is_signed_in (identity)) {
description = g_strdup_printf (_("The network realm %s will soon be inaccessible."),
name);
} else {
description = g_strdup_printf (_("The network realm %s is now inaccessible."),
name);
}
g_free (name);
notification = notify_notification_new (_("Realm Access"),
description,
"dialog-password-symbolic");
g_free (description);
notify_notification_set_app_name (notification, _("Network Realm"));
cancellable = g_cancellable_new ();
request = sign_in_request_new (self, identity, notification, cancellable);
g_object_set_data (G_OBJECT (identity), "sign-in-request", request);
g_cancellable_connect (cancellable,
G_CALLBACK (close_notification),
notification,
NULL);
g_signal_connect_swapped (G_OBJECT (notification),
"closed",
G_CALLBACK (sign_in_request_free),
request);
request->refreshed_signal_id = g_signal_connect (G_OBJECT (self->priv->identity_manager),
"identity-refreshed",
G_CALLBACK (cancel_sign_in),
request);
notify_notification_add_action (notification,
"sign-in",
_("Sign In"),
(NotifyActionCallback)
on_sign_in_clicked,
request,
NULL);
notify_notification_show (notification, NULL);
}
static void
on_identity_expiring (GsdIdentityManager *identity_manager,
GsdIdentity *identity,
GsdIdentityPlugin *self)
{
g_debug ("GsdIdentityPlugin: identity expiring");
ask_to_sign_in (self, identity);
}
static void
on_identity_expired (GsdIdentityManager *identity_manager,
GsdIdentity *identity,
GsdIdentityPlugin *self)
{
g_debug ("GsdIdentityPlugin: identity expired");
ask_to_sign_in (self, identity);
}
static void
impl_activate (GnomeSettingsPlugin *plugin)
{
GsdIdentityPlugin *self = GSD_IDENTITY_PLUGIN (plugin);
if (self->priv->identity_manager != NULL) {
g_debug ("GsdIdentityPlugin: Not activating identity plugin, because it's "
"already active");
return;
}
g_debug ("GsdIdentityPlugin: Activating identity plugin");
self->priv->identity_manager = gsd_kerberos_identity_manager_new ();
g_signal_connect (G_OBJECT (self->priv->identity_manager),
"identity-needs-renewal",
G_CALLBACK (on_identity_needs_renewal),
self);
g_signal_connect (G_OBJECT (self->priv->identity_manager),
"identity-expiring",
G_CALLBACK (on_identity_expiring),
self);
g_signal_connect (G_OBJECT (self->priv->identity_manager),
"identity-expired",
G_CALLBACK (on_identity_expired),
self);
}
static void
impl_deactivate (GnomeSettingsPlugin *plugin)
{
GsdIdentityPlugin *self = GSD_IDENTITY_PLUGIN (plugin);
if (self->priv->identity_manager == NULL) {
g_debug ("GsdIdentityPlugin: Not deactivating identity plugin, "
"because it's already inactive");
return;
}
g_debug ("GsdIdentityPlugin: Deactivating identity plugin");
g_signal_handlers_disconnect_by_func (self, on_identity_needs_renewal, self);
g_clear_object (&self->priv->identity_manager);
}
static void
gsd_identity_plugin_class_init (GsdIdentityPluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GnomeSettingsPluginClass *plugin_class = GNOME_SETTINGS_PLUGIN_CLASS (klass);
object_class->finalize = gsd_identity_plugin_finalize;
plugin_class->activate = impl_activate;
plugin_class->deactivate = impl_deactivate;
g_type_class_add_private (klass, sizeof (GsdIdentityPluginPrivate));
}
static void
gsd_identity_plugin_class_finalize (GsdIdentityPluginClass *klass)
{
}

View File

@@ -0,0 +1,59 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GSD_IDENTITY_PLUGIN_H__
#define __GSD_IDENTITY_PLUGIN_H__
#include <glib.h>
#include <glib-object.h>
#include <gmodule.h>
#include "gnome-settings-plugin.h"
G_BEGIN_DECLS
#define GSD_TYPE_IDENTITY_PLUGIN (gsd_identity_plugin_get_type ())
#define GSD_IDENTITY_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_IDENTITY_PLUGIN, GsdIdentityPlugin))
#define GSD_IDENTITY_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSD_TYPE_IDENTITY_PLUGIN, GsdIdentityPluginClass))
#define GSD_IS_IDENTITY_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_IDENTITY_PLUGIN))
#define GSD_IS_IDENTITY_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_IDENTITY_PLUGIN))
#define GSD_IDENTITY_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_IDENTITY_PLUGIN, GsdIdentityPluginClass))
typedef struct GsdIdentityPluginPrivate GsdIdentityPluginPrivate;
typedef struct
{
GnomeSettingsPlugin parent;
GsdIdentityPluginPrivate *priv;
} GsdIdentityPlugin;
typedef struct
{
GnomeSettingsPluginClass parent_class;
} GsdIdentityPluginClass;
GType gsd_identity_plugin_get_type (void) G_GNUC_CONST;
/* All the plugins must implement this function */
G_MODULE_EXPORT GType register_gnome_settings_plugin (GTypeModule *module);
G_END_DECLS
#endif /* __GSD_IDENTITY_PLUGIN_H__ */

View File

@@ -0,0 +1,57 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include <glib-object.h>
#include <glib/gi18n.h>
#include "gsd-identity.h"
G_DEFINE_INTERFACE (GsdIdentity, gsd_identity, G_TYPE_OBJECT);
static void
gsd_identity_default_init (GsdIdentityInterface *interface)
{
}
GQuark
gsd_identity_error_quark (void)
{
static GQuark error_quark = 0;
if (error_quark == 0) {
error_quark = g_quark_from_static_string ("gsd-identity-error");
}
return error_quark;
}
const char *
gsd_identity_get_identifier (GsdIdentity *self)
{
return GSD_IDENTITY_GET_IFACE (self)->get_identifier (self);
}
gboolean
gsd_identity_is_signed_in (GsdIdentity *self)
{
return GSD_IDENTITY_GET_IFACE (self)->is_signed_in (self);
}

View File

@@ -0,0 +1,66 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Ray Strode <rstrode@redhat.com>
*/
#ifndef __GSD_IDENTITY_H__
#define __GSD_IDENTITY_H__
#include <glib.h>
#include <glib-object.h>
G_BEGIN_DECLS
#define GSD_TYPE_IDENTITY (gsd_identity_get_type ())
#define GSD_IDENTITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_IDENTITY, GsdIdentity))
#define GSD_IDENTITY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_IDENTITY, GsdIdentityInterface))
#define GSD_IS_IDENTITY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_IDENTITY))
#define GSD_IDENTITY_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), GSD_TYPE_IDENTITY, GsdIdentityInterface))
#define GSD_IDENTITY_ERROR (gsd_identity_error_quark ())
typedef struct _GsdIdentity GsdIdentity;
typedef struct _GsdIdentityInterface GsdIdentityInterface;
typedef enum _GsdIdentityError GsdIdentityError;
struct _GsdIdentityInterface
{
GTypeInterface base_interface;
const char * (* get_identifier) (GsdIdentity *identity);
gboolean (* is_signed_in) (GsdIdentity *identity);
};
enum _GsdIdentityError
{
GSD_IDENTITY_ERROR_VERIFYING,
GSD_IDENTITY_ERROR_SIGNING_IN,
GSD_IDENTITY_ERROR_RENEWING,
GSD_IDENTITY_ERROR_ERASING
};
GType gsd_identity_get_type (void);
GQuark gsd_identity_error_quark (void);
const char *gsd_identity_get_identifier (GsdIdentity *identity);
gboolean gsd_identity_is_signed_in (GsdIdentity *identity);
G_END_DECLS
#endif /* __GSD_IDENTITY_H__ */

View File

@@ -0,0 +1,363 @@
/* -*- Mode: C; tab-width: 8; ident-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Ray Strode
*/
#include "config.h"
#include "gsd-kerberos-identity-inquiry.h"
#include "gsd-identity-inquiry-private.h"
#include <string.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
struct _GsdKerberosIdentityInquiryPrivate
{
GsdIdentity *identity;
char *name;
char *banner;
GList *queries;
int number_of_queries;
int number_of_unanswered_queries;
};
typedef struct
{
GsdIdentityInquiry *inquiry;
krb5_prompt *kerberos_prompt;
gboolean is_answered;
} GsdKerberosIdentityQuery;
static void identity_inquiry_interface_init (GsdIdentityInquiryInterface *interface);
static void initable_interface_init (GInitableIface *interface);
G_DEFINE_TYPE_WITH_CODE (GsdKerberosIdentityInquiry,
gsd_kerberos_identity_inquiry,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_interface_init)
G_IMPLEMENT_INTERFACE (GSD_TYPE_IDENTITY_INQUIRY,
identity_inquiry_interface_init));
static gboolean
gsd_kerberos_identity_inquiry_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
return FALSE;
}
return TRUE;
}
static void
initable_interface_init (GInitableIface *interface)
{
interface->init = gsd_kerberos_identity_inquiry_initable_init;
}
static GsdKerberosIdentityQuery *
gsd_kerberos_identity_query_new (GsdIdentityInquiry *inquiry,
krb5_prompt *kerberos_prompt)
{
GsdKerberosIdentityQuery *query;
query = g_slice_new (GsdKerberosIdentityQuery);
query->inquiry = inquiry;
query->kerberos_prompt = kerberos_prompt;
query->is_answered = FALSE;
return query;
}
static void
gsd_kerberos_identity_query_free (GsdKerberosIdentityQuery *query)
{
g_slice_free (GsdKerberosIdentityQuery, query);
}
static void
gsd_kerberos_identity_inquiry_dispose (GObject *object)
{
GsdKerberosIdentityInquiry *self = GSD_KERBEROS_IDENTITY_INQUIRY (object);
g_clear_object (&self->priv->identity);
g_clear_pointer (&self->priv->name, (GDestroyNotify) g_free);
g_clear_pointer (&self->priv->banner, (GDestroyNotify) g_free);
g_list_foreach (self->priv->queries,
(GFunc)
gsd_kerberos_identity_query_free,
NULL);
g_clear_pointer (&self->priv->queries, (GDestroyNotify) g_list_free);
}
static void
gsd_kerberos_identity_inquiry_finalize (GObject *object)
{
G_OBJECT_CLASS (gsd_kerberos_identity_inquiry_parent_class)->finalize (object);
}
static void
gsd_kerberos_identity_inquiry_class_init (GsdKerberosIdentityInquiryClass *klass)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gsd_kerberos_identity_inquiry_dispose;
object_class->finalize = gsd_kerberos_identity_inquiry_finalize;
g_type_class_add_private (klass, sizeof (GsdKerberosIdentityInquiryPrivate));
}
static void
gsd_kerberos_identity_inquiry_init (GsdKerberosIdentityInquiry *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GSD_TYPE_KERBEROS_IDENTITY_INQUIRY,
GsdKerberosIdentityInquiryPrivate);
}
GsdIdentityInquiry *
gsd_kerberos_identity_inquiry_new (GsdKerberosIdentity *identity,
const char *name,
const char *banner,
krb5_prompt prompts[],
int number_of_prompts)
{
GObject *object;
GsdIdentityInquiry *inquiry;
GsdKerberosIdentityInquiry *self;
GError *error;
int i;
g_return_val_if_fail (GSD_IS_KERBEROS_IDENTITY (identity), NULL);
g_return_val_if_fail (number_of_prompts > 0, NULL);
object = g_object_new (GSD_TYPE_KERBEROS_IDENTITY_INQUIRY, NULL);
inquiry = GSD_IDENTITY_INQUIRY (object);
self = GSD_KERBEROS_IDENTITY_INQUIRY (object);
/* FIXME: make these construct properties */
self->priv->identity = g_object_ref (identity);
self->priv->name = g_strdup (name);
self->priv->banner = g_strdup (banner);
self->priv->number_of_queries = 0;
for (i = 0; i < number_of_prompts; i++) {
GsdKerberosIdentityQuery *query;
query = gsd_kerberos_identity_query_new (inquiry, &prompts[i]);
self->priv->queries = g_list_prepend (self->priv->queries, query);
self->priv->number_of_queries++;
}
self->priv->queries = g_list_reverse (self->priv->queries);
self->priv->number_of_unanswered_queries = self->priv->number_of_queries;
error = NULL;
if (!g_initable_init (G_INITABLE (self), NULL, &error)) {
g_debug ("%s", error->message);
g_error_free (error);
g_object_unref (self);
return NULL;
}
return inquiry;
}
static GsdIdentity *
gsd_kerberos_identity_inquiry_get_identity (GsdIdentityInquiry *inquiry)
{
GsdKerberosIdentityInquiry *self;
g_return_val_if_fail (GSD_IS_KERBEROS_IDENTITY_INQUIRY (inquiry), NULL);
self = GSD_KERBEROS_IDENTITY_INQUIRY (inquiry);
return self->priv->identity;
}
static char *
gsd_kerberos_identity_inquiry_get_name (GsdIdentityInquiry *inquiry)
{
GsdKerberosIdentityInquiry *self;
g_return_val_if_fail (GSD_IS_KERBEROS_IDENTITY_INQUIRY (inquiry), NULL);
self = GSD_KERBEROS_IDENTITY_INQUIRY (inquiry);
return g_strdup (self->priv->name);
}
static char *
gsd_kerberos_identity_inquiry_get_banner (GsdIdentityInquiry *inquiry)
{
GsdKerberosIdentityInquiry *self;
g_return_val_if_fail (GSD_IS_KERBEROS_IDENTITY_INQUIRY (inquiry), NULL);
self = GSD_KERBEROS_IDENTITY_INQUIRY (inquiry);
return g_strdup (self->priv->banner);
}
static gboolean
gsd_kerberos_identity_inquiry_is_complete (GsdIdentityInquiry *inquiry)
{
GsdKerberosIdentityInquiry *self;
g_return_val_if_fail (GSD_IS_KERBEROS_IDENTITY_INQUIRY (inquiry), FALSE);
self = GSD_KERBEROS_IDENTITY_INQUIRY (inquiry);
return self->priv->number_of_unanswered_queries == 0;
}
static void
gsd_kerberos_identity_inquiry_mark_query_answered (GsdKerberosIdentityInquiry *self,
GsdKerberosIdentityQuery *query)
{
if (query->is_answered) {
return;
}
query->is_answered = TRUE;
self->priv->number_of_unanswered_queries--;
if (self->priv->number_of_unanswered_queries == 0) {
_gsd_identity_inquiry_emit_complete (GSD_IDENTITY_INQUIRY (self));
}
}
static void
gsd_kerberos_identity_inquiry_answer_query (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query,
const char *answer)
{
GsdKerberosIdentityInquiry *self;
GsdKerberosIdentityQuery *kerberos_query = (GsdKerberosIdentityQuery *) query;
g_return_if_fail (GSD_IS_KERBEROS_IDENTITY_INQUIRY (inquiry));
g_return_if_fail (inquiry == kerberos_query->inquiry);
g_return_if_fail (!gsd_kerberos_identity_inquiry_is_complete (inquiry));
self = GSD_KERBEROS_IDENTITY_INQUIRY (inquiry);
inquiry = kerberos_query->inquiry;
strncpy (kerberos_query->kerberos_prompt->reply->data,
answer,
kerberos_query->kerberos_prompt->reply->length);
kerberos_query->kerberos_prompt->reply->length = (unsigned int) strlen (kerberos_query->kerberos_prompt->reply->data);
gsd_kerberos_identity_inquiry_mark_query_answered (self, kerberos_query);
}
static void
gsd_kerberos_identity_inquiry_iter_init (GsdIdentityInquiryIter *iter,
GsdIdentityInquiry *inquiry)
{
GsdKerberosIdentityInquiry *self = GSD_KERBEROS_IDENTITY_INQUIRY (inquiry);
iter->data = self->priv->queries;
}
static GsdIdentityQuery *
gsd_kerberos_identity_inquiry_iter_next (GsdIdentityInquiryIter *iter,
GsdIdentityInquiry *inquiry)
{
GsdIdentityQuery *query;
GList *node;
node = iter->data;
if (node == NULL) {
return NULL;
}
query = (GsdIdentityQuery *) node->data;
node = node->next;
iter->data = node;
return query;
}
static GsdIdentityQueryMode
gsd_kerberos_identity_query_get_mode (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query)
{
GsdKerberosIdentityQuery *kerberos_query = (GsdKerberosIdentityQuery *) query;
g_return_val_if_fail (GSD_IS_KERBEROS_IDENTITY_INQUIRY (inquiry), GSD_KERBEROS_IDENTITY_QUERY_MODE_INVISIBLE);
g_return_val_if_fail (inquiry == kerberos_query->inquiry, GSD_KERBEROS_IDENTITY_QUERY_MODE_INVISIBLE);
if (kerberos_query->kerberos_prompt->hidden) {
return GSD_KERBEROS_IDENTITY_QUERY_MODE_INVISIBLE;
} else {
return GSD_KERBEROS_IDENTITY_QUERY_MODE_VISIBLE;
}
}
static char *
gsd_kerberos_identity_query_get_prompt (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query)
{
GsdKerberosIdentityQuery *kerberos_query = (GsdKerberosIdentityQuery *) query;
g_return_val_if_fail (GSD_IS_KERBEROS_IDENTITY_INQUIRY (inquiry), GSD_KERBEROS_IDENTITY_QUERY_MODE_INVISIBLE);
g_return_val_if_fail (inquiry == kerberos_query->inquiry, NULL);
return g_strdup (kerberos_query->kerberos_prompt->prompt);
}
static gboolean
gsd_kerberos_identity_query_is_answered (GsdIdentityInquiry *inquiry,
GsdIdentityQuery *query)
{
GsdKerberosIdentityQuery *kerberos_query = (GsdKerberosIdentityQuery *) query;
g_return_val_if_fail (GSD_IS_KERBEROS_IDENTITY_INQUIRY (inquiry), GSD_KERBEROS_IDENTITY_QUERY_MODE_INVISIBLE);
g_return_val_if_fail (inquiry == kerberos_query->inquiry, FALSE);
return kerberos_query->is_answered;
}
static void
identity_inquiry_interface_init (GsdIdentityInquiryInterface *interface)
{
interface->get_identity = gsd_kerberos_identity_inquiry_get_identity;
interface->get_name = gsd_kerberos_identity_inquiry_get_name;
interface->get_banner = gsd_kerberos_identity_inquiry_get_banner;
interface->is_complete = gsd_kerberos_identity_inquiry_is_complete;
interface->answer_query = gsd_kerberos_identity_inquiry_answer_query;
interface->iter_init = gsd_kerberos_identity_inquiry_iter_init;
interface->iter_next = gsd_kerberos_identity_inquiry_iter_next;
interface->get_mode = gsd_kerberos_identity_query_get_mode;
interface->get_prompt = gsd_kerberos_identity_query_get_prompt;
interface->is_answered = gsd_kerberos_identity_query_is_answered;
}

View File

@@ -0,0 +1,74 @@
/* -*- Mode: C; tab-width: 8; ident-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Ray Strode
*/
#ifndef __GSD_KERBEROS_IDENTITY_INQUIRY_H__
#define __GSD_KERBEROS_IDENTITY_INQUIRY_H__
#include <stdint.h>
#include <glib.h>
#include <glib-object.h>
#include "gsd-identity-inquiry.h"
#include "gsd-kerberos-identity.h"
G_BEGIN_DECLS
#define GSD_TYPE_KERBEROS_IDENTITY_INQUIRY (gsd_kerberos_identity_inquiry_get_type ())
#define GSD_KERBEROS_IDENTITY_INQUIRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_KERBEROS_IDENTITY_INQUIRY, GsdKerberosIdentityInquiry))
#define GSD_KERBEROS_IDENTITY_INQUIRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_KERBEROS_IDENTITY_INQUIRY, GsdKerberosIdentityInquiryClass))
#define GSD_IS_KERBEROS_IDENTITY_INQUIRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_KERBEROS_IDENTITY_INQUIRY))
#define GSD_IS_KERBEROS_IDENTITY_INQUIRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_KERBEROS_IDENTITY_INQUIRY))
#define GSD_KERBEROS_IDENTITY_INQUIRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSD_TYPE_KERBEROS_IDENTITY_INQUIRY, GsdKerberosIdentityInquiryClass))
typedef struct _GsdKerberosIdentity GsdKerberosIdentity;
typedef struct _GsdKerberosIdentityInquiry GsdKerberosIdentityInquiry;
typedef struct _GsdKerberosIdentityInquiryClass GsdKerberosIdentityInquiryClass;
typedef struct _GsdKerberosIdentityInquiryPrivate GsdKerberosIdentityInquiryPrivate;
typedef struct _GsdKerberosIdentityInquiryIter GsdKerberosIdentityInquiryIter;
typedef enum
{
GSD_KERBEROS_IDENTITY_QUERY_MODE_INVISIBLE,
GSD_KERBEROS_IDENTITY_QUERY_MODE_VISIBLE
} GsdKerberosIdentityQueryMode;
struct _GsdKerberosIdentityInquiry
{
GObject parent;
GsdKerberosIdentityInquiryPrivate *priv;
};
struct _GsdKerberosIdentityInquiryClass
{
GObjectClass parent_class;
};
GType gsd_kerberos_identity_inquiry_get_type (void);
GsdIdentityInquiry *gsd_kerberos_identity_inquiry_new (GsdKerberosIdentity *identity,
const char *name,
const char *banner,
krb5_prompt prompts[],
int number_of_prompts);
#endif /* __GSD_KERBEROS_IDENTITY_INQUIRY_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Ray Strode
*/
#ifndef __GSD_KERBEROS_IDENTITY_MANAGER_H__
#define __GSD_KERBEROS_IDENTITY_MANAGER_H__
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include "gsd-identity-manager.h"
G_BEGIN_DECLS
#define GSD_TYPE_KERBEROS_IDENTITY_MANAGER (gsd_kerberos_identity_manager_get_type ())
#define GSD_KERBEROS_IDENTITY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GSD_TYPE_KERBEROS_IDENTITY_MANAGER, GsdKerberosIdentityManager))
#define GSD_KERBEROS_IDENTITY_MANAGER_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GSD_TYPE_KERBEROS_IDENTITY_MANAGER, GsdKerberosIdentityManagerClass))
#define GSD_IS_KERBEROS_IDENTITY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GSD_TYPE_KERBEROS_IDENTITY_MANAGER))
#define GSD_IS_KERBEROS_IDENTITY_MANAGER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GSD_TYPE_KERBEROS_IDENTITY_MANAGER))
#define GSD_KERBEROS_IDENTITY_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_KERBEROS_IDENTITY_MANAGER, GsdKerberosIdentityManagerClass))
typedef struct _GsdKerberosIdentityManager GsdKerberosIdentityManager;
typedef struct _GsdKerberosIdentityManagerClass GsdKerberosIdentityManagerClass;
typedef struct _GsdKerberosIdentityManagerPrivate GsdKerberosIdentityManagerPrivate; struct _GsdKerberosIdentityManager
{
GObject parent_instance;
GsdKerberosIdentityManagerPrivate *priv;
};
struct _GsdKerberosIdentityManagerClass
{
GObjectClass parent_class;
};
GType gsd_kerberos_identity_manager_get_type (void);
GsdIdentityManager* gsd_kerberos_identity_manager_new (void);
void gsd_kerberos_identity_manager_start_test (GsdKerberosIdentityManager *manager,
GError **error);
G_END_DECLS
#endif /* __GSD_KERBEROS_IDENTITY_MANAGER_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Red Hat, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Ray Strode
*/
#ifndef __GSD_KERBEROS_IDENTITY_H__
#define __GSD_KERBEROS_IDENTITY_H__
#include <glib.h>
#include <glib-object.h>
#include <krb5.h>
#include "gsd-kerberos-identity-inquiry.h"
G_BEGIN_DECLS
#define GSD_TYPE_KERBEROS_IDENTITY (gsd_kerberos_identity_get_type ())
#define GSD_KERBEROS_IDENTITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_KERBEROS_IDENTITY, GsdKerberosIdentity))
#define GSD_KERBEROS_IDENTITY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_KERBEROS_IDENTITY, GsdKerberosIdentityClass))
#define GSD_IS_KERBEROS_IDENTITY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_KERBEROS_IDENTITY))
#define GSD_IS_KERBEROS_IDENTITY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_KERBEROS_IDENTITY))
#define GSD_KERBEROS_IDENTITY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSD_TYPE_KERBEROS_IDENTITY, GsdKerberosIdentityClass))
typedef struct _GsdKerberosIdentity GsdKerberosIdentity;
typedef struct _GsdKerberosIdentityClass GsdKerberosIdentityClass;
typedef struct _GsdKerberosIdentityPrivate GsdKerberosIdentityPrivate;
typedef enum _GsdKerberosIdentityDescriptionLevel GsdKerberosIdentityDescriptionLevel;
enum _GsdKerberosIdentityDescriptionLevel
{
GSD_KERBEROS_IDENTITY_DESCRIPTION_REALM,
GSD_KERBEROS_IDENTITY_DESCRIPTION_USERNAME_AND_REALM,
GSD_KERBEROS_IDENTITY_DESCRIPTION_USERNAME_ROLE_AND_REALM
};
struct _GsdKerberosIdentity
{
GObject parent;
GsdKerberosIdentityPrivate *priv;
};
struct _GsdKerberosIdentityClass
{
GObjectClass parent_class;
};
GType gsd_kerberos_identity_get_type (void);
GsdIdentity *gsd_kerberos_identity_new (krb5_context kerberos_context,
krb5_ccache cache);
gboolean gsd_kerberos_identity_sign_in (GsdKerberosIdentity *self,
const char *principal_name,
GsdIdentityInquiryFunc inquiry_func,
gpointer inquiry_data,
GDestroyNotify destroy_notify,
GCancellable *cancellable,
GError **error);
void gsd_kerberos_identity_update (GsdKerberosIdentity *identity,
GsdKerberosIdentity *new_identity);
gboolean gsd_kerberos_identity_renew (GsdKerberosIdentity *self,
GError **error);
gboolean gsd_kerberos_identity_erase (GsdKerberosIdentity *self,
GError **error);
char *gsd_kerberos_identity_get_principal_name (GsdKerberosIdentity *self);
char *gsd_kerberos_identity_get_realm_name (GsdKerberosIdentity *self);
G_END_DECLS
#endif /* __GSD_KERBEROS_IDENTITY_H__ */

View File

@@ -421,7 +421,7 @@ enterprise_permit_user_login (UmAccountDialog *self)
remove[0] = NULL;
um_realm_kerberos_call_change_permitted_logins (self->selected_realm,
add, remove,
add, remove, "",
self->cancellable,
on_permit_user_login,
g_object_ref (self));
@@ -544,6 +544,11 @@ on_realm_joined (GObject *source,
um_realm_join_finish (self->selected_realm,
result, &error);
/* If we're already enrolled treat that as a success */
if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_ALREADY_ENROLLED)) {
g_clear_error (&error);
}
/* Yay, joined the domain, register the user locally */
if (error == NULL) {
enterprise_permit_user_login (self);

View File

@@ -282,14 +282,47 @@ on_realm_diagnostics (GDBusConnection *connection,
gpointer user_data)
{
const gchar *message;
const gchar *unused;
if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(s)"))) {
if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(ss)"))) {
/* Data is already formatted appropriately for stderr */
g_variant_get (parameters, "(&s)", &message);
g_variant_get (parameters, "(&s&s)", &message, &unused);
g_printerr ("%s", message);
}
}
static gboolean
number_at_least (const gchar *number,
guint minimum)
{
gchar *end;
if (strtol (number, &end, 10) < (long)minimum)
return FALSE;
if (!end || *end != '\0')
return FALSE;
return TRUE;
}
static gboolean
version_compare (const char *version,
guint req_major,
guint req_minor)
{
gboolean match = FALSE;
gchar **parts;
parts = g_strsplit (version, ".", 2);
if (parts[0] && parts[1]) {
match = number_at_least (parts[0], req_major) &&
number_at_least (parts[1], req_minor);
}
g_strfreev (parts);
return match;
}
static void
on_realm_manager_async_init (GObject *source,
GAsyncResult *result,
@@ -298,6 +331,7 @@ on_realm_manager_async_init (GObject *source,
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
UmRealmManager *self;
GError *error = NULL;
const gchar *version;
GDBusProxy *proxy;
GObject *object;
guint sig;
@@ -306,6 +340,20 @@ on_realm_manager_async_init (GObject *source,
if (error != NULL)
g_simple_async_result_take_error (async, error);
/* This is temporary until the dbus interface stabilizes */
if (object) {
version = um_realm_provider_get_version (UM_REALM_PROVIDER (object));
if (!version_compare (version, 0, 2)) {
/* No need to bother translators with this temporary message */
g_simple_async_result_set_error (async, UM_REALM_ERROR,
UM_REALM_ERROR_GENERIC,
"Unsupported version of realmd: %s", version);
g_object_unref (object);
object = NULL;
}
}
if (object != NULL) {
proxy = G_DBUS_PROXY (object);
sig = g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (proxy),
@@ -450,7 +498,7 @@ um_realm_manager_discover (UmRealmManager *self,
discover->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
g_simple_async_result_set_op_res_gpointer (res, discover, discover_closure_free);
um_realm_provider_call_discover (UM_REALM_PROVIDER (self), input, cancellable,
um_realm_provider_call_discover (UM_REALM_PROVIDER (self), input, "", cancellable,
on_provider_discover, g_object_ref (res));
g_object_unref (res);
@@ -516,6 +564,7 @@ um_realm_join (UmRealmKerberos *realm,
um_realm_kerberos_call_enroll_with_credential_cache (realm,
g_variant_ref_sink (creds),
g_variant_ref_sink (options),
"",
cancellable,
callback,
user_data);
@@ -553,6 +602,10 @@ um_realm_join_finish (UmRealmKerberos *self,
g_set_error (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN,
call_error->message);
g_error_free (call_error);
} else if (g_str_equal (dbus_error, "org.freedesktop.realmd.Error.AlreadyEnrolled")) {
g_set_error (error, UM_REALM_ERROR, UM_REALM_ERROR_ALREADY_ENROLLED,
call_error->message);
g_error_free (call_error);
} else {
g_propagate_error (error, call_error);
}

View File

@@ -29,6 +29,7 @@ G_BEGIN_DECLS
typedef enum {
UM_REALM_ERROR_BAD_LOGIN,
UM_REALM_ERROR_BAD_PASSWORD,
UM_REALM_ERROR_ALREADY_ENROLLED,
UM_REALM_ERROR_GENERIC,
} UmRealmErrors;

View File

@@ -41,8 +41,14 @@
#include "um-user.h"
#include "um-user-manager.h"
#include "gsd-identity-manager.h"
#ifdef HAVE_KERBEROS
#include "gsd-kerberos-identity-manager.h"
#endif
#include "cc-strength-bar.h"
#include "um-editable-button.h"
#include "um-editable-combo.h"
@@ -57,9 +63,20 @@
G_DEFINE_DYNAMIC_TYPE (UmUserPanel, um_user_panel, CC_TYPE_PANEL)
#define OTHER_PASSWORDS_PROGRAM "seahorse"
#define UM_USER_PANEL_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), UM_TYPE_USER_PANEL, UmUserPanelPrivate))
typedef struct {
UmUserPanelPrivate *d;
char *identifier;
GsdIdentity *identity;
GtkWidget *box;
GtkWidget *label;
GtkWidget *button;
} Realm;
struct _UmUserPanelPrivate {
UmUserManager *um;
GtkBuilder *builder;
@@ -68,6 +85,8 @@ struct _UmUserPanelPrivate {
GPermission *permission;
GtkWidget *language_chooser;
GHashTable *accessible_realms;
GsdIdentityManager *identity_manager;
UmAccountDialog *account_dialog;
UmPasswordDialog *password_dialog;
UmPhotoDialog *photo_dialog;
@@ -397,12 +416,8 @@ delete_user_response (GtkWidget *dialog,
user = get_selected_user (d);
um_user_manager_delete_user (d->um,
user,
remove_files,
(GAsyncReadyCallback)delete_user_done,
d,
NULL);
um_user_manager_delete_user (d->um, user, remove_files,
(GAsyncReadyCallback) delete_user_done, d, NULL);
g_object_unref (user);
}
@@ -555,6 +570,87 @@ autologin_changed (GObject *object,
g_object_unref (user);
}
#ifdef HAVE_KERBEROS
static void
get_position_of_accessible_realms_label (UmUserPanelPrivate *d,
int *left_position,
int *top_position)
{
GtkWidget *grid, *label;
grid = get_widget (d, "user-grid");
label = get_widget (d, "accessible-realms-label");
gtk_container_child_get (GTK_CONTAINER (grid),
label,
"left-attach", left_position,
"top-attach", top_position,
NULL);
}
static void
get_position_of_next_realm_box (UmUserPanelPrivate *d,
int *left_position,
int *top_position)
{
GtkWidget *grid;
GHashTableIter iter;
gpointer key, value;
grid = get_widget (d, "user-grid");
get_position_of_accessible_realms_label (d, left_position, top_position);
*left_position += 1;
g_hash_table_iter_init (&iter, d->accessible_realms);
while (g_hash_table_iter_next (&iter, &key, &value)) {
int other_realm_top_position;
Realm *realm = value;
gtk_container_child_get (GTK_CONTAINER (grid),
realm->box,
"top-attach", &other_realm_top_position,
NULL);
*top_position = MAX (*top_position, other_realm_top_position + 1);
}
}
static void
update_accessible_realms_visiblity (UmUserPanelPrivate *d)
{
GtkWidget *label;
GHashTableIter iter;
gpointer key, value;
UmUser *user;
uid_t uid;
gboolean should_show;
label = get_widget (d, "accessible-realms-label");
user = get_selected_user (d);
uid = um_user_get_uid (user);
if (g_hash_table_size (d->accessible_realms) > 0 && uid == geteuid ()) {
should_show = TRUE;
} else {
should_show = FALSE;
}
gtk_widget_set_visible (label, should_show);
g_hash_table_iter_init (&iter, d->accessible_realms);
while (g_hash_table_iter_next (&iter, &key, &value)) {
Realm *realm = value;
gtk_widget_set_visible (realm->box, should_show);
}
}
#else /* HAVE_KERBEROS */
static void
update_accessible_realms_visiblity (UmUserPanelPrivate *d)
{
}
#endif /* HAVE_KERBEROS */
static void
show_user (UmUser *user, UmUserPanelPrivate *d)
{
@@ -617,9 +713,26 @@ show_user (UmUser *user, UmUserPanelPrivate *d)
gtk_widget_show (label);
gtk_widget_show (widget);
}
widget = get_widget (d, "other-passwords-button");
if (um_user_get_uid (user) != getuid()) {
gtk_widget_hide (widget);
} else {
char *other_passwords;
other_passwords = g_find_program_in_path (OTHER_PASSWORDS_PROGRAM);
if (other_passwords != NULL) {
gtk_widget_show (widget);
g_free (other_passwords);
} else {
gtk_widget_hide (widget);
}
}
update_accessible_realms_visiblity (d);
}
static void on_permission_changed (GPermission *permission, GParamSpec *pspec, gpointer data);
static void on_permission_changed (GPermission *permission, GParamSpec *pspec, UmUserPanelPrivate *d);
static void
selected_user_changed (GtkTreeSelection *selection, UmUserPanelPrivate *d)
@@ -673,6 +786,7 @@ account_type_changed (UmEditableCombo *combo,
if (account_type != um_user_get_account_type (user)) {
um_user_set_account_type (user, account_type);
on_permission_changed (d->permission, NULL, d);
}
g_object_unref (user);
@@ -774,6 +888,22 @@ change_password (GtkButton *button, UmUserPanelPrivate *d)
g_object_unref (user);
}
static void
edit_other_passwords (GtkButton *button, UmUserPanelPrivate *d)
{
GError *error;
error = NULL;
g_spawn_command_line_async (OTHER_PASSWORDS_PROGRAM, &error);
if (error != NULL) {
g_warning ("unable to launch " OTHER_PASSWORDS_PROGRAM ": %s",
error->message);
g_error_free (error);
}
}
static void
change_fingerprint (GtkButton *button, UmUserPanelPrivate *d)
{
@@ -912,14 +1042,69 @@ remove_unlock_tooltip (GtkWidget *button)
}
static void
on_permission_changed (GPermission *permission,
GParamSpec *pspec,
gpointer data)
hide_administrative_tasks (UmUserPanelPrivate *d)
{
GtkWidget *widget;
widget = get_widget (d, "userlist-vbox");
gtk_widget_hide (widget);
widget = get_widget (d, "account-type-label");
gtk_widget_hide (widget);
widget = get_widget (d, "account-type-combo");
gtk_widget_hide (widget);
widget = get_widget (d, "language-label");
gtk_widget_hide (widget);
widget = get_widget (d, "account-language-combo");
gtk_widget_hide (widget);
widget = get_widget (d, "autologin-label");
gtk_widget_hide (widget);
widget = get_widget (d, "autologin-switch");
gtk_widget_hide (widget);
}
static void
show_administrative_tasks (UmUserPanelPrivate *d)
{
GtkWidget *widget;
widget = get_widget (d, "userlist-vbox");
gtk_widget_show (widget);
widget = get_widget (d, "account-type-label");
gtk_widget_show (widget);
widget = get_widget (d, "account-type-combo");
gtk_widget_show (widget);
widget = get_widget (d, "language-label");
gtk_widget_show (widget);
widget = get_widget (d, "account-language-combo");
gtk_widget_show (widget);
widget = get_widget (d, "autologin-label");
gtk_widget_show (widget);
widget = get_widget (d, "autologin-switch");
gtk_widget_show (widget);
}
static void
on_permission_changed (GPermission *permission,
GParamSpec *pspec,
UmUserPanelPrivate *d)
{
UmUserPanelPrivate *d = data;
gboolean is_authorized;
gboolean self_selected;
UmUser *user;
UmUser *self_user;
UmAccountType self_account_type;
GtkWidget *widget;
user = get_selected_user (d);
@@ -930,6 +1115,9 @@ on_permission_changed (GPermission *permission,
is_authorized = g_permission_get_allowed (G_PERMISSION (d->permission));
self_selected = um_user_get_uid (user) == geteuid ();
self_user = um_user_manager_get_user_by_id (d->um, geteuid ());
self_account_type = um_user_get_account_type (self_user);
widget = get_widget (d, "add-user-toolbutton");
gtk_widget_set_sensitive (widget, is_authorized);
if (is_authorized) {
@@ -1015,6 +1203,12 @@ on_permission_changed (GPermission *permission,
gtk_notebook_set_current_page (GTK_NOTEBOOK (get_widget (d, "account-fingerprint-notebook")), 0);
}
if (is_authorized || self_account_type == UM_ACCOUNT_TYPE_ADMINISTRATOR) {
show_administrative_tasks (d);
} else {
hide_administrative_tasks (d);
}
um_password_dialog_set_privileged (d->password_dialog, is_authorized);
g_object_unref (user);
@@ -1213,6 +1407,9 @@ setup_main_window (UmUserPanelPrivate *d)
button = get_widget (d, "account-password-button");
g_signal_connect (button, "start-editing", G_CALLBACK (change_password), d);
button = get_widget (d, "other-passwords-button");
g_signal_connect (button, "clicked", G_CALLBACK (edit_other_passwords), d);
button = get_widget (d, "account-language-combo");
g_signal_connect (button, "editing-done", G_CALLBACK (language_changed), d);
@@ -1245,6 +1442,280 @@ setup_main_window (UmUserPanelPrivate *d)
g_object_unref (icon);
}
#ifdef HAVE_KERBEROS
static void
remove_accessible_realm_for_identity (UmUserPanelPrivate *d,
GsdIdentity *identity)
{
GtkWidget *grid;
Realm *realm;
GHashTableIter iter;
gpointer key, value;
int top_position;
realm = g_hash_table_lookup (d->accessible_realms,
(gpointer)
gsd_identity_get_identifier (identity));
if (realm == NULL) {
return;
}
grid = get_widget (d, "user-grid");
gtk_container_child_get (GTK_CONTAINER (grid),
realm->box,
"top-attach", &top_position,
NULL);
g_hash_table_remove (d->accessible_realms, realm->identifier);
g_hash_table_iter_init (&iter, d->accessible_realms);
while (g_hash_table_iter_next (&iter, &key, &value)) {
int other_realm_top_position;
realm = value;
gtk_container_child_get (GTK_CONTAINER (grid),
realm->box,
"top-attach", &other_realm_top_position,
NULL);
if (other_realm_top_position > top_position) {
other_realm_top_position--;
gtk_container_child_set (GTK_CONTAINER (grid),
realm->box,
"top-attach", other_realm_top_position,
NULL);
}
}
update_accessible_realms_visiblity (d);
}
static void
rename_accessible_realm_for_identity (UmUserPanelPrivate *d,
GsdIdentity *identity)
{
Realm *realm;
char *name;
realm = g_hash_table_lookup (d->accessible_realms,
(gpointer)
gsd_identity_get_identifier (identity));
if (realm == NULL) {
return;
}
name = gsd_identity_manager_name_identity (d->identity_manager,
identity);
gtk_label_set_text (GTK_LABEL (realm->label), name);
g_free (name);
}
static void
on_signed_out (GsdIdentityManager *manager,
GAsyncResult *result,
gpointer user_data)
{
GsdIdentity *identity = GSD_IDENTITY (user_data);
gsd_identity_manager_sign_identity_out_finish (manager,
result,
NULL);
g_object_unref (identity);
}
static void
on_sign_out_clicked (GtkButton *button,
Realm *realm)
{
UmUserPanelPrivate *d = realm->d;
gsd_identity_manager_sign_identity_out (d->identity_manager, realm->identity, NULL,
(GAsyncReadyCallback) on_signed_out,
g_object_ref (realm->identity));
}
static Realm *
realm_new (UmUserPanelPrivate *d,
GsdIdentity *identity)
{
Realm *realm;
char *name;
realm = g_slice_new (Realm);
realm->d = d;
realm->identifier = g_strdup (gsd_identity_get_identifier (identity));
realm->identity = identity;
realm->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
name = gsd_identity_manager_name_identity (d->identity_manager,
identity);
realm->label = gtk_label_new (name);
g_free (name);
gtk_container_add (GTK_CONTAINER (realm->box), realm->label);
realm->button = gtk_button_new_with_label (_("Sign Out"));
gtk_widget_set_halign (GTK_WIDGET (realm->button),
GTK_ALIGN_END);
gtk_widget_set_hexpand (GTK_WIDGET (realm->button),
TRUE);
g_signal_connect (G_OBJECT (realm->button),
"clicked",
G_CALLBACK (on_sign_out_clicked),
realm);
gtk_container_add (GTK_CONTAINER (realm->box), realm->button);
gtk_widget_show_all (realm->box);
return realm;
}
static void
realm_free (Realm *realm)
{
gtk_widget_destroy (realm->box);
g_free (realm->identifier);
g_slice_free (Realm, realm);
}
static void
add_accessible_realm_for_identity (UmUserPanelPrivate *d,
GsdIdentity *identity)
{
Realm *realm;
GtkWidget *grid;
int left_position, top_position;
remove_accessible_realm_for_identity (d, identity);
realm = realm_new (d, identity);
grid = get_widget (d, "user-grid");
get_position_of_next_realm_box (d, &left_position, &top_position);
g_hash_table_replace (d->accessible_realms,
realm->identifier,
realm);
gtk_grid_attach (GTK_GRID (grid),
realm->box,
left_position,
top_position,
1,
1);
update_accessible_realms_visiblity (d);
}
static void
on_identity_added (GsdIdentityManager *manager,
GsdIdentity *identity,
UmUserPanelPrivate *d)
{
add_accessible_realm_for_identity (d, identity);
}
static void
on_identity_refreshed (GsdIdentityManager *manager,
GsdIdentity *identity,
UmUserPanelPrivate *d)
{
add_accessible_realm_for_identity (d, identity);
}
static void
on_identity_removed (GsdIdentityManager *manager,
GsdIdentity *identity,
UmUserPanelPrivate *d)
{
remove_accessible_realm_for_identity (d, identity);
}
static void
on_identity_expired (GsdIdentityManager *manager,
GsdIdentity *identity,
UmUserPanelPrivate *d)
{
remove_accessible_realm_for_identity (d, identity);
}
static void
on_identity_renamed (GsdIdentityManager *manager,
GsdIdentity *identity,
UmUserPanelPrivate *d)
{
rename_accessible_realm_for_identity (d, identity);
}
static void
on_identities_listed (GsdIdentityManager *manager,
GAsyncResult *result,
UmUserPanelPrivate *d)
{
GError *error = NULL;
GList *identities, *node;
g_signal_connect (manager,
"identity-added",
G_CALLBACK (on_identity_added),
d);
g_signal_connect (manager,
"identity-removed",
G_CALLBACK (on_identity_removed),
d);
g_signal_connect (manager,
"identity-expired",
G_CALLBACK (on_identity_expired),
d);
g_signal_connect (manager,
"identity-refreshed",
G_CALLBACK (on_identity_refreshed),
d);
g_signal_connect (manager,
"identity-renamed",
G_CALLBACK (on_identity_renamed),
d);
identities = gsd_identity_manager_list_identities_finish (manager,
result,
&error);
if (identities == NULL) {
if (error != NULL) {
g_warning ("UmUserPanel: Could not list identities: %s",
error->message);
g_error_free (error);
}
return;
}
for (node = identities; node != NULL; node = node->next) {
GsdIdentity *identity = node->data;
if (gsd_identity_is_signed_in (identity))
add_accessible_realm_for_identity (d, identity);
}
}
#endif /* HAVE_KERBEROS */
static void
setup_realms (UmUserPanelPrivate *d)
{
#ifdef HAVE_KERBEROS
d->accessible_realms = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify) realm_free);
d->identity_manager = gsd_kerberos_identity_manager_new ();
gsd_identity_manager_list_identities (d->identity_manager, NULL,
(GAsyncReadyCallback) on_identities_listed, d);
#endif
}
static void
um_user_panel_init (UmUserPanel *self)
{
@@ -1278,7 +1749,7 @@ um_user_panel_init (UmUserPanel *self)
g_error_free (error);
return;
}
setup_realms (d);
setup_main_window (d);
d->account_dialog = um_account_dialog_new ();
d->password_dialog = um_password_dialog_new ();
@@ -1326,6 +1797,17 @@ um_user_panel_dispose (GObject *object)
g_object_unref (priv->permission);
priv->permission = NULL;
}
if (priv->accessible_realms) {
g_hash_table_unref (priv->accessible_realms);
priv->accessible_realms = NULL;
}
if (priv->identity_manager) {
g_object_unref (priv->identity_manager);
priv->identity_manager = NULL;
}
G_OBJECT_CLASS (um_user_panel_parent_class)->dispose (object);
}