Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/src/readpassphrase_compat.h
2065 views
1
/* $OpenBSD: readpassphrase.c,v 1.24 2013/11/24 23:51:29 deraadt Exp $ */
2
3
/*
4
* Copyright (c) 2000-2002, 2007, 2010
5
* Todd C. Miller <[email protected]>
6
*
7
* Permission to use, copy, modify, and distribute this software for any
8
* purpose with or without fee is hereby granted, provided that the above
9
* copyright notice and this permission notice appear in all copies.
10
*
11
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
*
19
* Sponsored in part by the Defense Advanced Research Projects
20
* Agency (DARPA) and Air Force Research Laboratory, Air Force
21
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
22
*/
23
24
#ifndef READPASSPHRASE_COMPAT_H
25
#define READPASSPHRASE_COMPAT_H
26
27
#include <ctype.h>
28
#include <errno.h>
29
#include <fcntl.h>
30
#include <paths.h>
31
#include <pwd.h>
32
#include <signal.h>
33
#include <string.h>
34
#include <termios.h>
35
#include <unistd.h>
36
37
#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */
38
#define RPP_ECHO_ON 0x01 /* Leave echo on. */
39
#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */
40
#define RPP_FORCELOWER 0x04 /* Force input to lower case. */
41
#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */
42
#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */
43
#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */
44
45
#ifndef _NSIG
46
#define _NSIG 32
47
#endif
48
49
static volatile sig_atomic_t signo[_NSIG];
50
static void handler(int);
51
52
static char *
53
readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
54
{
55
ssize_t nr;
56
int input, output, save_errno, i, need_restart;
57
char ch, *p, *end;
58
struct termios term, oterm;
59
struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
60
struct sigaction savetstp, savettin, savettou, savepipe;
61
62
/* I suppose we could alloc on demand in this case (XXX). */
63
if (bufsiz == 0) {
64
errno = EINVAL;
65
return(NULL);
66
}
67
68
restart:
69
for (i = 0; i < _NSIG; i++)
70
signo[i] = 0;
71
nr = -1;
72
save_errno = 0;
73
need_restart = 0;
74
/*
75
* Read and write to /dev/tty if available. If not, read from
76
* stdin and write to stderr unless a tty is required.
77
*/
78
if ((flags & RPP_STDIN) ||
79
(input = output = open("/dev/tty", O_RDWR)) == -1) {
80
if (flags & RPP_REQUIRE_TTY) {
81
errno = ENOTTY;
82
return(NULL);
83
}
84
input = STDIN_FILENO;
85
output = STDERR_FILENO;
86
}
87
88
/*
89
* Turn off echo if possible.
90
* If we are using a tty but are not the foreground pgrp this will
91
* generate SIGTTOU, so do it *before* installing the signal handlers.
92
*/
93
if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
94
memcpy(&term, &oterm, sizeof(term));
95
if (!(flags & RPP_ECHO_ON))
96
term.c_lflag &= ~(ECHO | ECHONL);
97
(void)tcsetattr(input, TCSAFLUSH, &term);
98
} else {
99
memset(&term, 0, sizeof(term));
100
term.c_lflag |= ECHO;
101
memset(&oterm, 0, sizeof(oterm));
102
oterm.c_lflag |= ECHO;
103
}
104
105
/*
106
* Catch signals that would otherwise cause the user to end
107
* up with echo turned off in the shell. Don't worry about
108
* things like SIGXCPU and SIGVTALRM for now.
109
*/
110
sigemptyset(&sa.sa_mask);
111
sa.sa_flags = 0; /* don't restart system calls */
112
sa.sa_handler = handler;
113
(void)sigaction(SIGALRM, &sa, &savealrm);
114
(void)sigaction(SIGHUP, &sa, &savehup);
115
(void)sigaction(SIGINT, &sa, &saveint);
116
(void)sigaction(SIGPIPE, &sa, &savepipe);
117
(void)sigaction(SIGQUIT, &sa, &savequit);
118
(void)sigaction(SIGTERM, &sa, &saveterm);
119
(void)sigaction(SIGTSTP, &sa, &savetstp);
120
(void)sigaction(SIGTTIN, &sa, &savettin);
121
(void)sigaction(SIGTTOU, &sa, &savettou);
122
123
if (!(flags & RPP_STDIN))
124
(void)write(output, prompt, strlen(prompt));
125
end = buf + bufsiz - 1;
126
p = buf;
127
while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
128
if (p < end) {
129
if ((flags & RPP_SEVENBIT))
130
ch &= 0x7f;
131
if (isalpha((unsigned char)ch)) {
132
if ((flags & RPP_FORCELOWER))
133
ch = (char)tolower((unsigned char)ch);
134
if ((flags & RPP_FORCEUPPER))
135
ch = (char)toupper((unsigned char)ch);
136
}
137
*p++ = ch;
138
}
139
}
140
*p = '\0';
141
save_errno = errno;
142
if (!(term.c_lflag & ECHO))
143
(void)write(output, "\n", 1);
144
145
/* Restore old terminal settings and signals. */
146
if (memcmp(&term, &oterm, sizeof(term)) != 0) {
147
while (tcsetattr(input, TCSAFLUSH, &oterm) == -1 &&
148
errno == EINTR && !signo[SIGTTOU])
149
continue;
150
}
151
(void)sigaction(SIGALRM, &savealrm, NULL);
152
(void)sigaction(SIGHUP, &savehup, NULL);
153
(void)sigaction(SIGINT, &saveint, NULL);
154
(void)sigaction(SIGQUIT, &savequit, NULL);
155
(void)sigaction(SIGPIPE, &savepipe, NULL);
156
(void)sigaction(SIGTERM, &saveterm, NULL);
157
(void)sigaction(SIGTSTP, &savetstp, NULL);
158
(void)sigaction(SIGTTIN, &savettin, NULL);
159
(void)sigaction(SIGTTOU, &savettou, NULL);
160
if (input != STDIN_FILENO)
161
(void)close(input);
162
163
/*
164
* If we were interrupted by a signal, resend it to ourselves
165
* now that we have restored the signal handlers.
166
*/
167
for (i = 0; i < _NSIG; i++) {
168
if (signo[i]) {
169
kill(getpid(), i);
170
switch (i) {
171
case SIGTSTP:
172
case SIGTTIN:
173
case SIGTTOU:
174
need_restart = 1;
175
}
176
}
177
}
178
if (need_restart)
179
goto restart;
180
181
if (save_errno)
182
errno = save_errno;
183
return(nr == -1 ? NULL : buf);
184
}
185
186
static void handler(int s)
187
{
188
189
signo[s] = 1;
190
}
191
192
#endif
193
194