gpg: More check for symmetric key encryption.
[gnupg.git] / common / ttyio.c
1 /* ttyio.c -  tty i/O functions
2  * Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2006,2007,
3  *               2009, 2010 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of either
9  *
10  *   - the GNU Lesser General Public License as published by the Free
11  *     Software Foundation; either version 3 of the License, or (at
12  *     your option) any later version.
13  *
14  * or
15  *
16  *   - the GNU General Public License as published by the Free
17  *     Software Foundation; either version 2 of the License, or (at
18  *     your option) any later version.
19  *
20  * or both in parallel, as here.
21  *
22  * This file is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, see <https://www.gnu.org/licenses/>.
29  */
30
31 #include <config.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdarg.h>
36 #include <unistd.h>
37
38 #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
39 # define USE_W32_CONSOLE 1
40 #endif
41
42 #ifdef HAVE_TCGETATTR
43 #include <termios.h>
44 #else
45 #ifdef HAVE_TERMIO_H
46 /* simulate termios with termio */
47 #include <termio.h>
48 #define termios termio
49 #define tcsetattr ioctl
50 #define TCSAFLUSH TCSETAF
51 #define tcgetattr(A,B) ioctl(A,TCGETA,B)
52 #define HAVE_TCGETATTR
53 #endif
54 #endif
55 #ifdef USE_W32_CONSOLE
56 # ifdef HAVE_WINSOCK2_H
57 #  include <winsock2.h>
58 # endif
59 # include <windows.h>
60 # ifdef HAVE_TCGETATTR
61 #  error mingw32 and termios
62 # endif
63 #endif
64 #include <errno.h>
65 #include <ctype.h>
66
67 #include "util.h"
68 #include "ttyio.h"
69 #include "common-defs.h"
70
71 #define CONTROL_D ('D' - 'A' + 1)
72
73
74 #ifdef USE_W32_CONSOLE
75 static struct {
76     HANDLE in, out;
77 } con;
78 #define DEF_INPMODE  (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT    \
79                                         |ENABLE_PROCESSED_INPUT )
80 #define HID_INPMODE  (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT )
81 #define DEF_OUTMODE  (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)
82
83 #else /* yeah, we have a real OS */
84 static FILE *ttyfp = NULL;
85 #endif
86
87 static int initialized;
88 static int last_prompt_len;
89 static int batchmode;
90 static int no_terminal;
91
92 #ifdef HAVE_TCGETATTR
93     static struct termios termsave;
94     static int restore_termios;
95 #endif
96
97 /* Hooks set by gpgrlhelp.c if required. */
98 static void (*my_rl_set_completer) (rl_completion_func_t *);
99 static void (*my_rl_inhibit_completion) (int);
100 static void (*my_rl_cleanup_after_signal) (void);
101 static void (*my_rl_init_stream) (FILE *);
102 static char *(*my_rl_readline) (const char*);
103 static void (*my_rl_add_history) (const char*);
104
105
106 /* This is a wrapper around ttyname so that we can use it even when
107    the standard streams are redirected.  It figures the name out the
108    first time and returns it in a statically allocated buffer. */
109 const char *
110 tty_get_ttyname (void)
111 {
112   static char *name;
113
114   /* On a GNU system ctermid() always return /dev/tty, so this does
115      not make much sense - however if it is ever changed we do the
116      Right Thing now. */
117 #ifdef HAVE_CTERMID
118   static int got_name;
119
120   if (!got_name)
121     {
122       const char *s;
123       /* Note that despite our checks for these macros the function is
124          not necessarily thread save.  We mainly do this for
125          portability reasons, in case L_ctermid is not defined. */
126 # if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_POSIX_TRHEADS)
127       char buffer[L_ctermid];
128       s = ctermid (buffer);
129 # else
130       s = ctermid (NULL);
131 # endif
132       if (s)
133         name = strdup (s);
134       got_name = 1;
135     }
136 #endif /*HAVE_CTERMID*/
137   /* Assume the standard tty on memory error or when there is no
138      ctermid. */
139   return name? name : "/dev/tty";
140 }
141
142
143
144 #ifdef HAVE_TCGETATTR
145 static void
146 cleanup(void)
147 {
148     if( restore_termios ) {
149         restore_termios = 0; /* do it prios in case it is interrupted again */
150         if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
151             log_error("tcsetattr() failed: %s\n", strerror(errno) );
152     }
153 }
154 #endif
155
156 static void
157 init_ttyfp(void)
158 {
159     if( initialized )
160         return;
161
162 #if defined(USE_W32_CONSOLE)
163     {
164         SECURITY_ATTRIBUTES sa;
165
166         memset(&sa, 0, sizeof(sa));
167         sa.nLength = sizeof(sa);
168         sa.bInheritHandle = TRUE;
169         con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
170                                FILE_SHARE_READ|FILE_SHARE_WRITE,
171                                &sa, OPEN_EXISTING, 0, 0 );
172         if( con.out == INVALID_HANDLE_VALUE )
173             log_fatal("open(CONOUT$) failed: rc=%d", (int)GetLastError() );
174         memset(&sa, 0, sizeof(sa));
175         sa.nLength = sizeof(sa);
176         sa.bInheritHandle = TRUE;
177         con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE,
178                                FILE_SHARE_READ|FILE_SHARE_WRITE,
179                                &sa, OPEN_EXISTING, 0, 0 );
180         if( con.in == INVALID_HANDLE_VALUE )
181             log_fatal("open(CONIN$) failed: rc=%d", (int)GetLastError() );
182     }
183     SetConsoleMode(con.in, DEF_INPMODE );
184     SetConsoleMode(con.out, DEF_OUTMODE );
185
186 #elif defined(__EMX__)
187     ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */
188     if (my_rl_init_stream)
189       my_rl_init_stream (ttyfp);
190 #elif defined (HAVE_W32CE_SYSTEM)
191     ttyfp = stderr;
192 #else
193     ttyfp = batchmode? stderr : fopen (tty_get_ttyname (), "r+");
194     if( !ttyfp ) {
195         log_error("cannot open '%s': %s\n", tty_get_ttyname (),
196                   strerror(errno) );
197         exit(2);
198     }
199     if (my_rl_init_stream)
200       my_rl_init_stream (ttyfp);
201 #endif
202
203
204 #ifdef HAVE_TCGETATTR
205     atexit( cleanup );
206 #endif
207     initialized = 1;
208 }
209
210
211 int
212 tty_batchmode( int onoff )
213 {
214     int old = batchmode;
215     if( onoff != -1 )
216         batchmode = onoff;
217     return old;
218 }
219
220 int
221 tty_no_terminal(int onoff)
222 {
223     int old = no_terminal;
224     no_terminal = onoff ? 1 : 0;
225     return old;
226 }
227
228 void
229 tty_printf( const char *fmt, ... )
230 {
231     va_list arg_ptr;
232
233     if (no_terminal)
234         return;
235
236     if( !initialized )
237         init_ttyfp();
238
239     va_start( arg_ptr, fmt ) ;
240 #ifdef USE_W32_CONSOLE
241     {
242         char *buf = NULL;
243         int n;
244         DWORD nwritten;
245
246         n = vasprintf(&buf, fmt, arg_ptr);
247         if( !buf )
248             log_bug("vasprintf() failed\n");
249
250         if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
251             log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
252         if( n != nwritten )
253             log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
254         last_prompt_len += n;
255         xfree (buf);
256     }
257 #else
258     last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
259     fflush(ttyfp);
260 #endif
261     va_end(arg_ptr);
262 }
263
264
265 /* Same as tty_printf but if FP is not NULL, behave like a regular
266    fprintf. */
267 void
268 tty_fprintf (estream_t fp, const char *fmt, ... )
269 {
270   va_list arg_ptr;
271
272   if (fp)
273     {
274       va_start (arg_ptr, fmt) ;
275       es_vfprintf (fp, fmt, arg_ptr );
276       va_end (arg_ptr);
277       return;
278     }
279
280   if (no_terminal)
281     return;
282
283   if (!initialized)
284     init_ttyfp ();
285
286   va_start (arg_ptr, fmt);
287 #ifdef USE_W32_CONSOLE
288   {
289     char *buf = NULL;
290     int n;
291     DWORD nwritten;
292
293     n = vasprintf(&buf, fmt, arg_ptr);
294     if (!buf)
295       log_bug("vasprintf() failed\n");
296
297     if (!WriteConsoleA( con.out, buf, n, &nwritten, NULL ))
298       log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
299     if (n != nwritten)
300       log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
301     last_prompt_len += n;
302     xfree (buf);
303   }
304 #else
305   last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
306   fflush(ttyfp);
307 #endif
308   va_end(arg_ptr);
309 }
310
311
312 /* Print a string, but filter all control characters out.  If FP is
313  * not NULL print to that stream instead to the tty.  */
314 static void
315 do_print_string (estream_t fp, const byte *p, size_t n )
316 {
317   if (no_terminal && !fp)
318     return;
319
320   if (!initialized && !fp)
321     init_ttyfp();
322
323   if (fp)
324     {
325       print_utf8_buffer (fp, p, n);
326       return;
327     }
328
329 #ifdef USE_W32_CONSOLE
330   /* Not so effective, change it if you want */
331   for (; n; n--, p++)
332     {
333       if (iscntrl (*p))
334         {
335           if( *p == '\n' )
336             tty_printf ("\\n");
337           else if( !*p )
338             tty_printf ("\\0");
339           else
340             tty_printf ("\\x%02x", *p);
341         }
342       else
343         tty_printf ("%c", *p);
344     }
345 #else
346   for (; n; n--, p++)
347     {
348       if (iscntrl (*p))
349         {
350           putc ('\\', ttyfp);
351           if ( *p == '\n' )
352             putc ('n', ttyfp);
353           else if ( !*p )
354             putc ('0', ttyfp);
355           else
356             fprintf (ttyfp, "x%02x", *p );
357         }
358       else
359         putc (*p, ttyfp);
360     }
361 #endif
362 }
363
364
365 void
366 tty_print_utf8_string2 (estream_t fp, const byte *p, size_t n, size_t max_n)
367 {
368     size_t i;
369     char *buf;
370
371     if (no_terminal && !fp)
372         return;
373
374     /* we can handle plain ascii simpler, so check for it first */
375     for(i=0; i < n; i++ ) {
376         if( p[i] & 0x80 )
377             break;
378     }
379     if( i < n ) {
380         buf = utf8_to_native( (const char *)p, n, 0 );
381         if( max_n && (strlen( buf ) > max_n )) {
382             buf[max_n] = 0;
383         }
384         /*(utf8 conversion already does the control character quoting)*/
385         tty_fprintf (fp, "%s", buf);
386         xfree (buf);
387     }
388     else {
389         if( max_n && (n > max_n) ) {
390             n = max_n;
391         }
392         do_print_string (fp, p, n );
393     }
394 }
395
396
397 void
398 tty_print_utf8_string( const byte *p, size_t n )
399 {
400   tty_print_utf8_string2 (NULL, p, n, 0);
401 }
402
403
404 static char *
405 do_get( const char *prompt, int hidden )
406 {
407   char *buf;
408 #ifndef __riscos__
409   byte cbuf[1];
410 #endif
411   int c, n, i;
412
413   if (batchmode)
414     {
415       log_error ("Sorry, we are in batchmode - can't get input\n");
416       exit (2);
417     }
418
419   if (no_terminal)
420     {
421       log_error ("Sorry, no terminal at all requested - can't get input\n");
422       exit (2);
423     }
424
425   if (!initialized)
426     init_ttyfp ();
427
428   last_prompt_len = 0;
429   tty_printf ("%s", prompt);
430   buf = xmalloc ((n=50));
431   i = 0;
432
433 #ifdef USE_W32_CONSOLE
434   if (hidden)
435     SetConsoleMode(con.in, HID_INPMODE );
436
437   for (;;)
438     {
439       DWORD nread;
440
441       if (!ReadConsoleA( con.in, cbuf, 1, &nread, NULL))
442         log_fatal ("ReadConsole failed: rc=%d", (int)GetLastError ());
443       if (!nread)
444         continue;
445       if (*cbuf == '\n')
446         break;
447
448       if (!hidden)
449         last_prompt_len++;
450       c = *cbuf;
451       if (c == '\t')
452         c = ' ';
453       else if ( (c >= 0 && c <= 0x1f) || c == 0x7f)
454         continue;
455       if (!(i < n-1))
456         {
457           n += 50;
458           buf = xrealloc (buf, n);
459         }
460       buf[i++] = c;
461     }
462
463   if (hidden)
464     SetConsoleMode(con.in, DEF_INPMODE );
465
466 #elif defined(__riscos__) || defined(HAVE_W32CE_SYSTEM)
467   do
468     {
469 #ifdef HAVE_W32CE_SYSTEM
470       /* Using getchar is not a correct solution but for now it
471          doesn't matter because we have no real console at all.  We
472          should rework this as soon as we have switched this entire
473          module to estream.  */
474       c = getchar();
475 #else
476       c = riscos_getchar();
477 #endif
478       if (c == 0xa || c == 0xd)  /* Return || Enter */
479         {
480           c = (int) '\n';
481         }
482       else if (c == 0x8 || c == 0x7f) /* Backspace || Delete */
483         {
484           if (i>0)
485             {
486               i--;
487               if (!hidden)
488                 {
489                   last_prompt_len--;
490                   fputc(8, ttyfp);
491                   fputc(32, ttyfp);
492                   fputc(8, ttyfp);
493                   fflush(ttyfp);
494                 }
495             }
496           else
497             {
498               fputc(7, ttyfp);
499               fflush(ttyfp);
500             }
501           continue;
502         }
503       else if (c == (int) '\t')  /* Tab */
504         {
505           c = ' ';
506         }
507       else if (c > 0xa0)
508         {
509           ; /* we don't allow 0xa0, as this is a protected blank which may
510              * confuse the user */
511         }
512       else if (iscntrl(c))
513         {
514           continue;
515         }
516       if (!(i < n-1))
517         {
518           n += 50;
519           buf = xrealloc (buf, n);
520         }
521       buf[i++] = c;
522       if (!hidden)
523         {
524           last_prompt_len++;
525           fputc(c, ttyfp);
526           fflush(ttyfp);
527         }
528     }
529   while (c != '\n');
530   i = (i>0) ? i-1 : 0;
531
532 #else /* Other systems. */
533
534   if (hidden)
535     {
536 #ifdef HAVE_TCGETATTR
537       struct termios term;
538
539       if (tcgetattr(fileno(ttyfp), &termsave))
540         log_fatal("tcgetattr() failed: %s\n", strerror(errno));
541       restore_termios = 1;
542       term = termsave;
543       term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
544       if (tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
545         log_fatal("tcsetattr() failed: %s\n", strerror(errno));
546 #endif
547     }
548
549   /* fixme: How can we avoid that the \n is echoed w/o disabling
550    * canonical mode - w/o this kill_prompt can't work */
551   while (read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n')
552     {
553       if (!hidden)
554         last_prompt_len++;
555       c = *cbuf;
556       if (c == CONTROL_D)
557         log_info ("Control-D detected\n");
558
559       if (c == '\t') /* Map tab to a space.  */
560         c = ' ';
561       else if ( (c >= 0 && c <= 0x1f) || c == 0x7f)
562         continue; /* Skip all other ASCII control characters.  */
563       if (!(i < n-1))
564         {
565           n += 50;
566           buf = xrealloc (buf, n);
567         }
568       buf[i++] = c;
569     }
570   if (*cbuf != '\n')
571     {
572       buf[0] = CONTROL_D;
573       i = 1;
574     }
575
576   if (hidden)
577     {
578 #ifdef HAVE_TCGETATTR
579       if (tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave))
580         log_error ("tcsetattr() failed: %s\n", strerror(errno));
581       restore_termios = 0;
582 #endif
583     }
584 #endif /* end unix version */
585
586   buf[i] = 0;
587   return buf;
588 }
589
590
591
592 /* Note: This function never returns NULL. */
593 char *
594 tty_get( const char *prompt )
595 {
596   if (!batchmode && !no_terminal && my_rl_readline && my_rl_add_history)
597     {
598       char *line;
599       char *buf;
600
601       if (!initialized)
602         init_ttyfp();
603
604       last_prompt_len = 0;
605
606       line = my_rl_readline (prompt?prompt:"");
607
608       /* We need to copy it to memory controlled by our malloc
609          implementations; further we need to convert an EOF to our
610          convention. */
611       buf = xmalloc(line? strlen(line)+1:2);
612       if (line)
613         {
614           strcpy (buf, line);
615           trim_spaces (buf);
616           if (strlen (buf) > 2 )
617             my_rl_add_history (line); /* Note that we test BUF but add LINE. */
618           free (line);
619         }
620       else
621         {
622           buf[0] = CONTROL_D;
623           buf[1] = 0;
624         }
625       return buf;
626     }
627   else
628     return do_get ( prompt, 0 );
629 }
630
631 /* Variable argument version of tty_get.  The prompt is actually a
632    format string with arguments.  */
633 char *
634 tty_getf (const char *promptfmt, ... )
635 {
636   va_list arg_ptr;
637   char *prompt;
638   char *answer;
639
640   va_start (arg_ptr, promptfmt);
641   if (gpgrt_vasprintf (&prompt, promptfmt, arg_ptr) < 0)
642     log_fatal ("estream_vasprintf failed: %s\n", strerror (errno));
643   va_end (arg_ptr);
644   answer = tty_get (prompt);
645   xfree (prompt);
646   return answer;
647 }
648
649
650
651 char *
652 tty_get_hidden( const char *prompt )
653 {
654     return do_get( prompt, 1 );
655 }
656
657
658 void
659 tty_kill_prompt()
660 {
661     if ( no_terminal )
662         return;
663
664     if( !initialized )
665         init_ttyfp();
666
667     if( batchmode )
668         last_prompt_len = 0;
669     if( !last_prompt_len )
670         return;
671 #ifdef USE_W32_CONSOLE
672     tty_printf("\r%*s\r", last_prompt_len, "");
673 #else
674     {
675         int i;
676         putc('\r', ttyfp);
677         for(i=0; i < last_prompt_len; i ++ )
678             putc(' ', ttyfp);
679         putc('\r', ttyfp);
680         fflush(ttyfp);
681     }
682 #endif
683     last_prompt_len = 0;
684 }
685
686
687 int
688 tty_get_answer_is_yes( const char *prompt )
689 {
690     int yes;
691     char *p = tty_get( prompt );
692     tty_kill_prompt();
693     yes = answer_is_yes(p);
694     xfree(p);
695     return yes;
696 }
697
698
699 /* Called by gnupg_rl_initialize to setup the readline support. */
700 void
701 tty_private_set_rl_hooks (void (*init_stream) (FILE *),
702                           void (*set_completer) (rl_completion_func_t*),
703                           void (*inhibit_completion) (int),
704                           void (*cleanup_after_signal) (void),
705                           char *(*readline_fun) (const char*),
706                           void (*add_history_fun) (const char*))
707 {
708   my_rl_init_stream = init_stream;
709   my_rl_set_completer = set_completer;
710   my_rl_inhibit_completion = inhibit_completion;
711   my_rl_cleanup_after_signal = cleanup_after_signal;
712   my_rl_readline = readline_fun;
713   my_rl_add_history = add_history_fun;
714 }
715
716
717 #ifdef HAVE_LIBREADLINE
718 void
719 tty_enable_completion (rl_completion_func_t *completer)
720 {
721   if (no_terminal || !my_rl_set_completer )
722     return;
723
724   if (!initialized)
725     init_ttyfp();
726
727   my_rl_set_completer (completer);
728 }
729
730 void
731 tty_disable_completion (void)
732 {
733   if (no_terminal || !my_rl_inhibit_completion)
734     return;
735
736   if (!initialized)
737     init_ttyfp();
738
739   my_rl_inhibit_completion (1);
740 }
741 #endif
742
743 void
744 tty_cleanup_after_signal (void)
745 {
746 #ifdef HAVE_TCGETATTR
747   cleanup ();
748 #endif
749 }
750
751 void
752 tty_cleanup_rl_after_signal (void)
753 {
754   if (my_rl_cleanup_after_signal)
755     my_rl_cleanup_after_signal ();
756 }