volume_key/volume_key-0.3.4-getpass.patch
Miloslav Trmač f93fc197bb Make it possible to interrupt password prompts
* Fri Oct  8 2010 Miloslav Trmač <mitr@redhat.com> - 0.3.4-3
- Make it possible to interrupt password prompts
  Resolves: #641111
2010-10-08 19:30:21 +02:00

162 lines
3.6 KiB
Diff

Subject: [PATCH] Don't use getpass (), it is difficult to interrupt
2010-10-08 Miloslav Trmač <mitr@redhat.com>
* src/volume_key.c (get_password): New function.
(nss_password_fn, generic_ui_cb, passphrase_ui_cb): Use get_password ()
instead of getpass ().
diff --git a/src/volume_key.c b/src/volume_key.c
index abdd838..7f9f391 100644
--- a/src/volume_key.c
+++ b/src/volume_key.c
@@ -24,6 +24,7 @@ Author: Miloslav Trmač <mitr@redhat.com> */
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
+#include <termios.h>
#include <unistd.h>
#include <glib.h>
@@ -391,36 +392,93 @@ read_batch_string (void)
return res;
}
+/* Read a password (from /dev/tty if possible).
+ Return a password for g_free (), or NULL on error.
+ Unlike getpass(), does not block SIGINT and other signals. (We rely on the
+ shell to re-enable ECHO on SIGINT.) */
+static char *
+get_password (const char *prompt)
+{
+ FILE *tty, *in_file, *out_file;
+ char buf[LINE_MAX], *p;
+ struct termios otermios;
+ gboolean echo_disabled;
+
+ tty = fopen ("/dev/tty", "r+");
+ if (tty != NULL)
+ {
+ in_file = tty;
+ out_file = tty;
+ }
+ else
+ {
+ in_file = stdin;
+ out_file = stderr;
+ }
+
+ fputs (prompt, out_file);
+ fflush (out_file);
+
+ if (tcgetattr (fileno (in_file), &otermios) != 0)
+ echo_disabled = FALSE;
+ else
+ {
+ struct termios ntermios;
+
+ ntermios = otermios;
+ ntermios.c_lflag &= ~ECHO;
+ echo_disabled = tcsetattr (fileno (in_file), TCSAFLUSH, &ntermios) == 0;
+ }
+
+ p = fgets(buf, sizeof(buf), in_file);
+
+ if (echo_disabled)
+ {
+ (void)tcsetattr (fileno (in_file), TCSAFLUSH, &otermios);
+ putc ('\n', out_file);
+ }
+
+ if (tty != NULL)
+ fclose (tty);
+
+ if (p == NULL)
+ return NULL;
+
+ p = strchr(buf, '\r');
+ if (p != NULL)
+ *p = '\0';
+ p = strchr(buf, '\n');
+ if (p != NULL)
+ *p = '\0';
+
+ return g_strdup (buf);
+}
+
/* A PK11_SetPaswordFunc handler */
static char *
nss_password_fn (PK11SlotInfo *slot, PRBool retry, void *arg)
{
+ char *s, *res;
+
+ (void)arg;
if (batch_mode == 0)
{
- char *prompt, *s;
+ char *prompt;
- (void)arg;
if (retry)
fprintf (stderr, _("Error, try again.\n"));
prompt = g_strdup_printf (_("Enter password for `%s': "),
PK11_GetTokenName (slot));
- s = getpass (prompt);
+ s = get_password (prompt);
g_free (prompt);
- if (s == NULL)
- return NULL;
- return PL_strdup (s);
}
else
- {
- char *s, *res;
-
- s = read_batch_string ();
- if (s == NULL)
- return NULL;
- res = PL_strdup (s);
- g_free (s);
- return res;
- }
+ s = read_batch_string ();
+ if (s == NULL)
+ return NULL;
+ res = PL_strdup (s);
+ g_free (s);
+ return res;
}
/* A "generic" struct libvk_ui callback. */
@@ -435,10 +493,11 @@ generic_ui_cb (void *id, const char *prompt, int echo)
char *s, *res;
s = g_strdup_printf (_("%s: "), prompt);
- res = getpass (s);
+ res = get_password (s);
g_free (s);
if (res != NULL && res[0] != '\0')
- return g_strdup (res);
+ return res;
+ g_free (res);
return NULL;
}
else
@@ -487,10 +546,11 @@ passphrase_ui_cb (void *data, const char *prompt, unsigned failed_attempts)
return read_batch_string ();
}
s = g_strdup_printf (_("%s: "), prompt);
- res = getpass (s);
+ res = get_password (s);
g_free (s);
if (res != NULL && res[0] != '\0')
- return g_strdup (res);
+ return res;
+ g_free (res);
return NULL;
}
--
1.7.2.3