aboutsummaryrefslogtreecommitdiff
path: root/src/krb5-auth-dialog.c
diff options
context:
space:
mode:
authorGuido Guenther <agx@sigxcpu.org>2008-06-08 17:29:02 +0200
committerGuido Guenther <agx@sigxcpu.org>2008-06-08 17:29:02 +0200
commit279a8cbf7ce72e92632266a32a36af9eba2bda78 (patch)
treebefc32d5d6b05b9c36b656406c935d765717e8d5 /src/krb5-auth-dialog.c
parentset a default icon (diff)
parentImported Upstream version 0.7.git30891fc (diff)
downloadkrb5-auth-dialog-279a8cbf7ce72e92632266a32a36af9eba2bda78.tar.gz
krb5-auth-dialog-279a8cbf7ce72e92632266a32a36af9eba2bda78.tar.bz2
krb5-auth-dialog-279a8cbf7ce72e92632266a32a36af9eba2bda78.zip
Merge branch 'upstream'
Diffstat (limited to 'src/krb5-auth-dialog.c')
-rw-r--r--src/krb5-auth-dialog.c650
1 files changed, 418 insertions, 232 deletions
diff --git a/src/krb5-auth-dialog.c b/src/krb5-auth-dialog.c
index 81f4f38..de5d9c9 100644
--- a/src/krb5-auth-dialog.c
+++ b/src/krb5-auth-dialog.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004,2005 Red Hat, Inc.
+ * Copyright (C) 2004,2005,2006 Red Hat, Inc.
* Authored by Christopher Aillon <caillon@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -20,43 +20,160 @@
#include "config.h"
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-#include <gnome.h>
#include <stdlib.h>
#include <time.h>
#include <krb5.h>
#include <stdio.h>
#include <sys/wait.h>
#include <string.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <glade/glade.h>
+
+#include "gtksecentry.h"
+#include "secmem-util.h"
+#include "memory.h"
+#include "krb5-auth-dialog.h"
+#include "krb5-auth-applet.h"
+#include "krb5-auth-gconf.h"
+#include "krb5-auth-dbus.h"
#ifdef ENABLE_NETWORK_MANAGER
#include <libnm_glib.h>
#endif
-static GladeXML *xml = NULL;
static krb5_context kcontext;
static krb5_principal kprincipal;
+static krb5_timestamp creds_expiry;
+static krb5_timestamp canceled_creds_expiry;
+static gboolean canceled;
static gboolean invalid_password;
static gboolean always_run;
-static gint creds_expiry;
-static int renew_credentials ();
+static int grab_credentials (Krb5AuthApplet* applet, gboolean renewable);
static gboolean get_tgt_from_ccache (krb5_context context, krb5_creds *creds);
+/* YAY for different Kerberos implementations */
+static int
+get_cred_forwardable(krb5_creds *creds)
+{
+#if defined(HAVE_KRB5_CREDS_TICKET_FLAGS) && defined(TKT_FLG_FORWARDABLE)
+ return creds->ticket_flags & TKT_FLG_FORWARDABLE;
+#elif defined(HAVE_KRB5_CREDS_FLAGS_B_FORWARDABLE)
+ return creds->flags.b.forwardable;
+#elif defined(HAVE_KRB5_CREDS_FLAGS) && defined(KDC_OPT_FORWARDABLE)
+ return creds->flags & KDC_OPT_FORWARDABLE;
+#endif
+}
+
+static int
+get_cred_renewable(krb5_creds *creds)
+{
+#if defined(HAVE_KRB5_CREDS_TICKET_FLAGS) && defined(TKT_FLG_RENEWABLE)
+ return creds->ticket_flags & TKT_FLG_RENEWABLE;
+#elif defined(HAVE_KRB5_CREDS_FLAGS_B_RENEWABLE)
+ return creds->flags.b.renewable;
+#elif defined(HAVE_KRB5_CREDS_FLAGS) && defined(KDC_OPT_RENEWABLE)
+ return creds->flags & KDC_OPT_RENEWABLE;
+#endif
+}
+
+static krb5_error_code
+get_renewed_creds(krb5_context context,
+ krb5_creds *creds,
+ krb5_principal client,
+ krb5_ccache ccache,
+ char *in_tkt_service)
+{
+#ifdef HAVE_KRB5_GET_RENEWED_CREDS
+ return krb5_get_renewed_creds (context, creds, client, ccache, in_tkt_service);
+#else
+ return 1; /* XXX is there something better to return? */
+#endif
+}
+
+static int
+get_cred_proxiable(krb5_creds *creds)
+{
+#if defined(HAVE_KRB5_CREDS_TICKET_FLAGS) && defined(TKT_FLG_PROXIABLE)
+ return creds->ticket_flags & TKT_FLG_PROXIABLE;
+#elif defined(HAVE_KRB5_CREDS_FLAGS_B_PROXIABLE)
+ return creds->flags.b.proxiable;
+#elif defined(HAVE_KRB5_CREDS_FLAGS) && defined(KDC_OPT_PROXIABLE)
+ return creds->flags & KDC_OPT_PROXIABLE;
+#endif
+}
+
+static size_t
+get_principal_realm_length(krb5_principal p)
+{
+#if defined(HAVE_KRB5_PRINCIPAL_REALM_AS_STRING)
+ return strlen(p->realm);
+#elif defined(HAVE_KRB5_PRINCIPAL_REALM_AS_DATA)
+ return p->realm.length;
+#endif
+}
+
+static const char *
+get_principal_realm_data(krb5_principal p)
+{
+#if defined(HAVE_KRB5_PRINCIPAL_REALM_AS_STRING)
+ return p->realm;
+#elif defined(HAVE_KRB5_PRINCIPAL_REALM_AS_DATA)
+ return p->realm.data;
+#endif
+}
+/* ***************************************************************** */
+/* ***************************************************************** */
+
+static gboolean
+credentials_expiring_real (Krb5AuthApplet* applet, gboolean *renewable)
+{
+ krb5_creds my_creds;
+ krb5_timestamp now;
+ gboolean retval = FALSE;
+ *renewable = FALSE;
+
+ if (!get_tgt_from_ccache (kcontext, &my_creds)) {
+ creds_expiry = 0;
+ retval = TRUE;
+ goto out;
+ }
+
+ if (krb5_principal_compare (kcontext, my_creds.client, kprincipal)) {
+ krb5_free_principal(kcontext, kprincipal);
+ krb5_copy_principal(kcontext, my_creds.client, &kprincipal);
+ }
+ creds_expiry = my_creds.times.endtime;
+ if ((krb5_timeofday(kcontext, &now) == 0) &&
+ (now + applet->pw_prompt_secs > my_creds.times.endtime))
+ retval = TRUE;
+
+ /* If our creds are expiring, determine whether they are renewable */
+ if (retval && get_cred_renewable(&my_creds) && my_creds.times.renew_till > now) {
+ *renewable = TRUE;
+ }
+
+ krb5_free_cred_contents (kcontext, &my_creds);
+
+out:
+ ka_update_status(applet, creds_expiry);
+ return retval;
+}
+
+
static gchar* minutes_to_expiry_text (int minutes)
{
gchar *expiry_text;
gchar *tmp;
- if (minutes > 0)
+ if (minutes > 0) {
expiry_text = g_strdup_printf (ngettext("Your credentials expire in %d minute",
"Your credentials expire in %d minutes",
minutes),
minutes);
- else
- {
+ } else {
expiry_text = g_strdup (_("Your credentials have expired"));
tmp = g_strdup_printf ("<span foreground=\"red\">%s</span>", expiry_text);
g_free (expiry_text);
@@ -66,18 +183,22 @@ static gchar* minutes_to_expiry_text (int minutes)
return expiry_text;
}
+
static gboolean
-krb5_auth_dialog_wrong_label_update_expiry (gpointer data)
+krb5_auth_dialog_wrong_label_update_expiry (GtkWidget* label)
{
- GtkWidget *label = GTK_WIDGET(data);
int minutes_left;
+ krb5_timestamp now;
gchar *expiry_text;
gchar *expiry_markup;
- g_return_val_if_fail (label != NULL, FALSE);
+ g_return_val_if_fail (label!= NULL, FALSE);
- minutes_left = (creds_expiry - time(0)) / 60;
+ if (krb5_timeofday(kcontext, &now) != 0) {
+ return TRUE;
+ }
+ minutes_left = (creds_expiry - now) / 60;
expiry_text = minutes_to_expiry_text (minutes_left);
expiry_markup = g_strdup_printf ("<span size=\"smaller\" style=\"italic\">%s</span>", expiry_text);
@@ -88,23 +209,45 @@ krb5_auth_dialog_wrong_label_update_expiry (gpointer data)
return TRUE;
}
+
+/* Check for things we have to do while the password dialog is open */
+static gboolean
+krb5_auth_dialog_do_updates(gpointer data)
+{
+ Krb5AuthApplet* applet = (Krb5AuthApplet*)data;
+ gboolean refreshable;
+
+ g_return_val_if_fail (applet != NULL, FALSE);
+
+ /* Update creds_expiry and close the applet if we got the creds by other means (e.g. kinit) */
+ if (!credentials_expiring_real(applet, &refreshable)) {
+ KA_DEBUG("PW Dialog persist is %d", applet->pw_dialog_persist);
+ if (!applet->pw_dialog_persist)
+ gtk_widget_hide(applet->pw_dialog);
+ }
+
+ /* Update the expiry information in the dialog */
+ krb5_auth_dialog_wrong_label_update_expiry (applet->pw_wrong_label);
+ return TRUE;
+}
+
+
static void
-krb5_auth_dialog_setup (GtkWidget *dialog,
+krb5_auth_dialog_setup (Krb5AuthApplet *applet,
const gchar *krb5prompt,
gboolean hide_password)
{
GtkWidget *entry;
GtkWidget *label;
- GtkWidget *wrong_label;
gchar *wrong_text;
gchar *wrong_markup;
gchar *prompt;
int pw4len;
- if (krb5prompt == NULL)
+
+ if (krb5prompt == NULL) {
prompt = g_strdup (_("Please enter your Kerberos password."));
- else
- {
+ } else {
/* Kerberos's prompts are a mess, and basically impossible to
* translate. There's basically no way short of doing a lot of
* string parsing to translate them. The most common prompt is
@@ -112,72 +255,69 @@ krb5_auth_dialog_setup (GtkWidget *dialog,
* cannot do any of the fancier strings (like challenges),
* though. */
pw4len = strlen ("Password for ");
- if (strncmp (krb5prompt, "Password for ", pw4len) == 0)
- {
+ if (strncmp (krb5prompt, "Password for ", pw4len) == 0) {
gchar *uid = (gchar *) (krb5prompt + pw4len);
prompt = g_strdup_printf (_("Please enter the password for '%s'"), uid);
- }
- else
+ } else {
prompt = g_strdup (krb5prompt);
+ }
}
/* Clear the password entry field */
- entry = glade_xml_get_widget (xml, "krb5_entry");
- gtk_entry_set_text (GTK_ENTRY (entry), "");
- gtk_entry_set_visibility (GTK_ENTRY (entry), !hide_password);
+ entry = glade_xml_get_widget (applet->pw_xml, "krb5_entry");
+ gtk_secure_entry_set_text (GTK_SECURE_ENTRY (entry), "");
/* Use the prompt label that krb5 provides us */
- label = glade_xml_get_widget (xml, "krb5_message_label");
+ label = glade_xml_get_widget (applet->pw_xml, "krb5_message_label");
gtk_label_set_text (GTK_LABEL (label), prompt);
/* Add our extra message hints, if any */
- wrong_label = glade_xml_get_widget (xml, "krb5_wrong_label");
wrong_text = NULL;
- if (wrong_label)
- {
- if (invalid_password)
+ if (applet->pw_wrong_label) {
+ if (invalid_password) {
wrong_text = g_strdup (_("The password you entered is invalid"));
- else
- {
- int minutes_left = (creds_expiry - time(0)) / 60;
-
+ } else {
+ krb5_timestamp now;
+ int minutes_left;
+
+ if (krb5_timeofday(kcontext, &now) == 0)
+ minutes_left = (creds_expiry - now) / 60;
+ else
+ minutes_left = 0;
wrong_text = minutes_to_expiry_text (minutes_left);
}
}
- if (wrong_text)
- {
+ if (wrong_text) {
wrong_markup = g_strdup_printf ("<span size=\"smaller\" style=\"italic\">%s</span>", wrong_text);
- gtk_label_set_markup (GTK_LABEL (wrong_label), wrong_markup);
+ gtk_label_set_markup (GTK_LABEL (applet->pw_wrong_label), wrong_markup);
g_free(wrong_text);
g_free(wrong_markup);
+ } else {
+ gtk_label_set_text (GTK_LABEL (applet->pw_wrong_label), "");
}
- else
- gtk_label_set_text (GTK_LABEL (wrong_label), "");
-
g_free (prompt);
}
+
static krb5_error_code
-krb5_gtk_prompter (krb5_context ctx,
- void *data,
- const char *name,
- const char *banner,
- int num_prompts,
- krb5_prompt prompts[])
+auth_dialog_prompter (krb5_context ctx,
+ void *data,
+ const char *name,
+ const char *banner,
+ int num_prompts,
+ krb5_prompt prompts[])
{
- GtkWidget *dialog;
- GtkWidget *wrong_label;
+ Krb5AuthApplet* applet = (Krb5AuthApplet*)data;
krb5_error_code errcode;
int i;
errcode = KRB5_LIBOS_CANTREADPWD;
+ canceled = FALSE;
+ canceled_creds_expiry = 0;
- dialog = glade_xml_get_widget (xml, "krb5_dialog");
-
- for (i = 0; i < num_prompts; i++)
- {
+ for (i = 0; i < num_prompts; i++) {
const gchar *password = NULL;
int password_len = 0;
int response;
@@ -187,25 +327,27 @@ krb5_gtk_prompter (krb5_context ctx,
errcode = KRB5_LIBOS_CANTREADPWD;
- entry = glade_xml_get_widget(xml, "krb5_entry");
- krb5_auth_dialog_setup (dialog, (gchar *) prompts[i].prompt, prompts[i].hidden);
+ krb5_auth_dialog_setup (applet, (gchar *) prompts[i].prompt, prompts[i].hidden);
+ entry = glade_xml_get_widget(applet->pw_xml, "krb5_entry");
+ gtk_widget_grab_focus(entry);
- wrong_label = glade_xml_get_widget (xml, "krb5_wrong_label");
- source_id = g_timeout_add (5000, (GSourceFunc)krb5_auth_dialog_wrong_label_update_expiry,
- wrong_label);
-
- response = gtk_dialog_run (GTK_DIALOG (dialog));
+ source_id = g_timeout_add_seconds (5, (GSourceFunc)krb5_auth_dialog_do_updates, applet);
+ response = gtk_dialog_run (GTK_DIALOG (applet->pw_dialog));
switch (response)
{
case GTK_RESPONSE_OK:
- password = gtk_entry_get_text (GTK_ENTRY (entry));
+ password = gtk_secure_entry_get_text (GTK_SECURE_ENTRY (entry));
password_len = strlen (password);
errcode = 0;
break;
case GTK_RESPONSE_CANCEL:
+ canceled = TRUE;
+ break;
+ case GTK_RESPONSE_NONE:
case GTK_RESPONSE_DELETE_EVENT:
break;
default:
+ g_warning ("Unknown Response: %d", response);
g_assert_not_reached ();
}
@@ -216,7 +358,7 @@ krb5_gtk_prompter (krb5_context ctx,
}
/* Reset this, so we know the next time we get a TRUE value, it is accurate. */
- gtk_widget_hide (dialog);
+ gtk_widget_hide (applet->pw_dialog);
invalid_password = FALSE;
return errcode;
@@ -252,101 +394,38 @@ network_state_cb (libnm_glib_ctx *context,
}
#endif
-static gboolean
-credentials_expiring_real (void)
-{
- krb5_creds my_creds;
- gboolean retval = FALSE;
-
- if (!get_tgt_from_ccache (kcontext, &my_creds)) {
- creds_expiry = 0;
- return TRUE;
- }
-
- if (krb5_principal_compare (kcontext, my_creds.client, kprincipal)) {
- krb5_free_principal(kcontext, kprincipal);
- krb5_copy_principal(kcontext, my_creds.client, &kprincipal);
- }
- creds_expiry = my_creds.times.endtime;
- if (time(NULL) + MINUTES_BEFORE_PROMPTING * 60 > my_creds.times.endtime)
- retval = TRUE;
-
- krb5_free_cred_contents(kcontext, &my_creds);
-
- return retval;
-}
static gboolean
credentials_expiring (gpointer *data)
{
- if (credentials_expiring_real () && is_online)
- renew_credentials ();
-
+ int retval;
+ gboolean give_up;
+ gboolean renewable;
+ Krb5AuthApplet* applet = (Krb5AuthApplet*) data;
+
+ KA_DEBUG("Checking expiry: %d", applet->pw_prompt_secs);
+ if (credentials_expiring_real (applet, &renewable) && is_online) {
+ give_up = canceled && (creds_expiry == canceled_creds_expiry);
+ if (!give_up) {
+ do {
+ retval = grab_credentials (applet, renewable);
+ give_up = canceled &&
+ (creds_expiry == canceled_creds_expiry);
+ } while ((retval != 0) &&
+ (retval != KRB5_REALM_CANT_RESOLVE) &&
+ (retval != KRB5_KDC_UNREACH) &&
+ invalid_password &&
+ !give_up);
+ }
+ }
+ ka_update_status(applet, creds_expiry);
return TRUE;
}
-#if defined(HAVE_KRB5_CREDS_TICKET_FLAGS) && defined(TKT_FLG_FORWARDABLE)
-static int
-get_cred_forwardable(krb5_creds *creds)
-{
- return creds->ticket_flags & TKT_FLG_FORWARDABLE;
-}
-#elif defined(HAVE_KRB5_CREDS_FLAGS_B_FORWARDABLE)
-static int
-get_cred_forwardable(krb5_creds *creds)
-{
- return creds->flags.b.forwardable;
-}
-#elif defined(HAVE_KRB5_CREDS_FLAGS) && defined(KDC_OPT_FORWARDABLE)
-static int
-get_cred_forwardable(krb5_creds *creds)
-{
- return creds->flags & KDC_OPT_FORWARDABLE;
-}
-#endif
-
-#if defined(HAVE_KRB5_CREDS_TICKET_FLAGS) && defined(TKT_FLG_RENEWABLE)
-static int
-get_cred_renewable(krb5_creds *creds)
-{
- return creds->ticket_flags & TKT_FLG_RENEWABLE;
-}
-#elif defined(HAVE_KRB5_CREDS_FLAGS_B_RENEWABLE)
-static int
-get_cred_renewable(krb5_creds *creds)
-{
- return creds->flags.b.renewable;
-}
-#elif defined(HAVE_KRB5_CREDS_FLAGS) && defined(KDC_OPT_RENEWABLE)
-static int
-get_cred_renewable(krb5_creds *creds)
-{
- return creds->flags & KDC_OPT_RENEWABLE;
-}
-#endif
-
-#if defined(HAVE_KRB5_CREDS_TICKET_FLAGS) && defined(TKT_FLG_PROXIABLE)
-static int
-get_cred_proxiable(krb5_creds *creds)
-{
- return creds->ticket_flags & TKT_FLG_PROXIABLE;
-}
-#elif defined(HAVE_KRB5_CREDS_FLAGS_B_PROXIABLE)
-static int
-get_cred_proxiable(krb5_creds *creds)
-{
- return creds->flags.b.proxiable;
-}
-#elif defined(HAVE_KRB5_CREDS_FLAGS) && defined(KDC_OPT_PROXIABLE)
-static int
-get_cred_proxiable(krb5_creds *creds)
-{
- return creds->flags & KDC_OPT_PROXIABLE;
-}
-#endif
static void
-set_options_using_creds(krb5_context context,
+set_options_using_creds(const Krb5AuthApplet* applet,
+ krb5_context context,
krb5_creds *creds,
krb5_get_init_creds_opt *opts)
{
@@ -365,7 +444,7 @@ set_options_using_creds(krb5_context context,
renew_lifetime);
}
if (creds->times.endtime >
- creds->times.starttime + MINUTES_BEFORE_PROMPTING * 60) {
+ creds->times.starttime + applet->pw_prompt_secs) {
krb5_get_init_creds_opt_set_tkt_life(opts,
creds->times.endtime -
creds->times.starttime);
@@ -375,92 +454,84 @@ set_options_using_creds(krb5_context context,
}
static int
-renew_credentials (void)
+grab_credentials (Krb5AuthApplet* applet, gboolean renewable)
{
krb5_error_code retval;
krb5_creds my_creds;
krb5_ccache ccache;
krb5_get_init_creds_opt opts;
+ memset(&my_creds, 0, sizeof(my_creds));
+
if (kprincipal == NULL) {
- retval = krb5_parse_name(kcontext, g_get_user_name (),
+ retval = krb5_parse_name(kcontext, applet->principal,
&kprincipal);
if (retval) {
return retval;
}
}
- krb5_get_init_creds_opt_init(&opts);
- if (get_tgt_from_ccache (kcontext, &my_creds))
- {
- set_options_using_creds(kcontext, &my_creds, &opts);
+ retval = krb5_cc_default (kcontext, &ccache);
+ if (retval)
+ return retval;
+
+ krb5_get_init_creds_opt_init (&opts);
+ if (get_tgt_from_ccache (kcontext, &my_creds)) {
+ set_options_using_creds (applet, kcontext, &my_creds, &opts);
creds_expiry = my_creds.times.endtime;
- krb5_free_cred_contents(kcontext, &my_creds);
+
+ if (renewable) {
+ retval = get_renewed_creds (kcontext, &my_creds, kprincipal, ccache, NULL);
+
+ /* If we succeeded in renewing the credentials, we store it. */
+ if (retval == 0) {
+ goto store;
+ }
+ /* Else, try to get new credentials, so just fall through */
+ }
+ krb5_free_cred_contents (kcontext, &my_creds);
} else {
creds_expiry = 0;
}
retval = krb5_get_init_creds_password(kcontext, &my_creds, kprincipal,
- NULL, krb5_gtk_prompter, 0,
- 0, NULL, &opts);
- if (retval)
- {
+ NULL, auth_dialog_prompter, applet,
+ 0, NULL, &opts);
+ if (canceled) {
+ canceled_creds_expiry = creds_expiry;
+ }
+ if (retval) {
switch (retval) {
case KRB5KDC_ERR_PREAUTH_FAILED:
case KRB5KRB_AP_ERR_BAD_INTEGRITY:
/* Invalid password, try again. */
invalid_password = TRUE;
- return renew_credentials();
+ goto out;
default:
break;
}
- return retval;
+ goto out;
}
- retval = krb5_cc_default(kcontext, &ccache);
- if (retval)
- return retval;
-
+store:
retval = krb5_cc_initialize(kcontext, ccache, kprincipal);
- if (retval)
+ if (retval) {
goto out;
+ }
retval = krb5_cc_store_cred(kcontext, ccache, &my_creds);
- if (retval)
+ if (retval) {
goto out;
+ }
creds_expiry = my_creds.times.endtime;
-
out:
+ krb5_free_cred_contents (kcontext, &my_creds);
krb5_cc_close (kcontext, ccache);
return retval;
}
-#if defined(HAVE_KRB5_PRINCIPAL_REALM_AS_STRING)
-static size_t
-get_principal_realm_length(krb5_principal p)
-{
- return strlen(p->realm);
-}
-static const char *
-get_principal_realm_data(krb5_principal p)
-{
- return p->realm;
-}
-#elif defined(HAVE_KRB5_PRINCIPAL_REALM_AS_DATA)
-static size_t
-get_principal_realm_length(krb5_principal p)
-{
- return p->realm.length;
-}
-static const char *
-get_principal_realm_data(krb5_principal p)
-{
- return p->realm.data;
-}
-#endif
-
static gboolean
get_tgt_from_ccache (krb5_context context, krb5_creds *creds)
{
@@ -471,11 +542,9 @@ get_tgt_from_ccache (krb5_context context, krb5_creds *creds)
memset(&ccache, 0, sizeof(ccache));
ret = FALSE;
- if (krb5_cc_default(context, &ccache) == 0)
- {
+ if (krb5_cc_default(context, &ccache) == 0) {
memset(&principal, 0, sizeof(principal));
- if (krb5_cc_get_principal(context, ccache, &principal) == 0)
- {
+ if (krb5_cc_get_principal(context, ccache, &principal) == 0) {
memset(&tgt_principal, 0, sizeof(tgt_principal));
if (krb5_build_principal_ext(context, &tgt_principal,
get_principal_realm_length(principal),
@@ -492,8 +561,7 @@ get_tgt_from_ccache (krb5_context context, krb5_creds *creds)
if (krb5_cc_retrieve_cred(context, ccache,
0,
&mcreds,
- creds) == 0)
- {
+ creds) == 0) {
ret = TRUE;
} else {
memset(creds, 0, sizeof(*creds));
@@ -515,8 +583,9 @@ using_krb5()
krb5_creds creds;
err = krb5_init_context(&kcontext);
- if (err)
+ if (err) {
return TRUE;
+ }
have_tgt = get_tgt_from_ccache(kcontext, &creds);
if (have_tgt) {
@@ -527,50 +596,170 @@ using_krb5()
return have_tgt;
}
+
+void
+ka_destroy_cache (GtkMenuItem *menuitem, gpointer data)
+{
+ Krb5AuthApplet* applet = (Krb5AuthApplet*) data;
+ krb5_ccache ccache;
+ const char* cache;
+ krb5_error_code ret;
+ gboolean renewable;
+
+ cache = krb5_cc_default_name(kcontext);
+ ret = krb5_cc_resolve(kcontext, cache, &ccache);
+ ret = krb5_cc_destroy (kcontext, ccache);
+
+ credentials_expiring_real(applet, &renewable);
+}
+
+
+static void
+ka_error_dialog(int err)
+{
+ const char* msg = error_message(err);
+ GtkWidget *dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("Couldn't acquire kerberos ticket: '%s'"), msg);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+
+/* this is done on leftclick, update the tooltip immediately */
+void
+ka_grab_credentials (Krb5AuthApplet* applet)
+{
+ int retval;
+ gboolean renewable, retry;
+
+ applet->pw_dialog_persist = TRUE;
+ do {
+ retry = TRUE;
+ retval = grab_credentials (applet, FALSE);
+ switch (retval) {
+ case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+ retry = TRUE;
+ break;
+ case 0: /* success */
+ case KRB5_LIBOS_CANTREADPWD: /* canceled */
+ retry = FALSE;
+ break;
+ case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
+ default:
+ ka_error_dialog(retval);
+ retry = FALSE;
+ break;
+ }
+ } while(retry);
+
+ applet->pw_dialog_persist = FALSE;
+ credentials_expiring_real(applet, &renewable);
+}
+
+
+static GtkWidget*
+ka_create_gtk_secure_entry (GladeXML *xml, gchar *func_name, gchar *name,
+ gchar *s1, gchar *s2, gint i1, gint i2,
+ gpointer user_data)
+{
+ GtkWidget* entry = NULL;
+
+ if (!strcmp(name, "krb5_entry")) {
+ entry = gtk_secure_entry_new ();
+ gtk_secure_entry_set_activates_default(GTK_SECURE_ENTRY(entry), TRUE);
+ gtk_widget_show (entry);
+ } else {
+ g_warning("Don't know anything about widget %s", name);
+ }
+ return entry;
+}
+
+
+static void
+ka_secmem_init ()
+{
+ /* Initialize secure memory. 1 is too small, so the default size
+ will be used. */
+ secmem_init (1);
+ secmem_set_flags (SECMEM_WARN);
+ drop_privs ();
+
+ if (atexit (secmem_term))
+ g_error("Couln't register atexit handler");
+}
+
+
int
main (int argc, char *argv[])
{
- GtkWidget *dialog;
- GnomeClient *client;
- int run_auto = 0, run_always = 0;
- struct poptOption options[] = {
- {"auto", 'a', 0, &run_auto, 0,
- "Only run if an initialized ccache is found (default)", NULL},
- {"always", 'A', 0, &run_always, 0,
- "Always run", NULL},
- {NULL},
+ Krb5AuthApplet *applet;
+ GOptionContext *context;
+ GError *error = NULL;
+
+ guint status = 0;
+ gboolean run_auto = FALSE, run_always = FALSE;
+
+ const char *help_msg = "Run '" PACKAGE " --help' to see a full list of available command line options";
+ const GOptionEntry options [] = {
+ {"auto", 'a', 0, G_OPTION_ARG_NONE, &run_auto,
+ "Only run if an initialized ccache is found (default)", NULL},
+ {"always", 'A', 0, G_OPTION_ARG_NONE, &run_always,
+ "Always run", NULL},
+ { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
};
#ifdef ENABLE_NETWORK_MANAGER
libnm_glib_ctx *nm_context;
guint32 nm_callback_id;
#endif
+ context = g_option_context_new ("- Kerberos 5 credential checking");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
+ g_option_context_parse (context, &argc, &argv, &error);
+ if (error) {
+ g_print ("%s\n%s\n",
+ error->message,
+ help_msg);
+ g_error_free (error);
+ return 1;
+ }
+ textdomain(PACKAGE);
+ bind_textdomain_codeset(PACKAGE, "UTF-8");
+ bindtextdomain(PACKAGE, LOCALE_DIR);
+ ka_secmem_init();
- gnome_program_init (PACKAGE, VERSION, LIBGNOMEUI_MODULE,
- argc, argv, GNOME_PARAM_POPT_TABLE, options,
- GNOME_PARAM_NONE);
-
- client = gnome_master_client ();
- gnome_client_set_restart_style (client, GNOME_RESTART_ANYWAY);
+ if(!ka_dbus_connect (&status))
+ exit(status);
- if (run_always && !run_auto)
- always_run++;
- if (using_krb5 () || always_run)
- {
- g_signal_connect (G_OBJECT (client), "die",
- G_CALLBACK (gtk_main_quit), NULL);
+ if (run_always && !run_auto) {
+ always_run = TRUE;
+ }
+ if (using_krb5 () || always_run) {
+ applet = ka_create_applet();
+ if (!applet)
+ return 1;
+ if (!ka_gconf_init(applet, argc, argv))
+ return 1;
+
+ /* setup the pw dialog */
+ glade_set_custom_handler (&ka_create_gtk_secure_entry, NULL);
+ applet->pw_xml = glade_xml_new (GLADEDIR "krb5-auth-dialog.glade", NULL, NULL);
+ applet->pw_wrong_label = glade_xml_get_widget (applet->pw_xml, "krb5_wrong_label");
+ applet->pw_dialog = glade_xml_get_widget (applet->pw_xml, "krb5_dialog");
g_set_application_name (_("Network Authentication"));
+ gtk_window_set_default_icon_name(applet->icons[1]);
#ifdef ENABLE_NETWORK_MANAGER
nm_context = libnm_glib_init ();
- if (!nm_context)
+ if (!nm_context) {
g_warning ("Could not initialize libnm_glib");
- else
- {
+ } else {
nm_callback_id = libnm_glib_register_callback (nm_context, network_state_cb, &is_online, NULL);
- if (nm_callback_id == 0)
- {
+ if (nm_callback_id == 0) {
libnm_glib_shutdown (nm_context);
nm_context = NULL;
@@ -579,12 +768,9 @@ main (int argc, char *argv[])
}
#endif /* ENABLE_NETWORK_MANAGER */
- xml = glade_xml_new (GLADEDIR "krb5-auth-dialog.glade", NULL, NULL);
- dialog = glade_xml_get_widget (xml, "krb5_dialog");
-
- if (credentials_expiring (NULL))
- g_timeout_add (CREDENTIAL_CHECK_INTERVAL * 1000, (GSourceFunc)credentials_expiring, NULL);
-
+ if (credentials_expiring ((gpointer)applet)) {
+ g_timeout_add_seconds (CREDENTIAL_CHECK_INTERVAL, (GSourceFunc)credentials_expiring, applet);
+ }
gtk_main ();
}
bgstack15