/*
 * genpwd -- generate random passwords
 *
 * This program generates a number of triplets
 *	(encrypted password, salt, plaintext password)
 * the number of triplets being the first argument or NPASS, if none given.
 * This should be linked using the standard UNIX password encryption
 * algorithm (slow, but accurate), since this is used to generate input
 * for the password checker and timer.
 * If the option "-s" is given, the standard setting for the random number
 * generator is used; otherwise, the low order bits of the time are used
 * to seed the RNG.
 *
 * (c) Copyright 1987 by Matt Bishop and the Universities Space Research
 *			 Association.
 * This work was funded by grant NCC 2-398 from the National Aeronautics
 * and Space Administration to the Universities Space Research Association.
 *
 * Author's Address:
 *		Matt Bishop
 *		Research Institute for Advanced Computer Science
 *		NASA Ames Research Center
 *		Moffett Field, CA  94035
 * ARPANET:	mab@riacs.edu, mab@icarus.riacs.edu
 * CSNET:	mab@riacs.edu
 * UUCP:	...!decvax!decwrl!riacs!mab
 *		...!ihnp4!ames!riacs!mab
 *		...!ucbvax!ames!riacs!mab
 */
#include <ctype.h>
#include <stdio.h>

/*
 * the default number of passwords generated
 */
#define NPASS	1

#define TRUE 1
#define FALSE 0
/*
 * the Berkeley interface is simpler, so we
 * put it on top of the System V stuff
 */
#if defined(SYSV) || defined(UTS) || defined(CRAY1) || defined(CRAY2)
#	define random()		lrand48()
#	define srandom(x)	srand48((long) (x))
#endif

/*
 * the random number generator (normalized)
 */
#define randm(low, high)	(low + (random() % (high - low + 1)))

char *progname;		/* program name */
char passwd[9];		/* the plaintext password */
char salt[3];		/* the salt */

/* the legal password alphabet */
char alpha[65] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

/* library routine */
char *crypt();		/* password encryptor */

main(argc, argv)
     int argc;
     char *argv[];
{
  register int i;		/* counter in a for loop */
  int pwds = NPASS;		/* number of passwords to generate, default = NPASS */
  int dif = FALSE;		/* TRUE to generate different salts for each password */

  progname = argv[0];
  for(i = 1; i < argc; i++){
    if (strncmp(argv[i], "-s", 2) == 0){	/* reseed the RNG */
      if (argv[i][2] == '\0')
	setsalt(0, 1);
      else if (isnum(&argv[i][2]))
	setsalt(atoi(&argv[i][2]), 0);
      else
	fprintf(stderr, "%s: bad RNG seed %s\n",
		progname, &argv[1][2]);
    }
    else if (strcmp(argv[i], "-d") == 0) 	/* generate different salts*/
      dif = TRUE;
    else if (isnum(argv[i]))
      pwds = atoi(argv[i]);
    else
      fprintf(stderr, "Usage: %s [-d] [-s[n]] [npass]\n",
	      progname);
  }
  genpwd(pwds,dif);
  exit(0);
}

/*
 * return 1 if this is an integer, 0 if not
 */
int isnum(s)
     char *s;
{
  /* eat leading sign */
  if (*s == '+' || *s == '-')
    s++;

  /* ignore digits */
  while(isdigit(*s))
    s++;

  /* non-digit better be end of string!  */
  return(*s == '\0');
}

/*
 * generate the passwords
 */
genpwd(n, dif)
     int n;
     int dif;		/* TRUE if a different salt should be used on each password */
{
  register int i;		/* counter in a for loop */
  char *p;		/* points to encrypted password */
  
  if (n <= 0){
    fprintf(stderr, "%s: argument must be more than 0.\n", progname);
    return;
  }
  
  /* initialize password, salt */

  passwd[8] = '\0';
  salt[2] = '\0';

  /* generate the requisite number of passwords  */

  if (!dif)
    genrand(salt, 2);

  for(i = 0; i < n; i++){
    genrand(passwd, randm(1, 8));	/* generate the password */
    if (dif) genrand(salt, 2); 		/* generate the salt */
    p = crypt(passwd, salt);		/* encrypt the sucker */
    printf("%s %s %s\n", p, salt, passwd);
  }
}



/*
 * reseed the RNG
 */
int setsalt(seed, def)
     int seed;			/* use this as seed */
     int def;			/* 1 if to use default (time(0)) */
{
  if (def)
    srandom((int) time(0));
  else
    srandom(seed);
}

/*
 * fill the array with len random characters from alpha[]
 */
genrand(arr, len)
     char arr[];			/* array to be filled */
     int len;			/* number of elements of array to be filled */
{
  register int i;		/* counter in a for loop */
  
  /*
   * fill it up and end with a nul
   */
  for(i = 0; i < len; i++)
    arr[i] = alpha[randm(0,63)];
  arr[len] = '\0';
}





