[gnome-keyring] [prompt] Use 'secure' memory for buffer for prompt password entries.



commit 224ae44851c96f117dbc72c282998b6c200d7298
Author: Stef Walter <stef memberwebs com>
Date:   Sat Dec 19 01:11:05 2009 +0000

    [prompt] Use 'secure' memory for buffer for prompt password entries.

 daemon/prompt/Makefile.am         |    1 +
 daemon/prompt/gkd-prompt-buffer.c |  199 +++++++++++++++++++++++++++++++++++++
 daemon/prompt/gkd-prompt-buffer.h |   59 +++++++++++
 daemon/prompt/gkd-prompt-tool.c   |   26 +++++
 4 files changed, 285 insertions(+), 0 deletions(-)
---
diff --git a/daemon/prompt/Makefile.am b/daemon/prompt/Makefile.am
index 2269fd0..c739fe2 100644
--- a/daemon/prompt/Makefile.am
+++ b/daemon/prompt/Makefile.am
@@ -61,6 +61,7 @@ libexec_PROGRAMS= \
 
 gnome_keyring_prompt_SOURCES = \
 	gkd-prompt-tool.c \
+	gkd-prompt-buffer.c gkd-prompt-buffer.h \
 	gkd-prompt-util.c gkd-prompt-util.h
 
 gnome_keyring_prompt_LDADD = \
diff --git a/daemon/prompt/gkd-prompt-buffer.c b/daemon/prompt/gkd-prompt-buffer.c
new file mode 100644
index 0000000..3e07400
--- /dev/null
+++ b/daemon/prompt/gkd-prompt-buffer.c
@@ -0,0 +1,199 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* egg-secure-buffer.c - secure memory gtkentry buffer
+
+   Copyright (C) 2009 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "gkd-prompt-buffer.h"
+
+#include "egg/egg-secure-memory.h"
+
+#include <string.h>
+
+/* Initial size of buffer, in bytes */
+#define MIN_SIZE 16
+
+struct _GkdPromptBufferPrivate
+{
+	gchar *text;
+	gsize text_size;
+	gsize text_bytes;
+	guint text_chars;
+};
+
+G_DEFINE_TYPE (GkdPromptBuffer, gkd_prompt_buffer, GTK_TYPE_ENTRY_BUFFER);
+
+/* --------------------------------------------------------------------------------
+ * SECURE IMPLEMENTATIONS OF TEXT BUFFER
+ */
+
+static const gchar*
+gkd_prompt_buffer_real_get_text (GtkEntryBuffer *buffer, gsize *n_bytes)
+{
+	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (buffer);
+	if (n_bytes)
+		*n_bytes = self->priv->text_bytes;
+	if (!self->priv->text)
+		return "";
+	return self->priv->text;
+}
+
+static guint
+gkd_prompt_buffer_real_get_length (GtkEntryBuffer *buffer)
+{
+	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (buffer);
+	return self->priv->text_chars;
+}
+
+static guint
+gkd_prompt_buffer_real_insert_text (GtkEntryBuffer *buffer, guint position,
+                                    const gchar *chars, guint n_chars)
+{
+	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (buffer);
+	GkdPromptBufferPrivate *pv = self->priv;
+	gsize n_bytes;
+	gsize at;
+
+	n_bytes = g_utf8_offset_to_pointer (chars, n_chars) - chars;
+
+	/* Need more memory */
+	if (n_bytes + pv->text_bytes + 1 > pv->text_size) {
+
+		/* Calculate our new buffer size */
+		while (n_bytes + pv->text_bytes + 1 > pv->text_size) {
+			if (pv->text_size == 0) {
+				pv->text_size = MIN_SIZE;
+			} else {
+				if (2 * pv->text_size < GTK_ENTRY_BUFFER_MAX_SIZE) {
+					pv->text_size *= 2;
+				} else {
+					pv->text_size = GTK_ENTRY_BUFFER_MAX_SIZE;
+					if (n_bytes > pv->text_size - pv->text_bytes - 1) {
+						n_bytes = pv->text_size - pv->text_bytes - 1;
+						n_bytes = g_utf8_find_prev_char (chars, chars + n_bytes + 1) - chars;
+						n_chars = g_utf8_strlen (chars, n_bytes);
+					}
+					break;
+				}
+			}
+		}
+
+		pv->text = egg_secure_realloc (pv->text, pv->text_size);
+	}
+
+	/* Actual text insertion */
+	at = g_utf8_offset_to_pointer (pv->text, position) - pv->text;
+	g_memmove (pv->text + at + n_bytes, pv->text + at, pv->text_bytes - at);
+	memcpy (pv->text + at, chars, n_bytes);
+
+	/* Book keeping */
+	pv->text_bytes += n_bytes;
+	pv->text_chars += n_chars;
+	pv->text[pv->text_bytes] = '\0';
+
+	gtk_entry_buffer_emit_inserted_text (buffer, position, chars, n_chars);
+	return n_chars;
+}
+
+static guint
+gkd_prompt_buffer_real_delete_text (GtkEntryBuffer *buffer, guint position, guint n_chars)
+{
+	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (buffer);
+	GkdPromptBufferPrivate *pv = self->priv;
+	gsize start, end;
+
+	if (position > pv->text_chars)
+		position = pv->text_chars;
+	if (position + n_chars > pv->text_chars)
+		n_chars = pv->text_chars - position;
+
+	if (n_chars > 0) {
+		start = g_utf8_offset_to_pointer (pv->text, position) - pv->text;
+		end = g_utf8_offset_to_pointer (pv->text, position + n_chars) - pv->text;
+
+		g_memmove (pv->text + start, pv->text + end, pv->text_bytes + 1 - end);
+		pv->text_chars -= n_chars;
+		pv->text_bytes -= (end - start);
+
+		gtk_entry_buffer_emit_deleted_text (buffer, position, n_chars);
+	}
+
+	return n_chars;
+}
+
+/* --------------------------------------------------------------------------------
+ *
+ */
+
+static void
+gkd_prompt_buffer_init (GkdPromptBuffer *self)
+{
+	GkdPromptBufferPrivate *pv;
+	pv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GKD_TYPE_PROMPT_BUFFER, GkdPromptBufferPrivate);
+
+	pv->text = NULL;
+	pv->text_chars = 0;
+	pv->text_bytes = 0;
+	pv->text_size = 0;
+}
+
+static void
+gkd_prompt_buffer_finalize (GObject *obj)
+{
+	GkdPromptBuffer *self = GKD_PROMPT_BUFFER (obj);
+	GkdPromptBufferPrivate *pv = self->priv;
+
+	if (pv->text) {
+		egg_secure_strfree (pv->text);
+		pv->text = NULL;
+		pv->text_bytes = pv->text_size = 0;
+		pv->text_chars = 0;
+	}
+
+	G_OBJECT_CLASS (gkd_prompt_buffer_parent_class)->finalize (obj);
+}
+
+static void
+gkd_prompt_buffer_class_init (GkdPromptBufferClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GtkEntryBufferClass *buffer_class = GTK_ENTRY_BUFFER_CLASS (klass);
+
+	gobject_class->finalize = gkd_prompt_buffer_finalize;
+
+	buffer_class->get_text = gkd_prompt_buffer_real_get_text;
+	buffer_class->get_length = gkd_prompt_buffer_real_get_length;
+	buffer_class->insert_text = gkd_prompt_buffer_real_insert_text;
+	buffer_class->delete_text = gkd_prompt_buffer_real_delete_text;
+
+	g_type_class_add_private (gobject_class, sizeof (GkdPromptBufferPrivate));
+}
+
+/* --------------------------------------------------------------------------------
+ *
+ */
+
+GtkEntryBuffer*
+gkd_prompt_buffer_new (void)
+{
+	return g_object_new (GKD_TYPE_PROMPT_BUFFER, NULL);
+}
diff --git a/daemon/prompt/gkd-prompt-buffer.h b/daemon/prompt/gkd-prompt-buffer.h
new file mode 100644
index 0000000..35a5884
--- /dev/null
+++ b/daemon/prompt/gkd-prompt-buffer.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* egg-secure-buffer.h - secure memory gtkentry buffer
+
+   Copyright (C) 2009 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#ifndef __GKD_PROMPT_BUFFER_H__
+#define __GKD_PROMPT_BUFFER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GKD_TYPE_PROMPT_BUFFER            (gkd_prompt_buffer_get_type ())
+#define GKD_PROMPT_BUFFER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKD_TYPE_PROMPT_BUFFER, GkdPromptBuffer))
+#define GKD_PROMPT_BUFFER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GKD_TYPE_PROMPT_BUFFER, GkdPromptBufferClass))
+#define GKD_IS_PROMPT_BUFFER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKD_TYPE_PROMPT_BUFFER))
+#define GKD_IS_PROMPT_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GKD_TYPE_PROMPT_BUFFER))
+#define GKD_PROMPT_BUFFER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GKD_TYPE_PROMPT_BUFFER, GkdPromptBufferClass))
+
+typedef struct _GkdPromptBuffer            GkdPromptBuffer;
+typedef struct _GkdPromptBufferClass       GkdPromptBufferClass;
+typedef struct _GkdPromptBufferPrivate     GkdPromptBufferPrivate;
+
+struct _GkdPromptBuffer
+{
+	GtkEntryBuffer parent;
+	GkdPromptBufferPrivate *priv;
+};
+
+struct _GkdPromptBufferClass
+{
+	GtkEntryBufferClass parent_class;
+};
+
+GType                     gkd_prompt_buffer_get_type               (void) G_GNUC_CONST;
+
+GtkEntryBuffer*           gkd_prompt_buffer_new                    (void);
+
+G_END_DECLS
+
+#endif /* __GKD_PROMPT_BUFFER_H__ */
diff --git a/daemon/prompt/gkd-prompt-tool.c b/daemon/prompt/gkd-prompt-tool.c
index 1e360e6..96bb054 100644
--- a/daemon/prompt/gkd-prompt-tool.c
+++ b/daemon/prompt/gkd-prompt-tool.c
@@ -22,6 +22,7 @@
 
 #include "config.h"
 
+#include "gkd-prompt-buffer.h"
 #include "gkd-prompt-util.h"
 
 #include "egg/egg-dh.h"
@@ -188,6 +189,30 @@ prepare_buttons (GtkBuilder *builder, GtkDialog *dialog)
 }
 
 static void
+prepare_password_entry (GtkEntry *entry)
+{
+	GtkEntryBuffer *buffer = gkd_prompt_buffer_new ();
+	g_return_if_fail (entry);
+	gtk_entry_set_buffer (entry, buffer);
+	g_object_unref (buffer);
+}
+
+static void
+prepare_passwords (GtkBuilder *builder, GtkDialog *dialog)
+{
+	GtkEntry *entry;
+
+	entry = GTK_ENTRY(gtk_builder_get_object (builder, "password_entry"));
+	prepare_password_entry (entry);
+
+	entry = GTK_ENTRY(gtk_builder_get_object (builder, "original_entry"));
+	prepare_password_entry (entry);
+
+	entry = GTK_ENTRY(gtk_builder_get_object (builder, "confirm_entry"));
+	prepare_password_entry (entry);
+}
+
+static void
 prepare_security (GtkBuilder *builder, GtkDialog *dialog)
 {
 	/*
@@ -219,6 +244,7 @@ prepare_dialog (GtkBuilder *builder)
 	prepare_prompt (builder, dialog);
 	prepare_visibility (builder, dialog);
 	prepare_buttons (builder, dialog);
+	prepare_passwords (builder, dialog);
 	prepare_security (builder, dialog);
 
 	return dialog;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]