/*
 * S/KEY v1.1b (skey.c)
 *
 * Authors:
 *          Neil M. Haller <nmh@thumper.bellcore.com>
 *          Philip R. Karn <karn@chicago.qualcomm.com>
 *          John S. Walden <jsw@thumper.bellcore.com>
 *          Scott Chasin <chasin@crimelab.com>
 *
 *
 * Stand-alone program for computing responses to S/Key challenges.
 * Takes the iteration count and seed as command line args, prompts
 * for the user's key, and produces both word and hex format responses.
 *
 * Usage example:
 *	>skey 88 ka9q2
 *	Enter password:
 *	OMEN US HORN OMIT BACK AHOY
 *	>
 */

#include <stdio.h>
#ifdef HAS_STD_LIB
#include <stdlib.h>
#else
#include <sys/types.h>
#endif
#include <string.h>
#ifdef	__MSDOS__
#include <dos.h>
#else				/* Assume BSD unix */
#include <fcntl.h>
#include <sgtty.h>
#endif
#include "md4.h"
#include "skey.h"

char *skey_readpass ();
void usage ();
int getopt ();
extern int optind;
extern char *optarg;

main (argc, argv)
  int argc;
  char *argv[];
{
  int n, cnt, i, pass = 0;
  char passwd[256], key[8], buf[33], *seed, *slash;
  int noecho = 1;

  cnt = 1;

  while ((i = getopt (argc, argv, "en:p:")) != EOF)
  {
    switch (i)
    {
    case 'e':
      noecho = 0;
      break;
    case 'n':
      cnt = atoi (optarg);
      break;
    case 'p':
      strcpy (passwd, optarg);
      pass = 1;
      break;
    }
  }

  /* could be in the form <number>/<seed> */

  if (argc <= optind + 1)
  {
    /* look for / in it */
    if (argc <= optind)
    {
      usage (argv[0]);
      exit (1); 
    }

    slash = strchr (argv[optind], '/');
    if (slash == NULL)
    {
      usage (argv[0]);
      exit (1);
    }
    *slash++ = '\0';
    seed = slash;

    if ((n = atoi (argv[optind])) < 0)
    {
      printf ("%s not positive\n", argv[optind]);
      usage (argv[0]);
      exit (1);
    }
  }
  else
  {

    if ((n = atoi (argv[optind])) < 0)
    {
      printf ("%s not positive\n", argv[optind]);
      usage (argv[0]);
      exit (1);
    }
    seed = argv[++optind];
  }

  /* Get user's secret password */
  if (!pass)
  {
    printf ("Reminder - Do not use this program while logged in via telnet or rlogin.\n");
    printf ("Enter secret password: ");
    if (noecho)
      {
	skey_set_term ();
	skey_echo_off ();
      }

    skey_readpass (passwd, sizeof (passwd));

    if (noecho)
      skey_unset_term ();
  }

  skey_rip (passwd);

  /* Crunch seed and password into starting key */
  if (skey_keycrunch (key, seed, passwd) != 0)
  {
    fprintf (stderr, "%s: key crunch failed\n", argv[0]);
    exit (1);
  }
  if (cnt == 1)
  {
    while (n-- != 0)
      skey_f (key);
    printf ("%s\n", skey_btoe (buf, key));
#ifdef	HEXIN
    printf ("%s\n", put8 (buf, key));
#endif
   }
  else
  {
    for (i = 0; i <= n - cnt; i++)
      skey_f (key);
    for (; i <= n; i++)
    {
#ifdef	HEXIN
      printf ("%d: %-29s  %s\n", i, skey_btoe (buf, key), put8 (buf, key));
#else
      printf ("%d: %-29s\n", i, skey_btoe (buf, key));
#endif
      skey_f (key);
    }
  }
  exit (0);
}

void
 usage (s)
  char *s;
{
  printf ("Usage: %s [-e] [-n count] [-p password ] <sequence #>[/] <key> \n", s);
}
