re-establish kernel assert()s.
[minix.git] / commands / simple / pwdauth.c
blob65044b7f7ba0a6291f0c88caaad97d381516341f
1 /* pwdauth 2.0 - check a shadow password Author: Kees J. Bot
2 * 7 Feb 1994
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.
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.
13 * Otherwise the key will be encrypted normally and the result returned.
15 * As a special case, anything matches a null encrypted password to allow
16 * a no-password login.
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>
27 #define LEN 1024
28 char SHADOW[] = "/etc/shadow";
30 int main(int argc, char **argv)
32 char key[LEN];
33 char *salt;
34 struct passwd *pw;
35 int n;
37 /* Read input data. Check if there are exactly two null terminated
38 * strings.
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;
48 if (salt[0] == '#' && salt[1] == '#') {
49 /* Get the encrypted password from the shadow password file,
50 * encrypt key and compare.
52 setpwfile(SHADOW);
54 if ((pw= getpwnam(salt + 2)) == nil) return 2;
56 /* A null encrypted password matches a null key, otherwise
57 * do the normal crypt(3) authentication check.
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;
65 } else {
66 /* Normal encryption. */
67 if (*salt == 0 && *key == 0) {
68 /* fine */
69 } else {
70 salt= crypt(key, salt);
74 /* Return the (possibly new) salt to the caller. */
75 if (write(1, salt, strlen(salt) + 1) < 0) return 1;
76 return 0;
79 /* The one and only crypt(3) function. */
81 /* From Andy Tanenbaum's book "Computer Networks",
82 rewritten in C
85 struct block {
86 unsigned char b_data[64];
89 struct ordering {
90 unsigned char o_data[64];
93 static struct block key;
95 static 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,
102 static 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,
109 static 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,
116 static 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,
123 static 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,
130 static 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,
137 static 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,
142 static 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,
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,
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,
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,
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,
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,
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,
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,
192 static int rots[] = {
193 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
196 static void transpose(struct block *data, struct ordering *t, int n)
198 struct block x;
200 x = *data;
202 while (n-- > 0) {
203 data->b_data[n] = x.b_data[t->o_data[n] - 1];
207 static void rotate(struct block *key)
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];
213 while (p++ < ep) *(p-1) = *p;
214 key->b_data[27] = data0;
215 key->b_data[55] = data28;
218 static struct ordering *EP = &etr;
220 static void f(int i, struct block *key, struct block *a, struct block *x)
222 struct block e, ikey, y;
223 int k;
224 unsigned char *p, *q, *r;
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;
237 q = x->b_data;
238 for (k = 0; k < 8; k++) {
239 int xb, r;
241 r = *p++ << 5;
242 r += *p++ << 3;
243 r += *p++ << 2;
244 r += *p++ << 1;
245 r += *p++;
246 r += *p++ << 4;
248 xb = s_boxes[k][r];
250 *q++ = (xb >> 3) & 1;
251 *q++ = (xb>>2) & 1;
252 *q++ = (xb>>1) & 1;
253 *q++ = (xb & 1);
255 transpose(x, &ptr, 32);
258 static void setkey(char *k)
261 key = *((struct block *) k);
262 transpose(&key, &KeyTr1, 56);
265 static void encrypt(char *blck, int edflag)
267 struct block *p = (struct block *) blck;
268 int i;
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;
276 b = *p;
277 for (k = 31; k >= 0; k--) {
278 p->b_data[k] = b.b_data[k + 32];
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];
285 transpose(p, &swap, 64);
286 transpose(p, &FinalTr, 64);
289 char *crypt(const char *pw, const char *salt)
291 char pwb[66];
292 char *cp;
293 static char result[16];
294 char *p = pwb;
295 struct ordering new_etr;
296 int i;
298 while (*pw && p < &pwb[64]) {
299 int j = 7;
301 while (j--) {
302 *p++ = (*pw >> j) & 01;
304 pw++;
305 *p++ = 0;
307 while (p < &pwb[64]) *p++ = 0;
309 setkey(p = pwb);
311 while (p < &pwb[66]) *p++ = 0;
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;
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;
335 if (result[1] == 0) result[1] = result[0];
337 for (i = 0; i < 25; i++) encrypt(pwb,0);
338 EP = &etr;
340 p = pwb;
341 cp = result+2;
342 while (p < &pwb[66]) {
343 int c = 0;
344 int j = 6;
346 while (j--) {
347 c <<= 1;
348 c |= *p++;
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;
355 *cp = 0;
356 return result;