1 /*
2 ** Copyright 1998 - 2006 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5 
6 #if	HAVE_CONFIG_H
7 #include	"config.h"
8 #endif
9 #include	<sys/types.h>
10 #if	HAVE_SYS_STAT_H
11 #include	<sys/stat.h>
12 #endif
13 #if	HAVE_FCNTL_H
14 #include	<fcntl.h>
15 #endif
16 #if	HAVE_UNISTD_H
17 #include	<unistd.h>
18 #endif
19 #if TIME_WITH_SYS_TIME
20 #include <sys/time.h>
21 #include <time.h>
22 #else
23 #if HAVE_SYS_TIME_H
24 #include <sys/time.h>
25 #else
26 #include <time.h>
27 #endif
28 #endif
29 #if	HAVE_MD5
30 #include	"md5/md5.h"
31 #endif
32 #if	HAVE_HMAC
33 #include	"libhmac/hmac.h"
34 #endif
35 
36 #if	HAVE_BCRYPT
37 #include	<pwd.h>
38 #endif
39 #include	<string.h>
40 #include	<stdio.h>
41 #include	<signal.h>
42 #include	<stdlib.h>
43 #if	HAVE_TERMIOS_H
44 #include	<termios.h>
45 #endif
46 #if	HAVE_CRYPT_H
47 #include	<crypt.h>
48 #endif
49 
50 #if HAVE_CRYPT
51 #if NEED_CRYPT_PROTOTYPE
52 extern char *crypt(const char *, const char *);
53 #endif
54 #endif
55 
56 extern char userdb_hex64[];
57 
58 #ifdef	RANDOM
59 extern void userdb_get_random(char *buf, unsigned n);
60 #endif
61 
62 #if	HAVE_MD5
63 
64 char *userdb_mkmd5pw(const char *);
65 
66 #endif
67 
68 /*
69 **	Where possible, we turn off echo when entering the password.
70 **	We set up a signal handler to catch signals and restore the echo
71 **	prior to exiting.
72 */
73 
74 #if	HAVE_TERMIOS_H
75 static struct termios tios;
76 static int have_tios;
77 
sighandler(int signum)78 static RETSIGTYPE sighandler(int signum)
79 {
80 	if (write(1, "\n", 1) < 0)
81 		; /* ignore gcc warning */
82 	tcsetattr(0, TCSANOW, &tios);
83 	_exit(0);
84 #if	RETSIGTYPE != void
85 	return (0);
86 #endif
87 }
88 #endif
89 
read_pw(char * buf)90 static void read_pw(char *buf)
91 {
92 int	n, c;
93 
94 	n=0;
95 	while ((c=getchar()) != EOF && c != '\n')
96 		if (n < BUFSIZ-1)
97 			buf[n++]=c;
98 	if (c == EOF && n == 0)	exit(1);
99 	buf[n]=0;
100 }
101 
main(int argc,char ** argv)102 int main(int argc, char **argv)
103 {
104 int	n=1;
105 int	md5=0;
106 char	buf[BUFSIZ];
107 char	salt[9];
108 #if HAVE_BCRYPT
109 char	*cryptsalt;
110 #endif
111 #if	HAVE_HMAC
112 struct hmac_hashinfo	*hmac=0;
113 #endif
114 
115 	while (n < argc)
116 	{
117 		if (strcmp(argv[n], "-md5") == 0)
118 		{
119 			md5=1;
120 			++n;
121 			continue;
122 		}
123 #if	HAVE_HMAC
124 		if (strncmp(argv[n], "-hmac-", 6) == 0)
125 		{
126 		int	i;
127 
128 			for (i=0; hmac_list[i] &&
129 				strcmp(hmac_list[i]->hh_name, argv[n]+6); i++)
130 				;
131 			if (hmac_list[i])
132 			{
133 				hmac=hmac_list[i];
134 				++n;
135 				continue;
136 			}
137 		}
138 #endif
139 		fprintf(stderr, "%s: invalid argument.\n", argv[0]);
140 		exit(1);
141 	}
142 
143 	/* Read the password */
144 #if	HAVE_TERMIOS_H
145 
146 	have_tios=0;
147 	if (tcgetattr(0, &tios) == 0)
148 	{
149 	struct	termios tios2;
150 	char	buf2[BUFSIZ];
151 
152 		have_tios=1;
153 		signal(SIGINT, sighandler);
154 		signal(SIGHUP, sighandler);
155 		tios2=tios;
156 		tios2.c_lflag &= ~ECHO;
157 		tcsetattr(0, TCSANOW, &tios2);
158 
159 		for (;;)
160 		{
161 			if (write(2, "Password: ", 10) < 0)
162 				; /* ignore gcc warning */
163 			read_pw(buf);
164 			if (write(2, "\nReenter password: ", 19) < 0)
165 				; /* ignore gcc warning */
166 			read_pw(buf2);
167 			if (strcmp(buf, buf2) == 0)	break;
168 			if (write(2, "\nPasswords don't match.\n\n", 25) < 0)
169 				; /* ignore gcc warning */
170 		}
171 
172 	}
173 	else
174 #endif
175 		read_pw(buf);
176 
177 #if	HAVE_TERMIOS_H
178 	if (have_tios)
179 	{
180 		if (write(2, "\n", 1) < 0)
181 			; /* ignore gcc warning */
182 
183 		tcsetattr(0, TCSANOW, &tios);
184 		signal(SIGINT, SIG_DFL);
185 		signal(SIGHUP, SIG_DFL);
186 	}
187 #endif
188 
189 	/* Set the password */
190 
191 #if	HAVE_HMAC
192 	if (hmac)
193 	{
194 	unsigned char *p=malloc(hmac->hh_L*2);
195 	unsigned i;
196 
197 		if (!p)
198 		{
199 			perror("malloc");
200 			exit(1);
201 		}
202 
203 		hmac_hashkey(hmac, buf, strlen(buf), p, p+hmac->hh_L);
204 		for (i=0; i<hmac->hh_L*2; i++)
205 			printf("%02x", (int)p[i]);
206 		printf("\n");
207 		exit(0);
208 	}
209 #endif
210 
211 #if	HAVE_CRYPT
212 
213 #else
214 	md5=1;
215 #endif
216 
217 #if	HAVE_MD5
218 	if (md5)
219 	{
220 
221 		printf("%s\n", userdb_mkmd5pw(buf));
222 		exit(0);
223 	}
224 #endif
225 #ifdef	RANDOM
226 	userdb_get_random(salt, 2);
227 	salt[0]=userdb_hex64[salt[0] & 63];
228 	salt[1]=userdb_hex64[salt[0] & 63];
229 #else
230 	{
231 	time_t	t;
232 	int	i;
233 
234 		time(&t);
235 		t ^= getpid();
236 		salt[0]=0;
237 		salt[1]=0;
238 		for (i=0; i<6; i++)
239 		{
240 			salt[0] <<= 1;
241 			salt[1] <<= 1;
242 			salt[0] |= (t & 1);
243 			t >>= 1;
244 			salt[1] |= (t & 1);
245 			t >>= 1;
246 		}
247 		salt[0]=userdb_hex64[(unsigned)salt[0]];
248 		salt[1]=userdb_hex64[(unsigned)salt[1]];
249 	}
250 #endif
251 
252 #if	HAVE_BCRYPT
253 	cryptsalt=bcrypt_gensalt(8);
254 	printf("%s\n", crypt(buf, cryptsalt));
255 	fflush(stdout);
256 #elif	HAVE_CRYPT
257 	printf("%s\n", crypt(buf, salt));
258 	fflush(stdout);
259 #endif
260 	return (0);
261 }
262