diff options
author | Guido Günther <agx@sigxcpu.org> | 2008-10-18 18:17:19 +0200 |
---|---|---|
committer | Guido Guenther <agx@sigxcpu.org> | 2008-10-18 18:17:19 +0200 |
commit | 6a45cdd4cc1321567d929f41721792c9e3d38401 (patch) | |
tree | c3fd44df49218df644765e624c247d16358bd474 /src | |
parent | Imported Upstream version 0.7.git7cc1d84 (diff) | |
download | krb5-auth-dialog-6a45cdd4cc1321567d929f41721792c9e3d38401.tar.gz krb5-auth-dialog-6a45cdd4cc1321567d929f41721792c9e3d38401.tar.bz2 krb5-auth-dialog-6a45cdd4cc1321567d929f41721792c9e3d38401.zip |
Imported Upstream version 0.7.jit26357da
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/krb5-auth-applet.c | 94 | ||||
-rw-r--r-- | src/krb5-auth-applet.h | 6 | ||||
-rw-r--r-- | src/krb5-auth-dialog.c | 395 | ||||
-rw-r--r-- | src/krb5-auth-dialog.schemas.in | 55 | ||||
-rw-r--r-- | src/krb5-auth-gconf.c | 16 | ||||
-rw-r--r-- | src/krb5-auth-notify.c | 19 | ||||
-rw-r--r-- | src/krb5-auth-notify.h | 4 |
8 files changed, 429 insertions, 169 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 066e582..2837be8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,6 +10,13 @@ autostart_in_files = krb5-auth-dialog.desktop.in autostart_DATA = $(autostart_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ +schemadir = $(sysconfdir)/gconf/schemas +schema_in_files = $(PACKAGE).schemas.in +schema_DATA = $(PACKAGE).schemas + +%.schemas: $(srcdir)/%.schemas.in + sed -e "s,::PACKAGE::,$(PACKAGE)," < $< > $@ + krb5_auth_dialog_SOURCES = \ krb5-auth-dialog.c \ krb5-auth-dialog.h \ @@ -42,7 +49,9 @@ glade_DATA = \ EXTRA_DIST = \ $(glade_DATA) \ + $(schama_in_files) \ $(autostart_in_files) \ krb5-auth-dialog.1.in +CLEANFILES = $(schema_DATA) DISTCLEANFILES = krb5-auth-dialog.desktop diff --git a/src/krb5-auth-applet.c b/src/krb5-auth-applet.c index 4a11d09..c915240 100644 --- a/src/krb5-auth-applet.c +++ b/src/krb5-auth-applet.c @@ -24,65 +24,97 @@ #include "krb5-auth-applet.h" #include "krb5-auth-dialog.h" -#ifdef HAVE_LIBNOTIFY #include "krb5-auth-notify.h" -#endif #define NOTIFY_SECONDS 300 -/* update the tray icon's tooltip and icon */ -int -ka_update_status(Krb5AuthApplet* applet, krb5_timestamp expiry) +enum ka_icon { + inv_icon = 0, + exp_icon, + val_icon, +}; + + +/* determine the new tooltip text */ +static char* +ka_tooltip_text(Krb5AuthApplet* applet, int remaining) { - gchar* expiry_text; - int now = time(0); - int remaining = expiry - now; - static int last_warn = 0; - static gboolean expiry_notified = FALSE; + int hours, minutes; + gchar* tooltip_text; if (remaining > 0) { - int hours, minutes; if (remaining >= 3600) { hours = remaining / 3600; minutes = (remaining % 3600) / 60; - expiry_text = g_strdup_printf (_("Your credentials expire in %.2d:%.2dh"), hours, minutes); + tooltip_text = g_strdup_printf (_("Your credentials expire in %.2d:%.2dh"), hours, minutes); } else { minutes = remaining / 60; - expiry_text = g_strdup_printf (ngettext( + tooltip_text = g_strdup_printf (ngettext( "Your credentials expire in %d minute", "Your credentials expire in %d minutes", minutes), minutes); } - gtk_status_icon_set_from_icon_name (applet->tray_icon, applet->icons[1]); -#ifdef HAVE_LIBNOTIFY + } else + tooltip_text = g_strdup (_("Your credentials have expired")); + return tooltip_text; +} + + +/* determine the current icon */ +static const char* +ka_select_icon(Krb5AuthApplet* applet, int remaining) +{ + enum ka_icon tray_icon = inv_icon; + + if (remaining > 0) { + if (remaining < applet->pw_prompt_secs && + !applet->renewable) + tray_icon = exp_icon; + else + tray_icon = val_icon; + } + + return applet->icons[tray_icon]; +} + + +/* update the tray icon's tooltip and icon */ +int +ka_update_status(Krb5AuthApplet* 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); + + if (remaining > 0) { if (expiry_notified) { - ka_send_event_notification (applet, NOTIFY_URGENCY_NORMAL, + ka_send_event_notification (applet, _("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) { - ka_send_event_notification (applet, NOTIFY_URGENCY_NORMAL, + } else if (remaining < applet->pw_prompt_secs && (now - last_warn) > NOTIFY_SECONDS && + !applet->renewable) { + ka_send_event_notification (applet, _("Network credentials expiring"), - expiry_text, NULL); + tooltip_text, NULL); last_warn = now; } -#endif } else { - expiry_text = g_strdup (_("Your credentials have expired")); - gtk_status_icon_set_from_icon_name (applet->tray_icon, applet->icons[0]); -#ifdef HAVE_LIBNOTIFY if (!expiry_notified) { - ka_send_event_notification (applet, NOTIFY_URGENCY_NORMAL, + ka_send_event_notification (applet, _("Network credentials expired"), _("Your Kerberos credentails have expired."), NULL); expiry_notified = TRUE; last_warn = 0; } -#endif } - gtk_status_icon_set_tooltip (applet->tray_icon, expiry_text); - g_free (expiry_text); + gtk_status_icon_set_from_icon_name (applet->tray_icon, tray_icon); + gtk_status_icon_set_tooltip (applet->tray_icon, tooltip_text); + g_free(tooltip_text); return 0; } @@ -213,7 +245,7 @@ ka_create_tray_icon (Krb5AuthApplet* 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[0]); + gtk_status_icon_set_from_icon_name (tray_icon, applet->icons[exp_icon]); gtk_status_icon_set_tooltip (tray_icon, PACKAGE); return tray_icon; } @@ -222,8 +254,9 @@ ka_create_tray_icon (Krb5AuthApplet* applet) int ka_setup_icons (Krb5AuthApplet* applet) { - applet->icons[0] = "krb-no-valid-ticket"; - applet->icons[1] = "krb-valid-ticket"; + applet->icons[val_icon] = "krb-valid-ticket"; + applet->icons[exp_icon] = "krb-expiring-ticket"; + applet->icons[inv_icon] = "krb-no-valid-ticket"; return TRUE; } @@ -240,6 +273,7 @@ ka_create_applet() g_error ("Failure to create tray icon"); if (!(applet->context_menu = ka_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); return applet; diff --git a/src/krb5-auth-applet.h b/src/krb5-auth-applet.h index 062e148..e137794 100644 --- a/src/krb5-auth-applet.h +++ b/src/krb5-auth-applet.h @@ -35,7 +35,7 @@ typedef struct { GtkStatusIcon* tray_icon; /* the tray icon */ GtkWidget* context_menu; /* the tray icon's context menu */ - const char* icons[2]; /* for expired and valid tickts */ + const char* icons[3]; /* for invalid, expiring and valid tickts */ gboolean show_trayicon; /* show the trayicon */ /* The password dialog */ @@ -49,6 +49,8 @@ typedef struct { NotifyNotification* notification;/* notification messages */ #endif /* HAVE_LIBNOTIFY */ char* principal; /* the principal to request */ + gboolean renewable; /* credentials renewable? */ + char* pk_userid; /* "userid" for pkint */ } Krb5AuthApplet; Krb5AuthApplet* ka_create_applet(); @@ -59,7 +61,7 @@ gboolean ka_show_tray_icon(Krb5AuthApplet* applet); #ifdef ENABLE_DEBUG #define KA_DEBUG(fmt,...) \ - g_printf ("DEBUG: %s: " fmt "\n", __func__, __VA_ARGS__) + g_printf ("DEBUG: %s: " fmt "\n", __func__, ##__VA_ARGS__) #else #define KA_DEBUG(fmt,...) \ do { } while (0) diff --git a/src/krb5-auth-dialog.c b/src/krb5-auth-dialog.c index f376ffd..c8fc27c 100644 --- a/src/krb5-auth-dialog.c +++ b/src/krb5-auth-dialog.c @@ -43,16 +43,21 @@ #include <libnm_glib.h> #endif +#ifdef HAVE_HX509_ERR_H +# include <hx509_err.h> +#endif + 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 invalid_auth; static gboolean always_run; -static int grab_credentials (Krb5AuthApplet* applet, gboolean renewable); -static gboolean get_tgt_from_ccache (krb5_context context, krb5_creds *creds); +static int grab_credentials (Krb5AuthApplet* applet); +static int ka_renew_credentials (Krb5AuthApplet* applet); +static gboolean ka_get_tgt_from_ccache (krb5_context context, krb5_creds *creds); /* YAY for different Kerberos implementations */ static int @@ -124,18 +129,45 @@ get_principal_realm_data(krb5_principal p) return p->realm.data; #endif } + +static const char* +get_error_message(krb5_context context, krb5_error_code err) +{ + const char *msg = NULL; + +#if defined(HAVE_KRB5_GET_ERROR_MESSAGE) + msg = krb5_get_error_message(context, err); +#else + msg = error_message(err); +#endif + if (msg == NULL) + return "unknown error"; + else + return msg; +} + +static void +ka_krb5_cc_clear_mcred(krb5_creds* mcred) +{ +#if defined HAVE_KRB5_CC_CLEAR_MCRED + krb5_cc_clear_mcred(mcred); +#else + memset(mcred, 0, sizeof(krb5_creds)); +#endif +} + /* ***************************************************************** */ /* ***************************************************************** */ static gboolean -credentials_expiring_real (Krb5AuthApplet* applet, gboolean *renewable) +credentials_expiring_real (Krb5AuthApplet* applet) { krb5_creds my_creds; krb5_timestamp now; gboolean retval = FALSE; - *renewable = FALSE; + applet->renewable = FALSE; - if (!get_tgt_from_ccache (kcontext, &my_creds)) { + if (!ka_get_tgt_from_ccache (kcontext, &my_creds)) { creds_expiry = 0; retval = TRUE; goto out; @@ -152,7 +184,7 @@ credentials_expiring_real (Krb5AuthApplet* applet, gboolean *renewable) /* 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; + applet->renewable = TRUE; } krb5_free_cred_contents (kcontext, &my_creds); @@ -215,13 +247,12 @@ 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 (!credentials_expiring_real(applet)) { + KA_DEBUG("PW Dialog persist: %d", applet->pw_dialog_persist); if (!applet->pw_dialog_persist) gtk_widget_hide(applet->pw_dialog); } @@ -275,7 +306,7 @@ krb5_auth_dialog_setup (Krb5AuthApplet *applet, wrong_text = NULL; if (applet->pw_wrong_label) { - if (invalid_password) { + if (invalid_auth) { wrong_text = g_strdup (_("The password you entered is invalid")); } else { krb5_timestamp now; @@ -313,7 +344,7 @@ auth_dialog_prompter (krb5_context ctx, krb5_error_code errcode; int i; - errcode = KRB5_LIBOS_CANTREADPWD; + errcode = KRB5KRB_ERR_GENERIC; canceled = FALSE; canceled_creds_expiry = 0; @@ -321,7 +352,7 @@ auth_dialog_prompter (krb5_context ctx, const gchar *password = NULL; int password_len = 0; int response; - guint32 source_id = 0; + guint32 source_id; GtkWidget *entry; @@ -338,7 +369,6 @@ auth_dialog_prompter (krb5_context ctx, case GTK_RESPONSE_OK: password = gtk_secure_entry_get_text (GTK_SECURE_ENTRY (entry)); password_len = strlen (password); - errcode = 0; break; case GTK_RESPONSE_CANCEL: canceled = TRUE; @@ -350,16 +380,23 @@ auth_dialog_prompter (krb5_context ctx, g_warning ("Unknown Response: %d", response); g_assert_not_reached (); } - g_source_remove (source_id); - prompts[i].reply->data = (char *) password; + if (!password) + goto cleanup; + if (password_len+1 > prompts[i].reply->length) { + g_warning("Password too long %d/%d", password_len+1, prompts[i].reply->length); + goto cleanup; + } + + memcpy(prompts[i].reply->data, (char *) password, password_len + 1); prompts[i].reply->length = password_len; + errcode = 0; } - +cleanup: /* Reset this, so we know the next time we get a TRUE value, it is accurate. */ gtk_widget_hide (applet->pw_dialog); - invalid_password = FALSE; + invalid_auth = FALSE; return errcode; } @@ -394,72 +431,132 @@ network_state_cb (libnm_glib_ctx *context, } #endif - static gboolean credentials_expiring (gpointer *data) { 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 && !applet->show_trayicon) { + KA_DEBUG("Checking expiry <%ds", applet->pw_prompt_secs); + if (credentials_expiring_real (applet) && is_online) { + KA_DEBUG("Expiry @ %ld", creds_expiry); + + if (!ka_renew_credentials (applet)) { + KA_DEBUG("Credentials renewed"); + goto out; + } + + /* no popup when using a trayicon */ + if (applet->show_trayicon) + goto out; + give_up = canceled && (creds_expiry == canceled_creds_expiry); if (!give_up) { do { - retval = grab_credentials (applet, renewable); + retval = grab_credentials (applet); give_up = canceled && (creds_expiry == canceled_creds_expiry); } while ((retval != 0) && (retval != KRB5_REALM_CANT_RESOLVE) && (retval != KRB5_KDC_UNREACH) && - invalid_password && + invalid_auth && !give_up); } } +out: ka_update_status(applet, creds_expiry); return TRUE; } static void -set_options_using_creds(const Krb5AuthApplet* applet, - krb5_context context, - krb5_creds *creds, - krb5_get_init_creds_opt *opts) +set_options_from_creds(const Krb5AuthApplet* applet, + krb5_context context, + krb5_creds *in, + krb5_get_init_creds_opt *out) { krb5_deltat renew_lifetime; int flag; - flag = get_cred_forwardable(creds) != 0; - krb5_get_init_creds_opt_set_forwardable(opts, flag); - flag = get_cred_proxiable(creds) != 0; - krb5_get_init_creds_opt_set_proxiable(opts, flag); - flag = get_cred_renewable(creds) != 0; - if (flag && (creds->times.renew_till > creds->times.starttime)) { - renew_lifetime = creds->times.renew_till - - creds->times.starttime; - krb5_get_init_creds_opt_set_renew_life(opts, +#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_DEFAULT_FLAGS + krb5_get_init_creds_opt_set_default_flags(kcontext, PACKAGE, + krb5_principal_get_realm(kcontext, kprincipal), out); +#endif + + flag = get_cred_forwardable(in) != 0; + krb5_get_init_creds_opt_set_forwardable(out, flag); + flag = get_cred_proxiable(in) != 0; + krb5_get_init_creds_opt_set_proxiable(out, flag); + flag = get_cred_renewable(in) != 0; + if (flag && (in->times.renew_till > in->times.starttime)) { + renew_lifetime = in->times.renew_till - + in->times.starttime; + krb5_get_init_creds_opt_set_renew_life(out, renew_lifetime); } - if (creds->times.endtime > - creds->times.starttime + applet->pw_prompt_secs) { - krb5_get_init_creds_opt_set_tkt_life(opts, - creds->times.endtime - - creds->times.starttime); + if (in->times.endtime > + in->times.starttime + applet->pw_prompt_secs) { + krb5_get_init_creds_opt_set_tkt_life(out, + in->times.endtime - + in->times.starttime); } /* This doesn't do a deep copy -- fix it later. */ - /* krb5_get_init_creds_opt_set_address_list(opts, creds->addresses); */ + /* krb5_get_init_creds_opt_set_address_list(out, creds->addresses); */ +} + + +static krb5_error_code +ka_auth_pkinit(Krb5AuthApplet* applet, krb5_creds* creds) +{ +#ifdef ENABLE_PKINIT + krb5_get_init_creds_opt *opts = NULL; + krb5_error_code retval; + + KA_DEBUG("pkinit with %s", applet->pk_userid); + + if (!applet->pk_userid) + return 0; + + retval = krb5_get_init_creds_opt_alloc (kcontext, &opts); + if (retval) + goto out; + set_options_from_creds (applet, kcontext, creds, opts); + + retval = krb5_get_init_creds_opt_set_pkinit(kcontext, opts, + kprincipal, + applet->pk_userid, + NULL, /* x509 anchors */ + NULL, + NULL, + 0, /* pk_use_enc_key */ + auth_dialog_prompter, + applet, /* data */ + NULL); /* passwd */ + KA_DEBUG("pkinit returned with %d", retval); + if (retval) + goto out; + + retval = krb5_get_init_creds_password(kcontext, creds, kprincipal, + NULL, auth_dialog_prompter, applet, + 0, NULL, opts); +out: + krb5_get_init_creds_opt_free(kcontext, opts); + return retval; +#else /* ENABLE_PKINIT */ + return 0; +#endif /* ! ENABLE_PKINIT */ } + +/* grab credentials interactively */ static int -grab_credentials (Krb5AuthApplet* applet, gboolean renewable) +grab_credentials (Krb5AuthApplet* applet) { krb5_error_code retval; krb5_creds my_creds; krb5_ccache ccache; - krb5_get_init_creds_opt opts; + krb5_get_init_creds_opt *opt = NULL; memset(&my_creds, 0, sizeof(my_creds)); @@ -475,103 +572,148 @@ grab_credentials (Krb5AuthApplet* applet, gboolean renewable) 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; - - 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); +#if ENABLE_PKINIT + if (applet->pk_userid) { /* try pkinit */ +#else + if (0) { +#endif + retval = ka_auth_pkinit(applet, &my_creds); } else { - creds_expiry = 0; + retval = krb5_get_init_creds_opt_alloc (kcontext, &opt); + if (retval) + goto out; + set_options_from_creds (applet, kcontext, &my_creds, opt); + retval = krb5_get_init_creds_password(kcontext, &my_creds, kprincipal, + NULL, auth_dialog_prompter, applet, + 0, NULL, opt); } - - retval = krb5_get_init_creds_password(kcontext, &my_creds, kprincipal, - NULL, auth_dialog_prompter, applet, - 0, NULL, &opts); - if (canceled) { + creds_expiry = my_creds.times.endtime; + 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; +#ifdef HAVE_HX509_ERR_H + case HX509_PKCS11_LOGIN: +#endif + /* Invalid password/pin, try again. */ + invalid_auth = TRUE; goto out; default: + KA_DEBUG("Auth failed with %d: %s", retval, + get_error_message(kcontext, retval)); break; } goto out; } - -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: + if (opt) + krb5_get_init_creds_opt_free(kcontext, opt); krb5_free_cred_contents (kcontext, &my_creds); krb5_cc_close (kcontext, ccache); return retval; } -static gboolean -get_tgt_from_ccache (krb5_context context, krb5_creds *creds) +/* try to renew the credentials noninteractively */ +static int +ka_renew_credentials (Krb5AuthApplet* applet) { + krb5_error_code retval; + krb5_creds my_creds; krb5_ccache ccache; - krb5_creds mcreds; - krb5_principal principal, tgt_principal; - gboolean ret; - - memset(&ccache, 0, sizeof(ccache)); - ret = FALSE; - if (krb5_cc_default(context, &ccache) == 0) { - memset(&principal, 0, sizeof(principal)); - 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), - get_principal_realm_data(principal), - KRB5_TGS_NAME_SIZE, - KRB5_TGS_NAME, - get_principal_realm_length(principal), - get_principal_realm_data(principal), - 0) == 0) { - memset(creds, 0, sizeof(*creds)); - memset(&mcreds, 0, sizeof(mcreds)); - mcreds.client = principal; - mcreds.server = tgt_principal; - if (krb5_cc_retrieve_cred(context, ccache, - 0, - &mcreds, - creds) == 0) { - ret = TRUE; - } else { - memset(creds, 0, sizeof(*creds)); - } - krb5_free_principal(context, tgt_principal); - } - krb5_free_principal(context, principal); + krb5_get_init_creds_opt opts; + + if (kprincipal == NULL) { + retval = krb5_parse_name(kcontext, applet->principal, + &kprincipal); + if (retval) + return retval; + } + + retval = krb5_cc_default (kcontext, &ccache); + if (retval) + return retval; + + retval = ka_get_tgt_from_ccache (kcontext, &my_creds); + if (!retval) { + krb5_cc_close (kcontext, ccache); + return -1; + } + + krb5_get_init_creds_opt_init (&opts); + set_options_from_creds (applet, kcontext, &my_creds, &opts); + + if (applet->renewable) { + retval = get_renewed_creds (kcontext, &my_creds, kprincipal, ccache, NULL); + if (retval) + goto out; + + retval = krb5_cc_initialize(kcontext, ccache, kprincipal); + if(retval) { + g_warning("krb5_cc_initialize: %s", get_error_message(kcontext, retval)); + goto out; + } + retval = krb5_cc_store_cred(kcontext, ccache, &my_creds); + if (retval) { + g_warning("krb5_cc_store_cred: %s", get_error_message(kcontext, retval)); + goto out; } - krb5_cc_close(context, ccache); } +out: + creds_expiry = my_creds.times.endtime; + krb5_free_cred_contents (kcontext, &my_creds); + krb5_cc_close (kcontext, ccache); + return retval; +} + + +/* get principal associated with the default credentials cache - if found store + * it in *creds, return FALSE otwerwise */ +static gboolean +ka_get_tgt_from_ccache (krb5_context context, krb5_creds *creds) +{ + krb5_ccache ccache; + krb5_creds pattern; + krb5_principal principal; + gboolean ret = FALSE; + + ka_krb5_cc_clear_mcred(&pattern); + + if (krb5_cc_default(context, &ccache)) + return FALSE; + + if (krb5_cc_get_principal(context, ccache, &principal)) + goto out; + + if (krb5_build_principal_ext(context, &pattern.server, + get_principal_realm_length(principal), + get_principal_realm_data(principal), + KRB5_TGS_NAME_SIZE, + KRB5_TGS_NAME, + get_principal_realm_length(principal), + get_principal_realm_data(principal), 0)) { + goto out_free_princ; + } + + pattern.client = principal; + if (!krb5_cc_retrieve_cred(context, ccache, 0, &pattern, creds)) + ret = TRUE; + krb5_free_principal(context, pattern.server); + +out_free_princ: + krb5_free_principal(context, principal); +out: + krb5_cc_close(context, ccache); return ret; } @@ -583,11 +725,10 @@ using_krb5() krb5_creds creds; err = krb5_init_context(&kcontext); - if (err) { - return TRUE; - } + if (err) + return FALSE; - have_tgt = get_tgt_from_ccache(kcontext, &creds); + have_tgt = ka_get_tgt_from_ccache(kcontext, &creds); if (have_tgt) { krb5_copy_principal(kcontext, creds.client, &kprincipal); krb5_free_cred_contents (kcontext, &creds); @@ -604,20 +745,19 @@ ka_destroy_cache (GtkMenuItem *menuitem, gpointer 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); + credentials_expiring_real(applet); } static void ka_error_dialog(int err) { - const char* msg = error_message(err); + const char* msg = get_error_message(kcontext, err); GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, @@ -633,18 +773,18 @@ void ka_grab_credentials (Krb5AuthApplet* applet) { int retval; - gboolean renewable, retry; + gboolean retry; applet->pw_dialog_persist = TRUE; do { retry = TRUE; - retval = grab_credentials (applet, FALSE); + retval = grab_credentials (applet); + if (invalid_auth) + continue; switch (retval) { - case KRB5KRB_AP_ERR_BAD_INTEGRITY: - retry = TRUE; - break; case 0: /* success */ - case KRB5_LIBOS_CANTREADPWD: /* canceled */ + case KRB5_LIBOS_PWDINTR: /* canceled (heimdal) */ + case KRB5_LIBOS_CANTREADPWD: /* canceled (mit) */ retry = FALSE; break; case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: @@ -656,7 +796,7 @@ ka_grab_credentials (Krb5AuthApplet* applet) } while(retry); applet->pw_dialog_persist = FALSE; - credentials_expiring_real(applet, &renewable); + credentials_expiring_real(applet); } @@ -679,7 +819,7 @@ ka_create_gtk_secure_entry (GladeXML *xml, gchar *func_name, gchar *name, } -static void +static void ka_secmem_init () { /* Initialize secure memory. 1 is too small, so the default size @@ -752,7 +892,6 @@ main (int argc, char *argv[]) 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 (); diff --git a/src/krb5-auth-dialog.schemas.in b/src/krb5-auth-dialog.schemas.in new file mode 100644 index 0000000..2a3a707 --- /dev/null +++ b/src/krb5-auth-dialog.schemas.in @@ -0,0 +1,55 @@ +<gconfschemafile> + <schemalist> + <schema> + <key>/schemas/apps/::PACKAGE::/show_trayicon</key> + <applyto>/apps/::PACKAGE::/show_trayicon</applyto> + <owner>::PACKAGE::</owner> + <type>bool</type> + <default>1</default> + + <locale name="C"> + <short>Show trayicon</short> + <long>Show a trayicon in the status area of the panel</long> + </locale> + </schema> + + <schema> + <key>/schemas/apps/::PACKAGE::/principal</key> + <applyto>/apps/::PACKAGE::/principal</applyto> + <owner>::PACKAGE::</owner> + <type>string</type> + <default></default> + + <locale name="C"> + <short>Kerberos principal</short> + <long>The kerberos principal to acquire the ticket for</long> + </locale> + </schema> + + <schema> + <key>/schemas/apps/::PACKAGE::/pk_userid</key> + <applyto>/apps/::PACKAGE::/pk_userid</applyto> + <owner>::PACKAGE::</owner> + <type>string</type> + <default></default> + + <locale name="C"> + <short>Pkinit identifier</short> + <long>The principal's public/private/certificate identifier when using pkinit</long> + </locale> + </schema> + + <schema> + <key>/schemas/apps/::PACKAGE::/prompt_minutes</key> + <applyto>/apps/::PACKAGE::/prompt_minutes</applyto> + <owner>::PACKAGE::</owner> + <type>int</type> + <default>30</default> + + <locale name="C"> + <short>Prompt minutes before expiry</short> + <long>Start prompting/displaying notifications that many minutes before expiry</long> + </locale> + </schema> + </schemalist> +</gconfschemafile> diff --git a/src/krb5-auth-gconf.c b/src/krb5-auth-gconf.c index 20d22ce..a11370c 100644 --- a/src/krb5-auth-gconf.c +++ b/src/krb5-auth-gconf.c @@ -26,6 +26,7 @@ #define KA_GCONF_PATH "/apps/" PACKAGE #define KA_GCONF_KEY_PRINCIPAL KA_GCONF_PATH "/principal" +#define KA_GCONF_KEY_PK_USERID KA_GCONF_PATH "/pk_userid" #define KA_GCONF_KEY_PROMPT_MINS KA_GCONF_PATH "/prompt_minutes" #define KA_GCONF_KEY_SHOW_TRAYICON KA_GCONF_PATH "/show_trayicon" @@ -124,6 +125,18 @@ ka_gconf_set_principal (GConfClient* client, Krb5AuthApplet* applet) static gboolean +ka_gconf_set_pk_userid (GConfClient* client, Krb5AuthApplet* applet) +{ + g_free (applet->pk_userid); + if(!ka_gconf_get_string (client, KA_GCONF_KEY_PK_USERID, &applet->pk_userid)) { + applet->pk_userid = NULL; + } + KA_DEBUG("Setting pk_userid to %s", applet->pk_userid ? applet->pk_userid : "<disabled>"); + return TRUE; +} + + +static gboolean ka_gconf_set_prompt_mins (GConfClient* client, Krb5AuthApplet* applet) { if(!ka_gconf_get_int (client, KA_GCONF_KEY_PROMPT_MINS, &applet->pw_prompt_secs)) { @@ -168,6 +181,8 @@ ka_gconf_key_changed_callback (GConfClient* client, ka_gconf_set_prompt_mins (client, applet); } else if (g_strcmp0 (key, KA_GCONF_KEY_SHOW_TRAYICON) == 0) { ka_gconf_set_show_trayicon (client, applet); + } else if (g_strcmp0 (key, KA_GCONF_KEY_PK_USERID) == 0) { + ka_gconf_set_pk_userid (client, applet); } else g_warning("Received notification for unknown gconf key %s", key); return; @@ -195,6 +210,7 @@ ka_gconf_init (Krb5AuthApplet* applet, int argc, char* argv[]) ka_gconf_set_principal (client, applet); ka_gconf_set_prompt_mins (client, applet); ka_gconf_set_show_trayicon (client, applet); + ka_gconf_set_pk_userid(client, applet); success = TRUE; out: diff --git a/src/krb5-auth-notify.c b/src/krb5-auth-notify.c index 3186a47..019662e 100644 --- a/src/krb5-auth-notify.c +++ b/src/krb5-auth-notify.c @@ -18,15 +18,14 @@ */ #include "config.h" - -#ifdef HAVE_LIBNOTIFY - #include "krb5-auth-applet.h" #include "krb5-auth-notify.h" +#ifdef HAVE_LIBNOTIFY +#include <libnotify/notify.h> + void ka_send_event_notification (Krb5AuthApplet *applet, - NotifyUrgency urgency, const char *summary, const char *message, const char *icon) @@ -50,8 +49,18 @@ ka_send_event_notification (Krb5AuthApplet *applet, applet->notification = \ notify_notification_new_with_status_icon(summary, message, notify_icon, applet->tray_icon); - notify_notification_set_urgency (applet->notification, urgency); + notify_notification_set_urgency (applet->notification, NOTIFY_URGENCY_NORMAL); notify_notification_show (applet->notification, NULL); } +#else /* HAVE_LIBNOTIFY */ + +void +ka_send_event_notification (Krb5AuthApplet *applet __attribute__((__unused__)), + const char *summary __attribute__((__unused__)), + const char *message __attribute__((__unused__)), + const char *icon __attribute__((__unused__))) +{ +} + #endif /* HAVE_LIBNOTIFY */ diff --git a/src/krb5-auth-notify.h b/src/krb5-auth-notify.h index 7d27b8a..9c0ce55 100644 --- a/src/krb5-auth-notify.h +++ b/src/krb5-auth-notify.h @@ -21,12 +21,8 @@ #ifndef KRB5_AUTH_NOTIFY_H #define KRB5_AUTH_NOTIFY_H -#include <libnotify/notify.h> - void ka_send_event_notification (Krb5AuthApplet *applet, - NotifyUrgency urgency, const char *summary, const char *message, const char *icon); #endif - |