1 /*
2 * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
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 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 /*****************************************************************************
28 getpw.cpp
29
30 Helper function to get a password from the user
31 *****************************************************************************/
32
33 #include <config.h>
34 #include "getpw.h"
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #ifdef _WIN32
41 #include <windows.h>
42 #else
43 #include <unistd.h>
44 #include <termios.h>
45 #include <signal.h>
46 #endif
47
48 #ifndef _WIN32
49 // Remember the signal number
50 static volatile sig_atomic_t signo;
51
sighandler(int s)52 void sighandler(int s)
53 {
54 signo = s;
55 }
56 #endif
57
getpin(const char * prompt,char * buffer,size_t size)58 int getpin(const char* prompt, char* buffer, size_t size)
59 {
60 if (prompt == NULL || buffer == NULL || size < 1)
61 return -1;
62
63 printf("%s", prompt);
64
65 #ifdef _WIN32
66 HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
67 DWORD mode;
68
69 // Save current console mode
70 if (!GetConsoleMode(hstdin, &mode))
71 return -1;
72
73 // Update the console mode
74 if (hstdin == INVALID_HANDLE_VALUE || !(SetConsoleMode(hstdin, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT)))
75 return -1;
76 #else
77 struct termios new_attr, old_attr;
78
79 // Get current terminal attributes
80 if (tcgetattr(STDIN_FILENO, &old_attr) < 0)
81 return -1;
82
83 // Save the mode flags
84 new_attr = old_attr;
85
86 // Update the mode flags
87 new_attr.c_lflag &= ~ICANON;
88 new_attr.c_lflag &= ~ECHO;
89
90 // Handle the SIGINT signal
91 signo = 0;
92 struct sigaction osa, sa;
93 sigaction(SIGINT, NULL, &osa);
94 if (osa.sa_handler != SIG_IGN)
95 {
96 sigemptyset(&sa.sa_mask);
97 sa.sa_flags = 0;
98 sa.sa_handler = sighandler;
99 sigaction(SIGINT, &sa, &osa);
100 }
101
102 // Set the new terminal attributes
103 if (tcsetattr(STDIN_FILENO, 0, &new_attr) < 0)
104 return -1;
105 #endif
106
107 size_t nread = 0;
108 int ch = 0;
109 while ((ch = getchar()) != '\n' && ch != EOF)
110 {
111 // Check buffer size
112 if ((nread+2) > size)
113 continue;
114
115 putchar('*');
116 buffer[nread] = ch;
117 nread++;
118 }
119
120 putchar('\n');
121 buffer[nread] = '\0';
122
123 #ifdef _WIN32
124 // Restore the console mode
125 if (!SetConsoleMode(hstdin, mode))
126 return -1;
127 #else
128 // Restore terminal
129 if (tcsetattr(STDIN_FILENO, 0, &old_attr) < 0)
130 return -1;
131
132 // Restore the signal
133 sigaction(SIGINT, &osa, NULL);
134 if (signo)
135 raise(signo);
136 #endif
137
138 return nread;
139 }
140
141 // Get a password from the user
getPW(char * pin,char * newPIN,CK_ULONG userType)142 int getPW(char* pin, char* newPIN, CK_ULONG userType)
143 {
144 char password1[MAX_PIN_LEN+1];
145 char password2[MAX_PIN_LEN+1];
146 size_t size = MAX_PIN_LEN+1;
147 int length = 0;
148
149 // Check if the user has provided a password
150 if (pin)
151 {
152 length = strlen(pin);
153 // Save the PIN if it has the correct length
154 if (length >= MIN_PIN_LEN && length <= MAX_PIN_LEN)
155 memcpy(password1, pin, length+1);
156 }
157
158 while (length < MIN_PIN_LEN || length > MAX_PIN_LEN)
159 {
160 if (userType == CKU_SO)
161 {
162 printf("=== SO PIN (%i-%i characters) ===\n",
163 MIN_PIN_LEN, MAX_PIN_LEN);
164 length = getpin("Please enter SO PIN: ",
165 password1, size);
166 }
167 else
168 {
169 printf("=== User PIN (%i-%i characters) ===\n",
170 MIN_PIN_LEN, MAX_PIN_LEN);
171 length = getpin("Please enter user PIN: ",
172 password1, size);
173 }
174
175 if (length < 0)
176 return 1;
177 if (length < MIN_PIN_LEN || length > MAX_PIN_LEN)
178 {
179 fprintf(stderr, "ERROR: The length of the PIN is out of range.\n");
180 length = 0;
181 continue;
182 }
183
184 if (userType == CKU_SO)
185 {
186 length = getpin("Please reenter SO PIN: ",
187 password2, size);
188 }
189 else
190 {
191 length = getpin("Please reenter user PIN: ",
192 password2, size);
193 }
194
195 if (length < 0)
196 return 1;
197 if (strcmp(password1, password2))
198 {
199 fprintf(stderr, "ERROR: The entered PINs are not equal.\n");
200 length = 0;
201 continue;
202 }
203 }
204
205 memcpy(newPIN, password1, length+1);
206 return 0;
207 }
208