## utils/md5_pw.c

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

## DEFINITIONS

This source file includes following functions.

1. POINTER
2. UINT2
3. UINT4
4. MD5_CTX
5. MD5Init
6. MD5Update
7. MD5Final
8. MD5Transform
9. Encode
10. Decode
11. MD5_memcpy
12. MD5_memset
13. _crypt_to64
14. crypt_md5
15. salt_invalid
16. main

       1 /***************************************
       2   $Revision: 1.1 $
       3
       4   Stand alone utilitie for creating crypt md5 passwords
       5
       6   Status: NOT REVIEWED, TESTED
       7
       8   Author(s):       Denis Walker
       9
      10   ******************/ /******************
      11   Modification History:
      12         denis (29/04/2002) Created.
      13   ******************/ /******************
      14   Copyright (c) 2002                    RIPE NCC
      15
      16   All Rights Reserved
      17
      18   Permission to use, copy, modify, and distribute this software and its
      19   documentation for any purpose and without fee is hereby granted,
      20   provided that the above copyright notice appear in all copies and that
      21   both that copyright notice and this permission notice appear in
      22   supporting documentation, and that the name of the author not be
      23   used in advertising or publicity pertaining to distribution of the
      24   software without specific, written prior permission.
      25
      26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
      27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
      28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
      29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
      30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      32  ***************************************/
      33
      34 #include <unistd.h>
      35 #include <stdio.h>
      36 #include <stdlib.h>
      37 #include <string.h>
      38 /*#include <md5.h>*/
      39 /* #include "crypt.h" */
      40 #include <sys/types.h>
      41
      42 /* magic sizes */
      43 #define MD5_SIZE 16
      44
      45 /* PROTOTYPES should be set to one if and only if the compiler supports
      46   function argument prototyping.
      47 The following makes PROTOTYPES default to 0 if it has not already
      48   been defined with C compiler flags.
      49  */
      50 #ifndef PROTOTYPES
      51 #define PROTOTYPES 0
      52 #endif
      53
      54 /* POINTER defines a generic pointer type */
      55 typedef unsigned char *POINTER;
         /* [<][>][^][v][top][bottom][index][help] */
      56
      57 /* UINT2 defines a two byte word */
      58 typedef unsigned short int UINT2;
         /* [<][>][^][v][top][bottom][index][help] */
      59
      60 /* UINT4 defines a four byte word */
      61 typedef unsigned long int UINT4;
         /* [<][>][^][v][top][bottom][index][help] */
      62
      63 /* MD5 context. */
      64 typedef struct {
      65   UINT4 state[4];                                   /* state (ABCD) */
      66   UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
      67   unsigned char buffer[64];                         /* input buffer */
      68 } MD5_CTX;
         /* [<][>][^][v][top][bottom][index][help] */
      69
      70 /* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
      71 If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
      72   returns an empty list.
      73  */
      74 #if PROTOTYPES
      75 #define PROTO_LIST(list) list
      76 #else
      77 #define PROTO_LIST(list) ()
      78 #endif
      79
      80
      81 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
      82  */
      83
      84 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
      85 rights reserved.
      86
      87 License to copy and use this software is granted provided that it
      88 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
      89 Algorithm" in all material mentioning or referencing this software
      90 or this function.
      91
      92 License is also granted to make and use derivative works provided
      93 that such works are identified as "derived from the RSA Data
      94 Security, Inc. MD5 Message-Digest Algorithm" in all material
      95 mentioning or referencing the derived work.
      96
      97 RSA Data Security, Inc. makes no representations concerning either
      98 the merchantability of this software or the suitability of this
      99 software for any particular purpose. It is provided "as is"
     100 without express or implied warranty of any kind.
     101
     102 These notices must be retained in any copies of any part of this
     103 documentation and/or software.
     104  */
     105
     106 /* Constants for MD5Transform routine.
     107  */
     108
     109 #define S11 7
     110 #define S12 12
     111 #define S13 17
     112 #define S14 22
     113 #define S21 5
     114 #define S22 9
     115 #define S23 14
     116 #define S24 20
     117 #define S31 4
     118 #define S32 11
     119 #define S33 16
     120 #define S34 23
     121 #define S41 6
     122 #define S42 10
     123 #define S43 15
     124 #define S44 21
     125
     126 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
     127 static void Encode PROTO_LIST
     128   ((unsigned char *, UINT4 *, unsigned int));
     129 static void Decode PROTO_LIST
     130   ((UINT4 *, unsigned char *, unsigned int));
     131 static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
     132 static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
     133
     134 static unsigned char PADDING[64] = {
     135   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     136   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     137   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     138 };
     139
     140 /* F, G, H and I are basic MD5 functions.
     141  */
     142 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
     143 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
     144 #define H(x, y, z) ((x) ^ (y) ^ (z))
     145 #define I(x, y, z) ((y) ^ ((x) | (~z)))
     146
     147 /* ROTATE_LEFT rotates x left n bits.
     148  */
     149 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
     150
     151 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
     152 Rotation is separate from addition to prevent recomputation.
     153  */
     154 #define FF(a, b, c, d, x, s, ac) { \
     155  (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
     156  (a) = ROTATE_LEFT ((a), (s)); \
     157  (a) += (b); \
     158   }
     159 #define GG(a, b, c, d, x, s, ac) { \
     160  (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
     161  (a) = ROTATE_LEFT ((a), (s)); \
     162  (a) += (b); \
     163   }
     164 #define HH(a, b, c, d, x, s, ac) { \
     165  (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
     166  (a) = ROTATE_LEFT ((a), (s)); \
     167  (a) += (b); \
     168   }
     169 #define II(a, b, c, d, x, s, ac) { \
     170  (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
     171  (a) = ROTATE_LEFT ((a), (s)); \
     172  (a) += (b); \
     173   }
     174
     175 /* MD5 initialization. Begins an MD5 operation, writing a new context.
     176  */
     177 void MD5Init (context)
         /* [<][>][^][v][top][bottom][index][help] */
     178 MD5_CTX *context;                                        /* context */
     179 {
     180   context->count[0] = context->count[1] = 0;
     181   /* Load magic initialization constants.
     182 */
     183   context->state[0] = 0x67452301;
     184   context->state[1] = 0xefcdab89;
     185   context->state[2] = 0x98badcfe;
     186   context->state[3] = 0x10325476;
     187 }
     188
     189 /* MD5 block update operation. Continues an MD5 message-digest
     190   operation, processing another message block, and updating the
     191   context.
     192  */
     193 void MD5Update (context, input, inputLen)
         /* [<][>][^][v][top][bottom][index][help] */
     194 MD5_CTX *context;                                        /* context */
     195 unsigned char *input;                                /* input block */
     196 unsigned int inputLen;                     /* length of input block */
     197 {
     198   unsigned int i, index, partLen;
     199
     200   /* Compute number of bytes mod 64 */
     201   index = (unsigned int)((context->count[0] >> 3) & 0x3F);
     202
     203   /* Update number of bits */
     204   if ((context->count[0] += ((UINT4)inputLen << 3))
     205    < ((UINT4)inputLen << 3))
     206  context->count[1]++;
     207   context->count[1] += ((UINT4)inputLen >> 29);
     208
     209   partLen = 64 - index;
     210
     211   /* Transform as many times as possible.
     212 */
     213   if (inputLen >= partLen) {
     214  MD5_memcpy
     215    ((POINTER)&context->buffer[index], (POINTER)input, partLen);
     216  MD5Transform (context->state, context->buffer);
     217
     218  for (i = partLen; i + 63 < inputLen; i += 64)
     219    MD5Transform (context->state, &input[i]);
     220
     221  index = 0;
     222   }
     223   else
     224  i = 0;
     225
     226   /* Buffer remaining input */
     227   MD5_memcpy
     228  ((POINTER)&context->buffer[index], (POINTER)&input[i],
     229   inputLen-i);
     230 }
     231
     232 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
     233   the message digest and zeroizing the context.
     234  */
     235 void MD5Final (digest, context)
         /* [<][>][^][v][top][bottom][index][help] */
     236 unsigned char digest[16];                         /* message digest */
     237 MD5_CTX *context;                                       /* context */
     238 {
     239   unsigned char bits[8];
     240   unsigned int index, padLen;
     241
     242   /* Save number of bits */
     243   Encode (bits, context->count, 8);
     244
     245   /* Pad out to 56 mod 64.
     246 */
     247   index = (unsigned int)((context->count[0] >> 3) & 0x3f);
     248   padLen = (index < 56) ? (56 - index) : (120 - index);
     249   MD5Update (context, PADDING, padLen);
     250
     251   /* Append length (before padding) */
     252   MD5Update (context, bits, 8);
     253
     254   /* Store state in digest */
     255   Encode (digest, context->state, 16);
     256
     257   /* Zeroize sensitive information.
     258 */
     259   MD5_memset ((POINTER)context, 0, sizeof (*context));
     260 }
     261
     262 /* MD5 basic transformation. Transforms state based on block.
     263  */
     264 static void MD5Transform (state, block)
         /* [<][>][^][v][top][bottom][index][help] */
     265 UINT4 state[4];
     266 unsigned char block[64];
     267 {
     268   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
     269
     270   Decode (x, block, 64);
     271
     272   /* Round 1 */
     273   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
     274   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
     275   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
     276   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
     277   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
     278   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
     279   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
     280   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
     281   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
     282   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
     283   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
     284   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
     285   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
     286   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
     287   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
     288   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
     289
     290  /* Round 2 */
     291   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
     292   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
     293   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
     294   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
     295   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
     296   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
     297   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
     298   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
     299   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
     300   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
     301   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
     302   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
     303   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
     304   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
     305   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
     306   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
     307
     308   /* Round 3 */
     309   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
     310   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
     311   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
     312   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
     313   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
     314   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
     315   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
     316   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
     317   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
     318   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
     319   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
     320   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
     321   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
     322   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
     323   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
     324   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
     325
     326   /* Round 4 */
     327   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
     328   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
     329   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
     330   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
     331   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
     332   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
     333   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
     334   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
     335   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
     336   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
     337   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
     338   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
     339   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
     340   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
     341   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
     342   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
     343
     344   state[0] += a;
     345   state[1] += b;
     346   state[2] += c;
     347   state[3] += d;
     348
     349   /* Zeroize sensitive information.
     350 */
     351   MD5_memset ((POINTER)x, 0, sizeof (x));
     352 }
     353
     354 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
     355   a multiple of 4.
     356  */
     357 static void Encode (output, input, len)
         /* [<][>][^][v][top][bottom][index][help] */
     358 unsigned char *output;
     359 UINT4 *input;
     360 unsigned int len;
     361 {
     362   unsigned int i, j;
     363
     364   for (i = 0, j = 0; j < len; i++, j += 4) {
     365  output[j] = (unsigned char)(input[i] & 0xff);
     366  output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
     367  output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
     368  output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
     369   }
     370 }
     371
     372 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
     373   a multiple of 4.
     374  */
     375 static void Decode (output, input, len)
         /* [<][>][^][v][top][bottom][index][help] */
     376 UINT4 *output;
     377 unsigned char *input;
     378 unsigned int len;
     379 {
     380   unsigned int i, j;
     381
     382   for (i = 0, j = 0; j < len; i++, j += 4)
     383  output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
     384    (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
     385 }
     386
     387 /* Note: Replace "for loop" with standard memcpy if possible.
     388  */
     389
     390 static void MD5_memcpy (output, input, len)
         /* [<][>][^][v][top][bottom][index][help] */
     391 POINTER output;
     392 POINTER input;
     393 unsigned int len;
     394 {
     395   unsigned int i;
     396
     397   for (i = 0; i < len; i++)
     398
     399  output[i] = input[i];
     400 }
     401
     402 /* Note: Replace "for loop" with standard memset if possible.
     403  */
     404 static void MD5_memset (output, value, len)
         /* [<][>][^][v][top][bottom][index][help] */
     405 POINTER output;
     406 int value;
     407 unsigned int len;
     408 {
     409   unsigned int i;
     410
     411   for (i = 0; i < len; i++)
     412  ((char *)output)[i] = (char)value;
     413 }
     414
     415 /*
     416  * Copyright (c) 1999
     417  *      University of California.  All rights reserved.
     418  *
     419  * Redistribution and use in source and binary forms, with or without
     420  * modification, are permitted provided that the following conditions
     421  * are met:
     422  * 1. Redistributions of source code must retain the above copyright
     423  *    notice, this list of conditions and the following disclaimer.
     424  * 2. Redistributions in binary form must reproduce the above copyright
     425  *    notice, this list of conditions and the following disclaimer in the
     426  *    documentation and/or other materials provided with the distribution.
     427  * 3. Neither the name of the author nor the names of any co-contributors
     428  *    may be used to endorse or promote products derived from this software
     429  *    without specific prior written permission.
     430  *
     431  * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
     432  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     433  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     434  * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
     435  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     436  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     437  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     438  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     439  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     440  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     441  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     442  */
     443
     444 static char itoa64[] =          /* 0 ... 63 => ascii - 64 */
     445         "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     446
     447 void
     448 _crypt_to64(char *s, u_long v, int n)
         /* [<][>][^][v][top][bottom][index][help] */
     449 {
     450         while (--n >= 0) {
     451                 *s++ = itoa64[v&0x3f];
     452                 v >>= 6;
     453         }
     454 }
     455
     456 /*
     457  * ----------------------------------------------------------------------------
     458  * "THE BEER-WARE LICENSE" (Revision 42):
     459  * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
     460  * can do whatever you want with this stuff. If we meet some day, and you think
     461  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
     462  * ----------------------------------------------------------------------------
     463  */
     464
     465 char *
     466 crypt_md5(const char *pw, const char *salt)
         /* [<][>][^][v][top][bottom][index][help] */
     467 {
     468         MD5_CTX ctx,ctx1;
     469         unsigned long l;
     470         int sl, pl;
     471         u_int i;
     472         u_char final[MD5_SIZE];
     473         static const char *sp, *ep;
     474         static char passwd[120], *p;
     475         static const char *magic = "$1$";       /*
     476                                                  * This string is magic for
     477                                                  * this algorithm.  Having
     478                                                  * it this way, we can get
     479                                                  * better later on.
     480                                                  */
     481
     482         /* Refine the Salt first */
     483         sp = salt;
     484
     485         /* If it starts with the magic string, then skip that */
     486         if(!strncmp(sp, magic, strlen(magic)))
     487                 sp += strlen(magic);
     488
     489         /* It stops at the first '$', max 8 chars */
     490         for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
     491                 continue;
     492
     493         /* get the length of the true salt */
     494         sl = ep - sp;
     495
     496         MD5Init(&ctx);
     497
     498         /* The password first, since that is what is most unknown */
     499         MD5Update(&ctx, (u_char *)pw, strlen(pw));
     500
     501         /* Then our magic string */
     502         MD5Update(&ctx, (u_char *)magic, strlen(magic));
     503
     504         /* Then the raw salt */
     505         MD5Update(&ctx, (u_char *)sp, (u_int)sl);
     506
     507         /* Then just as many characters of the MD5(pw,salt,pw) */
     508         MD5Init(&ctx1);
     509         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
     510         MD5Update(&ctx1, (u_char *)sp, (u_int)sl);
     511         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
     512         MD5Final(final, &ctx1);
     513         for(pl = (int)strlen(pw); pl > 0; pl -= MD5_SIZE)
     514                 MD5Update(&ctx, (u_char *)final,
     515                     (u_int)(pl > MD5_SIZE ? MD5_SIZE : pl));
     516
     517         /* Don't leave anything around in vm they could use. */
     518         memset(final, 0, sizeof(final));
     519
     520         /* Then something really weird... */
     521         for (i = strlen(pw); i; i >>= 1)
     522                 if(i & 1)
     523                     MD5Update(&ctx, (u_char *)final, 1);
     524                 else
     525                     MD5Update(&ctx, (u_char *)pw, 1);
     526
     527         /* Now make the output string */
     528         strcpy(passwd, magic);
     529         strncat(passwd, sp, (u_int)sl);
     530         strcat(passwd, "$");
     531
     532         MD5Final(final, &ctx);
     533
     534         /*
     535          * and now, just to make sure things don't run too fast
     536          * On a 60 Mhz Pentium this takes 34 msec, so you would
     537          * need 30 seconds to build a 1000 entry dictionary...
     538          */
     539         for(i = 0; i < 1000; i++) {
     540                 MD5Init(&ctx1);
     541                 if(i & 1)
     542                         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
     543                 else
     544                         MD5Update(&ctx1, (u_char *)final, MD5_SIZE);
     545
     546                 if(i % 3)
     547                         MD5Update(&ctx1, (u_char *)sp, (u_int)sl);
     548
     549                 if(i % 7)
     550                         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
     551
     552                 if(i & 1)
     553                         MD5Update(&ctx1, (u_char *)final, MD5_SIZE);
     554                 else
     555                         MD5Update(&ctx1, (u_char *)pw, strlen(pw));
     556                 MD5Final(final, &ctx1);
     557         }
     558
     559         p = passwd + strlen(passwd);
     560
     561         l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
     562         _crypt_to64(p, l, 4); p += 4;
     563         l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
     564         _crypt_to64(p, l, 4); p += 4;
     565         l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
     566         _crypt_to64(p, l, 4); p += 4;
     567         l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
     568         _crypt_to64(p, l, 4); p += 4;
     569         l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
     570         _crypt_to64(p, l, 4); p += 4;
     571         l =                    final[11]                ;
     572         _crypt_to64(p, l, 2); p += 2;
     573         *p = '\0';
     574
     575         /* Don't leave anything around in vm they could use. */
     576         memset(final, 0, sizeof(final));
     577
     578         return passwd;
     579 }
     580
     581
     582 /* check for valid characters only in the salt value supplied */
     583
     584 int salt_invalid(char *salt)
         /* [<][>][^][v][top][bottom][index][help] */
     585 {
     586   int i;
     587
     588   for ( i=0; i<strlen(salt); i++ )
     589   {
     590     if ( (salt[i] >= 'A' && salt[i] <= 'Z')
     591         || (salt[i] >= 'a' && salt[i] <= 'z')
     592         || (salt[i] >= '0' && salt[i] <= '9')
     593         || salt[i] == '.' || salt[i] == '/' )
     594       continue;  /* valid character */
     595     else
     596       return 1;  /* invalid character found */
     597   }
     598   return 0;
     599 }
     600
     601
     602 int main(int argc, char **argv)
         /* [<][>][^][v][top][bottom][index][help] */
     603 {
     604   char *cryptpw;
     605   char *passwd;
     606   char *salt;
     607
     608
     609   if ( argc < 3 )
     610   {
     611     printf("\nUsage: md5_pw password salt\n\n");
     612     return(0);
     613   }
     614
     615   passwd = argv[1];
     616   salt = argv[2];
     617   if ( salt_invalid(salt) )
     618   {
     619     printf("\nsalt [%s] contains characters that are not allowed - only [A-Za-z0-9./] are allowed\n", salt);
     620     exit(0);
     621   }
     622   if (strlen(salt) > 8)
     623     printf("\nOnly first 8 characters of the salt were used\n");
     624
     625   /* printf("salt [%s]\n", salt);
     626   printf("password [%s]\n", passwd); */
     627
     628   cryptpw = crypt_md5((const char *)passwd, (const char *)salt );
     629   printf("\nmd5 crypt password: %s\n\n", cryptpw);
     630
     631   return(0);
     632 }

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