source: trunk/minix/commands/simple/pwdauth.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 8.3 KB
Line 
1/* pwdauth 2.0 - check a shadow password Author: Kees J. Bot
2 * 7 Feb 1994
3 *
4 * This program gets as input the key and salt arguments of the crypt(3)
5 * function as two null terminated strings. The crypt result is output as
6 * one null terminated string. Input and output must be <= 1024 characters.
7 * The exit code will be 1 on any error.
8 *
9 * If the key has the form '##name' then the key will be encrypted and the
10 * result checked to be equal to the encrypted password in the shadow password
11 * file. If equal than '##name' will be returned, otherwise exit code 2.
12 *
13 * Otherwise the key will be encrypted normally and the result returned.
14 *
15 * As a special case, anything matches a null encrypted password to allow
16 * a no-password login.
17 */
18#define nil 0
19#define crypt CRYPT /* The true crypt is included here. */
20#include <sys/types.h>
21#include <pwd.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <unistd.h>
26
27#define LEN 1024
28char SHADOW[] = "/etc/shadow";
29
30int main(int argc, char **argv)
31{
32 char key[LEN];
33 char *salt;
34 struct passwd *pw;
35 int n;
36
37 /* Read input data. Check if there are exactly two null terminated
38 * strings.
39 */
40 n= read(0, key, LEN);
41 if (n < 0) return 1;
42 salt = key + n;
43 n = 0;
44 while (salt > key) if (*--salt == 0) n++;
45 if (n != 2) return 1;
46 salt = key + strlen(key) + 1;
47
48 if (salt[0] == '#' && salt[1] == '#') {
49 /* Get the encrypted password from the shadow password file,
50 * encrypt key and compare.
51 */
52 setpwfile(SHADOW);
53
54 if ((pw= getpwnam(salt + 2)) == nil) return 2;
55
56 /* A null encrypted password matches a null key, otherwise
57 * do the normal crypt(3) authentication check.
58 */
59 if (*pw->pw_passwd == 0 && *key == 0) {
60 /* fine */
61 } else
62 if (strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd) != 0) {
63 return 2;
64 }
65 } else {
66 /* Normal encryption. */
67 if (*salt == 0 && *key == 0) {
68 /* fine */
69 } else {
70 salt= crypt(key, salt);
71 }
72 }
73
74 /* Return the (possibly new) salt to the caller. */
75 if (write(1, salt, strlen(salt) + 1) < 0) return 1;
76 return 0;
77}
78
79/* The one and only crypt(3) function. */
80
81/* From Andy Tanenbaum's book "Computer Networks",
82 rewritten in C
83*/
84
85struct block {
86 unsigned char b_data[64];
87};
88
89struct ordering {
90 unsigned char o_data[64];
91};
92
93static struct block key;
94
95static struct ordering InitialTr = {
96 58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4,
97 62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8,
98 57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3,
99 61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7,
100};
101
102static struct ordering FinalTr = {
103 40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31,
104 38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29,
105 36, 4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27,
106 34, 2,42,10,50,18,58,26,33, 1,41, 9,49,17,57,25,
107};
108
109static struct ordering swap = {
110 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
111 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
112 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
113 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
114};
115
116static struct ordering KeyTr1 = {
117 57,49,41,33,25,17, 9, 1,58,50,42,34,26,18,
118 10, 2,59,51,43,35,27,19,11, 3,60,52,44,36,
119 63,55,47,39,31,23,15, 7,62,54,46,38,30,22,
120 14, 6,61,53,45,37,29,21,13, 5,28,20,12, 4,
121};
122
123static struct ordering KeyTr2 = {
124 14,17,11,24, 1, 5, 3,28,15, 6,21,10,
125 23,19,12, 4,26, 8,16, 7,27,20,13, 2,
126 41,52,31,37,47,55,30,40,51,45,33,48,
127 44,49,39,56,34,53,46,42,50,36,29,32,
128};
129
130static struct ordering etr = {
131 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
132 8, 9,10,11,12,13,12,13,14,15,16,17,
133 16,17,18,19,20,21,20,21,22,23,24,25,
134 24,25,26,27,28,29,28,29,30,31,32, 1,
135};
136
137static struct ordering ptr = {
138 16, 7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10,
139 2, 8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25,
140};
141
142static unsigned char s_boxes[8][64] = {
143{ 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
144 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
145 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
146 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
147},
148
149{ 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
150 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
151 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
152 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
153},
154
155{ 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
156 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
157 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
158 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
159},
160
161{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
162 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
163 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
164 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
165},
166
167{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
168 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
169 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
170 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
171},
172
173{ 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
174 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
175 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
176 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
177},
178
179{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
180 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
181 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
182 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
183},
184
185{ 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
186 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
187 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
188 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
189},
190};
191
192static int rots[] = {
193 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
194};
195
196static void transpose(struct block *data, struct ordering *t, int n)
197{
198 struct block x;
199
200 x = *data;
201
202 while (n-- > 0) {
203 data->b_data[n] = x.b_data[t->o_data[n] - 1];
204 }
205}
206
207static void rotate(struct block *key)
208{
209 unsigned char *p = key->b_data;
210 unsigned char *ep = &(key->b_data[55]);
211 int data0 = key->b_data[0], data28 = key->b_data[28];
212
213 while (p++ < ep) *(p-1) = *p;
214 key->b_data[27] = data0;
215 key->b_data[55] = data28;
216}
217
218static struct ordering *EP = &etr;
219
220static void f(int i, struct block *key, struct block *a, struct block *x)
221{
222 struct block e, ikey, y;
223 int k;
224 unsigned char *p, *q, *r;
225
226 e = *a;
227 transpose(&e, EP, 48);
228 for (k = rots[i]; k; k--) rotate(key);
229 ikey = *key;
230 transpose(&ikey, &KeyTr2, 48);
231 p = &(y.b_data[48]);
232 q = &(e.b_data[48]);
233 r = &(ikey.b_data[48]);
234 while (p > y.b_data) {
235 *--p = *--q ^ *--r;
236 }
237 q = x->b_data;
238 for (k = 0; k < 8; k++) {
239 int xb, r;
240
241 r = *p++ << 5;
242 r += *p++ << 3;
243 r += *p++ << 2;
244 r += *p++ << 1;
245 r += *p++;
246 r += *p++ << 4;
247
248 xb = s_boxes[k][r];
249
250 *q++ = (xb >> 3) & 1;
251 *q++ = (xb>>2) & 1;
252 *q++ = (xb>>1) & 1;
253 *q++ = (xb & 1);
254 }
255 transpose(x, &ptr, 32);
256}
257
258static void setkey(char *k)
259{
260
261 key = *((struct block *) k);
262 transpose(&key, &KeyTr1, 56);
263}
264
265static void encrypt(char *blck, int edflag)
266{
267 struct block *p = (struct block *) blck;
268 int i;
269
270 transpose(p, &InitialTr, 64);
271 for (i = 15; i>= 0; i--) {
272 int j = edflag ? i : 15 - i;
273 int k;
274 struct block b, x;
275
276 b = *p;
277 for (k = 31; k >= 0; k--) {
278 p->b_data[k] = b.b_data[k + 32];
279 }
280 f(j, &key, p, &x);
281 for (k = 31; k >= 0; k--) {
282 p->b_data[k+32] = b.b_data[k] ^ x.b_data[k];
283 }
284 }
285 transpose(p, &swap, 64);
286 transpose(p, &FinalTr, 64);
287}
288
289char *crypt(const char *pw, const char *salt)
290{
291 char pwb[66];
292 char *cp;
293 static char result[16];
294 char *p = pwb;
295 struct ordering new_etr;
296 int i;
297
298 while (*pw && p < &pwb[64]) {
299 int j = 7;
300
301 while (j--) {
302 *p++ = (*pw >> j) & 01;
303 }
304 pw++;
305 *p++ = 0;
306 }
307 while (p < &pwb[64]) *p++ = 0;
308
309 setkey(p = pwb);
310
311 while (p < &pwb[66]) *p++ = 0;
312
313 new_etr = etr;
314 EP = &new_etr;
315 if (salt[0] == 0 || salt[1] == 0) salt = "**";
316 for (i = 0; i < 2; i++) {
317 char c = *salt++;
318 int j;
319
320 result[i] = c;
321 if ( c > 'Z') c -= 6 + 7 + '.'; /* c was a lower case letter */
322 else if ( c > '9') c -= 7 + '.';/* c was upper case letter */
323 else c -= '.'; /* c was digit, '.' or '/'. */
324 /* now, 0 <= c <= 63 */
325 for (j = 0; j < 6; j++) {
326 if ((c >> j) & 01) {
327 int t = 6*i + j;
328 int temp = new_etr.o_data[t];
329 new_etr.o_data[t] = new_etr.o_data[t+24];
330 new_etr.o_data[t+24] = temp;
331 }
332 }
333 }
334
335 if (result[1] == 0) result[1] = result[0];
336
337 for (i = 0; i < 25; i++) encrypt(pwb,0);
338 EP = &etr;
339
340 p = pwb;
341 cp = result+2;
342 while (p < &pwb[66]) {
343 int c = 0;
344 int j = 6;
345
346 while (j--) {
347 c <<= 1;
348 c |= *p++;
349 }
350 c += '.'; /* becomes >= '.' */
351 if (c > '9') c += 7; /* not in [./0-9], becomes upper */
352 if (c > 'Z') c += 6; /* not in [A-Z], becomes lower */
353 *cp++ = c;
354 }
355 *cp = 0;
356 return result;
357}
Note: See TracBrowser for help on using the repository browser.