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