aboutsummaryrefslogtreecommitdiff
path: root/src/krb5-auth-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/krb5-auth-dialog.c')
-rw-r--r--src/krb5-auth-dialog.c252
1 files changed, 175 insertions, 77 deletions
diff --git a/src/krb5-auth-dialog.c b/src/krb5-auth-dialog.c
index 38eeb6c..9942d35 100644
--- a/src/krb5-auth-dialog.c
+++ b/src/krb5-auth-dialog.c
@@ -31,12 +31,14 @@
#include <glade/glade.h>
#include <dbus/dbus-glib.h>
+#include "krb5-auth-dialog.h"
+#include "krb5-auth-applet.h"
+#include "krb5-auth-gconf.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;
@@ -45,7 +47,7 @@ static gboolean canceled;
static gboolean invalid_password;
static gboolean always_run;
-static int grab_credentials (gboolean renewable);
+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 */
@@ -121,6 +123,42 @@ get_principal_realm_data(krb5_principal p)
/* ***************************************************************** */
/* ***************************************************************** */
+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;
@@ -141,16 +179,16 @@ 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);
if (krb5_timeofday(kcontext, &now) != 0) {
return TRUE;
@@ -167,19 +205,42 @@ 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) {
prompt = g_strdup (_("Please enter your Kerberos password."));
} else {
@@ -199,47 +260,44 @@ krb5_auth_dialog_setup (GtkWidget *dialog,
}
/* Clear the password entry field */
- entry = glade_xml_get_widget (xml, "krb5_entry");
+ entry = glade_xml_get_widget (applet->pw_xml, "krb5_entry");
gtk_entry_set_text (GTK_ENTRY (entry), "");
gtk_entry_set_visibility (GTK_ENTRY (entry), !hide_password);
/* 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 (applet->pw_wrong_label) {
if (invalid_password) {
wrong_text = g_strdup (_("The password you entered is invalid"));
} else {
krb5_timestamp now;
int minutes_left;
- if (krb5_timeofday(kcontext, &now) == 0) {
+ if (krb5_timeofday(kcontext, &now) == 0)
minutes_left = (creds_expiry - now) / 60;
- } else {
+ else
minutes_left = 0;
- }
-
wrong_text = minutes_to_expiry_text (minutes_left);
}
}
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 (wrong_label), "");
+ gtk_label_set_text (GTK_LABEL (applet->pw_wrong_label), "");
}
-
g_free (prompt);
}
+
static krb5_error_code
auth_dialog_prompter (krb5_context ctx,
void *data,
@@ -248,8 +306,7 @@ auth_dialog_prompter (krb5_context ctx,
int num_prompts,
krb5_prompt prompts[])
{
- GtkWidget *dialog;
- GtkWidget *wrong_label;
+ Krb5AuthApplet* applet = (Krb5AuthApplet*)data;
krb5_error_code errcode;
int i;
@@ -257,8 +314,6 @@ auth_dialog_prompter (krb5_context ctx,
canceled = FALSE;
canceled_creds_expiry = 0;
- dialog = glade_xml_get_widget (xml, "krb5_dialog");
-
for (i = 0; i < num_prompts; i++) {
const gchar *password = NULL;
int password_len = 0;
@@ -269,15 +324,12 @@ auth_dialog_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);
+ entry = glade_xml_get_widget (applet->pw_xml, "krb5_entry");
+ krb5_auth_dialog_setup (applet, (gchar *) prompts[i].prompt, prompts[i].hidden);
gtk_widget_grab_focus (entry);
- wrong_label = glade_xml_get_widget (xml, "krb5_wrong_label");
- source_id = g_timeout_add_seconds (5, (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:
@@ -288,6 +340,7 @@ auth_dialog_prompter (krb5_context ctx,
case GTK_RESPONSE_CANCEL:
canceled = TRUE;
break;
+ case GTK_RESPONSE_NONE:
case GTK_RESPONSE_DELETE_EVENT:
break;
default:
@@ -302,7 +355,7 @@ auth_dialog_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;
@@ -338,37 +391,6 @@ network_state_cb (libnm_glib_ctx *context,
}
#endif
-static gboolean
-credentials_expiring_real (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;
- 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 ((krb5_timeofday(kcontext, &now) == 0) &&
- (now + MINUTES_BEFORE_PROMPTING * 60 > 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);
-
- return retval;
-}
static gboolean
credentials_expiring (gpointer *data)
@@ -376,12 +398,14 @@ credentials_expiring (gpointer *data)
int retval;
gboolean give_up;
gboolean renewable;
+ Krb5AuthApplet* applet = (Krb5AuthApplet*) data;
- if (credentials_expiring_real (&renewable) && is_online) {
+ 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 (renewable);
+ retval = grab_credentials (applet, renewable);
give_up = canceled &&
(creds_expiry == canceled_creds_expiry);
} while ((retval != 0) &&
@@ -391,12 +415,14 @@ credentials_expiring (gpointer *data)
!give_up);
}
}
-
+ ka_update_status(applet, creds_expiry);
return TRUE;
}
+
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)
{
@@ -415,7 +441,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);
@@ -425,7 +451,7 @@ set_options_using_creds(krb5_context context,
}
static int
-grab_credentials (gboolean renewable)
+grab_credentials (Krb5AuthApplet* applet, gboolean renewable)
{
krb5_error_code retval;
krb5_creds my_creds;
@@ -435,7 +461,7 @@ grab_credentials (gboolean renewable)
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;
@@ -448,7 +474,7 @@ grab_credentials (gboolean renewable)
krb5_get_init_creds_opt_init (&opts);
if (get_tgt_from_ccache (kcontext, &my_creds)) {
- set_options_using_creds (kcontext, &my_creds, &opts);
+ set_options_using_creds (applet, kcontext, &my_creds, &opts);
creds_expiry = my_creds.times.endtime;
if (renewable) {
@@ -466,7 +492,7 @@ grab_credentials (gboolean renewable)
}
retval = krb5_get_init_creds_password(kcontext, &my_creds, kprincipal,
- NULL, auth_dialog_prompter, NULL,
+ NULL, auth_dialog_prompter, applet,
0, NULL, &opts);
if (canceled) {
canceled_creds_expiry = creds_expiry;
@@ -567,10 +593,74 @@ 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);
+}
+
+
int
main (int argc, char *argv[])
{
- GtkWidget *dialog;
+ Krb5AuthApplet *applet;
GOptionContext *context;
GError *error = NULL;
DBusGConnection *session;
@@ -649,7 +739,19 @@ main (int argc, char *argv[])
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 */
+ 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 ();
@@ -666,12 +768,8 @@ 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");
- gtk_window_set_default_icon_name ("gtk-dialog-authentication");
-
- if (credentials_expiring (NULL)) {
- g_timeout_add_seconds (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 ();
}