Add a program to the pam_unix module directory which can be used for
calculating bigcrypt hashes.  This is mainly useful for testing the
bigcrypt option to pam_unix.

diff -uNr Linux-PAM-0.75/modules/pam_unix/Makefile pam-0.75/modules/pam_unix/Makefile
--- Linux-PAM-0.75/modules/pam_unix/Makefile	Mon Oct  1 14:54:30 2001
+++ pam-0.75/modules/pam_unix/Makefile	Thu Aug 30 23:21:01 2001
@@ -44,6 +44,8 @@
 
 CHKPWD=unix_chkpwd
 
+BIGCRYPT=bigcrypt
+
 EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\"
 
 ########################################################################
@@ -76,7 +78,7 @@
 
 ########################### don't edit below #######################
 
-all: dirs $(PLUS) $(LIBSHARED) $(LIBSTATIC) $(CHKPWD) register
+all: dirs $(PLUS) $(LIBSHARED) $(LIBSTATIC) $(CHKPWD) $(BIGCRYPT) register
 
 dynamic/%.o : %.c
 	$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
@@ -124,6 +126,9 @@
 		bigcrypt.o
 	$(CC) -o $(CHKPWD) $^ $(LDLIBS) $(LIBCRYPT)
 
+$(BIGCRYPT): bigcrypt_main.o bigcrypt.o
+	$(CC) -o $(BIGCRYPT) $^ $(LDLIBS) $(LIBCRYPT)
+
 unix_chkpwd.o: unix_chkpwd.c
 	$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
 
diff -uNr Linux-PAM-0.75/modules/pam_unix/bigcrypt_main.c pam-0.75/modules/pam_unix/bigcrypt_main.c
--- Linux-PAM-0.75/modules/pam_unix/bigcrypt_main.c	Wed Dec 31 19:00:00 1969
+++ pam-0.75/modules/pam_unix/bigcrypt_main.c	Thu Aug 30 23:21:08 2001
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <string.h>
+
+extern const char *bigcrypt(const char *password, const char *salt);
+
+int
+main(int argc, char **argv)
+{
+	if (argc < 3) {
+		fprintf(stderr, "Usage: %s password salt\n",
+			strchr(argv[0], '/') ?
+			(strchr(argv[0], '/') + 1) :
+			argv[0]);
+		return 0;
+	}
+	fprintf(stdout, "%s\n", bigcrypt(argv[1], argv[2]));
+	return 0;
+}
diff -uNr Linux-PAM-0.75/modules/pam_unix/bigcrypt.c Linux-PAM-0.75/modules/pam_unix/bigcrypt.c
--- Linux-PAM-0.75/modules/pam_unix/bigcrypt.c	Tue Oct  2 13:57:49 2001
+++ Linux-PAM-0.75/modules/pam_unix/bigcrypt.c	Tue Oct  2 14:20:30 2001
@@ -16,7 +16,7 @@
  * provides the salt for the suceeding block.
  * 
  * Restrictions: The buffer used to hold the encrypted result is
- * statically allocated. (see MAX_PASS_LEN below).  This is necessary,
+ * statically allocated. (see MAX_PASS_SEGS below).  This is necessary,
  * as the returned pointer points to "static data that are overwritten
  * by each call", (XPG3: XSI System Interface + Headers pg 109), and
  * this is a drop in replacement for crypt();
@@ -24,6 +24,7 @@
  * Andy Phillips <atp@mssl.ucl.ac.uk>
  */
 
+#include <sys/param.h>
 #include <crypt.h>
 #include <string.h>
 #include "../../libpam/include/security/_pam_macros.h"
@@ -36,33 +37,37 @@
  * password).
  */
 
-#define MAX_PASS_LEN       16
+#define MAX_PASS_SEGS      16
 #define SEGMENT_SIZE       8
 #define SALT_SIZE          2
-#define KEYBUF_SIZE        ((MAX_PASS_LEN*SEGMENT_SIZE)+SALT_SIZE)
-#define ESEGMENT_SIZE      11
-#define CBUF_SIZE          ((MAX_PASS_LEN*ESEGMENT_SIZE)+SALT_SIZE+1)
+#define KEYBUF_SIZE        ((MAX_PASS_SEGS*SEGMENT_SIZE)+SALT_SIZE)
+#define ESEGMENT_SIZE      (howmany(SEGMENT_SIZE*8,6))
+#define CBUF_SIZE          ((MAX_PASS_SEGS*ESEGMENT_SIZE)+SALT_SIZE)
 
 char *bigcrypt(const char *key, const char *salt)
 {
-	static char dec_c2_cryptbuf[CBUF_SIZE];		/* static storage area */
-
+	static char dec_c2_cryptbuf[CBUF_SIZE + 1]; /* static storage area which
+					       	     * holds the string we pass
+						     * back to the calling
+						     * function or app */
 	unsigned long int keylen, n_seg, j;
 	char *cipher_ptr, *plaintext_ptr, *tmp_ptr, *salt_ptr;
 	char keybuf[KEYBUF_SIZE + 1];
 
-	D(("called with key='%s', salt='%s'.", key, salt));
+	D(("called with key='%s', salt='%s'.", key ?: "(null)",
+	  salt ?: "(null)"));
 
 	/* reset arrays */
-	memset(keybuf, 0, KEYBUF_SIZE + 1);
-	memset(dec_c2_cryptbuf, 0, CBUF_SIZE);
+	memset(keybuf, '\0', sizeof(keybuf));
+	memset(dec_c2_cryptbuf, '\0', sizeof(dec_c2_cryptbuf));
 
 	/* fill KEYBUF_SIZE with key */
-	strncpy(keybuf, key, KEYBUF_SIZE);
+	strncpy(keybuf, key, sizeof(keybuf) - 1);
 
-	/* deal with case that we are doing a password check for a
+	/* Handle cases where we are doing a password check for a
 	   conventially encrypted password: the salt will be
 	   SALT_SIZE+ESEGMENT_SIZE long. */
+	if (salt[0] != '$')
 	if (strlen(salt) == (SALT_SIZE + ESEGMENT_SIZE))
 		keybuf[SEGMENT_SIZE] = '\0';	/* terminate password early(?) */
 
@@ -71,12 +76,12 @@
 	if (!keylen) {
 		n_seg = 1;
 	} else {
-		/* work out how many segments */
+		/* work out how many segments this password will produce */
-		n_seg = 1 + ((keylen - 1) / SEGMENT_SIZE);
+		n_seg = howmany(keylen, SEGMENT_SIZE);
 	}
 
-	if (n_seg > MAX_PASS_LEN)
+	if (n_seg > MAX_PASS_SEGS)
-		n_seg = MAX_PASS_LEN;	/* truncate at max length */
+		n_seg = MAX_PASS_SEGS;	/* truncate at max length */
 
 	/* set up some pointers */
 	cipher_ptr = dec_c2_cryptbuf;
@@ -86,7 +91,7 @@
 	tmp_ptr = crypt(plaintext_ptr, salt);	/* libc crypt() */
 
 	/* and place in the static area */
-	strncpy(cipher_ptr, tmp_ptr, 13);
+	strncpy(cipher_ptr, tmp_ptr, ESEGMENT_SIZE + SALT_SIZE);
 	cipher_ptr += ESEGMENT_SIZE + SALT_SIZE;
 	plaintext_ptr += SEGMENT_SIZE;	/* first block of SEGMENT_SIZE */
 
