/*
	cracker.c
	Designed and Programmed by Eric Shalov <eric@freehack.com>
	version 1.0

	To compile:
		gcc -Wall -o cracker cracker.c -lcrypt

	This program requires an ASCII file called "words" with a list of
	dictionary words.
	
	Usage:
		cracker <UNIX password filename>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
    
	This program is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	General Public License for more details.
        
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
           
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crypt.h>

struct word_list {
	char word[8+1];
	struct word_list *next;
};

/* prototypes */
struct word_list *read_words(char *filename);
int crack(char *password_file);

int main(int argc, char *argv[]) {
	crack(argv[1]);
	
	return 0;
}

int crack(char *password_file) {
	char s[200], *key;
	char *username, *cpass, *pass;
	struct word_list *w;
	int found;
	struct word_list *words = NULL;
	FILE *f;
	unsigned long crypts = 0;
	
	if( ! (f=fopen(password_file,"r")) ) {
		perror("open");
		exit(1);
	}
		
	words = read_words("words");
		
	while( fgets(s,100,f) != NULL ) {
		username = strdup( strtok(s,":") );
		cpass = strdup( strtok(NULL,":") );
		
		found = 0;
		for(w=words;w && !found;w=w->next) {
			pass=w->word;

			if(! (crypts%256) ) {
				printf("%8lu\r",
					crypts);
				fflush(stdout);
			}
			
			key = crypt(pass,cpass);
			++crypts;
			if(strcmp(key,cpass)==0) {
				printf("%s:%s\n",username,pass);
				found=1;
			}
		}
	}

	fclose(f);

	return 0;
}

struct word_list *read_words(char *filename) {
	FILE *f;
	char line[100];
	struct word_list *p = NULL, *new, *words = NULL;
	
	if( ! (f=fopen(filename,"r")) ) {
		perror("open");
		exit(1);
	}
	
	while(!feof(f)) {
		fgets(line,100,f);
		if(*line) line[strlen(line)-1]='\0';
		line[8]='\0';
		
		if( ! (new = malloc(sizeof(struct word_list))) ) {
			fprintf(stderr,"out of memory.\n");
			exit(1);
		}
		
		new->next = NULL;
		strcpy(new->word,line);

		if(words)
			p=p->next=new; else
			p=words=new;
	}
	
	fclose(f);
	
	return words;
}

