-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 NotDashEscaped: You need GnuPG to verify this message This is a patch file to create version 0.7.4 from 0.7.3. Please check the signature of this patch file: zcat somepath/pinentry-0.7.3-0.7.4.diff.gz | gpg --verify Change to directory pinentry-0.7.3 (or however you renamed it) and give this command: zcat somepath/pinentry-0.7.3-0.7.4.diff.gz | patch -p1 It is a good idea to rename your current directory to pinentry-0.7.4 now. diff -urpNP pinentry-0.7.3/ChangeLog pinentry-0.7.4/ChangeLog --- pinentry-0.7.3/ChangeLog 2007-07-06 12:40:34.000000000 +0000 +++ pinentry-0.7.4/ChangeLog 2007-11-29 13:59:41.000000000 +0000 @@ -1,3 +1,71 @@ +2007-11-29 Marcus Brinkmann + + Released 0.7.4. + +2007-11-19 Werner Koch + + * doc/pinentry.texi (Protocol): Typo fixes by Bernhard Herzog. + Describe SETQUALITYBAR_TT. + +2007-11-19 Bernhard Herzog (wk) + + * qt/pinentrydialog.cpp (PinEntryDialog): Fixed crash + +2007-11-19 Werner Koch + + * gtk+-2/pinentry-gtk-2.c (create_window): Use again map-event and + unmap-event as this works on my setup far more reliable than + expose-event/no-expose-event. + + * gtk+-2/gtksecentry.c (get_cursor_time): s/time/blinktime/ t + avoid shadowing warning. + + * pinentry/pinentry.h (struct pinentry): Change QUALITY_BAR to a + char ptr. + (struct pinentry): Add QUALITY_BAR_TT. + * pinentry/pinentry.c (cmd_setqualitybar): Allow to set a label text. + (cmd_setqualitybar_tt): New. + * gtk+-2/pinentry-gtk-2.c (create_window): Take label and tooltip + from global. + * qt/pinentrydialog.h (setQualityBar, setQualityBarTT) + (_quality_bar_label): New. + * qt/pinentrydialog.cpp (setQualityBar, setQualityBarTT): New. + (PinEntryDialog): Remove setting of tooltip. + + * qt/main.cpp (qt_cmd_handler): Propagate quality bar label and tootip. + +2007-11-19 Bernhard Herzog (wk) + + * qt/pinentrydialog.cpp (PinEntryDialog): Move the quality bar + below the text entry and align them properly. Show a tooltip. + * gtk+-2/pinentry-gtk-2.c (create_window): Ditto. Don't let it + change its height. + (QUALITYBAR_EMPTY_TEXT): New. + +2007-09-18 Werner Koch + + * qt/secqlineedit.h (SecQLineEdit): New signal textModified. + * qt/secqlineedit.cpp (finishChange): Emit it. + * qt/pinentrydialog.cpp (setPinentryInfo): New. + (PinEntryDialog): Add arg ENABLE_QUALITY_BAR. + * qt/pinentrydialog.h (setPinentryInfo): New. + (PinEntryDialog): Add arg ENABLE_QUALITY_BAR. + + * pinentry/pinentry.h (struct pinentry): Add member QUALITY_BAR + and CTX_ASSUAN. + * pinentry/pinentry.c (cmd_setqualitybar): New. + (copy_and_escape): New. + (pinentry_inq_quality): New. + +2007-07-09 Werner Koch + + * doc/pinentry.texi: Fixed direntry syntax. + + * configure.ac: Add --without-libcap. From the Gentoo patch archive. + + * gtk+-2/pinentry-gtk-2.c (create_window): Use expose-event + instead of map-event. From Alon Bar-Lev. + 2007-07-06 Werner Koch Released 0.7.3. diff -urpNP pinentry-0.7.3/NEWS pinentry-0.7.4/NEWS --- pinentry-0.7.3/NEWS 2007-07-06 12:33:00.000000000 +0000 +++ pinentry-0.7.4/NEWS 2007-11-29 13:58:55.000000000 +0000 @@ -1,3 +1,10 @@ +Noteworthy changes in version 0.7.4 (2007-11-29) +------------------------------------------------ + + * Pinentry-gtk-2 and pinentry-qt now support a simple passphrase + quality indicator. + + Noteworthy changes in version 0.7.3 (2007-07-06) ------------------------------------------------ diff -urpNP pinentry-0.7.3/THANKS pinentry-0.7.4/THANKS --- pinentry-0.7.3/THANKS 2007-06-14 16:51:38.000000000 +0000 +++ pinentry-0.7.4/THANKS 2007-08-09 20:52:49.000000000 +0000 @@ -1,3 +1,4 @@ +Alon Bar-Lev alon.barlev@gmail.com Albrecht Dress albrecht.dress@arcor.de Alexander Zangerl az at snafu.priv.at Michael Nottebrock michaelnottebrock at gmx.net diff -urpNP pinentry-0.7.3/TODO pinentry-0.7.4/TODO --- pinentry-0.7.3/TODO 2007-01-24 17:18:32.000000000 +0000 +++ pinentry-0.7.4/TODO 2007-11-28 22:57:55.000000000 +0000 @@ -17,3 +17,7 @@ * The gtk+-2 pinentry needs auditing. * Implement the one_button feature in Qt. + +* The format of the Assuan protocol description should be changed to + the one used by GnuPG. + diff -urpNP pinentry-0.7.3/assuan/assuan-util.c pinentry-0.7.4/assuan/assuan-util.c --- pinentry-0.7.3/assuan/assuan-util.c 2005-09-03 10:55:14.000000000 +0000 +++ pinentry-0.7.4/assuan/assuan-util.c 2007-11-28 22:57:55.000000000 +0000 @@ -161,7 +161,7 @@ _assuan_log_print_buffer (FILE *fp, cons void _assuan_log_sanitized_string (const char *string) { - const unsigned char *s = string; + const unsigned char *s = (const unsigned char*)string; #ifdef HAVE_JNLIB_LOGGING FILE *fp = log_get_stream (); #else diff -urpNP pinentry-0.7.3/configure pinentry-0.7.4/configure --- pinentry-0.7.3/configure 2007-07-06 13:16:57.000000000 +0000 +++ pinentry-0.7.4/configure 2007-11-29 14:00:17.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for pinentry 0.7.3. +# Generated by GNU Autoconf 2.61 for pinentry 0.7.4. # # Report bugs to . # @@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='pinentry' PACKAGE_TARNAME='pinentry' -PACKAGE_VERSION='0.7.3' -PACKAGE_STRING='pinentry 0.7.3' +PACKAGE_VERSION='0.7.4' +PACKAGE_STRING='pinentry 0.7.4' PACKAGE_BUGREPORT='gnupg-devel@gnupg.org' ac_unique_file="pinentry/pinentry.h" @@ -1289,7 +1289,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pinentry 0.7.3 to adapt to many kinds of systems. +\`configure' configures pinentry 0.7.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1363,7 +1363,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pinentry 0.7.3:";; + short | recursive ) echo "Configuration of pinentry 0.7.4:";; esac cat <<\_ACEOF @@ -1395,6 +1395,7 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --without-libcap Disable support for capabilities library --with-ncurses-include-dir=DIR Set directory containing the include files for use with -lncurses, when it isn't installed as @@ -1492,7 +1493,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pinentry configure 0.7.3 +pinentry configure 0.7.4 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1506,7 +1507,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pinentry $as_me 0.7.3, which was +It was created by pinentry $as_me 0.7.4, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -6000,7 +6001,15 @@ _ACEOF fi -# Extract the first word of "setcap", so it can be a program name with args. + +# Check whether --with-libcap was given. +if test "${with_libcap+set}" = set; then + withval=$with_libcap; +fi + + +if test "x$with_libcap" != "xno"; then + # Extract the first word of "setcap", so it can be a program name with args. set dummy setcap; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } @@ -6042,7 +6051,7 @@ echo "${ECHO_T}no" >&6; } fi -{ echo "$as_me:$LINENO: checking for cap_set_proc in -lcap" >&5 + { echo "$as_me:$LINENO: checking for cap_set_proc in -lcap" >&5 echo $ECHO_N "checking for cap_set_proc in -lcap... $ECHO_C" >&6; } if test "${ac_cv_lib_cap_cap_set_proc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -6110,10 +6119,11 @@ cat >>confdefs.h <<\_ACEOF #define USE_CAPABILITIES 1 _ACEOF - LIBCAP=-lcap + LIBCAP=-lcap fi +fi # Check whether --enable-pinentry-curses was given. @@ -11265,7 +11275,7 @@ for i in $qt_incdirs; do for j in $kde_qt_header; do - echo "configure: 11268: $i/$j" >&5 + echo "configure: 11278: $i/$j" >&5 if test -r "$i/$j"; then echo "taking that" >&5 qt_incdir=$i @@ -12163,7 +12173,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pinentry $as_me 0.7.3, which was +This file was extended by pinentry $as_me 0.7.4, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12216,7 +12226,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -pinentry config.status 0.7.3 +pinentry config.status 0.7.4 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff -urpNP pinentry-0.7.3/configure.ac pinentry-0.7.4/configure.ac --- pinentry-0.7.3/configure.ac 2007-07-06 12:40:23.000000000 +0000 +++ pinentry-0.7.4/configure.ac 2007-11-29 13:59:12.000000000 +0000 @@ -1,6 +1,6 @@ # configure.ac # Copyright (C) 1999 Robert Bihlmeyer -# Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH +# Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH # # This file is part of PINENTRY. # @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Remember to remove the "-cvs" suffix *before* a release and to bump the # version number immediately *after* a release and to re-append the suffix. -AC_INIT(pinentry, 0.7.3, [gnupg-devel@gnupg.org]) +AC_INIT(pinentry, 0.7.4, [gnupg-devel@gnupg.org]) AM_CONFIG_HEADER(config.h) AC_CONFIG_SRCDIR(pinentry/pinentry.h) AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION) @@ -116,11 +116,17 @@ dnl Checks for libsecmem. GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF) GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF) -AC_PATH_PROG(SETCAP, setcap, :, "$PATH:/sbin:/usr/sbin") -AC_CHECK_LIB(cap, cap_set_proc, [ - AC_DEFINE(USE_CAPABILITIES,1,[The capabilities support library is installed]) - LIBCAP=-lcap -]) +dnl Check for libcap +AC_ARG_WITH([libcap], AC_HELP_STRING([--without-libcap], + [Disable support for capabilities library])) + +if test "x$with_libcap" != "xno"; then + AC_PATH_PROG(SETCAP, setcap, :, "$PATH:/sbin:/usr/sbin") + AC_CHECK_LIB(cap, cap_set_proc, [ + AC_DEFINE(USE_CAPABILITIES,1,[The capabilities support library is installed]) + LIBCAP=-lcap + ]) +fi AC_SUBST(LIBCAP) dnl diff -urpNP pinentry-0.7.3/doc/pinentry.texi pinentry-0.7.4/doc/pinentry.texi --- pinentry-0.7.3/doc/pinentry.texi 2007-01-24 17:23:14.000000000 +0000 +++ pinentry-0.7.4/doc/pinentry.texi 2007-11-28 22:57:55.000000000 +0000 @@ -62,7 +62,7 @@ section entitled ``Copying''. @ifnottex @dircategory GNU Utilities @direntry -* pinentry:: Ask securely for a passphrase or PIN. +* pinentry: (pinentry). Ask securely for a passphrase or PIN. @end direntry This file documents the use and the internals of the @pinentry{}. @@ -276,6 +276,33 @@ a GETPIN or CONFIRM, and is only display S: OK @end example +@item Enable a passphrase quality indicator +Adds a quality indicator to the GETPIN window. This indicator is +updated as the passphrase is typed. The clients needs to implement an +inquiry named "QUALITY" which gets passed the current passpharse +(percent-plus escaped) and should send back a string with a single +numerical vauelue between -100 and 100. Negative values will be +displayed in red. +@example + C: SETQUALITYBAR + S: OK +@end example + +If a custom label for the quality bar is required, just add that label +as an argument as percent escaped string. You will need this feature to +translate the label because pinentry has no internal gettext except for +stock strings from the toolkit library. + +If you want to show a tooltip for the quality bar, you may use +@example + C: SETQUALITYBAR_TT string + S: OK +@end example + +@noindent +With STRING being a percent escaped string shown as the tooltip. + + @item Ask for a PIN The meat of this tool is to ask for a passphrase of PIN, it is done with this command: diff -urpNP pinentry-0.7.3/doc/stamp-vti pinentry-0.7.4/doc/stamp-vti --- pinentry-0.7.3/doc/stamp-vti 2007-07-06 13:17:19.000000000 +0000 +++ pinentry-0.7.4/doc/stamp-vti 2007-11-29 14:02:23.000000000 +0000 @@ -1,4 +1,4 @@ -@set UPDATED 24 January 2007 -@set UPDATED-MONTH January 2007 -@set EDITION 0.7.3 -@set VERSION 0.7.3 +@set UPDATED 28 November 2007 +@set UPDATED-MONTH November 2007 +@set EDITION 0.7.4 +@set VERSION 0.7.4 diff -urpNP pinentry-0.7.3/doc/version.texi pinentry-0.7.4/doc/version.texi --- pinentry-0.7.3/doc/version.texi 2007-07-06 12:42:28.000000000 +0000 +++ pinentry-0.7.4/doc/version.texi 2007-11-29 14:02:23.000000000 +0000 @@ -1,4 +1,4 @@ -@set UPDATED 24 January 2007 -@set UPDATED-MONTH January 2007 -@set EDITION 0.7.3 -@set VERSION 0.7.3 +@set UPDATED 28 November 2007 +@set UPDATED-MONTH November 2007 +@set EDITION 0.7.4 +@set VERSION 0.7.4 diff -urpNP pinentry-0.7.3/gtk+-2/gtksecentry.c pinentry-0.7.4/gtk+-2/gtksecentry.c --- pinentry-0.7.3/gtk+-2/gtksecentry.c 2005-09-03 10:55:15.000000000 +0000 +++ pinentry-0.7.4/gtk+-2/gtksecentry.c 2007-11-28 22:57:55.000000000 +0000 @@ -3210,11 +3210,11 @@ static gint get_cursor_time(GtkSecureEntry * entry) { GtkSettings *settings = gtk_widget_get_settings(GTK_WIDGET(entry)); - gint time; + gint blinktime; - g_object_get(settings, "gtk-cursor-blink-time", &time, NULL); + g_object_get(settings, "gtk-cursor-blink-time", &blinktime, NULL); - return time; + return blinktime; } static void diff -urpNP pinentry-0.7.3/gtk+-2/pinentry-gtk-2.c pinentry-0.7.4/gtk+-2/pinentry-gtk-2.c --- pinentry-0.7.3/gtk+-2/pinentry-gtk-2.c 2007-01-24 17:13:38.000000000 +0000 +++ pinentry-0.7.4/gtk+-2/pinentry-gtk-2.c 2007-11-28 22:57:55.000000000 +0000 @@ -1,6 +1,6 @@ /* pinentry-gtk-2.c Copyright (C) 1999 Robert Bihlmeyer - Copyright (C) 2001, 2002 g10 Code GmbH + Copyright (C) 2001, 2002, 2007 g10 Code GmbH Copyright (C) 2004 by Albrecht Dreß pinentry-gtk-2 is a pinentry application for the Gtk+-2 widget set. @@ -56,13 +56,22 @@ static int passphrase_ok; static int confirm_yes; static GtkWidget *entry; +static GtkWidget *qualitybar; static GtkWidget *insure; static GtkWidget *time_out; +static GtkTooltips *tooltips; /* Gnome hig small and large space in pixels. */ #define HIG_SMALL 6 #define HIG_LARGE 12 +/* The text shown in the quality bar when no text is shown. This is not + * the empty string, becase because with an empty string the height of + * the quality bar is less than with a non-empty string. This results + * in ugly layout changes when the text changes from non-empty to empty + * and vice versa */ +#define QUALITYBAR_EMPTY_TEXT " " + /* Constrain size of the window the window should not shrink beyond the requisition, and should not grow vertically. */ @@ -181,15 +190,60 @@ pinentry_utf8_validate (gchar *text) } +/* Handler called for "changed". We use it to update the quality + indicator. */ +static void +changed_text_handler (GtkWidget *widget) +{ + char textbuf[50]; + const char *s; + int length; + int percent; + GdkColor color = { 0, 0, 0, 0}; + + if (!qualitybar || !pinentry->quality_bar) + return; + + s = gtk_secure_entry_get_text (GTK_SECURE_ENTRY (widget)); + if (!s) + s = ""; + length = strlen (s); + percent = length? pinentry_inq_quality (pinentry, s, length) : 0; + if (!length) + { + strcpy(textbuf, QUALITYBAR_EMPTY_TEXT); + color.red = 0xffff; + } + else if (percent < 0) + { + snprintf (textbuf, sizeof textbuf, "(%d%%)", -percent); + color.red = 0xffff; + percent = -percent; + } + else + { + snprintf (textbuf, sizeof textbuf, "%d%%", percent); + color.green = 0xffff; + } + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (qualitybar), + (double)percent/100.0); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (qualitybar), textbuf); + gtk_widget_modify_bg (qualitybar, GTK_STATE_PRELIGHT, &color); +} + + + static GtkWidget * create_window (int confirm_mode) { GtkWidget *w; - GtkWidget *win, *box, *ebox; + GtkWidget *win, *box; GtkWidget *wvbox, *chbox, *bbox; GtkAccelGroup *acc; gchar *msg; + tooltips = gtk_tooltips_new (); + /* FIXME: check the grabbing code against the one we used with the old gpg-agent */ win = gtk_window_new (GTK_WINDOW_TOPLEVEL); @@ -237,7 +291,7 @@ create_window (int confirm_mode) g_free (msg); gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_box_pack_start (GTK_BOX (box), w, TRUE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (box), w, TRUE, FALSE, 0); } if (pinentry->error && !confirm_mode) { @@ -252,26 +306,56 @@ create_window (int confirm_mode) gtk_widget_modify_fg (w, GTK_STATE_NORMAL, &color); } - ebox = gtk_hbox_new (FALSE, HIG_SMALL); - gtk_box_pack_start (GTK_BOX(box), ebox, FALSE, FALSE, 0); + qualitybar = NULL; if (!confirm_mode) { + GtkWidget* table = gtk_table_new (pinentry->quality_bar ? 2 : 1, 2, + FALSE); + gtk_box_pack_start (GTK_BOX (box), table, FALSE, FALSE, 0); + if (pinentry->prompt) { msg = pinentry_utf8_validate (pinentry->prompt); w = gtk_label_new (msg); g_free (msg); - gtk_box_pack_start (GTK_BOX (ebox), w, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5); + gtk_table_attach (GTK_TABLE (table), w, 0, 1, 0, 1, + GTK_FILL, GTK_FILL, 4, 0); } + entry = gtk_secure_entry_new (); gtk_widget_set_size_request (entry, 200, -1); g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (enter_callback), entry); - gtk_box_pack_start (GTK_BOX (ebox), entry, TRUE, TRUE, 0); + g_signal_connect (G_OBJECT (entry), "changed", + G_CALLBACK (changed_text_handler), entry); + gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, + GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0); gtk_widget_grab_focus (entry); gtk_widget_show (entry); + if (pinentry->quality_bar) + { + msg = pinentry_utf8_validate (pinentry->quality_bar); + w = gtk_label_new (msg); + g_free (msg); + gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5); + gtk_table_attach (GTK_TABLE (table), w, 0, 1, 1, 2, + GTK_FILL, GTK_FILL, 4, 0); + qualitybar = gtk_progress_bar_new(); + gtk_widget_add_events (qualitybar, + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (qualitybar), + QUALITYBAR_EMPTY_TEXT); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (qualitybar), 0.0); + if (pinentry->quality_bar_tt) + gtk_tooltips_set_tip (GTK_TOOLTIPS (tooltips), qualitybar, + pinentry->quality_bar_tt, ""); + gtk_table_attach (GTK_TABLE (table), qualitybar, 1, 2, 1, 2, + GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0); + } + if (pinentry->enhanced) { GtkWidget *sbox = gtk_hbox_new (FALSE, HIG_SMALL); diff -urpNP pinentry-0.7.3/pinentry/pinentry.c pinentry-0.7.4/pinentry/pinentry.c --- pinentry-0.7.3/pinentry/pinentry.c 2007-06-14 16:51:38.000000000 +0000 +++ pinentry-0.7.4/pinentry/pinentry.c 2007-11-28 22:57:55.000000000 +0000 @@ -1,5 +1,5 @@ /* pinentry.c - The PIN entry support library - Copyright (C) 2002, 2003 g10 Code GmbH + Copyright (C) 2002, 2003, 2007 g10 Code GmbH This file is part of PINENTRY. @@ -69,11 +69,14 @@ struct pinentry pinentry = 0, /* Result. */ 0, /* Locale error flag. */ 0, /* One-button flag. */ + NULL, /* Quality-Bar flag and description. */ + NULL, /* Quality-Bar tooltip. */ PINENTRY_COLOR_DEFAULT, 0, PINENTRY_COLOR_DEFAULT, PINENTRY_COLOR_DEFAULT, - 0 + 0, + NULL /* Assuan context. */ }; @@ -208,6 +211,111 @@ pinentry_local_to_utf8 (char *lc_ctype, } #endif + +/* Copy TEXT or TEXTLEN to BUFFER and escape as required. Return a + pointer to the end of the new buffer. Note that BUFFER must be + large enough to keep the entire text; allocataing it 3 times of + TEXTLEN is sufficient. */ +static char * +copy_and_escape (char *buffer, const void *text, size_t textlen) +{ + int i; + const unsigned char *s = (unsigned char *)text; + char *p = buffer; + + for (i=0; i < textlen; i++) + { + if (s[i] < ' ' || s[i] == '+') + { + snprintf (p, 4, "%%%02X", s[i]); + p += 3; + } + else if (s[i] == ' ') + *p++ = '+'; + else + *p++ = s[i]; + } + return p; +} + + + +/* Run a quality inquiry for PASSPHRASE of LENGTH. (We need LENGTH + because not all backends might be able to return a proper + C-string.). Returns: A value between -100 and 100 to give an + estimate of the passphrase's quality. Negative values are use if + the caller won't even accept that passphrase. Note that we expect + just one data line which should not be escaped in any represent a + numeric signed decimal value. Extra data is currently ignored but + should not be send at all. */ +int +pinentry_inq_quality (pinentry_t pin, const char *passphrase, size_t length) +{ + ASSUAN_CONTEXT ctx = pin->ctx_assuan; + const char prefix[] = "INQUIRE QUALITY "; + char *command; + char *line; + size_t linelen; + int gotvalue = 0; + int value = 0; + int rc; + + if (!ctx) + return 0; /* Can't run the callback. */ + + if (length > 300) + length = 300; /* Limit so that it definitely fits into an Assuan + line. */ + + command = secmem_malloc (strlen (prefix) + 3*length + 1); + if (!command) + return 0; + strcpy (command, prefix); + copy_and_escape (command + strlen(command), passphrase, length); + rc = assuan_write_line (ctx, command); + secmem_free (command); + if (rc) + { + fprintf (stderr, "ASSUAN WRITE LINE failed: rc=%d\n", rc); + return 0; + } + + for (;;) + { + do + { + rc = assuan_read_line (ctx, &line, &linelen); + if (rc) + { + fprintf (stderr, "ASSUAN READ LINE failed: rc=%d\n", rc); + return 0; + } + } + while (*line == '#' || !linelen); + if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D' + && (!line[3] || line[3] == ' ')) + break; /* END command received*/ + if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N' + && (!line[3] || line[3] == ' ')) + break; /* CAN command received*/ + if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' + && (!line[3] || line[3] == ' ')) + break; /* ERR command received*/ + if (line[0] != 'D' || line[1] != ' ' || linelen < 3 || gotvalue) + continue; + gotvalue = 1; + value = atoi (line+2); + } + if (value < -100) + value = -100; + else if (value > 100) + value = 100; + + return value; +} + + + /* Try to make room for at least LEN bytes in the pinentry. Returns new buffer on success and 0 on failure or when the old buffer is sufficient. */ @@ -533,7 +641,7 @@ option_handler (ASSUAN_CONTEXT ctx, cons } -/* note, that it is sufficient to allocate the target string D as +/* Note, that it is sufficient to allocate the target string D as long as the source string S, i.e.: strlen(s)+1; */ static void strcpy_escaped (char *d, const unsigned char *s) @@ -638,6 +746,49 @@ cmd_setcancel (ASSUAN_CONTEXT ctx, char } + +static int +cmd_setqualitybar (ASSUAN_CONTEXT ctx, char *line) +{ + char *newval; + + if (!*line) + line = "Quality:"; + + newval = malloc (strlen (line) + 1); + if (!newval) + return ASSUAN_Out_Of_Core; + + strcpy_escaped (newval, line); + if (pinentry.quality_bar) + free (pinentry.quality_bar); + pinentry.quality_bar = newval; + return 0; +} + +/* Set the tooltip to be used for a quality bar. */ +static int +cmd_setqualitybar_tt (ASSUAN_CONTEXT ctx, char *line) +{ + char *newval; + + if (*line) + { + newval = malloc (strlen (line) + 1); + if (!newval) + return ASSUAN_Out_Of_Core; + + strcpy_escaped (newval, line); + } + else + newval = NULL; + if (pinentry.quality_bar_tt) + free (pinentry.quality_bar_tt); + pinentry.quality_bar_tt = newval; + return 0; +} + + static int cmd_getpin (ASSUAN_CONTEXT ctx, char *line) { @@ -654,8 +805,9 @@ cmd_getpin (ASSUAN_CONTEXT ctx, char *li } pinentry.locale_err = 0; pinentry.one_button = 0; - + pinentry.ctx_assuan = ctx; result = (*pinentry_cmd_handler) (&pinentry); + pinentry.ctx_assuan = NULL; if (pinentry.error) { free (pinentry.error); @@ -664,6 +816,8 @@ cmd_getpin (ASSUAN_CONTEXT ctx, char *li if (set_prompt) pinentry.prompt = NULL; + pinentry.quality_bar = 0; /* Reset it after the command. */ + if (result < 0) { if (pinentry.pin) @@ -704,6 +858,7 @@ cmd_confirm (ASSUAN_CONTEXT ctx, char *l int result; pinentry.one_button = !!strstr (line, "--one-button"); + pinentry.quality_bar = 0; pinentry.locale_err = 0; result = (*pinentry_cmd_handler) (&pinentry); if (pinentry.error) @@ -726,6 +881,7 @@ cmd_message (ASSUAN_CONTEXT ctx, char *l int result; pinentry.one_button = 1; + pinentry.quality_bar = 0; pinentry.locale_err = 0; result = (*pinentry_cmd_handler) (&pinentry); if (pinentry.error) @@ -759,6 +915,8 @@ register_commands (ASSUAN_CONTEXT ctx) { "GETPIN", 0, cmd_getpin }, { "CONFIRM", 0, cmd_confirm }, { "MESSAGE", 0, cmd_message }, + { "SETQUALITYBAR", 0, cmd_setqualitybar }, + { "SETQUALITYBAR_TT", 0, cmd_setqualitybar_tt }, { NULL } }; int i, j, rc; diff -urpNP pinentry-0.7.3/pinentry/pinentry.h pinentry-0.7.4/pinentry/pinentry.h --- pinentry-0.7.3/pinentry/pinentry.h 2007-06-14 16:51:38.000000000 +0000 +++ pinentry-0.7.4/pinentry/pinentry.h 2007-11-28 22:57:55.000000000 +0000 @@ -91,12 +91,25 @@ struct pinentry dismiss button is required. */ int one_button; + /* If this is not NULL, a passphrase quality indicator is shown. + There will also be an inquiry back to the caller to get an + indication of the quality for the passphrase entered so far. The + string is used as a labe for the auality bar. */ + char *quality_bar; + + /* The tooltip to be show for the qualitybar. Malloced or NULL. */ + char *quality_bar_tt; + /* For the curses pinentry, the color of error messages. */ pinentry_color_t color_fg; int color_fg_bright; pinentry_color_t color_bg; pinentry_color_t color_so; int color_so_bright; + + /* Fo the quality indicator we need to do an inquiry. Thus we need + to save the assuan ctx. */ + void *ctx_assuan; }; typedef struct pinentry *pinentry_t; @@ -124,6 +137,11 @@ char *pinentry_utf8_to_local (char *lc_c Return NULL on error. */ char *pinentry_local_to_utf8 (char *lc_ctype, char *text, int secure); + +/* Run a quality inquiry for PASSPHRASE of LENGTH. */ +int pinentry_inq_quality (pinentry_t pin, + const char *passphrase, size_t length); + /* Try to make room for at least LEN bytes for the pin in the pinentry PIN. Returns new buffer on success and 0 on failure. */ char *pinentry_setbufferlen (pinentry_t pin, int len); diff -urpNP pinentry-0.7.3/qt/main.cpp pinentry-0.7.4/qt/main.cpp --- pinentry-0.7.3/qt/main.cpp 2005-09-03 10:55:14.000000000 +0000 +++ pinentry-0.7.4/qt/main.cpp 2007-11-28 22:57:55.000000000 +0000 @@ -68,8 +68,9 @@ qt_cmd_handler (pinentry_t pe) if (pe->parent_wid) parent = new ForeignWidget (pe->parent_wid); - PinEntryDialog pinentry (parent, 0, true); + PinEntryDialog pinentry (parent, NULL, true, !!pe->quality_bar); + pinentry.setPinentryInfo (pe); pinentry.setPrompt (QString::fromUtf8 (pe->prompt)); pinentry.setDescription (QString::fromUtf8 (pe->description)); /* If we reuse the same dialog window. */ @@ -83,6 +84,10 @@ qt_cmd_handler (pinentry_t pe) pinentry.setCancelText (QString::fromUtf8 (pe->cancel)); if (pe->error) pinentry.setError (QString::fromUtf8 (pe->error)); + if (pe->quality_bar) + pinentry.setQualityBar (QString::fromUtf8 (pe->quality_bar)); + if (pe->quality_bar_tt) + pinentry.setQualityBarTT (QString::fromUtf8 (pe->quality_bar_tt)); bool ret = pinentry.exec (); if (!ret) diff -urpNP pinentry-0.7.3/qt/pinentrydialog.cpp pinentry-0.7.4/qt/pinentrydialog.cpp --- pinentry-0.7.3/qt/pinentrydialog.cpp 2005-09-03 10:55:14.000000000 +0000 +++ pinentry-0.7.4/qt/pinentrydialog.cpp 2007-11-29 13:58:03.000000000 +0000 @@ -1,5 +1,6 @@ /* pinentrydialog.cpp - A secure KDE dialog for PIN entry. Copyright (C) 2002 Klarälvdalens Datakonsult AB + Copyright (C) 2007 g10 Code GmbH Written by Steffen Hansen . This program is free software; you can redistribute it and/or @@ -17,16 +18,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ + #include #include #include #include +#include +#include #include "secqlineedit.h" #include "pinentrydialog.h" +#include "pinentry.h" -PinEntryDialog::PinEntryDialog( QWidget* parent, const char* name, bool modal ) +PinEntryDialog::PinEntryDialog( QWidget* parent, const char* name, + bool modal, bool enable_quality_bar ) : QDialog( parent, name, modal ), _grabbed( false ) { QBoxLayout* top = new QVBoxLayout( this, 6 ); @@ -44,16 +50,31 @@ PinEntryDialog::PinEntryDialog( QWidget* _desc = new QLabel( this ); labelLayout->addWidget( _desc ); - QBoxLayout* l = new QHBoxLayout( top ); + QGridLayout* grid = new QGridLayout( labelLayout ); + _prompt = new QLabel( this ); - l->addWidget( _prompt ); + _prompt->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); + grid->addWidget( _prompt, 0, 0 ); _edit = new SecQLineEdit( this ); _edit->setMaxLength( 256 ); _edit->setEchoMode( SecQLineEdit::Password ); - l->addWidget( _edit ); + grid->addWidget( _edit, 0, 1 ); + + if (enable_quality_bar) + { + _quality_bar_label = new QLabel( this ); + _quality_bar_label->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); + grid->addWidget ( _quality_bar_label, 1, 0 ); + _quality_bar = new QProgressBar( this ); + _quality_bar->setCenterIndicator( true ); + grid->addWidget( _quality_bar, 1, 1 ); + _have_quality_bar = true; + } + else + _have_quality_bar = false; + + QBoxLayout* l = new QHBoxLayout( top ); - l = new QHBoxLayout( top ); - _ok = new QPushButton( tr("OK"), this ); _cancel = new QPushButton( tr("Cancel"), this ); @@ -67,12 +88,12 @@ PinEntryDialog::PinEntryDialog( QWidget* this, SIGNAL( accepted() ) ); connect( _cancel, SIGNAL( clicked() ), this, SIGNAL( rejected() ) ); - + connect( _edit, SIGNAL( textModified(const SecQString&) ), + this, SLOT( updateQuality(const SecQString&) ) ); connect (this, SIGNAL (accepted ()), this, SLOT (accept ())); connect (this, SIGNAL (rejected ()), this, SLOT (reject ())); - _edit->setFocus(); } @@ -103,6 +124,42 @@ void PinEntryDialog::keyPressEvent( QKey QDialog::keyPressEvent( e ); } + +void PinEntryDialog::updateQuality( const SecQString & txt ) +{ + char *pin; + int length; + int percent; + QPalette pal; + + if (!_have_quality_bar || !_pinentry_info) + return; + pin = (char*)txt.utf8(); + length = strlen (pin); + percent = length? pinentry_inq_quality (_pinentry_info, pin, length) : 0; + ::secmem_free (pin); + if (!length) + { + _quality_bar->reset (); + } + else + { + pal = _quality_bar->palette (); + if (percent < 0) + { + pal.setColor (QColorGroup::Highlight, QColor("red")); + percent = -percent; + } + else + { + pal.setColor (QColorGroup::Highlight, QColor("green")); + } + _quality_bar->setPalette (pal); + _quality_bar->setProgress (percent); + } +} + + void PinEntryDialog::setDescription( const QString& txt ) { _desc->setText( txt ); @@ -117,7 +174,8 @@ QString PinEntryDialog::description() co void PinEntryDialog::setError( const QString& txt ) { - if( !txt.isNull() )_icon->setPixmap( QMessageBox::standardIcon( QMessageBox::Critical ) ); + if ( !txt.isNull() ) + _icon->setPixmap( QMessageBox::standardIcon( QMessageBox::Critical ) ); _error->setText( txt ); } @@ -155,3 +213,20 @@ void PinEntryDialog::setCancelText( cons { _cancel->setText( txt ); } + +void PinEntryDialog::setQualityBar( const QString& txt ) +{ + if (_have_quality_bar) + _quality_bar_label->setText( txt ); +} + +void PinEntryDialog::setQualityBarTT( const QString& txt ) +{ + if (_have_quality_bar) + QToolTip::add ( _quality_bar, txt ); +} + +void PinEntryDialog::setPinentryInfo (pinentry_t peinfo ) +{ + _pinentry_info = peinfo; +} diff -urpNP pinentry-0.7.3/qt/pinentrydialog.h pinentry-0.7.4/qt/pinentrydialog.h --- pinentry-0.7.3/qt/pinentrydialog.h 2005-09-03 10:55:14.000000000 +0000 +++ pinentry-0.7.4/qt/pinentrydialog.h 2007-11-28 22:57:55.000000000 +0000 @@ -21,9 +21,11 @@ #define __PINENTRYDIALOG_H__ #include +#include "pinentry.h" class QLabel; class QPushButton; +class QProgressBar; class SecQLineEdit; class SecQString; @@ -36,7 +38,8 @@ class PinEntryDialog : public QDialog { Q_PROPERTY( QString prompt READ prompt WRITE setPrompt ) public: friend class PinEntryController; // TODO: remove when assuan lets me use Qt eventloop. - PinEntryDialog( QWidget* parent = 0, const char* name = 0, bool modal = false ); + PinEntryDialog( QWidget* parent = 0, const char* name = 0, + bool modal = false, bool enable_quality_bar = false ); void setDescription( const QString& ); QString description() const; @@ -53,6 +56,14 @@ public: void setOkText( const QString& ); void setCancelText( const QString& ); + void setQualityBar( const QString& ); + void setQualityBarTT( const QString& ); + + void setPinentryInfo (pinentry_t); + +public slots: + void updateQuality(const SecQString &); + signals: void accepted(); void rejected(); @@ -67,10 +78,14 @@ private: QLabel* _desc; QLabel* _error; QLabel* _prompt; + QLabel* _quality_bar_label; + QProgressBar* _quality_bar; SecQLineEdit* _edit; QPushButton* _ok; QPushButton* _cancel; bool _grabbed; + bool _have_quality_bar; + pinentry_t _pinentry_info; }; diff -urpNP pinentry-0.7.3/qt/secqlineedit.cpp pinentry-0.7.4/qt/secqlineedit.cpp --- pinentry-0.7.3/qt/secqlineedit.cpp 2007-06-14 16:51:38.000000000 +0000 +++ pinentry-0.7.4/qt/secqlineedit.cpp 2007-10-02 12:47:30.000000000 +0000 @@ -30,7 +30,7 @@ /********************************************************************** -** $Id: secqlineedit.cpp 156 2007-04-13 00:06:55Z marcus $ +** $Id: secqlineedit.cpp 169 2007-09-18 17:45:38Z wk $ ** ** Implementation of SecQLineEdit widget class ** @@ -288,6 +288,9 @@ struct SecQLineEditPrivate : public Qt the Return or Enter key is pressed the returnPressed() signal is emitted. + When the text changes the textModified() signal is emitted in all + cases. + By default, SecQLineEdits have a frame as specified by the Windows and Motif style guides; you can turn it off by calling setFrame(FALSE). @@ -1845,6 +1848,7 @@ void SecQLineEditPrivate::finishChange( textDirty = FALSE; emit q->textChanged( text ); } + emit q->textModified( text ); #if defined(QT_ACCESSIBILITY_SUPPORT) QAccessible::updateAccessibility( q, 0, QAccessible::ValueChanged ); #endif diff -urpNP pinentry-0.7.3/qt/secqlineedit.h pinentry-0.7.4/qt/secqlineedit.h --- pinentry-0.7.3/qt/secqlineedit.h 2007-06-14 16:51:38.000000000 +0000 +++ pinentry-0.7.4/qt/secqlineedit.h 2007-10-02 12:47:30.000000000 +0000 @@ -29,7 +29,7 @@ #define SECURE 1 /********************************************************************** -** $Id: secqlineedit.h 156 2007-04-13 00:06:55Z marcus $ +** $Id: secqlineedit.h 169 2007-09-18 17:45:38Z wk $ ** ** Definition of SecQLineEdit widget class ** @@ -184,6 +184,7 @@ public slots: signals: void textChanged( const SecQString &); + void textModified( const SecQString &); void returnPressed(); void lostFocus(); void selectionChanged(); -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iQCVAwUBR07HmvuIYr380qKTAQIQtQQAhDt2B3HnoS/sHeSgT1eS9ofjd2ergdw6 Ruv33ILPvNoqJbmpnY5eCSzv/SFViDp5O8jVmyAo/sMPQI8ulN0ak8J15VaJy90K sSZFXTTwy9HjKFADgF4V1kiB2QJAghj2z4rOjN2lEnxTQeplSRit6tWyIIhvBOmj ja6psIa00bg= =S6VS -----END PGP SIGNATURE-----