pwdauth.c

Go to the documentation of this file.
00001 /*      pwdauth 2.0 - check a shadow password           Author: Kees J. Bot
00002  *                                                              7 Feb 1994
00003  *
00004  * This program gets as input the key and salt arguments of the crypt(3)
00005  * function as two null terminated strings.  The crypt result is output as
00006  * one null terminated string.  Input and output must be <= 1024 characters.
00007  * The exit code will be 1 on any error.
00008  *
00009  * If the key has the form '##name' then the key will be encrypted and the
00010  * result checked to be equal to the encrypted password in the shadow password
00011  * file.  If equal than '##name' will be returned, otherwise exit code 2.
00012  *
00013  * Otherwise the key will be encrypted normally and the result returned.
00014  *
00015  * As a special case, anything matches a null encrypted password to allow
00016  * a no-password login.
00017  */
00018 #define nil 0
00019 #define crypt   CRYPT   /* The true crypt is included here. */
00020 #include <sys/types.h>
00021 #include <pwd.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <unistd.h>
00026 
00027 #define LEN     1024
00028 char SHADOW[] = "/etc/shadow";
00029 
00030 int main(int argc, char **argv)
00031 {
00032         char key[LEN];
00033         char *salt;
00034         struct passwd *pw;
00035         int n;
00036 
00037         /* Read input data.  Check if there are exactly two null terminated
00038          * strings.
00039          */
00040         n= read(0, key, LEN);
00041         if (n < 0) return 1;
00042         salt = key + n;
00043         n = 0;
00044         while (salt > key) if (*--salt == 0) n++;
00045         if (n != 2) return 1;
00046         salt = key + strlen(key) + 1;
00047 
00048         if (salt[0] == '#' && salt[1] == '#') {
00049                 /* Get the encrypted password from the shadow password file,
00050                  * encrypt key and compare.
00051                  */
00052                 setpwfile(SHADOW);
00053 
00054                 if ((pw= getpwnam(salt + 2)) == nil) return 2;
00055 
00056                 /* A null encrypted password matches a null key, otherwise
00057                  * do the normal crypt(3) authentication check.
00058                  */
00059                 if (*pw->pw_passwd == 0 && *key == 0) {
00060                         /* fine */
00061                 } else
00062                 if (strcmp(crypt(key, pw->pw_passwd), pw->pw_passwd) != 0) {
00063                         return 2;
00064                 }
00065         } else {
00066                 /* Normal encryption. */
00067                 if (*salt == 0 && *key == 0) {
00068                         /* fine */
00069                 } else {
00070                         salt= crypt(key, salt);
00071                 }
00072         }
00073 
00074         /* Return the (possibly new) salt to the caller. */
00075         if (write(1, salt, strlen(salt) + 1) < 0) return 1;
00076         return 0;
00077 }
00078 
00079 /* The one and only crypt(3) function. */
00080 
00081 /*      From Andy Tanenbaum's book "Computer Networks",
00082         rewritten in C
00083 */
00084 
00085 struct block {
00086         unsigned char b_data[64];
00087 };
00088 
00089 struct ordering {
00090         unsigned char o_data[64];
00091 };
00092 
00093 static struct block key;
00094 
00095 static struct ordering InitialTr = {
00096         58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4,
00097         62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8,
00098         57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3,
00099         61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7,
00100 };
00101 
00102 static struct ordering FinalTr = {
00103         40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31,
00104         38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29,
00105         36, 4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27,
00106         34, 2,42,10,50,18,58,26,33, 1,41, 9,49,17,57,25,
00107 };
00108 
00109 static struct ordering swap = {
00110         33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
00111         49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
00112          1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
00113         17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
00114 };
00115 
00116 static struct ordering KeyTr1 = {
00117         57,49,41,33,25,17, 9, 1,58,50,42,34,26,18,
00118         10, 2,59,51,43,35,27,19,11, 3,60,52,44,36,
00119         63,55,47,39,31,23,15, 7,62,54,46,38,30,22,
00120         14, 6,61,53,45,37,29,21,13, 5,28,20,12, 4,
00121 };
00122 
00123 static struct ordering KeyTr2 = {
00124         14,17,11,24, 1, 5, 3,28,15, 6,21,10,
00125         23,19,12, 4,26, 8,16, 7,27,20,13, 2,
00126         41,52,31,37,47,55,30,40,51,45,33,48,
00127         44,49,39,56,34,53,46,42,50,36,29,32,
00128 };
00129 
00130 static struct ordering etr = {
00131         32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
00132          8, 9,10,11,12,13,12,13,14,15,16,17,
00133         16,17,18,19,20,21,20,21,22,23,24,25,
00134         24,25,26,27,28,29,28,29,30,31,32, 1,
00135 };
00136 
00137 static struct ordering ptr = {
00138         16, 7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10,
00139          2, 8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25,
00140 };
00141 
00142 static unsigned char s_boxes[8][64] = {
00143 {       14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
00144          0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
00145          4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
00146         15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
00147 },
00148 
00149 {       15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
00150          3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
00151          0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
00152         13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
00153 },
00154 
00155 {       10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
00156         13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
00157         13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
00158          1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
00159 },
00160 
00161 {        7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
00162         13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
00163         10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
00164          3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
00165 },
00166 
00167 {        2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
00168         14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
00169          4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
00170         11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
00171 },
00172 
00173 {       12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
00174         10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
00175          9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
00176          4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
00177 },
00178 
00179 {        4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
00180         13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
00181          1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
00182          6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
00183 },
00184 
00185 {       13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
00186          1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
00187          7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
00188          2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
00189 },
00190 };
00191 
00192 static int rots[] = {
00193         1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
00194 };
00195 
00196 static void transpose(struct block *data, struct ordering *t, int n)
00197 {
00198         struct block x;
00199 
00200         x = *data;
00201 
00202         while (n-- > 0) {
00203                 data->b_data[n] = x.b_data[t->o_data[n] - 1];
00204         }
00205 }
00206 
00207 static void rotate(struct block *key)
00208 {
00209         unsigned char *p = key->b_data;
00210         unsigned char *ep = &(key->b_data[55]);
00211         int data0 = key->b_data[0], data28 = key->b_data[28];
00212 
00213         while (p++ < ep) *(p-1) = *p;
00214         key->b_data[27] = data0;
00215         key->b_data[55] = data28;
00216 }
00217 
00218 static struct ordering *EP = &etr;
00219 
00220 static void f(int i, struct block *key, struct block *a, struct block *x)
00221 {
00222         struct block e, ikey, y;
00223         int k;
00224         unsigned char *p, *q, *r;
00225 
00226         e = *a;
00227         transpose(&e, EP, 48);
00228         for (k = rots[i]; k; k--) rotate(key);
00229         ikey = *key;
00230         transpose(&ikey, &KeyTr2, 48);
00231         p = &(y.b_data[48]);
00232         q = &(e.b_data[48]);
00233         r = &(ikey.b_data[48]);
00234         while (p > y.b_data) {
00235                 *--p = *--q ^ *--r;
00236         }
00237         q = x->b_data;
00238         for (k = 0; k < 8; k++) {
00239                 int xb, r;
00240 
00241                 r = *p++ << 5;
00242                 r += *p++ << 3;
00243                 r += *p++ << 2;
00244                 r += *p++ << 1;
00245                 r += *p++;
00246                 r += *p++ << 4;
00247 
00248                 xb = s_boxes[k][r];
00249 
00250                 *q++ = (xb >> 3) & 1;
00251                 *q++ = (xb>>2) & 1;
00252                 *q++ = (xb>>1) & 1;
00253                 *q++ = (xb & 1);
00254         }
00255         transpose(x, &ptr, 32);
00256 }
00257 
00258 static void setkey(char *k)
00259 {
00260 
00261         key = *((struct block *) k);
00262         transpose(&key, &KeyTr1, 56);
00263 }
00264 
00265 static void encrypt(char *blck, int edflag)
00266 {
00267         struct block *p = (struct block *) blck;
00268         int i;
00269 
00270         transpose(p, &InitialTr, 64);
00271         for (i = 15; i>= 0; i--) {
00272                 int j = edflag ? i : 15 - i;
00273                 int k;
00274                 struct block b, x;
00275 
00276                 b = *p;
00277                 for (k = 31; k >= 0; k--) {
00278                         p->b_data[k] = b.b_data[k + 32];
00279                 }
00280                 f(j, &key, p, &x);
00281                 for (k = 31; k >= 0; k--) {
00282                         p->b_data[k+32] = b.b_data[k] ^ x.b_data[k];
00283                 }
00284         }
00285         transpose(p, &swap, 64);
00286         transpose(p, &FinalTr, 64);
00287 }
00288 
00289 char *crypt(const char *pw, const char *salt)
00290 {
00291         char pwb[66];
00292         char *cp;
00293         static char result[16];
00294         char *p = pwb;
00295         struct ordering new_etr;
00296         int i;
00297 
00298         while (*pw && p < &pwb[64]) {
00299                 int j = 7;
00300 
00301                 while (j--) {
00302                         *p++ = (*pw >> j) & 01;
00303                 }
00304                 pw++;
00305                 *p++ = 0;
00306         }
00307         while (p < &pwb[64]) *p++ = 0;
00308 
00309         setkey(p = pwb);
00310 
00311         while (p < &pwb[66]) *p++ = 0;
00312 
00313         new_etr = etr;
00314         EP = &new_etr;
00315         if (salt[0] == 0 || salt[1] == 0) salt = "**";
00316         for (i = 0; i < 2; i++) {
00317                 char c = *salt++;
00318                 int j;
00319 
00320                 result[i] = c;
00321                 if ( c > 'Z') c -= 6 + 7 + '.'; /* c was a lower case letter */
00322                 else if ( c > '9') c -= 7 + '.';/* c was upper case letter */
00323                 else c -= '.';                  /* c was digit, '.' or '/'. */
00324                                                 /* now, 0 <= c <= 63 */
00325                 for (j = 0; j < 6; j++) {
00326                         if ((c >> j) & 01) {
00327                                 int t = 6*i + j;
00328                                 int temp = new_etr.o_data[t];
00329                                 new_etr.o_data[t] = new_etr.o_data[t+24];
00330                                 new_etr.o_data[t+24] = temp;
00331                         }
00332                 }
00333         }
00334 
00335         if (result[1] == 0) result[1] = result[0];
00336 
00337         for (i = 0; i < 25; i++) encrypt(pwb,0);
00338         EP = &etr;
00339 
00340         p = pwb;
00341         cp = result+2;
00342         while (p < &pwb[66]) {
00343                 int c = 0;
00344                 int j = 6;
00345 
00346                 while (j--) {
00347                         c <<= 1;
00348                         c |= *p++;
00349                 }
00350                 c += '.';               /* becomes >= '.' */
00351                 if (c > '9') c += 7;    /* not in [./0-9], becomes upper */
00352                 if (c > 'Z') c += 6;    /* not in [A-Z], becomes lower */
00353                 *cp++ = c;
00354         }
00355         *cp = 0;
00356         return result;
00357 }

Generated on Fri Apr 14 22:57:10 2006 for minix by  doxygen 1.4.6