## modules/au/crypt-md5.c

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following functions.

1. crypt_md5

       1 /*
       2  * ----------------------------------------------------------------------------
       3  * "THE BEER-WARE LICENSE" (Revision 42):
       4  * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
       5  * can do whatever you want with this stuff. If we meet some day, and you think
       6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
       7  * ----------------------------------------------------------------------------
       8  */
       9
      10 /* #include <sys/cdefs.h>
      11 __FBSDID("$FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.12 2002/03/25 15:55:36 phk Exp $");
      12 */
      13 #include <config.h>
      14 #include <unistd.h>
      15 #include <stdio.h>
      16 #include <string.h>
      17 #include <md5.h>
      18 /* #include <err.h> */
      19 #include "crypt.h"
      20
      21 /*
      22  * UNIX password
      23  */
      24
      25 char *
      26 crypt_md5(const char *pw, const char *salt)
         /* [<][>][^][v][top][bottom][index][help] */
      27 {
      28         MD5_CTX ctx,ctx1;
      29         unsigned long l;
      30         int sl, pl;
      31         u_int i;
      32         u_char final[MD5_SIZE];
      33         static const char *sp, *ep;
      34         static char passwd[120], *p;
      35         static const char *magic = "$1$";       /*
      36                                                  * This string is magic for
      37                                                  * this algorithm.  Having
      38                                                  * it this way, we can get
      39                                                  * better later on.
      40                                                  */
      41
      42         /* Refine the Salt first */
      43         sp = salt;
      44
      45         /* If it starts with the magic string, then skip that */
      46         if(!strncmp(sp, magic, strlen(magic)))
      47                 sp += strlen(magic);
      48
      49         /* It stops at the first '$', max 8 chars */
      50         for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
      51                 continue;
      52
      53         /* get the length of the true salt */
      54         sl = ep - sp;
      55
      56         MD5Init(&ctx);
      57
      58         /* The password first, since that is what is most unknown */
      59         MD5Update(&ctx, (u_char *)pw, strlen(pw));
      60
      61         /* Then our magic string */
      62         MD5Update(&ctx, (u_char *)magic, strlen(magic));
      63
      64         /* Then the raw salt */
      65         MD5Update(&ctx, (u_char *)sp, (u_int)sl);
      66
      67         /* Then just as many characters of the MD5(pw,salt,pw) */
      68         MD5Init(&ctx1);
      69         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
      70         MD5Update(&ctx1, (u_char *)sp, (u_int)sl);
      71         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
      72         MD5Final(final, &ctx1);
      73         for(pl = (int)strlen(pw); pl > 0; pl -= MD5_SIZE)
      74                 MD5Update(&ctx, (u_char *)final,
      75                     (u_int)(pl > MD5_SIZE ? MD5_SIZE : pl));
      76
      77         /* Don't leave anything around in vm they could use. */
      78         memset(final, 0, sizeof(final));
      79
      80         /* Then something really weird... */
      81         for (i = strlen(pw); i; i >>= 1)
      82                 if(i & 1)
      83                     MD5Update(&ctx, (u_char *)final, 1);
      84                 else
      85                     MD5Update(&ctx, (u_char *)pw, 1);
      86
      87         /* Now make the output string */
      88         strcpy(passwd, magic);
      89         strncat(passwd, sp, (u_int)sl);
      90         strcat(passwd, "$");
      91
      92         MD5Final(final, &ctx);
      93
      94         /*
      95          * and now, just to make sure things don't run too fast
      96          * On a 60 Mhz Pentium this takes 34 msec, so you would
      97          * need 30 seconds to build a 1000 entry dictionary...
      98          */
      99         for(i = 0; i < 1000; i++) {
     100                 MD5Init(&ctx1);
     101                 if(i & 1)
     102                         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
     103                 else
     104                         MD5Update(&ctx1, (u_char *)final, MD5_SIZE);
     105
     106                 if(i % 3)
     107                         MD5Update(&ctx1, (u_char *)sp, (u_int)sl);
     108
     109                 if(i % 7)
     110                         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
     111
     112                 if(i & 1)
     113                         MD5Update(&ctx1, (u_char *)final, MD5_SIZE);
     114                 else
     115                         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
     116                 MD5Final(final, &ctx1);
     117         }
     118
     119         p = passwd + strlen(passwd);
     120
     121         l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
     122         _crypt_to64(p, l, 4); p += 4;
     123         l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
     124         _crypt_to64(p, l, 4); p += 4;
     125         l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
     126         _crypt_to64(p, l, 4); p += 4;
     127         l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
     128         _crypt_to64(p, l, 4); p += 4;
     129         l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
     130         _crypt_to64(p, l, 4); p += 4;
     131         l =                    final[11]                ;
     132         _crypt_to64(p, l, 2); p += 2;
     133         *p = '\0';
     134
     135         /* Don't leave anything around in vm they could use. */
     136         memset(final, 0, sizeof(final));
     137
     138         return passwd;
     139 }
     140
     141

/* [<][>][^][v][top][bottom][index][help] */