Moved to math/e_gammal_r.c.
[kopensolaris-gnu/glibc.git] / crypt / md5-crypt.c
index 3b20ed1..7ba1491 100644 (file)
@@ -1,22 +1,24 @@
 /* One way encryption based on MD5 sum.
-   Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
+   Compatible with the behavior of MD5 crypt introduced in FreeBSD 2.0.
+   Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2004
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
    The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
 
    The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
+   Lesser General Public License for more details.
 
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
 
 #include <assert.h>
 #include <errno.h>
@@ -60,6 +62,8 @@ __md5_crypt_r (key, salt, buffer, buflen)
   size_t key_len;
   size_t cnt;
   char *cp;
+  char *copied_key = NULL;
+  char *copied_salt = NULL;
 
   /* Find beginning of salt string.  The prefix should normally always
      be present.  Just in case it is not.  */
@@ -73,18 +77,20 @@ __md5_crypt_r (key, salt, buffer, buflen)
   if ((key - (char *) 0) % __alignof__ (md5_uint32) != 0)
     {
       char *tmp = (char *) alloca (key_len + __alignof__ (md5_uint32));
-      key = memcpy (tmp + __alignof__ (md5_uint32)
-                   - (tmp - (char *) 0) % __alignof__ (md5_uint32),
-                   key, key_len);
+      key = copied_key =
+       memcpy (tmp + __alignof__ (md5_uint32)
+               - (tmp - (char *) 0) % __alignof__ (md5_uint32),
+               key, key_len);
       assert ((key - (char *) 0) % __alignof__ (md5_uint32) == 0);
     }
 
   if ((salt - (char *) 0) % __alignof__ (md5_uint32) != 0)
     {
       char *tmp = (char *) alloca (salt_len + __alignof__ (md5_uint32));
-      salt = memcpy (tmp + __alignof__ (md5_uint32)
-                    - (tmp - (char *) 0) % __alignof__ (md5_uint32),
-                    salt, salt_len);
+      salt = copied_salt =
+       memcpy (tmp + __alignof__ (md5_uint32)
+               - (tmp - (char *) 0) % __alignof__ (md5_uint32),
+               salt, salt_len);
       assert ((salt - (char *) 0) % __alignof__ (md5_uint32) == 0);
     }
 
@@ -175,10 +181,10 @@ __md5_crypt_r (key, salt, buffer, buflen)
   /* Now we can construct the result string.  It consists of three
      parts.  */
   cp = __stpncpy (buffer, md5_salt_prefix, MAX (0, buflen));
-  buflen -= sizeof (md5_salt_prefix);
+  buflen -= sizeof (md5_salt_prefix) - 1;
 
-  cp = __stpncpy (cp, salt, MIN ((size_t) buflen, salt_len));
-  buflen -= MIN ((size_t) buflen, salt_len);
+  cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
+  buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
 
   if (buflen > 0)
     {
@@ -215,12 +221,24 @@ __md5_crypt_r (key, salt, buffer, buflen)
 
   /* Clear the buffer for the intermediate result so that people
      attaching to processes or reading core dumps cannot get any
-     information.  */
-  memset (alt_result, '\0', sizeof (alt_result));
+     information.  We do it in this way to clear correct_words[]
+     inside the MD5 implementation as well.  */
+  __md5_init_ctx (&ctx);
+  __md5_finish_ctx (&ctx, alt_result);
+  memset (&ctx, '\0', sizeof (ctx));
+  memset (&alt_ctx, '\0', sizeof (alt_ctx));
+  if (copied_key != NULL)
+    memset (copied_key, '\0', key_len);
+  if (copied_salt != NULL)
+    memset (copied_salt, '\0', salt_len);
 
   return buffer;
 }
 
+#ifndef _LIBC
+# define libc_freeres_ptr(decl) decl
+#endif
+libc_freeres_ptr (static char *buffer);
 
 char *
 __md5_crypt (const char *key, const char *salt)
@@ -228,16 +246,27 @@ __md5_crypt (const char *key, const char *salt)
   /* We don't want to have an arbitrary limit in the size of the
      password.  We can compute the size of the result in advance and
      so we can prepare the buffer we pass to `md5_crypt_r'.  */
-  static char *buffer = NULL;
-  static int buflen = 0;
+  static int buflen;
   int needed = 3 + strlen (salt) + 1 + 26 + 1;
 
   if (buflen < needed)
     {
-      buflen = needed;
-      if ((buffer = realloc (buffer, buflen)) == NULL)
+      char *new_buffer = (char *) realloc (buffer, needed);
+      if (new_buffer == NULL)
        return NULL;
+
+      buffer = new_buffer;
+      buflen = needed;
     }
 
   return __md5_crypt_r (key, salt, buffer, buflen);
 }
+
+#ifndef _LIBC
+static void
+__attribute__ ((__destructor__))
+free_mem (void)
+{
+  free (buffer);
+}
+#endif