]>
iEval git - authen-passphrase-scrypt.git/blob - scrypt-1.2.1/libcperciva/util/readpass.c
7 #include "insecure_memzero.h"
12 #define MAXPASSLEN 2048
14 /* Signals we need to block. */
15 static const int badsigs
[] = {
16 SIGALRM
, SIGHUP
, SIGINT
,
17 SIGPIPE
, SIGQUIT
, SIGTERM
,
18 SIGTSTP
, SIGTTIN
, SIGTTOU
20 #define NSIGS sizeof(badsigs)/sizeof(badsigs[0])
22 /* Highest signal number we care about. */
23 #define MAX2(a, b) ((a) > (b) ? (a) : (b))
24 #define MAX4(a, b, c, d) MAX2(MAX2(a, b), MAX2(c, d))
25 #define MAX8(a, b, c, d, e, f, g, h) MAX2(MAX4(a, b, c, d), MAX4(e, f, g, h))
26 #define MAXBADSIG MAX2(SIGALRM, MAX8(SIGHUP, SIGINT, SIGPIPE, SIGQUIT, \
27 SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU))
29 /* Has a signal of this type been received? */
30 static volatile sig_atomic_t gotsig
[MAXBADSIG
+ 1];
40 /* Restore old signals and re-issue intercepted signals. */
42 resetsigs(struct sigaction savedsa
[NSIGS
])
46 /* Restore old signals. */
47 for (i
= 0; i
< NSIGS
; i
++)
48 sigaction(badsigs
[i
], &savedsa
[i
], NULL
);
50 /* If we intercepted a signal, re-issue it. */
51 for (i
= 0; i
< NSIGS
; i
++) {
52 if (gotsig
[badsigs
[i
]])
58 * readpass(passwd, prompt, confirmprompt, devtty)
59 * If ${devtty} is non-zero, read a password from /dev/tty if possible; if
60 * not, read from stdin. If reading from a tty (either /dev/tty or stdin),
61 * disable echo and prompt the user by printing ${prompt} to stderr. If
62 * ${confirmprompt} is non-NULL, read a second password (prompting if a
63 * terminal is being used) and repeat until the user enters the same password
64 * twice. Return the password as a malloced NUL-terminated string via
68 readpass(char ** passwd
, const char * prompt
,
69 const char * confirmprompt
, int devtty
)
72 char passbuf
[MAXPASSLEN
];
73 char confpassbuf
[MAXPASSLEN
];
74 struct sigaction sa
, savedsa
[NSIGS
];
75 struct termios term
, term_old
;
80 * If devtty != 0, try to open /dev/tty; if that fails, or if devtty
81 * is zero, we'll read the password from stdin instead.
83 if ((devtty
== 0) || ((readfrom
= fopen("/dev/tty", "r")) == NULL
))
86 /* We have not received any signals yet. */
87 for (i
= 0; i
<= MAXBADSIG
; i
++)
91 * If we receive a signal while we're reading the password, we might
92 * end up with echo disabled; to prevent this, we catch the signals
93 * here, and we'll re-send them to ourselves later after we re-enable
96 sa
.sa_handler
= handle
;
98 sigemptyset(&sa
.sa_mask
);
99 for (i
= 0; i
< NSIGS
; i
++)
100 sigaction(badsigs
[i
], &sa
, &savedsa
[i
]);
102 /* If we're reading from a terminal, try to disable echo. */
103 if ((usingtty
= isatty(fileno(readfrom
))) != 0) {
104 if (tcgetattr(fileno(readfrom
), &term_old
)) {
105 warnp("Cannot read terminal settings");
108 memcpy(&term
, &term_old
, sizeof(struct termios
));
109 term
.c_lflag
= (term
.c_lflag
& ~((tcflag_t
)ECHO
)) | ECHONL
;
110 if (tcsetattr(fileno(readfrom
), TCSANOW
, &term
)) {
111 warnp("Cannot set terminal settings");
117 /* If we have a terminal, prompt the user to enter the password. */
119 fprintf(stderr
, "%s: ", prompt
);
121 /* Read the password. */
122 if (fgets(passbuf
, MAXPASSLEN
, readfrom
) == NULL
) {
124 warn0("EOF reading password");
126 warnp("Cannot read password");
130 /* Confirm the password if necessary. */
131 if (confirmprompt
!= NULL
) {
133 fprintf(stderr
, "%s: ", confirmprompt
);
134 if (fgets(confpassbuf
, MAXPASSLEN
, readfrom
) == NULL
) {
136 warn0("EOF reading password");
138 warnp("Cannot read password");
141 if (strcmp(passbuf
, confpassbuf
)) {
143 "Passwords mismatch, please try again\n");
148 /* Terminate the string at the first "\r" or "\n" (if any). */
149 passbuf
[strcspn(passbuf
, "\r\n")] = '\0';
151 /* If we changed terminal settings, reset them. */
153 tcsetattr(fileno(readfrom
), TCSANOW
, &term_old
);
155 /* Restore old signals and re-issue intercepted signals. */
158 /* Close /dev/tty if we opened it. */
159 if (readfrom
!= stdin
)
162 /* Copy the password out. */
163 if ((*passwd
= strdup(passbuf
)) == NULL
) {
164 warnp("Cannot allocate memory");
169 * Zero any stored passwords. This is not guaranteed to work, since a
170 * "sufficiently intelligent" compiler can optimize these out due to
171 * the values not being accessed again; and even if we outwitted the
172 * compiler, all we can do is ensure that *a* buffer is zeroed but
173 * not that it is the only buffer containing the data in question.
174 * Unfortunately the C standard does not provide any way to mark data
175 * as "sensitive" in order to prevent extra copies being sprinkled
176 * around the implementation address space.
178 insecure_memzero(passbuf
, MAXPASSLEN
);
179 insecure_memzero(confpassbuf
, MAXPASSLEN
);
185 /* Reset terminal settings if necessary. */
187 tcsetattr(fileno(readfrom
), TCSAFLUSH
, &term_old
);
189 /* Close /dev/tty if we opened it. */
190 if (readfrom
!= stdin
)
193 /* Restore old signals and re-issue intercepted signals. */
196 /* Zero any stored passwords. */
197 insecure_memzero(passbuf
, MAXPASSLEN
);
198 insecure_memzero(confpassbuf
, MAXPASSLEN
);
This page took 0.053602 seconds and 4 git commands to generate.