File gensalt-fixes.diff of Package libxcrypt

2008-09-28  Thorsten Kukuk  <kukuk@suse.de>

	* src/xcrypt-private.h: Add prototype for _xcrypt_gensalt_sha256_rn
	and _xcrypt_gensalt_sha512_rn.
	* src/crypt_gensalt.c: Add new gensalt functions.
	* src/xcrypt.c: Use gensalt functions for sha512 and sha256.
	* src/gensalt-test.c: Enable test cases for sha256 and sha512.

2008-07-16  Thorsten Kukuk  <kukuk@suse.de>

	* src/xcrypt.c (__xcrypt_gensalt_r): Handle special
	MD5 case.
	* src/gensalt-test.c: New test case.
	* src/Makefile.am: Add gensalt-test as new test case.

 
--- src/Makefile.am	25 Oct 2007 13:16:41 -0000	1.15
+++ src/Makefile.am	16 Jul 2008 12:21:19 -0000	1.16
@@ -16,7 +16,7 @@
 
 EXTRA_DIST = libxcrypt.map cert.sh cert.input
 
-TESTS = cert.sh bigcrypt-test
+TESTS = cert.sh bigcrypt-test gensalt-test
 
 include_HEADERS = xcrypt.h
 noinst_HEADERS = crypt-private.h libc-symbols.h ufc-crypt.h xcrypt-private.h
@@ -30,7 +30,9 @@
 libxcrypt_la_SOURCES = crypt-entry.c crypt.c crypt_util.c \
                       crypt_gensalt.c xcrypt.c bigcrypt.c
 
-noinst_PROGRAMS = cert bigcrypt-test
+noinst_PROGRAMS = cert bigcrypt-test gensalt-test
 
 cert_LDADD = libxcrypt.la
 bigcrypt_test_LDADD = libxcrypt.la
+gensalt_test_LDADD = libxcrypt.la
+
--- src/crypt_gensalt.c	19 Oct 2007 13:32:40 -0000	1.5
+++ src/crypt_gensalt.c	27 Sep 2008 23:23:38 -0000	1.8
@@ -8,6 +8,8 @@
  */
 
 #include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
 
 #include <errno.h>
 #ifndef __set_errno
@@ -75,39 +77,173 @@
 	return output;
 }
 
-char *_xcrypt_gensalt_md5_rn(unsigned long count,
-	__CONST char *input, int size, char *output, int output_size)
+char *
+_xcrypt_gensalt_md5_rn (unsigned long count __attribute__((unused)),
+			const char *input, int size,
+			char *output, int output_size)
 {
-	unsigned long value;
+  unsigned long value;
 
-	if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000)) {
-		if (output_size > 0) output[0] = '\0';
-		__set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL);
-		return NULL;
+  if (size < 3 || output_size < 3 + 4 + 1)
+    {
+      if (output_size > 0)
+	output[0] = '\0';
+      errno = ERANGE;
+      return NULL;
+    }
+
+  output[0] = '$';
+  output[1] = '1';
+  output[2] = '$';
+  value = (unsigned long)(unsigned char)input[0] |
+    ((unsigned long)(unsigned char)input[1] << 8) |
+    ((unsigned long)(unsigned char)input[2] << 16);
+  output[3] = _xcrypt_itoa64[value & 0x3f];
+  output[4] = _xcrypt_itoa64[(value >> 6) & 0x3f];
+  output[5] = _xcrypt_itoa64[(value >> 12) & 0x3f];
+  output[6] = _xcrypt_itoa64[(value >> 18) & 0x3f];
+  output[7] = '\0';
+
+  if (size >= 6 && output_size >= 3 + 4 + 4 + 1) {
+    value = (unsigned long)(unsigned char)input[3] |
+      ((unsigned long)(unsigned char)input[4] << 8) |
+      ((unsigned long)(unsigned char)input[5] << 16);
+    output[7] = _xcrypt_itoa64[value & 0x3f];
+    output[8] = _xcrypt_itoa64[(value >> 6) & 0x3f];
+    output[9] = _xcrypt_itoa64[(value >> 12) & 0x3f];
+    output[10] = _xcrypt_itoa64[(value >> 18) & 0x3f];
+    output[11] = '\0';
+  }
+
+  return output;
+}
+
+char *
+_xcrypt_gensalt_sha256_rn (unsigned long count, const char *input, int size,
+			   char *output, int output_size)
+{
+  unsigned long value;
+  char *buf;
+  char buf2[12];
+
+  if (count > 0)
+    {
+      if (asprintf (&buf, "$5$rounds=%ld$", count) < 0)
+	{
+	  if (output_size > 0)
+	    output[0] = '\0';
+	  errno = ENOMEM;
+	  return NULL;
+	}
+    }
+  else
+    {
+      if (asprintf (&buf, "$5$") < 0)
+	{
+	  if (output_size > 0)
+	    output[0] = '\0';
+	  errno = ENOMEM;
+	  return NULL;
 	}
+    }
 
-	output[0] = '$';
-	output[1] = '1';
-	output[2] = '$';
-	value = (unsigned long)(unsigned char)input[0] |
-		((unsigned long)(unsigned char)input[1] << 8) |
-		((unsigned long)(unsigned char)input[2] << 16);
-	output[3] = _xcrypt_itoa64[value & 0x3f];
-	output[4] = _xcrypt_itoa64[(value >> 6) & 0x3f];
-	output[5] = _xcrypt_itoa64[(value >> 12) & 0x3f];
-	output[6] = _xcrypt_itoa64[(value >> 18) & 0x3f];
-	output[7] = '\0';
-
-	if (size >= 6 && output_size >= 3 + 4 + 4 + 1) {
-		value = (unsigned long)(unsigned char)input[3] |
-			((unsigned long)(unsigned char)input[4] << 8) |
-			((unsigned long)(unsigned char)input[5] << 16);
-		output[7] = _xcrypt_itoa64[value & 0x3f];
-		output[8] = _xcrypt_itoa64[(value >> 6) & 0x3f];
-		output[9] = _xcrypt_itoa64[(value >> 12) & 0x3f];
-		output[10] = _xcrypt_itoa64[(value >> 18) & 0x3f];
-		output[11] = '\0';
+  if (size < 3 || output_size < (int)strlen (buf) + 4 + 1)
+    {
+      free (buf);
+      if (output_size > 0)
+	output[0] = '\0';
+      errno = ERANGE;
+      return NULL;
+    }
+
+  value = (unsigned long)(unsigned char)input[0] |
+    ((unsigned long)(unsigned char)input[1] << 8) |
+    ((unsigned long)(unsigned char)input[2] << 16);
+  buf2[0] = _xcrypt_itoa64[value & 0x3f];
+  buf2[1] = _xcrypt_itoa64[(value >> 6) & 0x3f];
+  buf2[2] = _xcrypt_itoa64[(value >> 12) & 0x3f];
+  buf2[3] = _xcrypt_itoa64[(value >> 18) & 0x3f];
+  buf2[4] = '\0';
+
+  if (size >= 6 && output_size >= (int)strlen (buf) + 4 + 4 + 1)
+    {
+      value = (unsigned long)(unsigned char)input[3] |
+	((unsigned long)(unsigned char)input[4] << 8) |
+	((unsigned long)(unsigned char)input[5] << 16);
+      buf2[4] = _xcrypt_itoa64[value & 0x3f];
+      buf2[5] = _xcrypt_itoa64[(value >> 6) & 0x3f];
+      buf2[6] = _xcrypt_itoa64[(value >> 12) & 0x3f];
+      buf2[7] = _xcrypt_itoa64[(value >> 18) & 0x3f];
+      buf2[8] = '\0';
+    }
+
+  snprintf (output, output_size, "%s%s", buf, buf2);
+  free (buf);
+
+  return output;
+}
+
+char *
+_xcrypt_gensalt_sha512_rn (unsigned long count, const char *input, int size,
+			   char *output, int output_size)
+{
+  unsigned long value;
+  char *buf;
+  char buf2[12];
+
+  if (count > 0)
+    {
+      if (asprintf (&buf, "$6$rounds=%ld$", count) < 0)
+	{
+	  if (output_size > 0)
+	    output[0] = '\0';
+	  errno = ENOMEM;
+	  return NULL;
+	}
+    }
+  else
+    {
+      if (asprintf (&buf, "$6$") < 0)
+	{
+	  if (output_size > 0)
+	    output[0] = '\0';
+	  errno = ENOMEM;
+	  return NULL;
 	}
+    }
 
-	return output;
+  if (size < 3 || output_size < (int)strlen (buf) + 4 + 1)
+    {
+      free (buf);
+      if (output_size > 0)
+	output[0] = '\0';
+      __set_errno(ERANGE);
+      return NULL;
+    }
+
+  value = (unsigned long)(unsigned char)input[0] |
+    ((unsigned long)(unsigned char)input[1] << 8) |
+    ((unsigned long)(unsigned char)input[2] << 16);
+  buf2[0] = _xcrypt_itoa64[value & 0x3f];
+  buf2[1] = _xcrypt_itoa64[(value >> 6) & 0x3f];
+  buf2[2] = _xcrypt_itoa64[(value >> 12) & 0x3f];
+  buf2[3] = _xcrypt_itoa64[(value >> 18) & 0x3f];
+  buf2[4] = '\0';
+
+  if (size >= 6 && output_size >= (int)strlen (buf) + 4 + 4 + 1)
+    {
+      value = (unsigned long)(unsigned char)input[3] |
+	((unsigned long)(unsigned char)input[4] << 8) |
+	((unsigned long)(unsigned char)input[5] << 16);
+      buf2[4] = _xcrypt_itoa64[value & 0x3f];
+      buf2[5] = _xcrypt_itoa64[(value >> 6) & 0x3f];
+      buf2[6] = _xcrypt_itoa64[(value >> 12) & 0x3f];
+      buf2[7] = _xcrypt_itoa64[(value >> 18) & 0x3f];
+      buf2[8] = '\0';
+    }
+
+  snprintf (output, output_size, "%s%s", buf, buf2);
+  free (buf);
+
+  return output;
 }
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/gensalt-test.c	27 Sep 2008 23:23:38 -0000	1.2
@@ -0,0 +1,109 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/times.h>
+
+#include "xcrypt.h"
+
+#ifndef RANDOM_DEVICE
+#define RANDOM_DEVICE "/dev/urandom"
+#endif
+
+static int
+read_loop (int fd, char *buffer, int count)
+{
+  int offset, block;
+
+  offset = 0;
+  while (count > 0)
+    {
+      block = read(fd, &buffer[offset], count);
+
+      if (block < 0)
+        {
+          if (errno == EINTR)
+            continue;
+          return block;
+        }
+      if (!block)
+        return offset;
+
+      offset += block;
+      count -= block;
+    }
+
+  return offset;
+}
+
+static char *
+make_crypt_salt (const char *crypt_prefix, int crypt_rounds)
+{
+#define CRYPT_GENSALT_OUTPUT_SIZE (7 + 22 + 1)
+  int fd;
+  char entropy[16];
+  char *retval;
+  char output[CRYPT_GENSALT_OUTPUT_SIZE];
+
+  fd = open (RANDOM_DEVICE, O_RDONLY);
+  if (fd < 0)
+    {
+      fprintf (stderr, "Can't open %s for reading: %s\n",
+	       RANDOM_DEVICE, strerror (errno));
+      return NULL;
+    }
+
+  if (read_loop (fd, entropy, sizeof(entropy)) != sizeof(entropy))
+    {
+      close (fd);
+      fprintf (stderr, "Unable to obtain entropy from %s\n",
+	       RANDOM_DEVICE);
+      return NULL;
+    }
+
+  close (fd);
+
+  retval = crypt_gensalt_r (crypt_prefix, crypt_rounds, entropy,
+                            sizeof (entropy), output, sizeof(output));
+
+  memset (entropy, 0, sizeof (entropy));
+
+  if (!retval)
+    {
+      fprintf (stderr,
+	       "Unable to generate a salt, check your crypt settings.\n");
+      return NULL;
+    }
+
+  return strdup (retval);
+}
+
+static char *salt_input[] =
+  { "", "$1$", "$2a$" , "$5$", "$6$" };
+
+int
+main(void)
+{
+  int i;
+
+  for (i = 0; i < (int) (sizeof (salt_input) / sizeof (salt_input[0])); i++)
+    {
+      char *salt = make_crypt_salt (salt_input[i], 0);
+
+      if (salt_input[i][0] != '\0')
+	{
+	  if (strncmp (salt_input[i], salt, strlen (salt_input[i])) != 0)
+	    {
+	      fprintf (stderr, "ERROR: input=%s, output=%s\n",
+		       salt_input[i], salt);
+	      return 1;
+	    }
+	}
+    }
+
+  return 0;
+}
--- src/xcrypt-private.h	30 Oct 2007 11:21:09 -0000	1.6
+++ src/xcrypt-private.h	27 Sep 2008 23:07:21 -0000	1.7
@@ -29,6 +29,14 @@
 					  char *output, int output_size);
 extern char *_xcrypt_gensalt_md5_rn (unsigned long count, __const char *input,
 				     int size, char *output, int output_size);
+extern char *_xcrypt_gensalt_sha256_rn (unsigned long count,
+					__const char *input,
+					int size, char *output,
+					int output_size);
+extern char *_xcrypt_gensalt_sha512_rn (unsigned long count,
+					__const char *input,
+					int size, char *output,
+					int output_size);
 
 extern struct crypt_data _ufc_foobar;
 
--- src/xcrypt.c	25 Oct 2007 12:59:51 -0000	1.2
+++ src/xcrypt.c	27 Sep 2008 23:07:21 -0000	1.5
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007 Thorsten Kukuk
+/* Copyright (C) 2007, 2008 Thorsten Kukuk
    Author: Thorsten Kukuk <kukuk@thkukuk.de>
 
    This program is free software; you can redistribute it and/or modify
@@ -192,7 +192,16 @@
       struct plugin_t *plugin = get_plugin (hash_id);
 
       if (plugin == NULL || plugin->gensalt_r == NULL)
-	use = _xcrypt_gensalt_traditional_rn;
+	{
+	  if (hash_id[0] == '1') /* Special case: MD5 */
+	    use = _xcrypt_gensalt_md5_rn;
+	  else if (hash_id[0] == '5') /* sha256 */
+	    use = _xcrypt_gensalt_sha256_rn;
+	  else if (hash_id[0] == '6') /* sha512 */
+	    use = _xcrypt_gensalt_sha512_rn;
+	  else
+	    use = _xcrypt_gensalt_traditional_rn;
+	}
       else
 	use = plugin->gensalt_r;
     }
openSUSE Build Service is sponsored by