commit 1a6fd48def3ed490c5435bfdf4d5317a319479bd
parent 5290fd9e8d0643cbc37a1089eadb1fdb687b88b6
Author: Jaromil <jaromil@dyne.org>
Date:   Mon, 14 Feb 2011 10:24:31 +0100
cleanup of password entry mechanism
using pinentry (with Assuan protocol) instead of our own askpass
a bit less cooler but much more secure.
this also includes partial normalization of variable names
and the redirection of tomb operational output to stderr.
Diffstat:
4 files changed, 75 insertions(+), 411 deletions(-)
diff --git a/doc/Makefile.am b/doc/Makefile.am
@@ -6,4 +6,3 @@ EXTRA_DIST = Luks_on_disk_format.pdf New_methods_in_HD_encryption.pdf TKS1-draft
 install-data-hook:
 	ln -sf $(mandir)/man1/tomb.1 $(mandir)/man1/tomb-open.1
 	ln -sf $(mandir)/man1/tomb.1 $(mandir)/man1/tomb-status.1
-	ln -sf $(mandir)/man1/tomb.1 $(mandir)/man1/tomb-askpass.1-
\ No newline at end of file
diff --git a/src/Makefile.am b/src/Makefile.am
@@ -1,16 +1,12 @@
 
 bin_SCRIPTS = tomb tomb-open
 
-bin_PROGRAMS = tomb-status tomb-askpass
+bin_PROGRAMS = tomb-status
 
 tomb_status_SOURCES = tomb-status.c
 tomb_status_LDADD = @GTK2_LIBS@ @NOTIFY_LIBS@
 tomb_status_CFLAGS = @GTK2_CFLAGS@ @NOTIFY_CFLAGS@
 
-tomb_askpass_SOURCES = tomb-askpass.c
-tomb_askpass_LDADD = @GTK2_LIBS@
-tomb_askpass_CFLAGS = @GTK2_CFLAGS@
-
 EXTRA_DIST = monmort.xpm
 pixmapdir = $(datadir)/pixmaps
 pixmap_DATA = monmort.xpm
diff --git a/src/tomb b/src/tomb
@@ -27,10 +27,10 @@ DATE=Feb/2011
 
 # standard output message routines
 # it's always useful to wrap them, in case we change behaviour later
-notice() { if ! [ $QUIET ]; then echo "[*] $1"; fi }
-act()    { if ! [ $QUIET ]; then echo " .  $1"; fi }
-error()  { if ! [ $QUIET ]; then echo "[!] $1"; fi }
-func()   { if [ $DEBUG ]; then echo "[D] $1"; fi }
+notice() { if ! [ $QUIET ]; then echo "[*] $1" >&2; fi }
+act()    { if ! [ $QUIET ]; then echo " .  $1" >&2; fi }
+error()  { if ! [ $QUIET ]; then echo "[!] $1" >&2; fi }
+func()   { if [ $DEBUG ]; then   echo "[D] $1" >&2; fi }
 
 # which dd command to use
 which dcfldd > /dev/null
@@ -157,37 +157,31 @@ ask_usbkey() {
     return 0
 }
 
-# user interface (just to ask the password)
+# we use pinentry now
+# comes from gpg project and is much more secure
+# it also conveniently uses the right toolkit
 ask_password() {
 
-    xhost 2>&1 >/dev/null
-    if [ $? = 0 ]; then # we have access to the X display
-	
-	which tomb-askpass > /dev/null
-	if [ $? = 0 ]; then
-	    export scolopendro="`tomb-askpass ${1} 2>/dev/null`"
-	    return
-	fi
-	which ssh-askpass # 2>&1 > /dev/null
-	if [ $? = 0 ]; then
-	    export scolopendro="`ssh-askpass "Tomb: provide the password to unlock"`"
-	    return
-	fi
-	
-    else # we'll collect the password from commandline
-	
-	act "Tomb: provide the password to unlock"
-	echo -n " >  "
-	read -s scolopendro
-	export scolopendro
+    # pinentry has no custom icon setting
+    # so we need to temporary modify the gtk theme
+    cp ~/.gtkrc-2.0 ~/.gtkrc-2.0.bak
+    cat <<EOF  >> ~/.gtkrc-2.0
+    pixmap_path "/usr/local/share/pixmaps"
+    style "normal" { stock["gtk-dialog-authentication"] = {{"monmort.xpm"}} }
+    widget "*" style "normal"
+EOF
 
-    fi
+    cat <<EOF | pinentry | awk '/^D/ { print $2 }'
+SETTITLE Opening Tomb $1
+SETDESC You need a password to use its key
+SETPROMPT Password:
+GETPIN
+EOF
+
+    # restore gtk as it was
+    cp ~/.gtkrc-2.0.bak ~/.gtkrc-2.0
+    rm ~/.gtkrc-2.0.bak
 
-    # just in case we'd like to have dialog supported too:
-    # 	    dialog --backtitle "This file is encrypted for privacy protection" \
-    # 		--title "Security check" --insecure \
-    # 		--passwordbox "Enter password:" 10 30 2> /var/run/.scolopendro
-	    
 }
 
 # popup notification
@@ -247,18 +241,21 @@ check_priv() {
 	if [ $? = 0 ]; then
 	    func "Using sudo for root execution of 'tomb ${(f)ARGS}'"
 	    # check if sudo has a timestamp active
-	    sudo -n true 2> /dev/null
-	    if [ $? != 0 ]; then
-		# if not then ask a password
-		echo "SETDESC Sudo execution of Tomb ${ARGS[@]}
+	    sudok=false
+	    sudo -n tomb 2> /dev/null
+	    if [ $? != 0 ]; then # if not then ask a password
+		cat <<EOF | pinentry | awk '/^D/ { print $2 }' | sudo -S -v
+SETTITLE Super user privileges required
+SETDESC Sudo execution of Tomb ${ARGS[@]}
 SETPROMPT Insert your USER password:
-GETPIN" | pinentry | awk '/^D/ { print $2 }' | sudo -S -v
+GETPIN
+EOF
 	    fi
 	    sudo "tomb" ${(s: :)ARGS}
 	    exit $?
-	fi
+	fi # have sudo
 	return 1
-    fi
+    fi # are we root already
     return 0
 }
 
@@ -409,17 +406,17 @@ create_tomb() {
     # here user is prompted for key password
     for c in 1 2 3; do
 	# 3 tries to write two times a matching password
-	ask_password ${FILE}
-	scolotemp=$scolopendro
-	ask_password "${FILE} (again)"
-	if [ "$scolotemp" = "$scolopendro" ]; then
+	tombpass=`exec_as_user tomb -q askpass ${FILE}`
+	tombpasstmp=$tombpass
+	tombpass=`exec_as_user tomb -q askpass "${FILE} (again)"`
+	if [ "$tombpasstmp" = "$tombpass" ]; then
 	    break;
 	fi
-	unset $scolotemp
-	unset $scolopendro
+	unset tombpasstmp
+	unset tombpass
     done
 
-    if [ -z $scolopendro ]; then
+    if [ -z $tombpass ]; then
 	error "passwords don't match, aborting operation"
 	umount ${keytmp}
 	losetup -d $nstloop
@@ -427,8 +424,9 @@ create_tomb() {
 	exit 1
     fi
 
-    echo "${scolopendro}" | gpg --batch --no-options --no-tty --passphrase-fd 0 \
+    echo "${tombpass}" | gpg --batch --no-options --no-tty --passphrase-fd 0 \
 	-o "${FILE}.gpg" -c -a ${keytmp}/tomb.tmp
+
     if [ $? = 2 ]; then
 	error "setting password failed: gnupg returns 2"
 	umount ${keytmp}
@@ -491,7 +489,7 @@ create_tomb() {
 	    cp -v ${FILE}.gpg ${usbkey_mount}/.tomb/
 	    chmod -R go-rwx ${usbkey_mount}/.tomb
 	    umount ${usbkey_mount}
-	    unset  ${usbkey_mount}
+	    unset usbkey_mount
 	    notice "Key ${FILE}.gpg succesfully saved on your USB"
 	    act "now we proceed opening your new tomb"
 	    KEY=${FILE}.gpg
@@ -503,6 +501,8 @@ create_tomb() {
     else # kept besides (deprecated behaviour)
 	act "now we proceed opening your new tomb"
 	KEY=${FILE}.gpg
+	unset CMD2
+	unset CMD3
 	mount_tomb ${FILE}
     fi
 
@@ -515,7 +515,6 @@ mount_tomb() {
 	return 1
     elif [ -r $CMD2 ]; then
 	tombfile=`basename $CMD2`
-	tombdir=`dirname $CMD2`
     else
         # try also adding a .tomb extension
 	tombfile=${tombfile%%\.*}.tomb
@@ -525,6 +524,8 @@ mount_tomb() {
 	fi
     fi
 
+    tombdir=`dirname $CMD2`
+
     file ${tombdir}/${tombfile} | grep -i 'luks encrypted.*cbc-essiv' 2>&1 >/dev/null
     if [ $? != 0 ]; then
 	error "$CMD2 is not a valid tomb file, operation aborted"
@@ -533,7 +534,7 @@ mount_tomb() {
     fi
 
     tombname=${tombfile%%\.*}
-    act "mounting tomb named after $tombname"
+    act "mounting tomb named $tombname"
 
     if [ $KEY ]; then
 	tombkey="`basename $KEY`"
@@ -564,14 +565,14 @@ mount_tomb() {
     fi
 
     if ! [ $CMD3 ]; then
-	tombmount=/media/`basename ${tombfile}`
+	tombmount=/media/${tombfile}
 	act "mountpoint not specified, using default: $tombmount"
     elif ! [ -x $CMD3 ]; then
 	error "mountpoint $CMD3 doesn't exist, operation aborted."
 	if [ -n "$usbkey_mount" ]; then
 	    umount $usbkey_mount
 	    rmdir  $usbkey_mount
-	    unset  $usbkey_mount
+	    unset usbkey_mount
 	fi
 	return 1
     else
@@ -611,16 +612,16 @@ mount_tomb() {
     for c in 1 2 3; do
 	
 	if [ $c = 1 ]; then
-	    ask_password ${keyname}
+	    tombpass=`exec_as_user tomb -q askpass ${keyname}`
 	else
-	    ask_password "$keyname (retry $c)"
+	    tombpass=`exec_as_user tomb -q askpass "$keyname (retry $c)"`
 	fi
-	echo "${scolopendro}" \
+	echo "${tombpass}" \
 	    | gpg --batch --passphrase-fd 0 --no-tty --no-options \
-	          -d "${tombkeypath}" 2>/dev/null \
+	          -d "${tombkeypath}"  \
 	    | cryptsetup --key-file - luksOpen ${nstloop} ${mapper}
 	
-	unset scolopendro
+	unset tombpass
 	
 	if [ -r /dev/mapper/${mapper} ]; then
 	    break;  # password was correct
@@ -631,7 +632,7 @@ mount_tomb() {
     if [ -r ${usbkey_mount}/.tomb/${tombkey} ]; then
         umount ${usbkey_mount}
 	rmdir  ${usbkey_mount}
-	unset  ${usbkey_mount}
+	unset  usbkey_mount
     fi
     
     if ! [ -r /dev/mapper/${mapper} ]; then
@@ -644,7 +645,7 @@ mount_tomb() {
     act "encrypted storage filesystem check"
     fsck -p -C0 /dev/mapper/${mapper}
     act "tomb engraved as $tombname"
-    tune2fs -L ${tombname} /dev/mapper/${mapper}
+    tune2fs -L ${tombname} /dev/mapper/${mapper} > /dev/null
 
     mount -o rw,noatime,nodev /dev/mapper/${mapper} ${tombmount}
 
@@ -681,17 +682,17 @@ encode_key() {
     # here user is prompted for key password
     for c in 1 2 3; do
 	# 3 tries to write two times a matching password
-	ask_password ${FILE}
-	scolotemp=$scolopendro
-	ask_password "${FILE} (again)"
-	if [ "$scolotemp" = "$scolopendro" ]; then
+	tombpass=`exec_as_user tomb -q askpass ${FILE}`
+	tombpasstmp=$tombpass
+	tombpass=`exec_as_user tomb -q askpass "${FILE} (again)"`
+	if [ "$tombpasstmp" = "$tombpass" ]; then
 	    break;
 	fi
-	unset $scolotemp
-	unset $scolopendro
+	unset tombpasstmp
+	unset tombpass
     done
 
-    if [ -z $scolopendro ]; then
+    if [ -z $tombpass ]; then
 	error "passwords don't match, aborting operation."
 	return 1
     fi
@@ -702,7 +703,7 @@ encode_key() {
 /^Comment/ {next}
 {print $0}' ${tombkey} \
     | steghide embed --embedfile - --coverfile ${imagefile} \
-      -p ${scolopendro} -z 9 -e serpent cbc
+      -p ${tombpass} -z 9 -e serpent cbc
     if [ $? != 0 ]; then
 	error "encoding error: steghide reports problems"
 	res=1
@@ -711,7 +712,7 @@ encode_key() {
 	res=0
     fi
 
-    unset scolopendro
+    unset tombpass
 
     return $res
 }
@@ -731,11 +732,11 @@ decode_key() {
     notice "Decoding a key out of image $imagefile"
     for c in 1 2 3; do
 	if [ $c = 1 ]; then
-	    ask_password ${keyname}
+	    tombpass=`exec_as_user tomb -q askpass ${keyname}`
 	else
-	    ask_password "$keyname (retry $c)"
+	    tombpass=`exec_as_user tomb -q askpass "$keyname (retry $c)"`
 	fi
-	steghide extract -sf ${imagefile} -p ${scolopendro} -xf - \
+	steghide extract -sf ${imagefile} -p ${tombpass} -xf - \
 	    | awk '
 BEGIN {
 print "-----BEGIN PGP MESSAGE-----"
@@ -753,7 +754,7 @@ print "-----END PGP MESSAGE-----"
 	fi
     done
 
-    unset scolopendro
+    unset tombpass
 
     if [ $res != 0 ]; then
 	error "nothing found."
@@ -1030,6 +1031,7 @@ case "$CMD" in
 
     install)  check_priv ; install_tomb ;;
 
+    askpass)  ask_password $CMD2 $CMD3 ;;
     status)   tomb-status ;;
     notify)   tomb-notify $CMD2 $CMD3 ;;
 
@@ -1039,4 +1041,4 @@ case "$CMD" in
 	;;
 esac
 # return codes from called functions
-return $?
+# return $?
diff --git a/src/tomb-askpass.c b/src/tomb-askpass.c
@@ -1,332 +0,0 @@
-/* Tomb askpass
-   
-   Derived from gtk-led-askpass.c version 0.9
-   by Dafydd Harries <daf@muse.19inch.net>, 2003 2004
-   (An ssh-askpass alike software)
-   
-   Based on ideas from ssh-askpass-gnome, by Damien Miller and Nalin Dahyabhai,
-   and on Jim Knoble's x11-ssh-askpass.
-   
-   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 3 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
-   
-   See also:
-   
-   http://www.cgabriel.org/sw/gtk2-ssh-askpass/
-   -- Jim Knoble's x11-ssh-askpass
-   http://www.cgabriel.org/sw/gtk2-ssh-askpass/
-   -- Christopher Gabriel's gtk2-ssh-askpass
-   
-   Todo:
-
-   - Internationalise. Probably entails autotoolising.
-   - Add more eye candy.
-   - Implement optional mouse/server grabbing.
-   - Alow overriding the title on the command line.
-   - Make the LED box a proper GTK+ widget.
-   
-*/
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-
-/* The Tomb icon is an artwork by Jordi aka MonMort
-   a nomadic graffiti artist from Barcelona */
-#include <monmort.xpm>
-
-/* Title for the dialog. */
-#define TITLE "Unlocking tomb"
-
-/* Width of each LED. */
-#define LED_WIDTH 8
-/* Height of each LED. */
-#define LED_HEIGHT 16
-/* Space around and between LEDs. */
-#define LED_MARGIN 5
-/* Number of LEDs to have. */
-#define LED_COUNT 12
-
-/* How many times to attempt to grab the keyboard before giving up. */
-#define GRAB_TRIES_MAX 10
-/* How long to sleep, in microseconds, in between keyboard grab attempts. */
-#define GRAB_SLEEP 100000
-/* Sleep length, in milliseconds, after Control-U press. */
-#define CLEAR_SLEEP 800
-
-enum {
-	LED_STATE_OFF,
-	LED_STATE_GREEN,
-	LED_STATE_RED,
-	LED_STATES
-};
-
-GdkPixbuf *pb_monmort;
-
-GdkColor colours[LED_STATES] = {
-	/* LED_STATE_OFF */
-	{ 0, 0x3333, 0x6666, 0x3333 },
-	/* LED_STATE_GREEN */
-	{ 0, 0x6666, 0xFFFF, 0x6666 },
-	/* LED_STATE_RED */
-	{ 0, 0xDDDD, 0x3333, 0x3333 }
-};
-
-
-void draw_led(GtkWidget *widget, gint state, guint offset)
-{
-	GdkGC *gc = gdk_gc_new(widget->window);
-
-	/* Draw the border. */
-	gdk_draw_rectangle(widget->window,
-		widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
-		FALSE,
-		LED_MARGIN + offset * (LED_WIDTH + LED_MARGIN),
-		LED_MARGIN,
-		LED_WIDTH,
-		LED_HEIGHT);
-
-	gdk_gc_set_rgb_fg_color(gc, &(colours[state]));
-
-	/* Draw the inside rectangle. */
-	gdk_draw_rectangle(widget->window,
-		gc,
-		TRUE,
-		LED_MARGIN + offset * (LED_WIDTH + LED_MARGIN) + 1,
-		LED_MARGIN + 1,
-		LED_WIDTH - 1,
-		LED_HEIGHT - 1);
-}
-
-gboolean led_area_expose_handler(GtkWidget *led_area, GdkEventExpose *event,
-	GString *passphrase)
-{
-	gint i, width, height;
-	gint length = passphrase->len;
-
-	gdk_drawable_get_size(GDK_DRAWABLE(led_area->window), &width, &height);
-
-	/* Draw a focus indicator if appropriate. */
-	if (GTK_WIDGET_HAS_FOCUS(led_area))
-		gtk_paint_focus(led_area->style, led_area->window,
-			GTK_WIDGET_STATE(led_area), &(event->area), led_area,
-			"", 0, 0, width, height);
-
-	/* Draw each LED. */
-	for (i = 0; i < LED_COUNT; i++) {
-		/* This is the complicated bit. */
-		gboolean on = ((length / LED_COUNT) % 2 == 0) ?
-				(length % LED_COUNT >  i) :
-				(length % LED_COUNT <= i);
-
-		draw_led(led_area, on ? LED_STATE_GREEN : LED_STATE_OFF, i);
-	}
-
-	/* TRUE means not to propagate the event. */
-	return TRUE;
-}
-
-gboolean timeout_handler(GtkWidget *led_area)
-{
-	gtk_widget_queue_draw(led_area);
-
-	return FALSE;
-}
-
-void clear(GString *passphrase, GtkWidget *led_area)
-{
-	gint i;
-
-	/*
-	Delete bit by bit to ensure erasure. g_string_erase() will overwrite
-	the last character with 0, so we shouldn't need to worry about leaving
-	sensitive data in memory. Note that the string may be empty. This is
-	so that the interface responds consistently.
-	*/
-	while (passphrase->len > 0)
-		g_string_erase(passphrase, passphrase->len - 1, 1);
-
-	for (i = 0; i < LED_COUNT; i++)
-		draw_led(led_area, LED_STATE_RED, i);
-
-	/*
-	Remove the redness after a delay. If an exposure is triggered, such as
-	by a key getting pressed, then the redraw will simply happen early.
-	*/
-	gtk_timeout_add(CLEAR_SLEEP, (GtkFunction)timeout_handler, led_area);
-}
-
-gboolean led_area_key_press_handler(GtkWidget *led_area, GdkEventKey *event,
-				    GString *passphrase) {
-  /* Obtain Unicode representation of key released. */
-  gunichar c = gdk_keyval_to_unicode(event->keyval);
-  /* Determine whether the key released was printable. */
-  gint isprint = g_unichar_isprint(c);
-  /* Obtain default modifier mask. */
-  guint modifiers = gtk_accelerator_get_default_mod_mask();
-  
-  if (event->keyval == GDK_Delete) {
-    clear(passphrase, led_area);
-    return TRUE;
-  }
-
-  if ((event->state & modifiers) == GDK_CONTROL_MASK) {
-
-    if (event->keyval == GDK_u) {
-      /* C-u -- delete everything. */
-      clear(passphrase, led_area);
-      /* Return early in order to avoid the redraw. */
-      return TRUE;
-
-    } else {
-
-      /* Unrecognised keypress. */
-      return FALSE;
-    }
-    
-  } else if (event->keyval == GDK_BackSpace && passphrase->len > 0) {
-    /*
-      Backspace -- remove last character. See the comment above
-      about g_string_erase.
-    */
-    g_string_erase(passphrase, passphrase->len - 1, 1);
-	} else if (isprint) {
-		/* Printable character. */
-		g_string_append_unichar(passphrase, c);
-	} else {
-		/* Unrecognized keypress, propagate. */
-		return FALSE;
-	}
-
-	/* Trigger a redraw of the LED area. */
-	gtk_widget_queue_draw(led_area);
-
-	/* TRUE means not to propagate the event. */
-	return TRUE;
-}
-
-gboolean led_area_button_press_handler(GtkWidget *led_area,
-	GdkEventButton *event, gpointer data)
-{
-	gtk_widget_grab_focus(led_area);
-
-	return TRUE;
-}
-
-int main(int argc, char *argv[])
-{
-	gint response, grab_tries, i;
-	char keyname[256];
-	GString *passphrase = g_string_new("");
-	GtkWidget *dialog, *alignment, *led_area;
-	GList tmplist;
-
-	gtk_set_locale();
-	gtk_init(&argc, &argv);
-
-	if (argc > 1) {
-	  snprintf(keyname,255,"%s",argv[1]);
-	} else {
-	  sprintf(keyname,"unknown");
-	}
-	/*
-	dialog
-	`- vbox (implicit)
-	   `- aligment
-	      `- led_area
-	*/
-
-	/* Question dialog with no parent; OK and Cancel buttons. */
-	dialog = gtk_message_dialog_new_with_markup
-	  (NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK,
-	   "Enter the password to unlock\n"
-	   "<span font=\"Times 24\">%s</span>", keyname);
-	gtk_window_set_title(GTK_WINDOW(dialog), TITLE);
-
-	// set and show the image icon
-	pb_monmort = gdk_pixbuf_new_from_xpm_data(monmort);
-	tmplist.data = (gpointer*)pb_monmort;
-	tmplist.prev = tmplist.next = NULL;
-	gtk_window_set_icon_list(GTK_WINDOW(dialog), &tmplist);
-	gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(dialog), 
-				     gtk_image_new_from_pixbuf(pb_monmort));
-
-	/* Place the dialog in the middle of the screen. */
-	gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
-	/* OK is the default action. */
-	gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
-	
-	/* Add some spacing within the dialog's vbox. */
-	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), 3);
-
-	/* The alignment widget containing the drawing area. */
-	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
-	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), alignment);
-
-	/* The drawing area for the LEDs. */
-	led_area = gtk_drawing_area_new();
-	gtk_container_add(GTK_CONTAINER(alignment), led_area);
-	/* Make the LED widget focusable. */
-	GTK_WIDGET_SET_FLAGS(led_area, GTK_CAN_FOCUS);
-	/* Make the LED widget focused. */
-	gtk_widget_grab_focus(led_area);
-	/* Make the LED widget receive key press and button press events. */
-	gtk_widget_add_events(led_area,
-		GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK);
-	/* Set a size request. */
-	gtk_widget_set_size_request(led_area,
-		LED_MARGIN + (LED_WIDTH + LED_MARGIN) * LED_COUNT,
-		LED_HEIGHT + LED_MARGIN * 2);
-	/* Set up handler for key releases. */
-	g_signal_connect(G_OBJECT(led_area), "key_press_event",
-		G_CALLBACK(led_area_key_press_handler), passphrase);
-	/* Set up handler for button releases. */
-	g_signal_connect(G_OBJECT(led_area), "button_press_event",
-		G_CALLBACK(led_area_button_press_handler), NULL);
-	/* Set up handler for expose events. */
-	g_signal_connect(G_OBJECT(led_area), "expose_event",
-		G_CALLBACK(led_area_expose_handler), passphrase);
-
-	
-	/* Show all the widgets. */
-	gtk_widget_show_all(dialog);
-	/* Put the dialog on the screen now for the grab to work. */
-	gtk_widget_show_now(dialog);
-
-	/* Grab the keyboard */
-	gdk_keyboard_grab(GTK_WIDGET(dialog)->window, FALSE, GDK_CURRENT_TIME);
-	
-	/* Make the dialog stay on top. */
-	gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
-
-	/* Run the dialog. */
-	response = gtk_dialog_run(GTK_DIALOG(dialog));
-
-	/* Ungrab the keyboard. */
-	gdk_keyboard_ungrab(GDK_CURRENT_TIME);
-
-	/* If the OK button was pressed, print the passphrase. */
-	if (response == GTK_RESPONSE_OK)
-		g_print("%s\n", passphrase->str);
-
-	/* Scrub the passphrase, if any. */
-	for (i = 0; i < passphrase->len; i++)
-		passphrase->str[i] = '\0';
-
-	if (response == GTK_RESPONSE_OK)
-		return 0;
-
-	return 1;
-}
-