static int single_process_salt(struct db_salt *salt, char *rule) { struct db_keys *keys; struct db_password *pw, **last; int status, have_words = 0; keys = salt->keys; if (!keys->have_words) goto no_own_words; last = &salt->list; pw = *last; do { /* * "binary" is set to NULL on entries marked for removal (so we remove them * here) or already removed (yet we might hit them once in some obscure cases). */ if (pw->binary) { if (!(status = single_process_pw(salt, pw, rule))) { have_words = 1; goto next; } if (status < 0) /* no words for this hash */ goto next; if (status == 2) /* no hashes left for this salt */ return 0; return 1; /* no hashes left to crack for all salts */ } else { *last = pw->next; /* remove */ } next: last = &pw->next; } while ((pw = pw->next)); if (keys->count && rule_number - keys->rule > (key_count << 1)) if (single_process_buffer(salt)) return 1; if (!keys->count) keys->rule = rule_number; if (!have_words) { keys->have_words = 0; no_own_words: if (keys->count && single_process_buffer(salt)) return 1; } return 0; }
static int single_process_buffer(struct db_salt *salt) { struct db_salt *current; struct db_keys *keys; size_t size; if (crk_process_salt(salt)) return 1; /* * Flush the keys list (since we've just processed the keys), but not the hash * table to allow for more effective checking for duplicates. We could flush * the hash table too, such as by calling single_alloc_keys() here, which would * allow us to drop the update-hash-before-list-entry-reuse code from * single_add_key(). This would speed things up in terms of this source file's * code overhead, however it would allow more duplicates to pass. The apparent * c/s rate (counting duplicates as if they were distinct combinations) would * be higher, but the number of passwords cracked per unit of time might be * lower or higher depending on many things including the relative speed of * password hash computations vs. the "overhead". */ keys = salt->keys; keys->count = 0; keys->ptr = keys->buffer; keys->lock++; if (guessed_keys->count) { keys = mem_alloc(size = sizeof(struct db_keys) - 1 + length * guessed_keys->count); memcpy(keys, guessed_keys, size); keys->ptr = keys->buffer; do { current = single_db->salts; do { if (current == salt) continue; if (!current->list) continue; if (single_add_key(current->keys, keys->ptr)) if (single_process_buffer(current)) return 1; } while ((current = current->next)); keys->ptr += length; } while (--keys->count); MEM_FREE(keys); } keys = salt->keys; keys->lock--; if (!keys->count && !keys->lock) keys->rule = rule_number; return 0; }
static int single_add_key(struct db_salt *salt, char *key, int is_from_guesses) { struct db_keys *keys = salt->keys; int index, new_hash, reuse_hash; struct db_keys_hash_entry *entry; /* Check if this is a known duplicate, and reject it if so */ if ((index = keys->hash->hash[new_hash = single_key_hash(key)]) >= 0) do { entry = &keys->hash->list[index]; if (!strncmp(key, &keys->buffer[entry->offset], length)) return 0; } while ((index = entry->next) >= 0); /* Update the hash table removing the list entry we're about to reuse */ index = keys->hash->hash[reuse_hash = single_key_hash(keys->ptr)]; if (index == keys->count) keys->hash->hash[reuse_hash] = keys->hash->list[index].next; else if (index >= 0) { entry = &keys->hash->list[index]; while ((index = entry->next) >= 0) { if (index == keys->count) { entry->next = keys->hash->list[index].next; break; } entry = &keys->hash->list[index]; } } /* Add the new entry */ index = keys->hash->hash[new_hash]; entry = &keys->hash->list[keys->count]; entry->next = index; entry->offset = keys->ptr - keys->buffer; keys->hash->hash[new_hash] = keys->count; strnfcpy(keys->ptr, key, length); keys->ptr += length; keys->count_from_guesses += is_from_guesses; if (++(keys->count) >= key_count) return single_process_buffer(salt); return 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)); }
static int single_process_pw(struct db_salt *salt, struct db_password *pw, char *rule) { struct db_keys *keys; struct list_entry *first, *second; int first_number, second_number; char pair[RULE_WORD_SIZE]; int split; char *key; unsigned int c; if (!(first = pw->words->head)) return -1; keys = salt->keys; first_number = 0; do { if ((key = rules_apply(first->data, rule, 0, NULL))) if (ext_filter(key)) if (single_add_key(keys, key)) if (single_process_buffer(salt)) return 1; if (!salt->list) return 2; if (!pw->binary) return 0; if (++first_number > SINGLE_WORDS_PAIR_MAX) continue; c = (unsigned int)first->data[0] | 0x20; if (c < 'a' || c > 'z') continue; second_number = 0; second = pw->words->head; do if (first != second) { if ((split = strlen(first->data)) < length) { strnzcpy(pair, first->data, RULE_WORD_SIZE); strnzcat(pair, second->data, RULE_WORD_SIZE); if ((key = rules_apply(pair, rule, split, NULL))) if (ext_filter(key)) if (single_add_key(keys, key)) if (single_process_buffer(salt)) return 1; if (!salt->list) return 2; if (!pw->binary) return 0; } if (first->data[1]) { pair[0] = first->data[0]; pair[1] = 0; strnzcat(pair, second->data, RULE_WORD_SIZE); if ((key = rules_apply(pair, rule, 1, NULL))) if (ext_filter(key)) if (single_add_key(keys, key)) if (single_process_buffer(salt)) return 1; if (!salt->list) return 2; if (!pw->binary) return 0; } } while (++second_number <= SINGLE_WORDS_PAIR_MAX && (second = second->next)); } while ((first = first->next)); return 0; }