]> andersk Git - openssh.git/blob - openbsd-compat/readpassphrase.c
- (djm) Avoid bad and unportable sprintf usage in compat code
[openssh.git] / 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 char *
46 readpassphrase(prompt, buf, bufsiz, flags)
47         const char *prompt;
48         char *buf;
49         size_t bufsiz;
50         int flags;
51 {
52         struct termios term;
53         char ch, *p, *end;
54 #ifdef _POSIX_VDISABLE
55         u_char status;
56 #endif
57         int echo, input, output;
58         sigset_t oset, nset;
59
60         /* I suppose we could alloc on demand in this case (XXX). */
61         if (bufsiz == 0) {
62                 errno = EINVAL;
63                 return(NULL);
64         }
65
66         /*
67          * Read and write to /dev/tty if available.  If not, read from
68          * stdin and write to stderr unless a tty is required.
69          */
70         if ((input = output = open(_PATH_TTY, O_RDWR)) == -1) {
71                 if (flags & RPP_REQUIRE_TTY) {
72                         errno = ENOTTY;
73                         return(NULL);
74                 }
75                 input = STDIN_FILENO;
76                 output = STDERR_FILENO;
77         }
78
79         /*
80          * We block SIGINT and SIGTSTP so the terminal is not left
81          * in an inconsistent state (ie: no echo).  It would probably
82          * be better to simply catch these though.
83          */
84         sigemptyset(&nset);
85         sigaddset(&nset, SIGINT);
86         sigaddset(&nset, SIGTSTP);
87         (void)sigprocmask(SIG_BLOCK, &nset, &oset);
88
89         /* Turn off echo if possible. */
90         echo = 0;
91 #ifdef _POSIX_VDISABLE
92         status = _POSIX_VDISABLE;
93 #endif
94         if (tcgetattr(input, &term) == 0) {
95                 if (!(flags & RPP_ECHO_ON) && (term.c_lflag & ECHO)) {
96                         echo = 1;
97                         term.c_lflag &= ~ECHO;
98                 }
99 #ifdef VSTATUS
100                 if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) {
101                         status = term.c_cc[VSTATUS];
102                         term.c_cc[VSTATUS] = _POSIX_VDISABLE;
103                 }
104 #endif
105                 (void)tcsetattr(input, _T_FLUSH, &term);
106         }
107         if (!(flags & RPP_ECHO_ON)) {
108                 if (tcgetattr(input, &term) == 0 && (term.c_lflag & ECHO)) {
109                         echo = 1;
110                         term.c_lflag &= ~ECHO;
111                         (void)tcsetattr(input, _T_FLUSH, &term);
112                 }
113         }
114
115         (void)write(output, prompt, strlen(prompt));
116         end = buf + bufsiz - 1;
117         for (p = buf; read(input, &ch, 1) == 1 && ch != '\n' && ch != '\r';) {
118                 if (p < end) {
119                         if ((flags & RPP_SEVENBIT))
120                                 ch &= 0x7f;
121                         if (isalpha(ch)) {
122                                 if ((flags & RPP_FORCELOWER))
123                                         ch = tolower(ch);
124                                 if ((flags & RPP_FORCEUPPER))
125                                         ch = toupper(ch);
126                         }
127                         *p++ = ch;
128                 }
129         }
130         *p = '\0';
131 #ifdef _POSIX_VDISABLE
132         if (echo || status != _POSIX_VDISABLE) {
133 #else
134         if (echo) {
135 #endif
136                 if (echo) {
137                         (void)write(output, "\n", 1);
138                         term.c_lflag |= ECHO;
139                 }
140 #ifdef VSTATUS
141                 if (status != _POSIX_VDISABLE)
142                         term.c_cc[VSTATUS] = status;
143 #endif
144                 (void)tcsetattr(input, _T_FLUSH, &term);
145         }
146         (void)sigprocmask(SIG_SETMASK, &oset, NULL);
147         if (input != STDIN_FILENO)
148                 (void)close(input);
149         return(buf);
150 }
151 #endif /* HAVE_READPASSPHRASE */
152
153 #if 0
154 char *
155 getpass(prompt)
156         const char *prompt;
157 {
158         static char buf[_PASSWORD_LEN + 1];
159
160         return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
161 }
162 #endif
This page took 0.052274 seconds and 5 git commands to generate.