aboutsummaryrefslogtreecommitdiff
path: root/src/krb5-auth-applet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/krb5-auth-applet.c')
-rw-r--r--src/krb5-auth-applet.c461
1 files changed, 390 insertions, 71 deletions
diff --git a/src/krb5-auth-applet.c b/src/krb5-auth-applet.c
index 99b4007..996d862 100644
--- a/src/krb5-auth-applet.c
+++ b/src/krb5-auth-applet.c
@@ -1,6 +1,6 @@
/* Krb5 Auth Applet -- Acquire and release kerberos tickets
*
- * (C) 2008 Guido Guenther <agx@sigxcpu.org>
+ * (C) 2008,2009 Guido Guenther <agx@sigxcpu.org>
*
* 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
@@ -24,7 +24,9 @@
#include "krb5-auth-applet.h"
#include "krb5-auth-dialog.h"
-#include "krb5-auth-notify.h"
+#ifdef HAVE_LIBNOTIFY
+#include <libnotify/notify.h>
+#endif
#define NOTIFY_SECONDS 300
@@ -34,10 +36,222 @@ enum ka_icon {
val_icon,
};
+enum
+{
+ KA_PROP_0 = 0,
+ KA_PROP_PRINCIPAL,
+ KA_PROP_PK_USERID,
+ KA_PROP_TRAYICON,
+ KA_PROP_PW_PROMPT_MINS,
+};
+
+struct _KaApplet {
+ GObject parent;
+
+ KaAppletPrivate *priv;
+};
+
+struct _KaAppletClass {
+ GObjectClass parent;
+};
+
+G_DEFINE_TYPE(KaApplet, ka_applet, G_TYPE_OBJECT);
+
+struct _KaAppletPrivate
+{
+ GtkStatusIcon* tray_icon; /* the tray icon */
+ GtkWidget* context_menu; /* the tray icon's context menu */
+ const char* icons[3]; /* for invalid, expiring and valid tickts */
+ gboolean show_trayicon; /* show the trayicon */
+
+ /* The password dialog */
+ GtkWidget* pw_dialog; /* the password dialog itself */
+ GladeXML* pw_xml; /* the dialog's glade xml */
+ GtkWidget* pw_label; /* the wrong password/timeout label */
+ int pw_prompt_secs; /* when to start prompting for a password */
+ gboolean pw_dialog_persist; /* don't hide the dialog when creds are still valid */
+
+#ifdef HAVE_LIBNOTIFY
+ NotifyNotification* notification;/* notification messages */
+#endif /* HAVE_LIBNOTIFY */
+ char* principal; /* the principal to request */
+ gboolean renewable; /* credentials renewable? */
+ char* pk_userid; /* "userid" for pkint */
+};
+
+static void
+ka_applet_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ KaApplet* self = KA_APPLET (object);
+
+ switch (property_id) {
+ case KA_PROP_PRINCIPAL:
+ g_free (self->priv->principal);
+ self->priv->principal = g_value_dup_string (value);
+ KA_DEBUG ("%s: %s", pspec->name, self->priv->principal);
+ break;
+
+ case KA_PROP_PK_USERID:
+ g_free (self->priv->pk_userid);
+ self->priv->pk_userid = g_value_dup_string (value);
+ KA_DEBUG ("%s: %s", pspec->name, self->priv->pk_userid);
+ break;
+
+ case KA_PROP_TRAYICON:
+ self->priv->show_trayicon = g_value_get_boolean (value);
+ KA_DEBUG ("%s: %s", pspec->name, self->priv->show_trayicon ? "True" : "False");
+ break;
+
+ case KA_PROP_PW_PROMPT_MINS:
+ self->priv->pw_prompt_secs = g_value_get_uint (value) * 60;
+ KA_DEBUG ("%s: %d", pspec->name, self->priv->pw_prompt_secs/60);
+ break;
+
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+ka_applet_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ KaApplet *self = KA_APPLET (object);
+
+ switch (property_id)
+ {
+ case KA_PROP_PRINCIPAL:
+ g_value_set_string (value, self->priv->principal);
+ break;
+
+ case KA_PROP_PK_USERID:
+ g_value_set_string (value, self->priv->pk_userid);
+ break;
+
+ case KA_PROP_TRAYICON:
+ g_value_set_boolean (value, self->priv->show_trayicon);
+ break;
+
+ case KA_PROP_PW_PROMPT_MINS:
+ g_value_set_uint (value, self->priv->pw_prompt_secs / 60);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+static void
+ka_applet_dispose(GObject* object)
+{
+ KaApplet* applet = KA_APPLET(object);
+ GObjectClass *parent_class = G_OBJECT_CLASS (ka_applet_parent_class);
+
+ if (applet->priv->tray_icon) {
+ g_object_unref(applet->priv->tray_icon);
+ applet->priv->tray_icon = NULL;
+ }
+ if (applet->priv->pw_xml) {
+ g_object_unref(applet->priv->pw_xml);
+ applet->priv->pw_xml = NULL;
+ }
+
+ if (parent_class->dispose != NULL)
+ parent_class->dispose (object);
+}
+
+
+static void
+ka_applet_finalize(GObject *object)
+{
+ KaApplet* applet = KA_APPLET(object);
+ GObjectClass *parent_class = G_OBJECT_CLASS (ka_applet_parent_class);
+
+ g_free (applet->priv->principal);
+ g_free (applet->priv->pk_userid);
+ /* no need to free applet->priv */
+
+ if (parent_class->finalize != NULL)
+ parent_class->finalize (object);
+}
+
+static void
+ka_applet_init(KaApplet *applet)
+{
+ applet->priv = G_TYPE_INSTANCE_GET_PRIVATE(applet,
+ KA_TYPE_APPLET,
+ KaAppletPrivate);
+}
+
+static void
+ka_applet_class_init(KaAppletClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+ GParamSpec *pspec;
+
+ object_class->dispose = ka_applet_dispose;
+ object_class->finalize = ka_applet_finalize;
+ g_type_class_add_private(klass, sizeof(KaAppletPrivate));
+
+ object_class->set_property = ka_applet_set_property;
+ object_class->get_property = ka_applet_get_property;
+
+ pspec = g_param_spec_string ("principal",
+ "Principal",
+ "Get/Set Kerberos Principal",
+ "",
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class,
+ KA_PROP_PRINCIPAL,
+ pspec);
+
+ pspec = g_param_spec_string ("pk-userid",
+ "PKinit Identifier",
+ "Get/Set Pkinit identifier",
+ "",
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class,
+ KA_PROP_PK_USERID,
+ pspec);
+
+ pspec = g_param_spec_boolean("show-trayicon",
+ "Show tray icon",
+ "Show/Hide the tray icon",
+ TRUE,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class,
+ KA_PROP_TRAYICON,
+ pspec);
+
+ pspec = g_param_spec_uint ("pw-prompt-mins",
+ "Password Prompting Interval",
+ "Password Prompting Interval in Minutes",
+ 0, G_MAXUINT, MINUTES_BEFORE_PROMPTING,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+ g_object_class_install_property (object_class,
+ KA_PROP_PW_PROMPT_MINS,
+ pspec);
+}
+
+
+KaApplet *ka_applet_new(void)
+{
+ return g_object_new (KA_TYPE_APPLET, NULL);
+}
+
/* determine the new tooltip text */
static char*
-ka_tooltip_text(Krb5AuthApplet* applet, int remaining)
+ka_applet_tooltip_text(KaApplet* applet, int remaining)
{
int hours, minutes;
gchar* tooltip_text;
@@ -62,32 +276,64 @@ ka_tooltip_text(Krb5AuthApplet* applet, int remaining)
/* determine the current icon */
static const char*
-ka_select_icon(Krb5AuthApplet* applet, int remaining)
+ka_applet_select_icon(KaApplet* applet, int remaining)
{
enum ka_icon tray_icon = inv_icon;
if (remaining > 0) {
- if (remaining < applet->pw_prompt_secs &&
- !applet->renewable)
+ if (remaining < applet->priv->pw_prompt_secs &&
+ !applet->priv->renewable)
tray_icon = exp_icon;
else
tray_icon = val_icon;
}
- return applet->icons[tray_icon];
+ return applet->priv->icons[tray_icon];
+}
+
+
+void
+ka_send_event_notification (KaApplet *applet __attribute__((__unused__)),
+ const char *summary __attribute__((__unused__)),
+ const char *message __attribute__((__unused__)),
+ const char *icon __attribute__((__unused__)))
+{
+#ifdef HAVE_LIBNOTIFY
+ const char *notify_icon;
+
+ g_return_if_fail (applet != NULL);
+ g_return_if_fail (summary != NULL);
+ g_return_if_fail (message != NULL);
+
+ if (!notify_is_initted ())
+ notify_init (PACKAGE);
+
+ if (applet->priv->notification != NULL) {
+ notify_notification_close (applet->priv->notification, NULL);
+ g_object_unref (applet->priv->notification);
+ }
+
+ notify_icon = icon ? icon : "gtk-dialog-authentication";
+
+ applet->priv->notification = \
+ notify_notification_new_with_status_icon(summary, message, notify_icon, applet->priv->tray_icon);
+
+ notify_notification_set_urgency (applet->priv->notification, NOTIFY_URGENCY_NORMAL);
+ notify_notification_show (applet->priv->notification, NULL);
+#endif /* HAVE_LIBNOTIFY */
}
/* update the tray icon's tooltip and icon */
int
-ka_update_status(Krb5AuthApplet* applet, krb5_timestamp expiry)
+ka_applet_update_status(KaApplet* applet, krb5_timestamp expiry)
{
int now = time(0);
int remaining = expiry - now;
static int last_warn = 0;
static gboolean expiry_notified = FALSE;
- const char* tray_icon = ka_select_icon (applet, remaining);
- char* tooltip_text = ka_tooltip_text (applet, remaining);
+ const char* tray_icon = ka_applet_select_icon (applet, remaining);
+ char* tooltip_text = ka_applet_tooltip_text (applet, remaining);
if (remaining > 0) {
if (expiry_notified) {
@@ -95,8 +341,8 @@ ka_update_status(Krb5AuthApplet* applet, krb5_timestamp expiry)
_("Network credentials valid"),
_("Your Kerberos credentials have been refreshed."), NULL);
expiry_notified = FALSE;
- } else if (remaining < applet->pw_prompt_secs && (now - last_warn) > NOTIFY_SECONDS &&
- !applet->renewable) {
+ } else if (remaining < applet->priv->pw_prompt_secs && (now - last_warn) > NOTIFY_SECONDS &&
+ !applet->priv->renewable) {
ka_send_event_notification (applet,
_("Network credentials expiring"),
tooltip_text, NULL);
@@ -112,54 +358,53 @@ ka_update_status(Krb5AuthApplet* applet, krb5_timestamp expiry)
}
}
- gtk_status_icon_set_from_icon_name (applet->tray_icon, tray_icon);
- gtk_status_icon_set_tooltip (applet->tray_icon, tooltip_text);
+ gtk_status_icon_set_from_icon_name (applet->priv->tray_icon, tray_icon);
+ gtk_status_icon_set_tooltip (applet->priv->tray_icon, tooltip_text);
g_free(tooltip_text);
return 0;
}
static void
-ka_menu_add_separator_item (GtkWidget* menu)
+ka_applet_menu_add_separator_item (GtkWidget* menu)
{
- GtkWidget* menu_item;
+ GtkWidget* menu_item;
- menu_item = gtk_separator_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
- gtk_widget_show (menu_item);
+ menu_item = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+ gtk_widget_show (menu_item);
}
/* Free all resources and quit */
static void
-ka_quit_applet (GtkMenuItem* menuitem, gpointer user_data)
+ka_applet_cb_quit (GtkMenuItem* menuitem, gpointer user_data)
{
- Krb5AuthApplet* applet = (Krb5AuthApplet*) user_data;
+ KaApplet* applet = KA_APPLET(user_data);
- g_free (applet->principal);
- g_free (applet);
+ g_object_unref (applet);
gtk_main_quit ();
}
static void
-ka_about_dialog (GtkMenuItem* menuitem, gpointer user_data)
+ka_applet_cb_about_dialog (GtkMenuItem* menuitem, gpointer user_data)
{
gchar* authors[] = { "Christopher Aillon <caillon@redhat.com>",
"Colin Walters <walters@verbum.org>",
- "Guido Günther <agx@sigxpcu.org>",
+ "Guido Günther <agx@sigxpcu.org>",
NULL };
gtk_show_about_dialog (NULL,
- "authors", authors,
- "version", VERSION,
- "copyright", "Copyright (C) 2004,2005,2006 Red Hat, Inc.,\n2008 Guido Günther",
- NULL);
+ "authors", authors,
+ "version", VERSION,
+ "copyright", "Copyright (C) 2004,2005,2006 Red Hat, Inc.,\n2008,2009 Guido Günther",
+ NULL);
}
/* The tray icon's context menu */
-static GtkWidget*
-ka_create_context_menu (Krb5AuthApplet* applet)
+static gboolean
+ka_applet_create_context_menu (KaApplet* applet)
{
GtkWidget* menu;
GtkWidget* menu_item;
@@ -170,43 +415,44 @@ ka_create_context_menu (Krb5AuthApplet* applet)
/* kdestroy */
menu_item = gtk_image_menu_item_new_with_mnemonic (_("Remove Credentials _Cache"));
g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (ka_destroy_cache), applet);
- image = gtk_image_new_from_stock (GTK_STOCK_CANCEL, GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image);
+ image = gtk_image_new_from_stock (GTK_STOCK_CANCEL, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
- ka_menu_add_separator_item (menu);
+ ka_applet_menu_add_separator_item (menu);
/* About item */
menu_item = gtk_image_menu_item_new_with_mnemonic (_("_About"));
- g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (ka_about_dialog), applet);
+ g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (ka_applet_cb_about_dialog), applet);
image = gtk_image_new_from_stock (GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
- ka_menu_add_separator_item (menu);
+ ka_applet_menu_add_separator_item (menu);
/* Quit */
menu_item = gtk_image_menu_item_new_with_mnemonic (_("_Quit"));
- g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (ka_quit_applet), applet);
- image = gtk_image_new_from_stock (GTK_STOCK_QUIT, GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image);
+ g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (ka_applet_cb_quit), applet);
+ image = gtk_image_new_from_stock (GTK_STOCK_QUIT, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
gtk_widget_show_all (menu);
+ applet->priv->context_menu = menu;
- return menu;
+ return TRUE;
}
static void
ka_tray_icon_on_menu (GtkStatusIcon* status_icon, guint button,
- guint activate_time, gpointer user_data)
+ guint activate_time, gpointer user_data)
{
- Krb5AuthApplet* applet = (Krb5AuthApplet*) user_data;
+ KaApplet *applet = KA_APPLET(user_data);
- KA_DEBUG("Trayicon right clicked: %d", applet->pw_prompt_secs);
- gtk_menu_popup (GTK_MENU (applet->context_menu), NULL, NULL,
- gtk_status_icon_position_menu, applet->tray_icon,
+ KA_DEBUG("Trayicon right clicked: %d", applet->priv->pw_prompt_secs);
+ gtk_menu_popup (GTK_MENU (applet->priv->context_menu), NULL, NULL,
+ gtk_status_icon_position_menu, applet->priv->tray_icon,
button, activate_time);
}
@@ -214,70 +460,143 @@ ka_tray_icon_on_menu (GtkStatusIcon* status_icon, guint button,
static gboolean
ka_tray_icon_on_click (GtkStatusIcon* status_icon, gpointer data)
{
- Krb5AuthApplet* applet = (Krb5AuthApplet*) data;
- g_return_val_if_fail (applet != NULL, FALSE);
+ KaApplet *applet = KA_APPLET(data);
- KA_DEBUG("Trayicon clicked: %d", applet->pw_prompt_secs);
+ KA_DEBUG("Trayicon clicked: %d", applet->priv->pw_prompt_secs);
ka_grab_credentials (applet);
return TRUE;
}
-gboolean
-ka_show_tray_icon (Krb5AuthApplet* applet)
+static gboolean
+ka_applet_cb_show_trayicon (KaApplet* applet, GParamSpec* property, gpointer data)
{
g_return_val_if_fail (applet != NULL, FALSE);
- g_return_val_if_fail (applet->tray_icon != NULL, FALSE);
+ g_return_val_if_fail (applet->priv->tray_icon != NULL, FALSE);
- gtk_status_icon_set_visible (applet->tray_icon, applet->show_trayicon);
+ gtk_status_icon_set_visible (applet->priv->tray_icon, applet->priv->show_trayicon);
return TRUE;
}
-static GtkStatusIcon*
-ka_create_tray_icon (Krb5AuthApplet* applet)
+static gboolean
+ka_applet_create_tray_icon (KaApplet* applet)
{
GtkStatusIcon* tray_icon;
tray_icon = gtk_status_icon_new ();
+
g_signal_connect (G_OBJECT(tray_icon), "activate",
- G_CALLBACK(ka_tray_icon_on_click), applet);
+ G_CALLBACK(ka_tray_icon_on_click), applet);
g_signal_connect (G_OBJECT(tray_icon),
"popup-menu",
G_CALLBACK(ka_tray_icon_on_menu), applet);
- gtk_status_icon_set_from_icon_name (tray_icon, applet->icons[exp_icon]);
- gtk_status_icon_set_tooltip (tray_icon, PACKAGE);
- return tray_icon;
+ gtk_status_icon_set_from_icon_name (tray_icon, applet->priv->icons[exp_icon]);
+ gtk_status_icon_set_tooltip (tray_icon, PACKAGE);
+ applet->priv->tray_icon = tray_icon;
+ return TRUE;
}
-int
-ka_setup_icons (Krb5AuthApplet* applet)
+static int
+ka_applet_setup_icons (KaApplet* applet)
{
/* Add application specific icons to search path */
gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
KA_DATA_DIR G_DIR_SEPARATOR_S "icons");
- applet->icons[val_icon] = "krb-valid-ticket";
- applet->icons[exp_icon] = "krb-expiring-ticket";
- applet->icons[inv_icon] = "krb-no-valid-ticket";
+ applet->priv->icons[val_icon] = "krb-valid-ticket";
+ applet->priv->icons[exp_icon] = "krb-expiring-ticket";
+ applet->priv->icons[inv_icon] = "krb-no-valid-ticket";
+ return TRUE;
+}
+
+
+static gboolean
+ka_applet_glade_init(KaApplet *applet)
+{
+ KaAppletPrivate *priv = applet->priv;
+
+ priv->pw_xml = glade_xml_new (KA_DATA_DIR G_DIR_SEPARATOR_S
+ PACKAGE ".glade", NULL, NULL);
+ priv->pw_label = glade_xml_get_widget (priv->pw_xml, "krb5_wrong_label");
+ priv->pw_dialog = glade_xml_get_widget (priv->pw_xml, "krb5_dialog");
+
return TRUE;
}
+GladeXML*
+ka_applet_get_pwdialog_xml(const KaApplet* applet)
+{
+ return applet->priv->pw_xml;
+}
+
+guint
+ka_applet_get_pw_prompt_secs(const KaApplet* applet)
+{
+ return applet->priv->pw_prompt_secs;
+}
+
+gboolean
+ka_applet_get_show_trayicon(const KaApplet* applet)
+{
+ return applet->priv->show_trayicon;
+}
+
+void
+ka_applet_set_tgt_renewable(KaApplet* applet, gboolean renewable)
+{
+ applet->priv->renewable = renewable;
+}
+
+gboolean
+ka_applet_get_tgt_renewable(const KaApplet* applet)
+{
+ return applet->priv->renewable;
+}
+
+gint ka_applet_run_pw_dialog(const KaApplet* applet)
+{
+ return gtk_dialog_run (GTK_DIALOG (applet->priv->pw_dialog));
+}
+
+void
+ka_applet_hide_pw_dialog(KaApplet* applet, gboolean force)
+{
+ KA_DEBUG("PW Dialog persist: %d", applet->priv->pw_dialog_persist);
+ if (!applet->priv->pw_dialog_persist || force)
+ gtk_widget_hide(applet->priv->pw_dialog);
+}
+
+void
+ka_applet_set_pw_dialog_persist(KaApplet* applet, gboolean persist)
+{
+ applet->priv->pw_dialog_persist = persist;
+}
+
+GtkWidget*
+ka_applet_get_pw_label(const KaApplet* applet)
+{
+ return applet->priv->pw_label;
+}
+
/* create the tray icon applet */
-Krb5AuthApplet*
-ka_create_applet()
+KaApplet*
+ka_applet_create()
{
- Krb5AuthApplet* applet = g_malloc0 (sizeof(Krb5AuthApplet));
+ KaApplet* applet = ka_applet_new();
+
+ ka_applet_glade_init(applet);
- if (!(ka_setup_icons (applet)))
+ if (!(ka_applet_setup_icons (applet)))
g_error ("Failure to setup icons");
- if (!(applet->tray_icon = ka_create_tray_icon (applet)))
+ if (!ka_applet_create_tray_icon (applet))
g_error ("Failure to create tray icon");
- if (!(applet->context_menu = ka_create_context_menu (applet)))
+ if (!ka_applet_create_context_menu (applet))
g_error ("Failure to create context menu");
- gtk_window_set_default_icon_name (applet->icons[val_icon]);
- ka_show_tray_icon (applet);
+ gtk_window_set_default_icon_name (applet->priv->icons[val_icon]);
+ g_signal_connect (applet, "notify::show-trayicon",
+ G_CALLBACK (ka_applet_cb_show_trayicon), NULL);
return applet;
}