source: trunk/third/ssh/readpass.c @ 12646

Revision 12646, 7.6 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12645, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2
3readpass.c
4
5Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8                   All rights reserved
9
10Created: Mon Jul 10 22:08:59 1995 ylo
11
12Functions for reading passphrases and passwords.
13
14*/
15
16/*
17 * $Id: readpass.c,v 1.1.1.2 1999-03-08 17:43:25 danw Exp $
18 * $Log: not supported by cvs2svn $
19 * Revision 1.6  1997/05/13  22:30:18  kivinen
20 *      Added some casts.
21 *
22 * Revision 1.5  1997/04/17 04:01:52  kivinen
23 *      Added read_confirmation function.
24 *
25 * Revision 1.4  1997/04/05 21:49:28  kivinen
26 *      Fixed the '-quoting from \' to '\''.
27 *
28 * Revision 1.3  1997/03/26 07:15:23  kivinen
29 *      Fixed prompt quoting so ' will be quoted only if in command
30 *      line.
31 *
32 * Revision 1.2  1997/03/19 17:36:18  kivinen
33 *      Quote all unprintable characters in password prompt. Also
34 *      quote all '-characters.
35 *
36 * Revision 1.1.1.1  1996/02/18 21:38:12  ylo
37 *      Imported ssh-1.2.13.
38 *
39 * Revision 1.2  1995/07/13  01:31:04  ylo
40 *      Removed "Last modified" header.
41 *      Added cvs log.
42 *
43 * $Endlog$
44 */
45
46#include "includes.h"
47#include "xmalloc.h"
48#include "ssh.h"
49#include "userfile.h"
50
51/* Saved old terminal mode for read_passphrase. */
52#ifdef USING_TERMIOS
53static struct termios saved_tio;
54#endif
55#ifdef USING_SGTTY
56static struct sgttyb saved_tio;
57#endif
58
59/* Old interrupt signal handler for read_passphrase. */
60static RETSIGTYPE (*old_handler)(int sig) = NULL;
61
62/* Interrupt signal handler for read_passphrase. */
63
64RETSIGTYPE intr_handler(int sig)
65{
66  /* Restore terminal modes. */
67#ifdef USING_TERMIOS
68  tcsetattr(fileno(stdin), TCSANOW, &saved_tio);
69#endif
70#ifdef USING_SGTTY
71  ioctl(fileno(stdin), TIOCSETP, &saved_tio);
72#endif
73  /* Restore the old signal handler. */
74  signal(sig, old_handler);
75  /* Resend the signal, with the old handler. */
76  kill(getpid(), sig);
77}
78
79/* Reads a passphrase from /dev/tty with echo turned off.  Returns the
80   passphrase (allocated with xmalloc).  Exits if EOF is encountered.
81   The passphrase if read from stdin if from_stdin is true (as is the
82   case with ssh-keygen).  */
83
84char *read_passphrase(uid_t uid, const char *prompt, int from_stdin)
85{
86  char buf[1024], *cp;
87  unsigned char quoted_prompt[512];
88  unsigned const char *p;
89#ifdef USING_TERMIOS
90  struct termios tio;
91#endif
92#ifdef USING_SGTTY
93  struct sgttyb tio;
94#endif
95  FILE *f;
96  UserFile uf;
97  int i;
98 
99  if (from_stdin)
100    f = stdin;
101  else
102    {
103      /* Read the passphrase from /dev/tty to make it possible to ask it even
104         when stdin has been redirected. */
105      f = fopen("/dev/tty", "r");
106      if (!f)
107        {
108          if (getenv("DISPLAY"))
109            {
110              char command[512];
111             
112              fprintf(stderr,
113                      "Executing ssh-askpass to query the password...\n");
114              fflush(stdout);
115              fflush(stderr);
116              for(p = (unsigned const char *) prompt, i = 0;
117                  i < sizeof(quoted_prompt) - 5 && *p;
118                  i++, p++)
119                {
120                  if (*p == '\'')
121                    {
122                      quoted_prompt[i++] = '\'';
123                      quoted_prompt[i++] = '\\';
124                      quoted_prompt[i++] = '\'';
125                      quoted_prompt[i] = '\'';
126                    }
127                  else if (isprint(*p) || isspace(*p))
128                    quoted_prompt[i] = *p;
129                  else if (iscntrl(*p))
130                    {
131                      quoted_prompt[i++] = '^';
132                      if (*p < ' ')
133                        quoted_prompt[i] = *p + '@';
134                      else
135                        quoted_prompt[i] = '?';
136                    }
137                  else if (*p > 128)
138                    quoted_prompt[i] = *p;
139                }
140              quoted_prompt[i] = '\0';
141 
142              sprintf(command, "ssh-askpass '%.400s'", quoted_prompt);
143             
144              uf = userfile_popen(uid, command, "r");
145              if (uf == NULL)
146                {
147                  fprintf(stderr, "Could not query passphrase: '%.200s' failed.\n",
148                          command);
149                  exit(1);
150                }
151              if (!userfile_gets(buf, sizeof(buf), uf))
152                {
153                  userfile_pclose(uf);
154                  fprintf(stderr, "No passphrase supplied.  Exiting.\n");
155                  exit(1);
156                }
157              userfile_pclose(uf);
158              if (strchr(buf, '\n'))
159                *strchr(buf, '\n') = 0;
160              return xstrdup(buf);
161            }
162
163          /* No controlling terminal and no DISPLAY.  Nowhere to read. */
164          fprintf(stderr, "You have no controlling tty and no DISPLAY.  Cannot read passphrase.\n");
165          exit(1);
166        }
167    }
168
169  for(p = (unsigned const char *) prompt, i = 0;
170      i < sizeof(quoted_prompt) - 4 && *p; i++, p++)
171    {
172      if (isprint(*p) || isspace(*p))
173        quoted_prompt[i] = *p;
174      else if (iscntrl(*p))
175        {
176          quoted_prompt[i++] = '^';
177          if (*p < ' ')
178            quoted_prompt[i] = *p + '@';
179          else
180            quoted_prompt[i] = '?';
181        }
182      else if (*p > 128)
183        quoted_prompt[i] = *p;
184    }
185  quoted_prompt[i] = '\0';
186 
187  /* Display the prompt (on stderr because stdout might be redirected). */
188  fflush(stdout);
189  fprintf(stderr, "%s", quoted_prompt);
190  fflush(stderr);
191
192  /* Get terminal modes. */
193#ifdef USING_TERMIOS
194  tcgetattr(fileno(f), &tio);
195#endif
196#ifdef USING_SGTTY
197  ioctl(fileno(f), TIOCGETP, &tio);
198#endif
199  saved_tio = tio;
200  /* Save signal handler and set the new handler. */
201  old_handler = signal(SIGINT, intr_handler);
202
203  /* Set new terminal modes disabling all echo. */
204#ifdef USING_TERMIOS
205  tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
206  tcsetattr(fileno(f), TCSANOW, &tio);
207#endif
208#ifdef USING_SGTTY
209  tio.sg_flags &= ~(ECHO);
210  ioctl(fileno(f), TIOCSETP, &tio);
211#endif
212
213  /* Read the passphrase from the terminal. */
214  if (fgets(buf, sizeof(buf), f) == NULL)
215    {
216      /* Got EOF.  Just exit. */
217      /* Restore terminal modes. */
218#ifdef USING_TERMIOS
219      tcsetattr(fileno(f), TCSANOW, &saved_tio);
220#endif
221#ifdef USING_SGTTY
222      ioctl(fileno(f), TIOCSETP, &saved_tio);
223#endif
224      /* Restore the signal handler. */
225      signal(SIGINT, old_handler);
226      /* Print a newline (the prompt probably didn\'t have one). */
227      fprintf(stderr, "\n");
228      /* Close the file. */
229      if (f != stdin)
230        fclose(f);
231      exit(1);
232    }
233  /* Restore terminal modes. */
234#ifdef USING_TERMIOS
235  tcsetattr(fileno(f), TCSANOW, &saved_tio);
236#endif
237#ifdef USING_SGTTY
238  ioctl(fileno(f), TIOCSETP, &saved_tio);
239#endif
240  /* Restore the signal handler. */
241  (void)signal(SIGINT, old_handler);
242  /* Remove newline from the passphrase. */
243  if (strchr(buf, '\n'))
244    *strchr(buf, '\n') = 0;
245  /* Allocate a copy of the passphrase. */
246  cp = xstrdup(buf);
247  /* Clear the buffer so we don\'t leave copies of the passphrase laying
248     around. */
249  memset(buf, 0, sizeof(buf));
250  /* Print a newline since the prompt probably didn\'t have one. */
251  fprintf(stderr, "\n");
252  /* Close the file. */
253  if (f != stdin)
254    fclose(f);
255  return cp;
256}
257
258/* Reads a yes/no confirmation from /dev/tty.  Exits if EOF or "no" is
259   encountered. */
260
261void read_confirmation(const char *prompt)
262{
263  char buf[1024], *p;
264  FILE *f;
265 
266  if (isatty(fileno(stdin)))
267    f = stdin;
268  else
269    {
270      /* Read the passphrase from /dev/tty to make it possible to ask it even
271         when stdin has been redirected. */
272      f = fopen("/dev/tty", "r");
273      if (!f)
274        {
275          fprintf(stderr, "You have no controlling tty.  Cannot read confirmation.\n");
276          exit(1);
277        }
278    }
279
280  /* Read the passphrase from the terminal. */
281  do
282    {
283      /* Display the prompt (on stderr because stdout might be redirected). */
284      fflush(stdout);
285      fprintf(stderr, "%s", prompt);
286      fflush(stderr);
287      /* Read line */
288      if (fgets(buf, sizeof(buf), f) == NULL)
289        {
290          /* Got EOF.  Just exit. */
291          /* Print a newline (the prompt probably didn\'t have one). */
292          fprintf(stderr, "\n");
293          fprintf(stderr, "Aborted by user");
294          /* Close the file. */
295          if (f != stdin)
296            fclose(f);
297          exit(1);
298        }
299      p = buf + strlen(buf) - 1;
300      while (p > buf && isspace(*p))
301        *p-- = '\0';
302      p = buf;
303      while (*p && isspace(*p))
304        p++;
305      if (strcmp(p, "no") == 0)
306        {
307          /* Close the file. */
308          if (f != stdin)
309            fclose(f);
310          exit(1);
311        }
312    } while (strcmp(p, "yes") != 0);
313  /* Close the file. */
314  if (f != stdin)
315    fclose(f);
316}
Note: See TracBrowser for help on using the repository browser.