1 /* pwdauth 2.0 - check a shadow password Author: Kees J. Bot
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.
19 #define crypt CRYPT /* The true crypt is included here. */
20 #include <sys/types.h>
28 char SHADOW
[] = "/etc/shadow";
30 int main(int argc
, char **argv
)
37 /* Read input data. Check if there are exactly two null terminated
44 while (salt
> key
) if (*--salt
== 0) n
++;
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.
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) {
62 if (strcmp(crypt(key
, pw
->pw_passwd
), pw
->pw_passwd
) != 0) {
66 /* Normal encryption. */
67 if (*salt
== 0 && *key
== 0) {
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;
79 /* The one and only crypt(3) function. */
81 /* From Andy Tanenbaum's book "Computer Networks",
86 unsigned char b_data
[64];
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
)
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
;
224 unsigned char *p
, *q
, *r
;
227 transpose(&e
, EP
, 48);
228 for (k
= rots
[i
]; k
; k
--) rotate(key
);
230 transpose(&ikey
, &KeyTr2
, 48);
233 r
= &(ikey
.b_data
[48]);
234 while (p
> y
.b_data
) {
238 for (k
= 0; k
< 8; k
++) {
250 *q
++ = (xb
>> 3) & 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
;
270 transpose(p
, &InitialTr
, 64);
271 for (i
= 15; i
>= 0; i
--) {
272 int j
= edflag
? i
: 15 - i
;
277 for (k
= 31; k
>= 0; k
--) {
278 p
->b_data
[k
] = b
.b_data
[k
+ 32];
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
)
293 static char result
[16];
295 struct ordering new_etr
;
298 while (*pw
&& p
< &pwb
[64]) {
302 *p
++ = (*pw
>> j
) & 01;
307 while (p
< &pwb
[64]) *p
++ = 0;
311 while (p
< &pwb
[66]) *p
++ = 0;
315 if (salt
[0] == 0 || salt
[1] == 0) salt
= "**";
316 for (i
= 0; i
< 2; i
++) {
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
++) {
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);
342 while (p
< &pwb
[66]) {
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 */