diff --git a/configure.ac b/configure.ac
index 3156056..4b07544 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,7 @@ GCONF_REQUIRED="2.8"
 LIBNOTIFY_REQUIRED="0.4"
 GIO_UNIX_REQUIRED="0.0"
 GIO_REQUIRED="0.0"
+GNOME_KEYRING_REQUIRED="2.22.0"
 
 dnl check for deprecated symbols:
 dnl GNOME_MAINTAINER_MODE_DEFINES
@@ -40,6 +41,7 @@ PKG_CHECK_MODULES(DBUS, dbus-glib-1 >= $DBUS_REQUIRED)
 PKG_CHECK_MODULES(GCONF, gconf-2.0 >= $GCONF_REQUIRED)
 PKG_CHECK_MODULES(GIO_UNIX, gio-unix-2.0 >= $GIO_UNIX_REQUIRED)
 PKG_CHECK_MODULES(GIO, gio-2.0 >= $GIO_REQUIRED)
+PKG_CHECK_MODULES(GNOME_KEYRING, gnome-keyring-1 >= $GNOME_KEYRING_REQUIRED)
 
 AM_GCONF_SOURCE_2
 
@@ -230,6 +232,7 @@ AC_MSG_NOTICE([         kerberos: $KRB5_CFLAGS $KRB5_LIBS])
 AC_MSG_NOTICE([              gtk: $GTK_CFLAGS $GTK_LIBS])
 AC_MSG_NOTICE([             dbus: $DBUS_CFLAGS $DBUS_LIBS])
 AC_MSG_NOTICE([            gconf: $GCONF_CFLAGS $GCONF_LIBS])
+AC_MSG_NOTICE([    gnome-keyring: $GNOME_KEYRING_CFLAGS $GNOME_KEYRING_LIBS])
 AC_MSG_NOTICE([         gio-unix: $GIO_UNIX_CFLAGS $GIO_UNIX_LIBS $GIO_CFLAGS $GIO_LIBS])
 if test "$with_libnotify" = "yes" ; then
 AC_MSG_NOTICE([        libnotify: $LIBNOTIFY_CFLAGS $LIBNOTIFY_LIBS])
diff --git a/src/Makefile.am b/src/Makefile.am
index 92ab201..d3329d0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,6 +33,8 @@ krb5_auth_dialog_SOURCES =	\
 	krb5-auth-gconf-tools.h	\
 	krb5-auth-dbus.c	\
 	krb5-auth-dbus.h	\
+	krb5-auth-keyring.c	\
+	krb5-auth-keyring.h	\
 	dummy-strings.c		\
 	$(NULL)
 
@@ -48,6 +50,7 @@ krb5_auth_dialog_CFLAGS = \
 	$(GTK_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(GCONF_CFLAGS) \
+	$(GNOME_KEYRING_CFLAGS) \
 	$(KRB5_CFLAGS) \
 	$(NETWORK_MANAGER_CFLAGS) \
 	$(LIBNOTIFY_CFLAGS) \
@@ -64,6 +67,7 @@ krb5_auth_dialog_LDADD = \
 	$(LIBNOTIFY_LIBS) \
 	$(DBUS_LIBS) \
 	$(GCONF_LIBS) \
+	$(GNOME_KEYRING_LIBS) \
 	$(GIO_LIBS) \
 	$(GTK_LIBS) \
 	$(NULL)
diff --git a/src/krb5-auth-applet.c b/src/krb5-auth-applet.c
index a9a840e..fd5a613 100644
--- a/src/krb5-auth-applet.c
+++ b/src/krb5-auth-applet.c
@@ -47,6 +47,7 @@ enum
   KA_PROP_TGT_FORWARDABLE,
   KA_PROP_TGT_PROXIABLE,
   KA_PROP_TGT_RENEWABLE,
+  KA_PROP_USE_KEYRING,
 };
 
 struct _KaApplet {
@@ -81,6 +82,15 @@ struct _KaAppletPrivate
 	gboolean tgt_forwardable;	/* request a forwardable ticket */
 	gboolean tgt_renewable;		/* request a renewable ticket */
 	gboolean tgt_proxiable;		/* request a proxiable ticket */
+
+	/* Optional gnome keyring */
+	gboolean use_keyring;           /* use_keyring */
+	gboolean kr_only;               /* use gnome keyring only */
+	struct kr_items {               /* keyring items */
+		size_t num;
+		gchar **prompt;
+		gchar **passwd;
+	} kr;
 };
 
 static void
@@ -135,6 +145,11 @@ ka_applet_set_property (GObject      *object,
 	KA_DEBUG ("%s: %s", pspec->name, self->priv->tgt_renewable ? "True" : "False");
 	break;
 
+    case KA_PROP_USE_KEYRING:
+	self->priv->use_keyring = g_value_get_boolean (value);
+	KA_DEBUG ("%s: %s", pspec->name, self->priv->use_keyring ? "True" : "False");
+	break;
+
     default:
 	/* We don't have any other property... */
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -184,6 +199,10 @@ ka_applet_get_property (GObject    *object,
 	g_value_set_boolean (value, self->priv->tgt_renewable);
 	break;
 
+    case KA_PROP_USE_KEYRING:
+	g_value_set_boolean (value, self->priv->use_keyring);
+	break;
+
     default:
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 	break;
@@ -318,6 +337,15 @@ ka_applet_class_init(KaAppletClass *klass)
 	g_object_class_install_property (object_class,
                                          KA_PROP_TGT_RENEWABLE,
                                          pspec);
+
+	pspec = g_param_spec_boolean("use-keyring",
+				     "Use Gnome keyring",
+				     "wether to usr Gnome keyring",
+				     FALSE,
+				     G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+	g_object_class_install_property (object_class,
+                                         KA_PROP_USE_KEYRING,
+                                         pspec);
 }
 
 
@@ -662,6 +690,54 @@ ka_applet_get_pwdialog(const KaApplet* applet)
 	return applet->priv->pwdialog;
 }
 
+gboolean
+ka_applet_get_use_keyring(const KaApplet* applet)
+{
+	return applet->priv->use_keyring;
+}
+
+gboolean
+ka_applet_get_kr_only(const KaApplet* applet)
+{
+	return applet->priv->kr_only;
+}
+
+void
+ka_applet_set_kr_only(const KaApplet* applet, gboolean kr_only)
+{
+	applet->priv->kr_only = kr_only;
+}
+
+size_t
+ka_applet_get_kr_num(const KaApplet* applet)
+{
+	return applet->priv->kr.num;
+}
+
+void
+ka_applet_set_kr_num(const KaApplet* applet, size_t kr_num)
+{
+	applet->priv->kr.num = kr_num;
+}
+
+gchar ***
+ka_applet_get_kr_prompt(const KaApplet* applet)
+{
+	return &applet->priv->kr.prompt;
+}
+
+gchar ***
+ka_applet_get_kr_passwd(const KaApplet* applet)
+{
+	return &applet->priv->kr.passwd;
+}
+
+gchar *
+ka_applet_get_pk_userid(const KaApplet* applet)
+{
+	return applet->priv->pk_userid;
+}
+
 /* create the tray icon applet */
 KaApplet*
 ka_applet_create(GtkBuilder *xml)
diff --git a/src/krb5-auth-applet.h b/src/krb5-auth-applet.h
index 9f2dcf1..304c71d 100644
--- a/src/krb5-auth-applet.h
+++ b/src/krb5-auth-applet.h
@@ -54,6 +54,14 @@ void ka_applet_set_tgt_renewable(KaApplet* applet, gboolean renewable);
 gboolean ka_applet_get_tgt_renewable(const KaApplet* applet);
 guint ka_applet_get_pw_prompt_secs(const KaApplet* applet);
 KaPwDialog* ka_applet_get_pwdialog(const KaApplet* applet);
+gboolean ka_applet_get_use_keyring(const KaApplet* applet);
+gboolean ka_applet_get_kr_only(const KaApplet* applet);
+void ka_applet_set_kr_only(const KaApplet* applet, gboolean kr_only);
+size_t ka_applet_get_kr_num(const KaApplet* applet);
+void ka_applet_set_kr_num(const KaApplet* applet, size_t kr_num);
+gchar*** ka_applet_get_kr_prompt(const KaApplet* applet);
+gchar*** ka_applet_get_kr_passwd(const KaApplet* applet);
+gchar* ka_applet_get_pk_userid(const KaApplet* applet);
 
 /* create the applet */
 KaApplet* ka_applet_create(GtkBuilder* xml);
diff --git a/src/krb5-auth-dialog.c b/src/krb5-auth-dialog.c
index 778491d..bb5fa48 100644
--- a/src/krb5-auth-dialog.c
+++ b/src/krb5-auth-dialog.c
@@ -38,6 +38,7 @@
 
 #include "krb5-auth-dialog.h"
 #include "krb5-auth-applet.h"
+#include "krb5-auth-keyring.h"
 #include "krb5-auth-pwdialog.h"
 #include "krb5-auth-gconf.h"
 #include "krb5-auth-dbus.h"
@@ -262,14 +263,31 @@ auth_dialog_prompter (krb5_context ctx G_GNUC_UNUSED,
 	canceled = FALSE;
 	canceled_creds_expiry = 0;
 
+	ka_keyring_free_items (applet);
+	ka_keyring_alloc_items (applet, num_prompts);
+
 	for (i = 0; i < num_prompts; i++) {
 		const gchar *password = NULL;
 		int password_len = 0;
 		int response;
 		guint32 source_id;
+		GnomeKeyringResult rc;
 
 		errcode = KRB5_LIBOS_CANTREADPWD;
 
+		/* try gnome keyring first */
+		rc = ka_keyring_find_password (applet, prompts, i);
+		if (rc == GNOME_KEYRING_RESULT_OK) {
+			gchar ***passwd = ka_applet_get_kr_passwd (applet);
+
+			prompts[i].reply->data = (char *) (*passwd)[i];
+			prompts[i].reply->length = strlen ((*passwd)[i]);
+			errcode = 0;
+			continue;
+		} else if (ka_applet_get_kr_only(applet)) { /* no popup */
+			goto cleanup;
+		}
+
 		source_id = g_timeout_add_seconds (5, (GSourceFunc)krb5_auth_dialog_do_updates, applet);
 		ka_pwdialog_setup (pwdialog, (gchar *) prompts[i].prompt, invalid_auth);
 		response = ka_pwdialog_run (pwdialog);
@@ -278,6 +296,12 @@ auth_dialog_prompter (krb5_context ctx G_GNUC_UNUSED,
 			case GTK_RESPONSE_OK:
 				password = ka_pwdialog_get_password(pwdialog);
 				password_len = strlen (password);
+
+				/* got new, store in gnome keyring */
+				ka_keyring_store_password (applet,
+				                           prompts[i].prompt,
+				                           password);
+
 				break;
 			case GTK_RESPONSE_DELETE_EVENT:
 			case GTK_RESPONSE_CANCEL:
@@ -357,8 +381,17 @@ credentials_expiring (gpointer *data)
 		}
 
 		/* no popup when using a trayicon */
-		if (ka_applet_get_show_trayicon(applet))
+		if (ka_applet_get_show_trayicon(applet)) {
+			/* try gnome keyring once */
+			if (ka_applet_get_use_keyring(applet)) {
+				KA_DEBUG("Tray icon visible, keyring only try");
+				ka_applet_set_kr_only(applet, TRUE);
+				retval = grab_credentials (applet);
+				ka_applet_set_kr_only(applet, FALSE);
+			}
+
 			goto out;
+		}
 
 		give_up = canceled && (creds_expiry == canceled_creds_expiry);
 		if (!give_up) {
@@ -650,6 +683,10 @@ grab_credentials (KaApplet* applet)
 			case HX509_PKCS11_LOGIN:
 #endif 				/* Invalid password/pin, try again. */
 				invalid_auth = TRUE;
+
+				/* get rid of old passwords, they may be bad */
+				ka_keyring_delete_passwords (applet);
+
 				break;
 			default:
 				KA_DEBUG("Auth failed with %d: %s", retval,
@@ -666,6 +703,7 @@ grab_credentials (KaApplet* applet)
 	if (retval)
 		goto out;
 out:
+	ka_keyring_free_items (applet);
 	krb5_free_cred_contents (kcontext, &my_creds);
 	krb5_cc_close (kcontext, ccache);
 out2:
diff --git a/src/krb5-auth-dialog.schemas.in b/src/krb5-auth-dialog.schemas.in
index bc3143e..904dd8b 100644
--- a/src/krb5-auth-dialog.schemas.in
+++ b/src/krb5-auth-dialog.schemas.in
@@ -103,5 +103,18 @@
         <long>Requested tickets should be proxiable</long>
       </locale>
     </schema>
+
+    <schema>
+      <key>/schemas/apps/krb5-auth-dialog/use_keyring</key>
+      <applyto>/apps/krb5-auth-dialog/use_keyring</applyto>
+      <owner>krb5-auth-dialog</owner>
+      <type>bool</type>
+      <default>0</default>
+
+      <locale name="C">
+        <short>Use keyring</short>
+        <long>Use keyring to store Kerberos passwords</long>
+      </locale>
+    </schema>
   </schemalist>
 </gconfschemafile>
diff --git a/src/krb5-auth-gconf-tools.h b/src/krb5-auth-gconf-tools.h
index 9f9020f..b11066e 100644
--- a/src/krb5-auth-gconf-tools.h
+++ b/src/krb5-auth-gconf-tools.h
@@ -34,6 +34,7 @@
 #define KA_GCONF_KEY_FORWARDABLE	KA_GCONF_PATH "/forwardable"
 #define KA_GCONF_KEY_RENEWABLE		KA_GCONF_PATH "/renewable"
 #define KA_GCONF_KEY_PROXIABLE		KA_GCONF_PATH "/proxiable"
+#define KA_GCONF_KEY_USE_KEYRING	KA_GCONF_PATH "/use_keyring"
 
 gboolean ka_gconf_get_string (GConfClient* client, const char* key, char** value);
 gboolean ka_gconf_get_int (GConfClient* client, const char* key, int* value);
diff --git a/src/krb5-auth-gconf.c b/src/krb5-auth-gconf.c
index fec5457..3db1924 100644
--- a/src/krb5-auth-gconf.c
+++ b/src/krb5-auth-gconf.c
@@ -135,6 +135,20 @@ ka_gconf_set_tgt_proxiable (GConfClient* client, KaApplet* applet)
 }
 
 
+static gboolean
+ka_gconf_set_use_keyring (GConfClient* client, KaApplet* applet)
+{
+	gboolean use_keyring = FALSE;
+
+	if(!ka_gconf_get_bool(client, KA_GCONF_KEY_USE_KEYRING, &use_keyring)) {
+		use_keyring = FALSE;
+	}
+	g_object_set(applet, "use-keyring", use_keyring, NULL);
+	KA_DEBUG("Use keyring: %s", (use_keyring ? "yes" : "no" ));
+	return TRUE;
+}
+
+
 static void
 ka_gconf_key_changed_callback (GConfClient* client,
                                guint cnxn_id G_GNUC_UNUSED,
@@ -165,6 +179,8 @@ ka_gconf_key_changed_callback (GConfClient* client,
 		ka_gconf_set_tgt_renewable (client, applet);
 	} else if (g_strcmp0 (key, KA_GCONF_KEY_PROXIABLE) == 0) {
 		ka_gconf_set_tgt_proxiable (client, applet);
+	} else if (g_strcmp0 (key, KA_GCONF_KEY_USE_KEYRING) == 0) {
+		ka_gconf_set_use_keyring (client, applet);
 	} else
 		g_warning("Received notification for unknown gconf key %s", key);
 	return;
@@ -199,6 +215,7 @@ ka_gconf_init (KaApplet* applet,
 	ka_gconf_set_tgt_forwardable(client, applet);
 	ka_gconf_set_tgt_renewable(client, applet);
 	ka_gconf_set_tgt_proxiable(client, applet);
+	ka_gconf_set_use_keyring(client, applet);
 
 	success = TRUE;
 out:
diff --git a/src/krb5-auth-keyring.c b/src/krb5-auth-keyring.c
new file mode 100644
index 0000000..2dbe340
--- /dev/null
+++ b/src/krb5-auth-keyring.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2009 Bojan Smojver, Rexursive
+ *
+ * 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 "krb5-auth-keyring.h"
+
+/* keyring schema */
+static const GnomeKeyringPasswordSchema krb5_schema = {
+	GNOME_KEYRING_ITEM_GENERIC_SECRET,
+	{ 
+		{ "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
+		{ "prompt", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
+		{ NULL, 0 }
+	},
+	NULL, NULL, NULL
+};
+
+/* allocate keyring items */
+void ka_keyring_alloc_items (KaApplet* applet, int num_prompts)
+{
+	gchar ***prompt, ***passwd, *pk_userid;
+
+	prompt = ka_applet_get_kr_prompt(applet);
+	passwd = ka_applet_get_kr_passwd(applet);
+	pk_userid = ka_applet_get_pk_userid(applet);
+
+        /* never use keyring if using pkinit */
+	if (ka_applet_get_use_keyring(applet) && !(pk_userid && *pk_userid)) {
+		ka_applet_set_kr_num(applet, num_prompts);
+		*prompt = g_malloc0 (num_prompts * sizeof(**prompt));
+		*passwd = g_malloc0 (num_prompts * sizeof(**passwd));
+	}
+}
+
+/* free keyring items */
+void ka_keyring_free_items (KaApplet* applet)
+{
+	size_t num;
+	gchar ***prompt, ***passwd;
+
+	num = ka_applet_get_kr_num(applet);
+	prompt = ka_applet_get_kr_prompt(applet);
+	passwd = ka_applet_get_kr_passwd(applet);
+
+	/* free this even if keyring use was turned off */
+	if (*prompt) {
+		size_t i;
+
+		for (i = 0; i < num; i++) {
+			if ((*passwd)[i])
+				gnome_keyring_free_password ((*passwd)[i]);
+			if ((*prompt)[i])
+				g_free ((*prompt)[i]);
+		}
+		g_free (*passwd);
+		g_free (*prompt);
+
+		*prompt = *passwd = NULL;
+		ka_applet_set_kr_num(applet, 0);
+	}
+}
+
+/* find keyring password */
+GnomeKeyringResult
+ka_keyring_find_password (KaApplet* applet, krb5_prompt prompts[], int i)
+{
+	gchar ***prompt, ***passwd;
+
+	prompt = ka_applet_get_kr_prompt(applet);
+	passwd = ka_applet_get_kr_passwd(applet);
+
+	/* if keyring use was turned on after allocation, don't crash */
+	if (ka_applet_get_use_keyring(applet) && *prompt) {
+		GnomeKeyringResult rc;
+
+		(*prompt)[i] = g_strdup (prompts[i].prompt);
+
+		rc = gnome_keyring_find_password_sync(&krb5_schema,
+		                                      &(*passwd)[i],
+		                                      "application",
+		                                      "krb5-auth-dialog",
+		                                      "prompt",
+		                                      prompts[i].prompt,
+		                                      NULL);
+
+		return rc;
+	}
+	else {
+		return GNOME_KEYRING_RESULT_NO_MATCH;
+	}
+}
+
+/* store keyring password */
+void
+ka_keyring_store_password (KaApplet* applet,
+                           const char *prompt, const gchar *password)
+{
+	if (ka_applet_get_use_keyring(applet) &&
+	    *ka_applet_get_kr_prompt(applet)) {
+		gnome_keyring_store_password_sync(&krb5_schema,
+		                                  GNOME_KEYRING_DEFAULT,
+		                                  prompt, password,
+		                                  "application",
+		                                  "krb5-auth-dialog",
+		                                  "prompt", prompt,
+		                                  NULL);
+	}
+}
+
+/* delete keyring passwords */
+void ka_keyring_delete_passwords (KaApplet* applet)
+{
+	size_t num;
+	gchar ***prompt;
+
+	num = ka_applet_get_kr_num(applet);
+	prompt = ka_applet_get_kr_prompt(applet);
+
+	if (*prompt) {
+		size_t i;
+
+		/* delete bad passwords, even if keyring use was turned off */
+		for (i = 0; i < num; i++)
+			gnome_keyring_delete_password_sync(&krb5_schema,
+			                                   "application",
+			                                   "krb5-auth-dialog",
+			                                   "prompt",
+			                                   (*prompt)[i],
+			                                   NULL);
+	}
+}
diff --git a/src/krb5-auth-keyring.h b/src/krb5-auth-keyring.h
new file mode 100644
index 0000000..03406e2
--- /dev/null
+++ b/src/krb5-auth-keyring.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 Bojan Smojver, Rexursive
+ *
+ * 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.
+ *
+ */
+
+#ifndef KRB5_AUTH_KEYRING
+#define KRB5_AUTH_KEYRING
+
+#include <gnome-keyring.h>
+
+#include "krb5-auth-applet.h"
+
+void ka_keyring_alloc_items (KaApplet* applet, int num_prompts);
+void ka_keyring_free_items (KaApplet* applet);
+GnomeKeyringResult ka_keyring_find_password (KaApplet* applet,
+                                             krb5_prompt prompts[], int i);
+void ka_keyring_store_password (KaApplet* applet,
+                                const char *prompt, const gchar *password);
+void ka_keyring_delete_passwords (KaApplet* applet);
+
+#endif
