Merge branch 'debian'
[hcoop/debian/courier-authlib.git] / userdb / userdbpw.c
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
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
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
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 }