1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
/**
* libpassphrase – Personalisable library for TTY passphrase reading
*
* Copyright © 2013 Mattias Andrée (maandree@member.fsf.org)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include "passphrase.h"
#define START_PASSPHRASE_LIMIT 32
#ifndef PASSPHRASE_ECHO
/**
* The original TTY settings
*/
static struct termios saved_stty;
#endif
#ifndef PASSPHRASE_REALLOC
static inline char* xrealloc(char* array, size_t size)
{
char* rc = malloc(size);
int i;
if (rc)
for (i = 0; *(array + i); i++)
{
*(rc + i) = *(array + i);
*(array + i) = 0;
}
else
for (i = 0; *(array + i); i++)
*(array + i) = 0;
free(array);
return rc;
}
#else
#define xrealloc realloc
#endif
#define xprintf(...) ({ printf(__VA_ARGS__); fflush(stdout); })
/**
* Reads the passphrase from stdin
*
* @return The passphrase, should be wiped `free`:ed, `NULL` on error
*/
char* passphrase_read(void)
{
char* rc = malloc(START_PASSPHRASE_LIMIT * sizeof(char));
long size = START_PASSPHRASE_LIMIT;
long len = 0;
int c;
if (rc == NULL)
return NULL;
/* Read password until EOF or Enter, skip all \0 as that
is probably not a part of the passphrase (good luck typing
that in X.org) and can be echoed into stdin by the kernel. */
for (;;)
{
c = getchar();
if ((c < 0) || (c == '\n'))
break;
if (c != 0)
{
#ifdef PASSPHRASE_STAR
if ((c == 8) || (c == 127))
{
if (len == 0)
continue;
xprintf("\033[D \033[D");
*(rc + --len) = 0;
continue;
}
putchar('*');
#endif
*(rc + len++) = c;
if (len == size)
if ((rc = xrealloc(rc, (size <<= 1L) * sizeof(char))) == NULL)
return rc;
}
}
/* NUL-terminate passphrase */
*(rc + len) = 0;
#ifndef PASSPHRASE_ECHO
printf("\n");
#endif
return rc;
}
/**
* Disable echoing and do anything else to the terminal settnings `passphrase_read` requires
*/
void passphrase_disable_echo(void)
{
#ifndef PASSPHRASE_ECHO
struct termios stty;
tcgetattr(STDIN_FILENO, &stty);
saved_stty = stty;
stty.c_lflag &= ~ECHO;
#ifdef PASSPHRASE_STAR
stty.c_lflag &= ~ICANON;
#endif
tcsetattr(STDIN_FILENO, TCSAFLUSH, &stty);
#endif
}
/**
* Undo the actions of `passphrase_disable_echo`
*/
void passphrase_reenable_echo(void)
{
#ifndef PASSPHRASE_ECHO
tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_stty);
#endif
}
|