]> andersk Git - gssapi-openssh.git/blob - openssh/openbsd-compat/readpassphrase.c
fdef15809d7a54a3ca8aa681dc073a3b3981616e
[gssapi-openssh.git] / openssh / openbsd-compat / readpassphrase.c
1 /*
2  * Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
19  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #if defined(LIBC_SCCS) && !defined(lint)
29 static char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.5 2001/06/27 13:23:30 djm Exp $";
30 #endif /* LIBC_SCCS and not lint */
31
32 #include "includes.h"
33
34 #ifndef HAVE_READPASSPHRASE
35
36 #include <termios.h>
37 #include <readpassphrase.h>
38
39 #ifdef TCSASOFT
40 # define _T_FLUSH       (TCSAFLUSH|TCSASOFT)
41 #else
42 # define _T_FLUSH       (TCSAFLUSH)
43 #endif
44
45 /* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
46 #if !defined(_POSIX_VDISABLE) && defined(VDISABLE)
47 #  define _POSIX_VDISABLE       VDISABLE
48 #endif
49
50 char *
51 readpassphrase(prompt, buf, bufsiz, flags)
52         const char *prompt;
53         char *buf;
54         size_t bufsiz;
55         int flags;
56 {
57         struct termios term;
58         char ch, *p, *end;
59 #ifdef _POSIX_VDISABLE
60         u_char status;
61 #endif
62         int echo, input, output;
63         sigset_t oset, nset;
64
65         /* I suppose we could alloc on demand in this case (XXX). */
66         if (bufsiz == 0) {
67                 errno = EINVAL;
68                 return(NULL);
69         }
70
71         /*
72          * Read and write to /dev/tty if available.  If not, read from
73          * stdin and write to stderr unless a tty is required.
74          */
75         if ((input = output = open(_PATH_TTY, O_RDWR)) == -1) {
76                 if (flags & RPP_REQUIRE_TTY) {
77                         errno = ENOTTY;
78                         return(NULL);
79                 }
80                 input = STDIN_FILENO;
81                 output = STDERR_FILENO;
82         }
83
84         /*
85          * We block SIGINT and SIGTSTP so the terminal is not left
86          * in an inconsistent state (ie: no echo).  It would probably
87          * be better to simply catch these though.
88          */
89         sigemptyset(&nset);
90         sigaddset(&nset, SIGINT);
91         sigaddset(&nset, SIGTSTP);
92         (void)sigprocmask(SIG_BLOCK, &nset, &oset);
93
94         /* Turn off echo if possible. */
95         echo = 0;
96 #ifdef _POSIX_VDISABLE
97         status = _POSIX_VDISABLE;
98 #endif
99         if (tcgetattr(input, &term) == 0) {
100                 if (!(flags & RPP_ECHO_ON) && (term.c_lflag & ECHO)) {
101                         echo = 1;
102                         term.c_lflag &= ~ECHO;
103                 }
104 #ifdef VSTATUS
105                 if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) {
106                         status = term.c_cc[VSTATUS];
107                         term.c_cc[VSTATUS] = _POSIX_VDISABLE;
108                 }
109 #endif
110                 (void)tcsetattr(input, _T_FLUSH, &term);
111         }
112         if (!(flags & RPP_ECHO_ON)) {
113                 if (tcgetattr(input, &term) == 0 && (term.c_lflag & ECHO)) {
114                         echo = 1;
115                         term.c_lflag &= ~ECHO;
116                         (void)tcsetattr(input, _T_FLUSH, &term);
117                 }
118         }
119
120         (void)write(output, prompt, strlen(prompt));
121         end = buf + bufsiz - 1;
122         for (p = buf; read(input, &ch, 1) == 1 && ch != '\n' && ch != '\r';) {
123                 if (p < end) {
124                         if ((flags & RPP_SEVENBIT))
125                                 ch &= 0x7f;
126                         if (isalpha(ch)) {
127                                 if ((flags & RPP_FORCELOWER))
128                                         ch = tolower(ch);
129                                 if ((flags & RPP_FORCEUPPER))
130                                         ch = toupper(ch);
131                         }
132                         *p++ = ch;
133                 }
134         }
135         *p = '\0';
136 #ifdef _POSIX_VDISABLE
137         if (echo || status != _POSIX_VDISABLE) {
138 #else
139         if (echo) {
140 #endif
141                 if (echo) {
142                         (void)write(output, "\n", 1);
143                         term.c_lflag |= ECHO;
144                 }
145 #ifdef VSTATUS
146                 if (status != _POSIX_VDISABLE)
147                         term.c_cc[VSTATUS] = status;
148 #endif
149                 (void)tcsetattr(input, _T_FLUSH, &term);
150         }
151         (void)sigprocmask(SIG_SETMASK, &oset, NULL);
152         if (input != STDIN_FILENO)
153                 (void)close(input);
154         return(buf);
155 }
156 #endif /* HAVE_READPASSPHRASE */
157
158 #if 0
159 char *
160 getpass(prompt)
161         const char *prompt;
162 {
163         static char buf[_PASSWORD_LEN + 1];
164
165         return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
166 }
167 #endif
This page took 0.037585 seconds and 3 git commands to generate.