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] */