/* * Use a smaller alignment for binary ciphertexts and salts that are smaller * than ARCH_SIZE bytes. This saves some memory when dealing with 32-bit * values on a 64-bit system. */ static void *alloc_copy_autoalign(size_t size, void *src) { size_t align = MEM_ALIGN_NONE; if (size >= ARCH_SIZE) align = MEM_ALIGN_WORD; else if (size >= 4) align = 4; return mem_alloc_copy(size, align, src); }
void ldr_init_database(struct db_main *db, struct db_options *options) { db->loaded = 0; db->options = mem_alloc_copy(sizeof(struct db_options), MEM_ALIGN_WORD, options); db->salts = NULL; if (options->flags & DB_CRACKED) { db->salt_hash = NULL; db->password_hash = NULL; db->cracked_hash = mem_alloc( CRACKED_HASH_SIZE * sizeof(struct db_cracked *)); memset(db->cracked_hash, 0, CRACKED_HASH_SIZE * sizeof(struct db_cracked *)); } else { db->salt_hash = mem_alloc( SALT_HASH_SIZE * sizeof(struct db_salt *)); memset(db->salt_hash, 0, SALT_HASH_SIZE * sizeof(struct db_salt *)); db->password_hash = mem_alloc(LDR_HASH_SIZE); memset(db->password_hash, 0, LDR_HASH_SIZE); db->cracked_hash = NULL; if (options->flags & DB_WORDS) { options->flags |= DB_LOGIN; ldr_init_issep(); } } if (!options->max_pps) db->options->max_pps = (unsigned int)~0 >> 1; list_init(&db->plaintexts); db->salt_count = db->password_count = db->guess_count = 0; db->format = NULL; }
static void ldr_load_pw_line(struct db_main *db, char *line) { static int skip_dupe_checking = 0; struct fmt_main *format; int index, count; char *login, *ciphertext, *gecos, *home; char *piece; void *binary, *salt; int salt_hash, pw_hash; struct db_salt *current_salt, *last_salt; struct db_password *current_pw, *last_pw; struct list_main *words; size_t pw_size, salt_size; count = ldr_split_line(&login, &ciphertext, &gecos, &home, NULL, &db->format, db->options, line); if (count <= 0) return; if (count >= 2) db->options->flags |= DB_SPLIT; format = db->format; words = NULL; if (db->options->flags & DB_WORDS) { pw_size = sizeof(struct db_password); salt_size = sizeof(struct db_salt); } else { if (db->options->flags & DB_LOGIN) pw_size = sizeof(struct db_password) - sizeof(struct list_main *); else pw_size = sizeof(struct db_password) - (sizeof(char *) + sizeof(struct list_main *)); salt_size = sizeof(struct db_salt) - sizeof(struct db_keys *); } if (!db->password_hash) ldr_init_password_hash(db); for (index = 0; index < count; index++) { piece = format->methods.split(ciphertext, index, format); binary = format->methods.binary(piece); pw_hash = db->password_hash_func(binary); if (!(db->options->flags & DB_WORDS) && !skip_dupe_checking) { int collisions = 0; if ((current_pw = db->password_hash[pw_hash])) do { if (!memcmp(binary, current_pw->binary, format->params.binary_size) && !strcmp(piece, format->methods.source( current_pw->source, current_pw->binary))) { db->options->flags |= DB_NODUP; break; } if (++collisions <= LDR_HASH_COLLISIONS_MAX) continue; if (format->params.binary_size) fprintf(stderr, "Warning: " "excessive partial hash " "collisions detected\n%s", db->password_hash_func != fmt_default_binary_hash ? "" : "(cause: the \"format\" lacks " "proper binary_hash() function " "definitions)\n"); else fprintf(stderr, "Warning: " "check for duplicates partially " "bypassed to speedup loading\n"); skip_dupe_checking = 1; current_pw = NULL; /* no match */ break; } while ((current_pw = current_pw->next_hash)); if (current_pw) continue; } salt = format->methods.salt(piece); salt_hash = format->methods.salt_hash(salt); if ((current_salt = db->salt_hash[salt_hash])) do { if (!memcmp(current_salt->salt, salt, format->params.salt_size)) break; } while ((current_salt = current_salt->next)); if (!current_salt) { last_salt = db->salt_hash[salt_hash]; current_salt = db->salt_hash[salt_hash] = mem_alloc_tiny(salt_size, MEM_ALIGN_WORD); current_salt->next = last_salt; current_salt->salt = mem_alloc_copy(salt, format->params.salt_size, format->params.salt_align); current_salt->index = fmt_dummy_hash; current_salt->bitmap = NULL; current_salt->list = NULL; current_salt->hash = ¤t_salt->list; current_salt->hash_size = -1; current_salt->count = 0; if (db->options->flags & DB_WORDS) current_salt->keys = NULL; db->salt_count++; } current_salt->count++; db->password_count++; last_pw = current_salt->list; current_pw = current_salt->list = mem_alloc_tiny( pw_size, MEM_ALIGN_WORD); current_pw->next = last_pw; last_pw = db->password_hash[pw_hash]; db->password_hash[pw_hash] = current_pw; current_pw->next_hash = last_pw; /* If we're not going to use the source field for its usual purpose, see if we * can pack the binary value in it. */ if (format->methods.source != fmt_default_source && sizeof(current_pw->source) >= format->params.binary_size) current_pw->binary = memcpy(¤t_pw->source, binary, format->params.binary_size); else current_pw->binary = mem_alloc_copy(binary, format->params.binary_size, format->params.binary_align); if (format->methods.source == fmt_default_source) current_pw->source = str_alloc_copy(piece); if (db->options->flags & DB_WORDS) { if (!words) words = ldr_init_words(login, gecos, home); current_pw->words = words; } if (db->options->flags & DB_LOGIN) { if (count >= 2 && count <= 9) { current_pw->login = mem_alloc_tiny( strlen(login) + 3, MEM_ALIGN_NONE); sprintf(current_pw->login, "%s:%d", login, index + 1); } else if (login == no_username) current_pw->login = login; else if (words && *login) current_pw->login = words->head->data; else current_pw->login = str_alloc_copy(login); } } }
static void ldr_load_pw_line(struct db_main *db, char *line) { struct fmt_main *format; int index, count; char *login, *ciphertext, *gecos, *home; char *piece; void *binary, *salt; int salt_hash, pw_hash; struct db_salt *current_salt, *last_salt; struct db_password *current_pw, *last_pw; struct list_main *words; size_t pw_size, salt_size; extern struct fmt_main fmt_mscash; extern struct fmt_main fmt_oracle; count = ldr_split_line(&login, &ciphertext, &gecos, &home, NULL, &db->format, db->options, line); if (count <= 0) return; if (count >= 2) db->options->flags |= DB_SPLIT; format = db->format; words = NULL; if (db->options->flags & DB_WORDS) { pw_size = sizeof(struct db_password); salt_size = sizeof(struct db_salt); } else { if (db->options->flags & DB_LOGIN) pw_size = sizeof(struct db_password) - sizeof(struct list_main *); else pw_size = sizeof(struct db_password) - (sizeof(char *) + sizeof(struct list_main *)); salt_size = sizeof(struct db_salt) - sizeof(struct db_keys *); } for (index = 0; index < count; index++) { if (db->format == &fmt_mscash) { piece = (char *) mem_alloc_tiny(strlen(login) + strlen(ciphertext) + 4, MEM_ALIGN_NONE); sprintf(piece, "M$%s#%s", login, ciphertext); } else if (db->format == &fmt_oracle) { piece = (char *) mem_alloc_tiny(strlen(login) + strlen(ciphertext) + 4, MEM_ALIGN_NONE); sprintf(piece, "O$%s#%s", login, ciphertext); } else piece = format->methods.split(ciphertext, index); binary = format->methods.binary(piece); pw_hash = LDR_HASH_FUNC(binary); if ((current_pw = db->password_hash[pw_hash])) do { if (!memcmp(current_pw->binary, binary, format->params.binary_size) && !strcmp(current_pw->source, piece)) { if (!(db->options->flags & DB_WORDS) || !strcmp(current_pw->login, login)) break; } } while ((current_pw = current_pw->next_hash)); if (current_pw) continue; salt = format->methods.salt(piece); salt_hash = format->methods.salt_hash(salt); if ((current_salt = db->salt_hash[salt_hash])) do { if (!memcmp(current_salt->salt, salt, format->params.salt_size)) break; } while ((current_salt = current_salt->next)); if (!current_salt) { last_salt = db->salt_hash[salt_hash]; current_salt = db->salt_hash[salt_hash] = mem_alloc_tiny(salt_size, MEM_ALIGN_WORD); current_salt->next = last_salt; current_salt->salt = mem_alloc_copy( format->params.salt_size, MEM_ALIGN_WORD, salt); current_salt->index = fmt_dummy_hash; current_salt->list = NULL; current_salt->hash = ¤t_salt->list; current_salt->hash_size = -1; current_salt->count = 0; if (db->options->flags & DB_WORDS) current_salt->keys = NULL; db->salt_count++; } current_salt->count++; db->password_count++; last_pw = current_salt->list; current_pw = current_salt->list = mem_alloc_tiny( pw_size, MEM_ALIGN_WORD); current_pw->next = last_pw; last_pw = db->password_hash[pw_hash]; db->password_hash[pw_hash] = current_pw; current_pw->next_hash = last_pw; current_pw->binary = mem_alloc_copy( format->params.binary_size, MEM_ALIGN_WORD, binary); current_pw->source = str_alloc_copy(piece); if (db->options->flags & DB_WORDS) { if (!words) words = ldr_init_words(login, gecos, home); current_pw->words = words; } if (db->options->flags & DB_LOGIN) { if (count > 1) { current_pw->login = mem_alloc_tiny( strlen(login) + 3, MEM_ALIGN_NONE); sprintf(current_pw->login, "%s:%d", login, index + 1); } else if (words) current_pw->login = words->head->data; else current_pw->login = str_alloc_copy(login); } } }