(linenum→info "unix/slp.c:2238")

glibc/2.7/crypt/md5-crypt.c

    1: /* One way encryption based on MD5 sum.
    2:    Compatible with the behavior of MD5 crypt introduced in FreeBSD 2.0.
    3:    Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2004
    4:    Free Software Foundation, Inc.
    5:    This file is part of the GNU C Library.
    6:    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
    7: 
    8:    The GNU C Library is free software; you can redistribute it and/or
    9:    modify it under the terms of the GNU Lesser General Public
   10:    License as published by the Free Software Foundation; either
   11:    version 2.1 of the License, or (at your option) any later version.
   12: 
   13:    The GNU C Library is distributed in the hope that it will be useful,
   14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   16:    Lesser General Public License for more details.
   17: 
   18:    You should have received a copy of the GNU Lesser General Public
   19:    License along with the GNU C Library; if not, write to the Free
   20:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   21:    02111-1307 USA.  */
   22: 
   23: #include <assert.h>
   24: #include <errno.h>
   25: #include <stdlib.h>
   26: #include <string.h>
   27: #include <sys/param.h>
   28: 
   29: #include "md5.h"
   30: 
   31: 
   32: /* Define our magic string to mark salt for MD5 "encryption"
   33:    replacement.  This is meant to be the same as for other MD5 based
   34:    encryption implementations.  */
   35: static const char md5_salt_prefix[] = "$1$";
   36: 
   37: /* Table with characters for base64 transformation.  */
   38: static const char b64t[64] =
   39: "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
   40: 
   41: 
   42: /* Prototypes for local functions.  */
   43: extern char *__md5_crypt_r (const char *key, const char *salt,
   44:                             char *buffer, int buflen);
   45: extern char *__md5_crypt (const char *key, const char *salt);
   46: 
   47: 
   48: /* This entry point is equivalent to the `crypt' function in Unix
   49:    libcs.  */
   50: char *
   51: __md5_crypt_r (key, salt, buffer, buflen)
   52:      const char *key;
   53:      const char *salt;
   54:      char *buffer;
   55:      int buflen;
   56: {
   57:   unsigned char alt_result[16]
   58:     __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
   59:   struct md5_ctx ctx;
   60:   struct md5_ctx alt_ctx;
   61:   size_t salt_len;
   62:   size_t key_len;
   63:   size_t cnt;
   64:   char *cp;
   65:   char *copied_key = NULL;
   66:   char *copied_salt = NULL;
   67: 
   68:   /* Find beginning of salt string.  The prefix should normally always
   69:      be present.  Just in case it is not.  */
   70:   if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
   71:     /* Skip salt prefix.  */
   72:     salt += sizeof (md5_salt_prefix) - 1;
   73: 
   74:   salt_len = MIN (strcspn (salt, "$"), 8);
   75:   key_len = strlen (key);
   76: 
   77:   if ((key - (char *) 0) % __alignof__ (md5_uint32) != 0)
   78:     {
   79:       char *tmp = (char *) alloca (key_len + __alignof__ (md5_uint32));
   80:       key = copied_key =
   81:         memcpy (tmp + __alignof__ (md5_uint32)
   82:                 - (tmp - (char *) 0) % __alignof__ (md5_uint32),
   83:                 key, key_len);
   84:       assert ((key - (char *) 0) % __alignof__ (md5_uint32) == 0);
   85:     }
   86: 
   87:   if ((salt - (char *) 0) % __alignof__ (md5_uint32) != 0)
   88:     {
   89:       char *tmp = (char *) alloca (salt_len + __alignof__ (md5_uint32));
   90:       salt = copied_salt =
   91:         memcpy (tmp + __alignof__ (md5_uint32)
   92:                 - (tmp - (char *) 0) % __alignof__ (md5_uint32),
   93:                 salt, salt_len);
   94:       assert ((salt - (char *) 0) % __alignof__ (md5_uint32) == 0);
   95:     }
   96: 
   97:   /* Prepare for the real work.  */
   98:   __md5_init_ctx (&ctx);
   99: 
  100:   /* Add the key string.  */
  101:   __md5_process_bytes (key, key_len, &ctx);
  102: 
  103:   /* Because the SALT argument need not always have the salt prefix we
  104:      add it separately.  */
  105:   __md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, &ctx);
  106: 
  107:   /* The last part is the salt string.  This must be at most 8
  108:      characters and it ends at the first `$' character (for
  109:      compatibility with existing implementations).  */
  110:   __md5_process_bytes (salt, salt_len, &ctx);
  111: 
  112: 
  113:   /* Compute alternate MD5 sum with input KEY, SALT, and KEY.  The
  114:      final result will be added to the first context.  */
  115:   __md5_init_ctx (&alt_ctx);
  116: 
  117:   /* Add key.  */
  118:   __md5_process_bytes (key, key_len, &alt_ctx);
  119: 
  120:   /* Add salt.  */
  121:   __md5_process_bytes (salt, salt_len, &alt_ctx);
  122: 
  123:   /* Add key again.  */
  124:   __md5_process_bytes (key, key_len, &alt_ctx);
  125: 
  126:   /* Now get result of this (16 bytes) and add it to the other
  127:      context.  */
  128:   __md5_finish_ctx (&alt_ctx, alt_result);
  129: 
  130:   /* Add for any character in the key one byte of the alternate sum.  */
  131:   for (cnt = key_len; cnt > 16; cnt -= 16)
  132:     __md5_process_bytes (alt_result, 16, &ctx);
  133:   __md5_process_bytes (alt_result, cnt, &ctx);
  134: 
  135:   /* For the following code we need a NUL byte.  */
  136:   *alt_result = '\0';
  137: 
  138:   /* The original implementation now does something weird: for every 1
  139:      bit in the key the first 0 is added to the buffer, for every 0
  140:      bit the first character of the key.  This does not seem to be
  141:      what was intended but we have to follow this to be compatible.  */
  142:   for (cnt = key_len; cnt > 0; cnt >>= 1)
  143:     __md5_process_bytes ((cnt & 1) != 0 ? (const char *) alt_result : key, 1,
  144:                          &ctx);
  145: 
  146:   /* Create intermediate result.  */
  147:   __md5_finish_ctx (&ctx, alt_result);
  148: 
  149:   /* Now comes another weirdness.  In fear of password crackers here
  150:      comes a quite long loop which just processes the output of the
  151:      previous round again.  We cannot ignore this here.  */
  152:   for (cnt = 0; cnt < 1000; ++cnt)
  153:     {
  154:       /* New context.  */
  155:       __md5_init_ctx (&ctx);
  156: 
  157:       /* Add key or last result.  */
  158:       if ((cnt & 1) != 0)
  159:         __md5_process_bytes (key, key_len, &ctx);
  160:       else
  161:         __md5_process_bytes (alt_result, 16, &ctx);
  162: 
  163:       /* Add salt for numbers not divisible by 3.  */
  164:       if (cnt % 3 != 0)
  165:         __md5_process_bytes (salt, salt_len, &ctx);
  166: 
  167:       /* Add key for numbers not divisible by 7.  */
  168:       if (cnt % 7 != 0)
  169:         __md5_process_bytes (key, key_len, &ctx);
  170: 
  171:       /* Add key or last result.  */
  172:       if ((cnt & 1) != 0)
  173:         __md5_process_bytes (alt_result, 16, &ctx);
  174:       else
  175:         __md5_process_bytes (key, key_len, &ctx);
  176: 
  177:       /* Create intermediate result.  */
  178:       __md5_finish_ctx (&ctx, alt_result);
  179:     }
  180: 
  181:   /* Now we can construct the result string.  It consists of three
  182:      parts.  */
  183:   cp = __stpncpy (buffer, md5_salt_prefix, MAX (0, buflen));
  184:   buflen -= sizeof (md5_salt_prefix) - 1;
  185: 
  186:   cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
  187:   buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
  188: 
  189:   if (buflen > 0)
  190:     {
  191:       *cp++ = '$';
  192:       --buflen;
  193:     }
  194: 
  195: #define b64_from_24bit(B2, B1, B0, N)                                         \
  196:   do {                                                                        \
  197:     unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);                       \
  198:     int n = (N);                                                              \
  199:     while (n-- > 0 && buflen > 0)                                             \
  200:       {                                                                       \
  201:         *cp++ = b64t[w & 0x3f];                                                      \
  202:         --buflen;                                                            \
  203:         w >>= 6;                                                             \
  204:       }                                                                       \
  205:   } while (0)
  206: 
  207: 
  208:   b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4);
  209:   b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4);
  210:   b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4);
  211:   b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4);
  212:   b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4);
  213:   b64_from_24bit (0, 0, alt_result[11], 2);
  214:   if (buflen <= 0)
  215:     {
  216:       __set_errno (ERANGE);
  217:       buffer = NULL;
  218:     }
  219:   else
  220:     *cp = '\0';         /* Terminate the string.  */
  221: 
  222:   /* Clear the buffer for the intermediate result so that people
  223:      attaching to processes or reading core dumps cannot get any
  224:      information.  We do it in this way to clear correct_words[]
  225:      inside the MD5 implementation as well.  */
  226:   __md5_init_ctx (&ctx);
  227:   __md5_finish_ctx (&ctx, alt_result);
  228:   memset (&ctx, '\0', sizeof (ctx));
  229:   memset (&alt_ctx, '\0', sizeof (alt_ctx));
  230:   if (copied_key != NULL)
  231:     memset (copied_key, '\0', key_len);
  232:   if (copied_salt != NULL)
  233:     memset (copied_salt, '\0', salt_len);
  234: 
  235:   return buffer;
  236: }
  237: 
  238: #ifndef _LIBC
  239: # define libc_freeres_ptr(decl) decl
  240: #endif
  241: libc_freeres_ptr (static char *buffer);
  242: 
  243: char *
  244: __md5_crypt (const char *key, const char *salt)
  245: {
  246:   /* We don't want to have an arbitrary limit in the size of the
  247:      password.  We can compute the size of the result in advance and
  248:      so we can prepare the buffer we pass to `md5_crypt_r'.  */
  249:   static int buflen;
  250:   int needed = 3 + strlen (salt) + 1 + 26 + 1;
  251: 
  252:   if (buflen < needed)
  253:     {
  254:       char *new_buffer = (char *) realloc (buffer, needed);
  255:       if (new_buffer == NULL)
  256:         return NULL;
  257: 
  258:       buffer = new_buffer;
  259:       buflen = needed;
  260:     }
  261: 
  262:   return __md5_crypt_r (key, salt, buffer, buflen);
  263: }
  264: 
  265: #ifndef _LIBC
  266: static void
  267: __attribute__ ((__destructor__))
  268: free_mem (void)
  269: {
  270:   free (buffer);
  271: }
  272: #endif
Syntax (Markdown)