New pinentry-tty version for dumb terminals.
authorWerner Koch <wk@gnupg.org>
Tue, 12 Aug 2014 08:36:30 +0000 (10:36 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 12 Aug 2014 08:40:32 +0000 (10:40 +0200)
* Makefile.am: Add pinentry-tty.
* NEWS: Add news about pinentry-tty.
* README: Update.
* configure.ac: Add support for this pinentry.
* tty/Makefile.am: New.
* tty/pinentry-tty.c: New.
--

(Minor changes and re-indention by wk)

.gitignore
Makefile.am
NEWS
README
configure.ac
tty/Makefile.am [new file with mode: 0644]
tty/pinentry-tty.c [new file with mode: 0644]

index 575e011..9395e3c 100644 (file)
@@ -34,6 +34,8 @@ secmem/Makefile.in
 secmem/Makefile
 w32/Makefile.in
 w32/Makefile
+tty/Makefile.in
+tty/Makefile
 
 /qt4/pinentryconfirm.moc
 /qt4/pinentrydialog.moc
index f4fa814..a3fa819 100644 (file)
@@ -35,6 +35,12 @@ else
 pinentry_curses =
 endif
 
+if BUILD_PINENTRY_TTY
+pinentry_tty = tty
+else
+pinentry_tty =
+endif
+
 if BUILD_PINENTRY_GTK
 pinentry_gtk = gtk
 else
@@ -65,7 +71,7 @@ else
 pinentry_w32 =
 endif
 
-SUBDIRS = assuan secmem pinentry ${pinentry_curses} \
+SUBDIRS = assuan secmem pinentry ${pinentry_curses} ${pinentry_tty} \
        ${pinentry_gtk} ${pinentry_gtk_2} ${pinentry_qt} ${pinentry_qt4} \
        ${pinentry_w32} doc
 
diff --git a/NEWS b/NEWS
index 5bd874f..0375501 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
 Noteworthy changes in version 0.8.4 (unreleased)
 ------------------------------------------------
 
+ * New pinentry-tty version for dumb terminals.
+
  * Qt4: New option to enable pasting the passphrase from clipboard
 
  * Qt4: Improved accessiblity
diff --git a/README b/README
index 087208a..6bb0d85 100644 (file)
--- a/README
+++ b/README
@@ -17,6 +17,7 @@ GTK+ V2.0     --enable-pinentry-gtk2   Gimp Toolkit Library, Version 2.0
                                         eg. libgtk-x11-2.0 and libglib-2.0
 Qt             --enable-pinentry-qt     Qt, eg. libqt or libqt-mt
 Qt4            --enable-pinentry-qt4    Qt4
+TTY            --enable-pinentry-tty    Simple TTY version, no dependencies
 
 The GTK+ and Qt pinentries can fall back to the curses mode.  The
 option to enable this is --enable-fallback-curses, but this is also
index 595c2aa..94af6e1 100644 (file)
@@ -236,6 +236,20 @@ fi
 
 
 dnl
+dnl Check for tty pinentry program.
+dnl
+AC_ARG_ENABLE(pinentry-tty,
+            AC_HELP_STRING([--enable-pinentry-tty], [build tty pinentry]),
+            pinentry_tty=$enableval, pinentry_tty=maybe)
+AM_CONDITIONAL(BUILD_PINENTRY_TTY, test "$pinentry_tty" = "yes")
+
+if test "$pinentry_tty" = "yes"; then
+  AC_DEFINE(PINENTRY_TTY, 1,
+           [The TTY version of Pinentry is to be build])
+fi
+
+
+dnl
 dnl Check for GTK+ pinentry program.
 dnl
 AC_ARG_ENABLE(pinentry-gtk,
@@ -494,10 +508,14 @@ else
         if test "$pinentry_curses" = "yes"; then
           PINENTRY_DEFAULT=pinentry-curses
         else
-          if test "$pinentry_w32" = "yes"; then
-            PINENTRY_DEFAULT=pinentry-w32
+          if test "$pinentry_tty" = "yes"; then
+            PINENTRY_DEFAULT=pinentry-tty
           else
-            AC_MSG_ERROR([[No pinentry enabled.]])
+            if test "$pinentry_w32" = "yes"; then
+              PINENTRY_DEFAULT=pinentry-w32
+            else
+              AC_MSG_ERROR([[No pinentry enabled.]])
+            fi
           fi
         fi
       fi
@@ -512,6 +530,7 @@ assuan/Makefile
 secmem/Makefile
 pinentry/Makefile
 curses/Makefile
+tty/Makefile
 gtk/Makefile
 gtk+-2/Makefile
 qt/Makefile
@@ -531,6 +550,7 @@ AC_MSG_NOTICE([
        Platform:  $host
 
        Curses Pinentry ..: $pinentry_curses
+       TTY Pinentry .....: $pinentry_tty
        GTK+ Pinentry ....: $pinentry_gtk
        GTK+-2 Pinentry ..: $pinentry_gtk_2
        Qt Pinentry ......: $pinentry_qt
diff --git a/tty/Makefile.am b/tty/Makefile.am
new file mode 100644 (file)
index 0000000..d872fcc
--- /dev/null
@@ -0,0 +1,28 @@
+# Makefile.am - PIN entry curses frontend.
+# Copyright (C) 2002 g10 Code GmbH
+#
+# This file is part of PINENTRY.
+#
+# PINENTRY 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.
+#
+# PINENTRY 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, see <http://www.gnu.org/licenses/>.
+
+## Process this file with automake to produce Makefile.in
+
+bin_PROGRAMS = pinentry-tty
+
+AM_CPPFLAGS = -I$(top_srcdir)/pinentry
+LDADD = ../pinentry/libpinentry.a \
+       ../assuan/libassuan.a ../secmem/libsecmem.a \
+       $(LIBCAP) $(LIBICONV)
+
+pinentry_tty_SOURCES = pinentry-tty.c
diff --git a/tty/pinentry-tty.c b/tty/pinentry-tty.c
new file mode 100644 (file)
index 0000000..2c40d42
--- /dev/null
@@ -0,0 +1,202 @@
+/* pinentry-curses.c - A secure curses dialog for PIN entry, library version
+   Copyright (C) 2014 Serge Voilokov
+
+   This file is part of PINENTRY.
+
+   PINENTRY 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.
+
+   PINENTRY 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <termios.h>
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif /*HAVE_UTIME_H*/
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "pinentry.h"
+
+#ifndef HAVE_DOSISH_SYSTEM
+static int timed_out;
+#endif
+
+static struct termios n_term;
+static struct termios o_term;
+
+static int
+cbreak (int fd)
+{
+  if ((tcgetattr(fd, &o_term)) == -1)
+    return -1;
+  n_term = o_term;
+  n_term.c_lflag = n_term.c_lflag & ~(ECHO|ICANON);
+  n_term.c_cc[VMIN] = 1;
+  n_term.c_cc[VTIME]= 0;
+  if ((tcsetattr(fd, TCSAFLUSH, &n_term)) == -1)
+    return -1;
+  return 1;
+}
+
+static int
+read_password (pinentry_t pinentry, const char *tty_name, const char *tty_type)
+{
+  FILE *ttyfi = stdin;
+  FILE *ttyfo = stdout;
+  int count;
+
+  if (tty_name)
+    {
+      ttyfi = fopen (tty_name, "r");
+      if (!ttyfi)
+        return -1;
+
+      ttyfo = fopen (tty_name, "w");
+      if (!ttyfo)
+        {
+          int err = errno;
+          fclose (ttyfi);
+          errno = err;
+          return -1;
+        }
+    }
+
+  if (cbreak (fileno (ttyfi)) == -1)
+    {
+      int err = errno;
+      if (tty_name)
+        {
+          fclose (ttyfi);
+          fclose (ttyfo);
+        }
+      fprintf (stderr, "cbreak failure, exiting\n");
+      errno = err;
+      return -1;
+    }
+
+  fprintf (ttyfo, "%s\n%s:\n",
+           pinentry->description? pinentry->description:"",
+           pinentry->prompt? pinentry->prompt:"PIN? ");
+  fflush (ttyfo);
+
+  memset (pinentry->pin, 0, pinentry->pin_len);
+
+  count = 0;
+  while (count+1 < pinentry->pin_len)
+    {
+      char c = fgetc (ttyfi);
+      if (c == '\n')
+        break;
+
+      fflush (ttyfo);
+      pinentry->pin[count++] = c;
+    }
+
+  tcsetattr (fileno(ttyfi), TCSANOW, &o_term);
+  if (tty_name)
+    {
+      fclose (ttyfi);
+      fclose (ttyfo);
+    }
+  return strlen (pinentry->pin);
+}
+
+
+/* If a touch has been registered, touch that file.  */
+static void
+do_touch_file(pinentry_t pinentry)
+{
+#ifdef HAVE_UTIME_H
+  struct stat st;
+  time_t tim;
+
+  if (!pinentry->touch_file || !*pinentry->touch_file)
+    return;
+
+  if (stat(pinentry->touch_file, &st))
+    return; /* Oops.  */
+
+  /* Make sure that we actually update the mtime.  */
+  while ((tim = time(NULL)) == st.st_mtime)
+    sleep(1);
+
+  /* Update but ignore errors as we can't do anything in that case.
+     Printing error messages may even clubber the display further. */
+  utime (pinentry->touch_file, NULL);
+#endif /*HAVE_UTIME_H*/
+}
+
+#ifndef HAVE_DOSISH_SYSTEM
+static void
+catchsig(int sig)
+{
+  if (sig == SIGALRM)
+    timed_out = 1;
+}
+#endif
+
+int
+tty_cmd_handler(pinentry_t pinentry)
+{
+  int rc;
+
+#ifndef HAVE_DOSISH_SYSTEM
+  timed_out = 0;
+
+  if (pinentry->timeout)
+    {
+      struct sigaction sa;
+
+      memset(&sa, 0, sizeof(sa));
+      sa.sa_handler = catchsig;
+      sigaction(SIGALRM, &sa, NULL);
+      alarm(pinentry->timeout);
+    }
+#endif
+
+  rc = read_password (pinentry, pinentry->ttyname, pinentry->ttytype);
+  do_touch_file (pinentry);
+  return rc;
+}
+
+
+pinentry_cmd_handler_t pinentry_cmd_handler = tty_cmd_handler;
+
+
+int
+main (int argc, char *argv[])
+{
+  pinentry_init ("pinentry-tty");
+
+  /* Consumes all arguments.  */
+  if (pinentry_parse_opts(argc, argv))
+    {
+      printf ("pinentry-tty (pinentry) " VERSION "\n");
+      exit(EXIT_SUCCESS);
+    }
+
+  if (pinentry_loop ())
+    return 1;
+
+  return 0;
+}