Exemple #1
0
void do_regex_crack(struct db_main *db, const char *regex) {
	c_simplestring_ptr buffer = c_simplestring_new();
	c_iterator_ptr iter = NULL;
	charset encoding = CHARSET_UTF8;
	int ignore_case = 0;
	char word[WORDSIZE];

	if (john_main_process)
		fprintf(stderr, "Warning: regex mode currently can't be "
		        "resumed if aborted\n");

	rexgen_setlocale();
	status_init(&get_progress, 0);
	rec_restore_mode(restore_state);
	rec_init(db, save_state);
	crk_init(db, fix_state, NULL);
	iter = c_regex_iterator_cb(regex, ignore_case, encoding, callback);
	if (!iter) {
		fprintf(stderr, "Error, invalid regex expression.  John exiting now\n");
		exit(1);
	}
	while (c_iterator_next(iter)) {
		c_iterator_value(iter, buffer);
		c_simplestring_to_binary_string(buffer, &word[0], sizeof(word));
		c_simplestring_clear(buffer);
		if (ext_filter((char*)word)) {
			if (crk_process_key((char*)word))
				break;
		}
	}
	c_simplestring_delete(buffer);
	c_iterator_delete(iter);
	crk_done();
	rec_done(event_abort);
}
Exemple #2
0
static void john_mpi_wait(void)
{
	if (!database.password_count && !options.reload_at_crack) {
		int i;

		for (i = 0; i < mpi_p; i++) {
			if (i == mpi_id)
				continue;
			if (mpi_req[i] == NULL)
				mpi_req[i] = mem_alloc_tiny(sizeof(MPI_Request),
				                            MEM_ALIGN_WORD);
			else
				if (*mpi_req[i] != MPI_REQUEST_NULL)
					continue;
			MPI_Isend("r", 1, MPI_CHAR, i, JOHN_MPI_RELOAD,
			          MPI_COMM_WORLD, mpi_req[i]);
		}
	}

	if (john_main_process) {
		log_event("Waiting for other node%s to terminate",
		          mpi_p > 2 ? "s" : "");
		fprintf(stderr, "Waiting for other node%s to terminate\n",
		        mpi_p > 2 ? "s" : "");
		mpi_teardown();
	}

/* Close and possibly remove our .rec file now */
	rec_done(!event_abort ? -1 : -2);
}
Exemple #3
0
static void john_omp_fallback(char **argv) {
	if (!getenv("JOHN_NO_OMP_FALLBACK") && john_omp_threads_new <= 1) {
		rec_done(-2);
#define OMP_FALLBACK_PATHNAME JOHN_SYSTEMWIDE_EXEC "/" OMP_FALLBACK_BINARY
		execv(OMP_FALLBACK_PATHNAME, argv);
		perror("execv: " OMP_FALLBACK_PATHNAME);
	}
}
Exemple #4
0
void rec_init(struct db_main *db, void (*save_mode)(FILE *file))
{
	rec_done(1);

	if (!rec_argc) return;

	rec_name_complete();

	if ((rec_fd = open(path_expand(rec_name), O_RDWR | O_CREAT, 0600)) < 0)
		pexit("open: %s", path_expand(rec_name));
	rec_lock();
	if (!(rec_file = fdopen(rec_fd, "w"))) pexit("fdopen");

	rec_db = db;
	rec_save_mode = save_mode;
}
Exemple #5
0
void do_external_crack(struct db_main *db)
{
	unsigned char *internal;
	c_int *external;

	log_event("Proceeding with external mode: %.100s", ext_mode);

	if (!f_generate) {
		log_event("! No generate() function defined");
		fprintf(stderr, "No generate() for external mode: %s\n",
			ext_mode);
		error();
	}

	internal = (unsigned char *)int_word;
	external = ext_word;
	while (*external)
		*internal++ = *external++;
	*internal = 0;

	status_init(NULL, 0);

	rec_restore_mode(restore_state);
	rec_init(db, save_state);

	crk_init(db, fix_state, NULL);

	do {
		c_execute(f_generate);
		if (!ext_word[0]) break;

		c_execute(f_filter);
		if (!ext_word[0]) continue;

		internal = (unsigned char *)int_word;
		external = ext_word;
		while (*external)
			*internal++ = *external++;
		*internal = 0;

		if (crk_process_key(int_word)) break;
	} while (1);

	crk_done();
	rec_done(event_abort);
}
Exemple #6
0
static void john_wait(void)
{
	int waiting_for = john_child_count;

	log_event("Waiting for %d child%s to terminate",
	    waiting_for, waiting_for == 1 ? "" : "ren");
	log_flush();
	fprintf(stderr, "Waiting for %d child%s to terminate\n",
	    waiting_for, waiting_for == 1 ? "" : "ren");

	log_flush();

	/* Tell our friends there is nothing more to crack! */
	if (!database.password_count && !options.reload_at_crack &&
	    cfg_get_bool(SECTION_OPTIONS, NULL, "ReloadAtDone", 0))
		raise(SIGUSR2);

/*
 * Although we may block on wait(2), we still have signal handlers and a timer
 * in place, so we're relaying keypresses to child processes via signals.
 */
	while (waiting_for) {
		int i, status;
		int pid = wait(&status);
		if (pid == -1) {
			if (errno != EINTR)
				perror("wait");
		} else
		for (i = 0; i < john_child_count; i++) {
			if (john_child_pids[i] == pid) {
				john_child_pids[i] = 0;
				waiting_for--;
				children_ok = children_ok &&
				    WIFEXITED(status) && !WEXITSTATUS(status);
				break;
			}
		}
	}

/* Close and possibly remove our .rec file now */
	rec_done((children_ok && !event_abort) ? -1 : -2);
}
Exemple #7
0
static void single_done(void)
{
	struct db_salt *salt;

	if (!event_abort) {
		if ((salt = single_db->salts)) {
			log_event("- Processing the remaining buffered "
				"candidate passwords, if any");

			do {
				if (!salt->list) continue;
				if (salt->keys->count)
				if (single_process_buffer(salt)) break;
			} while ((salt = salt->next));
		}

		progress = 100;
	}

	rec_done(event_abort || (status.pass && single_db->salts));
}
Exemple #8
0
static void john_set_mpi(void)
{
	options.node_min += mpi_id;
	options.node_max = options.node_min;

	if (mpi_p > 1) {
		if (!john_main_process) {
			if (rec_restoring_now) {
				unsigned int node_id = options.node_min;
				rec_done(-2);
				rec_restore_args(1);
				if (node_id != options.node_min + mpi_id)
					fprintf(stderr,
					    "Inconsistent crash recovery file:"
					    " %s\n", rec_name);
				options.node_min = options.node_max = node_id;
			}
		}
	}
	fflush(stdout);
	fflush(stderr);
}
Exemple #9
0
void do_external_crack(struct db_main *db)
{
    unsigned char *internal;
    c_int *external;

    log_event("Proceeding with external mode: %.100s", ext_mode);

#ifdef HAVE_MPI
    if (mpi_p > 1) log_event("MPI: each node will process 1/%u of candidates", mpi_p);
#endif

    internal = (unsigned char *)int_word;
    external = ext_word;
    while (*external)
        *internal++ = *external++;
    *internal = 0;

    status_init(&get_progress, 0);

    rec_restore_mode(restore_state);
    rec_init(db, save_state);

    crk_init(db, fix_state, NULL);

    do {
        c_execute_fast(f_generate);
        if (!ext_word[0])
            break;

        if (f_filter) {
            c_execute_fast(f_filter);
            if (!ext_word[0])
                continue;
        }

#ifdef HAVE_MPI
        // MPI distribution
        if (mpi_line++ % mpi_p != mpi_id) continue;
#endif
        int_word[0] = ext_word[0];
        if ((int_word[1] = ext_word[1])) {
            internal = (unsigned char *)&int_word[2];
            external = &ext_word[2];
            do {
                if (!(internal[0] = external[0]))
                    break;
                if (!(internal[1] = external[1]))
                    break;
                if (!(internal[2] = external[2]))
                    break;
                if (!(internal[3] = external[3]))
                    break;
                internal += 4;
                external += 4;
            } while (1);
        }

        int_word[maxlen] = 0;
        if (crk_process_key(int_word)) break;
    } while (1);

    if (!event_abort)
        progress = 100; // For reporting DONE after a no-ETA run

    crk_done();
    rec_done(event_abort);
}
Exemple #10
0
void do_wordlist_crack(struct db_main *db, char *name, int rules)
{
	union {
		char buffer[2][LINE_BUFFER_SIZE + CACHE_BANK_SHIFT];
		ARCH_WORD dummy;
	} aligned;
	char *line = aligned.buffer[0], *last = aligned.buffer[1];
	struct rpp_context ctx;
	char *prerule, *rule, *word;
	char *(*apply)(char *word, char *rule, int split, char *last);
	int dist_rules, dist_switch;
	unsigned long my_words, their_words, my_words_left;

	log_event("Proceeding with wordlist mode");

	if (name) {
		if (!(word_file = fopen(path_expand(name), "r")))
			pexit("fopen: %s", path_expand(name));
		log_event("- Wordlist file: %.100s", path_expand(name));
	} else {
		word_file = stdin;
		log_event("- Reading candidate passwords from stdin");
	}

	length = db->format->params.plaintext_length;

	if (rules) {
		if (rpp_init(rule_ctx = &ctx, SUBSECTION_WORDLIST)) {
			log_event("! No wordlist mode rules found");
			if (john_main_process)
				fprintf(stderr,
				    "No wordlist mode rules found in %s\n",
				    cfg_name);
			error();
		}

		rules_init(length);
		rule_count = rules_count(&ctx, -1);

		log_event("- %d preprocessed word mangling rules", rule_count);

		apply = rules_apply;
	} else {
		rule_ctx = NULL;
		rule_count = 1;

		log_event("- No word mangling rules");

		apply = dummy_rules_apply;
	}

	rule_number = 0;
	line_number = 0;

	status_init(get_progress, 0);

	rec_restore_mode(restore_state);
	rec_init(db, save_state);

	crk_init(db, fix_state, NULL);

	prerule = rule = "";
	if (rules)
		prerule = rpp_next(&ctx);

/* A string that can't be produced by fgetl(). */
	last[0] = '\n';
	last[1] = 0;

	dist_rules = 0;
	dist_switch = rule_count; /* never */
	my_words = ~0UL; /* all */
	their_words = 0;
	if (options.node_count) {
		int rule_rem = rule_count % options.node_count;
		const char *now, *later = "";
		dist_switch = rule_count - rule_rem;
		if (!rule_rem || rule_number < dist_switch) {
			dist_rules = 1;
			now = "rules";
			if (rule_rem)
				later = ", then switch to distributing words";
		} else {
			dist_switch = rule_count; /* never */
			my_words = options.node_max - options.node_min + 1;
			their_words = options.node_count - my_words;
			now = "words";
		}
		log_event("- Will distribute %s across nodes%s", now, later);
	}

	my_words_left = my_words;
	if (their_words) {
		if (line_number) {
/* Restored session.  line_number is right after a word we've actually used. */
			int for_node = line_number % options.node_count + 1;
			if (for_node < options.node_min ||
			    for_node > options.node_max) {
/* We assume that line_number is at the beginning of other nodes' block */
				if (skip_lines(their_words, line) &&
/* Check for error since a mere EOF means next rule (the loop below should see
 * the EOF again, and it will skip to next rule if applicable) */
				    ferror(word_file))
					prerule = NULL;
			} else {
				my_words_left =
				    options.node_max - for_node + 1;
			}
		} else {
/* New session.  Skip lower-numbered nodes' lines. */
			if (skip_lines(options.node_min - 1, line))
				prerule = NULL;
		}
	}

	if (prerule)
	do {
		if (rules) {
			if (dist_rules) {
				int for_node =
				    rule_number % options.node_count + 1;
				if (for_node < options.node_min ||
				    for_node > options.node_max)
					goto next_rule;
			}
			if ((rule = rules_reject(prerule, -1, last, db))) {
				if (strcmp(prerule, rule))
					log_event("- Rule #%d: '%.100s'"
						" accepted as '%.100s'",
						rule_number + 1, prerule, rule);
				else
					log_event("- Rule #%d: '%.100s'"
						" accepted",
						rule_number + 1, prerule);
			} else {
				log_event("- Rule #%d: '%.100s' rejected",
					rule_number + 1, prerule);
				goto next_rule;
			}
		}

		while (fgetl(line, LINE_BUFFER_SIZE, word_file)) {
			line_number++;

			if (line[0] != '#') {
process_word:
				if ((word = apply(line, rule, -1, last))) {
					last = word;

					if (ext_filter(word))
					if (crk_process_key(word)) {
						rules = 0;
						break;
					}
				}
next_word:
				if (--my_words_left)
					continue;
				if (skip_lines(their_words, line))
					break;
				my_words_left = my_words;
				continue;
			}

			if (strncmp(line, "#!comment", 9))
				goto process_word;
			goto next_word;
		}

		if (ferror(word_file))
			break;

		if (rules) {
next_rule:
			if (!(rule = rpp_next(&ctx))) break;
			rule_number++;

			if (rule_number >= dist_switch) {
				log_event("- Switching to distributing words");
				dist_rules = 0;
				dist_switch = rule_count; /* not anymore */
				my_words =
				    options.node_max - options.node_min + 1;
				their_words = options.node_count - my_words;
			}

			line_number = 0;
			if (fseek(word_file, 0, SEEK_SET))
				pexit("fseek");

			if (their_words &&
			    skip_lines(options.node_min - 1, line))
				break;
		}

		my_words_left = my_words;
	} while (rules);

	crk_done();
	rec_done(event_abort || (status.pass && db->salts));

	if (ferror(word_file)) pexit("fgets");

	if (name) {
		if (event_abort)
			progress = get_progress();
		else
			progress = 100;

		if (fclose(word_file)) pexit("fclose");
		word_file = NULL;
	}
}
Exemple #11
0
static void john_fork(void)
{
	int i, pid;
	int *pids;

	fflush(stdout);
	fflush(stderr);

#if HAVE_MPI
/*
 * We already initialized MPI before knowing this is actually a fork session.
 * So now we need to tear that "1-node MPI session" down before forking, or
 * all sorts of funny things might happen.
 */
	mpi_teardown();
#endif
/*
 * It may cost less memory to reset john_main_process to 0 before fork()'ing
 * the children than to do it in every child process individually (triggering
 * copy-on-write of the entire page).  We then reset john_main_process back to
 * 1 in the parent, but this only costs one page, not one page per child.
 */
	john_main_process = 0;

	pids = mem_alloc_tiny((options.fork - 1) * sizeof(*pids),
	    sizeof(*pids));

	for (i = 1; i < options.fork; i++) {
		switch ((pid = fork())) {
		case -1:
			pexit("fork");

		case 0:
			sig_preinit();
			options.node_min += i;
			options.node_max = options.node_min;
#if HAVE_OPENCL
			// Poor man's multi-device support
			if (options.gpu_devices->count &&
			    strstr(database.format->params.label, "-opencl")) {
				// Pick device to use for this child
				opencl_preinit();
				gpu_id =
				    gpu_device_list[i % get_number_of_devices_in_use()];
				platform_id = get_platform_id(gpu_id);

				// Hide any other devices from list
				gpu_device_list[0] = gpu_id;
				gpu_device_list[1] = -1;

				// Postponed format init in forked process
				fmt_init(database.format);
			}
#endif
			if (rec_restoring_now) {
				unsigned int node_id = options.node_min;
				rec_done(-2);
				rec_restore_args(1);
				if (node_id != options.node_min + i)
					fprintf(stderr,
					    "Inconsistent crash recovery file:"
					    " %s\n", rec_name);
				options.node_min = options.node_max = node_id;
			}
			sig_init_child();
			return;

		default:
			pids[i - 1] = pid;
		}
	}

#if HAVE_OPENCL
	// Poor man's multi-device support
	if (options.gpu_devices->count &&
	    strstr(database.format->params.label, "-opencl")) {
		// Pick device to use for mother process
		opencl_preinit();
		gpu_id = gpu_device_list[0];
		platform_id = get_platform_id(gpu_id);

		// Hide any other devices from list
		gpu_device_list[1] = -1;

		// Postponed format init in mother process
		fmt_init(database.format);
	}
#endif
	john_main_process = 1;
	john_child_pids = pids;
	john_child_count = options.fork - 1;

	options.node_max = options.node_min;
}
void do_incremental_crack(struct db_main *db, char *mode)
{
	char *charset;
	int min_length, max_length, max_count;
	char *extra;
	FILE *file;
	struct charset_header *header;
	unsigned int check;
	char allchars[CHARSET_SIZE + 1];
	char char1[CHARSET_SIZE + 1];
	char2_table char2;
	chars_table chars[CHARSET_LENGTH - 2];
	unsigned char *ptr;
	unsigned int length, fixed, count;
	unsigned int real_count;
	int last_length, last_count;
	int pos;

	if (!mode) {
		if (db->format == &fmt_LM)
			mode = "LanMan";
		else if (db->format == &fmt_NETLM)
			mode = "LanMan";
		else if (db->format == &fmt_NETHALFLM)
			mode = "LanMan";
		else
			mode = "All";
	}

	log_event("Proceeding with \"incremental\" mode: %.100s", mode);

	if (!(charset = cfg_get_param(SECTION_INC, mode, "File"))) {
		log_event("! No charset defined");
		fprintf(stderr, "No charset defined for mode: %s\n", mode);
		error();
	}

	extra = cfg_get_param(SECTION_INC, mode, "Extra");

	if ((min_length = cfg_get_int(SECTION_INC, mode, "MinLen")) < 0)
		min_length = 0;
	if ((max_length = cfg_get_int(SECTION_INC, mode, "MaxLen")) < 0)
		max_length = CHARSET_LENGTH;
	max_count = cfg_get_int(SECTION_INC, mode, "CharCount");

	if (min_length > max_length) {
		log_event("! MinLen = %d exceeds MaxLen = %d",
			min_length, max_length);
		fprintf(stderr, "MinLen = %d exceeds MaxLen = %d\n",
			min_length, max_length);
		error();
	}

	if (min_length > db->format->params.plaintext_length) {
		log_event("! MinLen = %d is too large for this hash type",
			min_length);
		fprintf(stderr, "MinLen = %d exceeds the maximum possible "
			"length for the current hash type (%d)\n",
			min_length, db->format->params.plaintext_length);
		error();
	}

	if (max_length > db->format->params.plaintext_length) {
		log_event("! MaxLen = %d is too large for this hash type",
			max_length);
		fprintf(stderr, "Warning: "
			"MaxLen = %d is too large for the current hash type, "
			"reduced to %d\n",
			max_length, db->format->params.plaintext_length);
		max_length = db->format->params.plaintext_length;
	}

	if (max_length > CHARSET_LENGTH) {
		log_event("! MaxLen = %d exceeds the compile-time limit of %d",
			max_length, CHARSET_LENGTH);
		fprintf(stderr,
			"\n"
			"MaxLen = %d exceeds the compile-time limit of %d\n\n"
			"There are several good reasons why you probably don't "
			"need to raise it:\n"
			"- many hash types don't support passwords "
			"(or password halves) longer than\n"
			"7 or 8 characters;\n"
			"- you probably don't have sufficient statistical "
			"information to generate a\n"
			"charset file for lengths beyond 8;\n"
			"- the limitation applies to incremental mode only.\n",
			max_length, CHARSET_LENGTH);
		error();
	}

	if (!(file = fopen(path_expand(charset), "rb")))
		pexit("fopen: %s", path_expand(charset));

	header = (struct charset_header *)mem_alloc(sizeof(*header));

	charset_read_header(file, header);
	if (ferror(file)) pexit("fread");

	if (feof(file) ||
	    (memcmp(header->version, CHARSET_V1, sizeof(header->version)) &&
	    memcmp(header->version, CHARSET_V2, sizeof(header->version))) ||
	    !header->count)
		inc_format_error(charset);

	if (header->min != CHARSET_MIN || header->max != CHARSET_MAX ||
	    header->length != CHARSET_LENGTH) {
		log_event("! Incompatible charset file: %.100s", charset);
		fprintf(stderr, "Incompatible charset file: %s\n", charset);
		error();
	}

	if (header->count > CHARSET_SIZE)
		inc_format_error(charset);

	check =
		(unsigned int)header->check[0] |
		((unsigned int)header->check[1] << 8) |
		((unsigned int)header->check[2] << 16) |
		((unsigned int)header->check[3] << 24);
	if (!rec_restoring_now)
		rec_check = check;
	if (rec_check != check) {
		log_event("! Charset file has changed: %.100s", charset);
		fprintf(stderr, "Charset file has changed: %s\n", charset);
		error();
	}

	fread(allchars, header->count, 1, file);
	if (ferror(file)) pexit("fread");
	if (feof(file)) inc_format_error(charset);

	allchars[header->count] = 0;
	if (expand(allchars, extra ? extra : "", sizeof(allchars)))
		inc_format_error(charset);
	real_count = strlen(allchars);

	if (max_count < 0) max_count = CHARSET_SIZE;

	if (min_length != max_length)
		log_event("- Lengths %d to %d, up to %d different characters",
			min_length, max_length, max_count);
	else
		log_event("- Length %d, up to %d different characters",
			min_length, max_count);

	if ((unsigned int)max_count > real_count) {
		log_event("! Only %u characters available", real_count);
		fprintf(stderr, "Warning: only %u characters available\n",
			real_count);
	}

	if (!(db->format->params.flags & FMT_CASE))
	switch (is_mixedcase(allchars)) {
	case -1:
		inc_format_error(charset);

	case 1:
		log_event("! Mixed-case charset, "
			"but the hash type is case-insensitive");
		fprintf(stderr, "Warning: mixed-case charset, "
			"but the current hash type is case-insensitive;\n"
			"some candidate passwords may be unnecessarily "
			"tried more than once.\n");
	}

	if (header->length >= 2)
		char2 = (char2_table)mem_alloc(sizeof(*char2));
	else
		char2 = NULL;
	for (pos = 0; pos < (int)header->length - 2; pos++)
		chars[pos] = (chars_table)mem_alloc(sizeof(*chars[0]));

	rec_compat = 0;
	rec_entry = 0;
	memset(rec_numbers, 0, sizeof(rec_numbers));

	status_init(NULL, 0);
	rec_restore_mode(restore_state);

#ifdef WEBAPI
	if(packet_id) {
		int ret;

		// This is a new packet
		inc_rec_state.initialized = 0;

		inc_rec_state.words_requested = packet_rounds;
		inc_rec_state.words_generated = 0;
		inc_rec_state.cc_0 = -1;
		inc_rec_state.cc_1 = -1;
		inc_rec_state.cc_2 = -1;

		ret = sscanf(packet_state, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%127[^\n]", 
				&rec_entry,
				&rec_numbers[0], &rec_numbers[1], &rec_numbers[2], &rec_numbers[3],
				&rec_numbers[4], &rec_numbers[5], &rec_numbers[6], &rec_numbers[7],
				&inc_rec_state.pos,
				&inc_rec_state.numbers_cache,
				&inc_rec_state.cc_0, &inc_rec_state.cc_1, &inc_rec_state.cc_2,
				inc_rec_state.key_i);
		
		if(ret < 14 || ret > 15) {
			log_event("Invalid packet state, found %d fields in %s", ret, packet_state);
			// XXX - Handle more gracefully..
			error();
		}


		status_init(webapi_inc_get_progress, 0);
	}
#endif

	rec_init(db, save_state);

	ptr = header->order + (entry = rec_entry) * 3;
	memcpy(numbers, rec_numbers, sizeof(numbers));

	crk_init(db, fix_state, NULL);

	last_count = last_length = -1;

	entry--;
	while (ptr < &header->order[sizeof(header->order) - 1]) {
		entry++;
		length = *ptr++; fixed = *ptr++; count = *ptr++;

		if (length >= CHARSET_LENGTH ||
			fixed > length ||
			count >= CHARSET_SIZE) inc_format_error(charset);

		if (entry != rec_entry)
			memset(numbers, 0, sizeof(numbers));

		if (count >= real_count || (fixed && !count)) continue;

		if ((int)length + 1 < min_length ||
			(int)length >= max_length ||
			(int)count >= max_count) continue;

		if ((int)length != last_length) {
			inc_new_length(last_length = length,
				header, file, charset, char1, char2, chars);
			last_count = -1;
		}
		if ((int)count > last_count)
			inc_new_count(length, last_count = count, charset,
				allchars, char1, char2, chars);

		if (!length && !min_length) {
			min_length = 1;
			if (crk_process_key("")) break;
		}

#if 0
		log_event("- Trying length %d, fixed @%d, character count %d",
			length + 1, fixed + 1, count + 1);
#endif
		if (inc_key_loop(length, fixed, count, char1, char2, chars))
			break;
	}
	

	crk_done();
	rec_done(event_abort);

	for (pos = 0; pos < (int)header->length - 2; pos++)
		MEM_FREE(chars[pos]);
	MEM_FREE(char2);
	MEM_FREE(header);

	fclose(file);
}
Exemple #13
0
void do_external_crack(struct db_main *db)
{
	unsigned char *internal;
	c_int *external;
	int my_words, their_words;

	log_event("Proceeding with external mode: %.100s", ext_mode);

	internal = (unsigned char *)int_word;
	external = ext_word;
	while (*external)
		*internal++ = *external++;
	*internal = 0;

	seq = 0;

	status_init(&get_progress, 0);

	rec_restore_mode(restore_state);
	rec_init(db, save_state);

	crk_init(db, fix_state, NULL);

	my_words = options.node_max - options.node_min + 1;
	their_words = options.node_min - 1;

	if (seq) {
/* Restored session.  seq is right after a word we've actually used. */
		int for_node = seq % options.node_count + 1;
		if (for_node < options.node_min ||
		        for_node > options.node_max) {
/* We assume that seq is at the beginning of other nodes' block */
			their_words = options.node_count - my_words;
		} else {
			my_words = options.node_max - for_node + 1;
			their_words = 0;
		}
	}

	do {
		c_execute_fast(f_generate);
		if (!ext_word[0])
			break;

		if (options.node_count) {
			seq++;
			if (their_words) {
				their_words--;
				continue;
			}
			if (--my_words == 0) {
				my_words =
					options.node_max - options.node_min + 1;
				their_words = options.node_count - my_words;
			}
		}

		if (f_filter) {
			c_execute_fast(f_filter);
			if (!ext_word[0])
				continue;
		}

		int_word[0] = ext_word[0];
		if ((int_word[1] = ext_word[1])) {
			internal = (unsigned char *)&int_word[2];
			external = &ext_word[2];
			do {
				if (!(internal[0] = external[0]))
					break;
				if (!(internal[1] = external[1]))
					break;
				if (!(internal[2] = external[2]))
					break;
				if (!(internal[3] = external[3]))
					break;
				internal += 4;
				external += 4;
			} while (1);
		}

		int_word[maxlen] = 0;
		if (options.mask) {
			if (do_mask_crack(int_word))
				break;
		} else
		if (crk_process_key(int_word)) break;
	} while (1);

	if (!event_abort)
		progress = 100; // For reporting DONE after a no-ETA run

	crk_done();
	rec_done(event_abort);
}
Exemple #14
0
static void rec_name_complete(void)
{
	if (rec_name_completed)
		return;

#ifndef HAVE_MPI
	if (options.fork && !john_main_process) {
#else
	if (!john_main_process && options.node_min) {
#endif
		char *suffix = mem_alloc(1 + 20 + strlen(RECOVERY_SUFFIX) + 1);
		sprintf(suffix, ".%u%s", options.node_min, RECOVERY_SUFFIX);
		rec_name = path_session(rec_name, suffix);
		MEM_FREE(suffix);
	} else {
		rec_name = path_session(rec_name, RECOVERY_SUFFIX);
	}

	rec_name_completed = 1;
}

#if OS_FLOCK || FCNTL_LOCKS
static void rec_lock(int shared)
{
	int lockmode;
#if FCNTL_LOCKS
	int blockmode;
	struct flock lock;
#endif

	/*
	 * In options.c, MPI code path call rec_restore_args(mpi_p)
	 * relying on anything >1 meaning LOCK_SH. After restore, the
	 * root node must block, in case some other node has not yet
	 * closed the original file
	 */
	if (shared == 1) {
#if FCNTL_LOCKS
		lockmode = F_WRLCK;
		blockmode = F_SETLKW;
#else
		lockmode = LOCK_EX;
#endif
#ifdef HAVE_MPI
		if (!rec_restored || mpi_id || mpi_p == 1)
#endif
#if FCNTL_LOCKS
			blockmode = F_SETLK;
#else
			lockmode |= LOCK_NB;
#endif
	} else
#if FCNTL_LOCKS
	{
		lockmode = F_RDLCK;
		blockmode = F_SETLK;
	}

#else
		lockmode = LOCK_SH | LOCK_NB;
#endif

#ifdef LOCK_DEBUG
	fprintf(stderr, "%s(%u): Locking session file...\n", __FUNCTION__, options.node_min);
#endif
#if FCNTL_LOCKS
	memset(&lock, 0, sizeof(lock));
	lock.l_type = lockmode;
	if (fcntl(rec_fd, blockmode, &lock)) {
		if (errno == EAGAIN || errno == EACCES) {
#else
	if (flock(rec_fd, lockmode)) {
		if (errno == EWOULDBLOCK) {
#endif
#ifdef HAVE_MPI
			fprintf(stderr, "Node %d@%s: Crash recovery file is"
			        " locked: %s\n", mpi_id + 1, mpi_name,
			        path_expand(rec_name));
#else
			fprintf(stderr, "Crash recovery file is locked: %s\n",
				path_expand(rec_name));
#endif
			error();
		} else
#if FCNTL_LOCKS
			pexit("fcntl()");
#else
			pexit("flock()");
#endif
	}
#ifdef LOCK_DEBUG
	fprintf(stderr, "%s(%u): Locked session file (%s)\n", __FUNCTION__, options.node_min, shared == 1 ? "exclusive" : "shared");
#endif
}

static void rec_unlock(void)
{
#if FCNTL_LOCKS
	struct flock lock = { 0 };
	lock.l_type = F_UNLCK;
#endif
#ifdef LOCK_DEBUG
	fprintf(stderr, "%s(%u): Unlocking session file\n", __FUNCTION__, options.node_min);
#endif
#if FCNTL_LOCKS
	if (fcntl(rec_fd, F_SETLK, &lock))
		pexit("fcntl(F_UNLCK)");
#else
	if (flock(rec_fd, LOCK_UN))
		pexit("flock(LOCK_UN)");
#endif
}
#else
#define rec_lock(lock) \
	{}
#define rec_unlock() \
	{}
#endif

void rec_init(struct db_main *db, void (*save_mode)(FILE *file))
{
	rec_done(1);

	if (!rec_argc) return;

	rec_name_complete();

	if ((rec_fd = open(path_expand(rec_name), O_RDWR | O_CREAT, 0600)) < 0)
		pexit("open: %s", path_expand(rec_name));
	rec_lock(1);
	if (!(rec_file = fdopen(rec_fd, "w"))) pexit("fdopen");

	rec_db = db;
	rec_save_mode = save_mode;
}

void rec_save(void)
{
	int save_format;
#ifdef HAVE_MPI
	int fake_fork;
#endif
	int add_argc = 0, add_enc = 1, add_2nd_enc = 1;
	int add_mkv_stats = (options.mkv_stats ? 1 : 0);
	long size;
	char **opt;

	log_flush();

	if (!rec_file) return;

	if (fseek(rec_file, 0, SEEK_SET)) pexit("fseek");
#ifdef _MSC_VER
	if (_write(fileno(rec_file), "", 0)) pexit("ftruncate");
#elif __CYGWIN__
	if (ftruncate(rec_fd, 0)) pexit("ftruncate");
#endif

	save_format = !options.format && rec_db->loaded;

#ifdef HAVE_MPI
	fake_fork = (mpi_p > 1);
#endif
	opt = rec_argv;
	while (*++opt) {
#ifdef HAVE_MPI
		if (!strncmp(*opt, "--fork", 6))
			fake_fork = 0;
		else
#endif
		if (!strncmp(*opt, "--encoding", 10) ||
			!strncmp(*opt, "--input-encoding", 16))
			add_enc = 0;
		else if (!strncmp(*opt, "--internal-encoding", 19) ||
		         !strncmp(*opt, "--target-encoding", 17))
			add_2nd_enc = 0;
		else if (!strncmp(*opt, "--mkv-stats", 11))
			add_mkv_stats = 0;
	}

	if (add_2nd_enc && (options.flags & FLG_STDOUT) &&
	    (pers_opts.input_enc != UTF_8 || pers_opts.target_enc != UTF_8))
		add_2nd_enc = 0;

	add_argc = add_enc + add_2nd_enc + add_mkv_stats;
#ifdef HAVE_MPI
	add_argc += fake_fork;
#endif
	fprintf(rec_file, RECOVERY_V "\n%d\n",
		rec_argc + (save_format ? 1 : 0) + add_argc);

	opt = rec_argv;
	while (*++opt)
	{
		/* Add defaults as if they were actually on **argv */
		if (options.wordlist &&
		    !(strcmp(*opt, "--wordlist") && strcmp(*opt, "--loopback")))
			fprintf(rec_file, "%s=%s\n", *opt, options.wordlist);
		else if (!strcmp(*opt, "--rules"))
			fprintf(rec_file, "%s=%s\n", *opt,
			        pers_opts.activewordlistrules);
		else if (!strcmp(*opt, "--single"))
			fprintf(rec_file, "%s=%s\n", *opt,
			        pers_opts.activesinglerules);
		else if (!strcmp(*opt, "--incremental"))
			fprintf(rec_file, "%s=%s\n", *opt,
			        options.charset);
		else if (!strcmp(*opt, "--markov"))
			fprintf(rec_file, "%s=%s\n", *opt,
			        options.mkv_param);
		else
			fprintf(rec_file, "%s\n", *opt);
	}

	if (save_format)
		fprintf(rec_file, "--format=%s\n",
		    rec_db->format->params.label);

	if (add_enc)
		fprintf(rec_file, "--input-encoding=%s\n",
		        cp_id2name(pers_opts.input_enc));

	if (add_2nd_enc && pers_opts.input_enc == UTF_8 &&
	    pers_opts.target_enc == UTF_8)
		fprintf(rec_file, "--internal-encoding=%s\n",
		        cp_id2name(pers_opts.internal_enc));
	else if (add_2nd_enc)
		fprintf(rec_file, "--target-encoding=%s\n",
		        cp_id2name(pers_opts.target_enc));

	if (add_mkv_stats)
		fprintf(rec_file, "--mkv-stats=%s\n", options.mkv_stats);
#ifdef HAVE_MPI
	if (fake_fork)
		fprintf(rec_file, "--fork=%d\n", mpi_p);
#endif

	fprintf(rec_file, "%u\n%u\n%x\n%x\n%x\n%x\n%x\n%x\n%x\n"
	    "%d\n%d\n%d\n%x\n",
	    status_get_time() + 1,
	    status.guess_count,
	    status.combs.lo,
	    status.combs.hi,
	    status.combs_ehi,
	    status.crypts.lo,
	    status.crypts.hi,
	    status.cands.lo,
	    status.cands.hi,
	    status.compat,
	    status.pass,
	    status_get_progress ? (int)status_get_progress() : -1,
	    rec_check);

	if (rec_save_mode) rec_save_mode(rec_file);

	if (options.flags & FLG_MASK_STACKED)
		mask_save_state(rec_file);

	if (ferror(rec_file)) pexit("fprintf");

	if ((size = ftell(rec_file)) < 0) pexit("ftell");
	if (fflush(rec_file)) pexit("fflush");
#ifndef _MSC_VER
	if (ftruncate(rec_fd, size)) pexit("ftruncate");
#endif
#if HAVE_WINDOWS_H==0
	if (!options.fork && fsync(rec_fd))
		pexit("fsync");
#endif
}