static void process_shadow_line(char *line) { static struct shadow_entry **entry = NULL; struct shadow_entry *last; char *login, *passwd, *tail; if (!(passwd = strchr(line, ':'))) { while (*line == ' ' || *line == '\t') line++; /* AIX */ if (!strncmp(line, "password = "******"u_name=", 7)) { if ((passwd = strstr(passwd, ":u_pwd="))) passwd += 7; } else /* HP-UX tcb */ if (!strncmp(passwd, "u_pwd=", 6) && entry) { passwd += 6; if ((tail = strchr(passwd, ':'))) *tail = 0; (*entry)->passwd = str_alloc_copy(passwd); return; } if (passwd && (tail = strchr(passwd, ':'))) *tail = 0; entry = &shadow_table[login_hash(login)]; last = *entry; *entry = mem_alloc_tiny(sizeof(struct shadow_entry), MEM_ALIGN_WORD); (*entry)->next = last; (*entry)->login = str_alloc_copy(login); (*entry)->passwd = passwd ? str_alloc_copy(passwd) : "*"; }
char * str_alloc_copy_func(char * src #if defined(MEMDBG_ON) , char * file, int line #endif ) { size_t size; if (!src) return ""; if (!*src) return ""; size = strlen(src) + 1; #if defined(MEMDBG_ON) return (char *) memcpy( mem_alloc_tiny_func(size, MEM_ALIGN_NONE, file, line), src, size); #else return (char *) memcpy(mem_alloc_tiny(size, MEM_ALIGN_NONE), src, size); #endif }
static void init(struct fmt_main *self) { DES_std_init(); #if DES_BS DES_bs_init(0, (DES_bs_cpt + 28) / 29); #if DES_bs_mt fmt_BSDI.params.min_keys_per_crypt = DES_bs_min_kpc; fmt_BSDI.params.max_keys_per_crypt = DES_bs_max_kpc; #endif DES_std_set_salt(0); DES_count = 1; #else current_salt = -1; #endif buffer = mem_alloc_tiny( sizeof(*buffer) * fmt_BSDI.params.max_keys_per_crypt, MEM_ALIGN_CACHE); }
/* We're essentially using three salts, but we're going to pack it into a single blob for now. |Client Challenge (8 Bytes)|Server Challenge (8 Bytes)|Unicode(Username (<=20).Domain (<=15)) */ static void *get_salt(char *ciphertext) { static unsigned char *binary_salt; unsigned char identity[USERNAME_LENGTH + DOMAIN_LENGTH + 1]; UTF16 identity_ucs2[USERNAME_LENGTH + DOMAIN_LENGTH + 1]; int i, identity_length; int identity_ucs2_length; char *pos = NULL; if (!binary_salt) binary_salt = mem_alloc_tiny(SALT_SIZE, MEM_ALIGN_WORD); /* Calculate identity length */ for (pos = ciphertext + 9; *pos != '$'; pos++); identity_length = pos - (ciphertext + 9); /* Convert identity (username + domain) string to NT unicode */ strnzcpy((char *)identity, ciphertext + 9, sizeof(identity)); identity_ucs2_length = enc_to_utf16((UTF16 *)identity_ucs2, USERNAME_LENGTH + DOMAIN_LENGTH, (UTF8 *)identity, identity_length) * sizeof(int16); if (identity_ucs2_length < 0) // Truncated at Unicode conversion. identity_ucs2_length = strlen16((UTF16 *)identity_ucs2) * sizeof(int16); binary_salt[16] = (unsigned char)identity_ucs2_length; memcpy(&binary_salt[17], (char *)identity_ucs2, identity_ucs2_length); /* Set server challenge */ ciphertext += 10 + identity_length; for (i = 0; i < 8; i++) binary_salt[i] = (atoi16[ARCH_INDEX(ciphertext[i*2])] << 4) + atoi16[ARCH_INDEX(ciphertext[i*2+1])]; /* Set client challenge */ ciphertext += 2 + CHALLENGE_LENGTH / 2 + CIPHERTEXT_LENGTH; for (i = 0; i < 8; ++i) binary_salt[i + 8] = (atoi16[ARCH_INDEX(ciphertext[i*2])] << 4) + atoi16[ARCH_INDEX(ciphertext[i*2+1])]; /* Return a concatenation of the server and client challenges and the identity value */ return (void*)binary_salt; }
static void cfg_add_line(char *line, int number) { struct cfg_list *list; struct cfg_line *entry; entry = mem_alloc_tiny(sizeof(struct cfg_line), MEM_ALIGN_WORD); entry->next = NULL; entry->data = str_alloc_copy(line); entry->number = number; entry->cfg_name = cfg_name; list = cfg_database->list; if (list->tail) { entry->id = list->tail->id + 1; list->tail = list->tail->next = entry; } else { entry->id = 0; list->tail = list->head = entry; } }
static void *get_salt(char *ciphertext) { char *ctcopy = strdup(ciphertext); char *keeptr = ctcopy; int i; char *p; ctcopy += 11; /* skip over "$keychain$*" */ salt_struct = mem_alloc_tiny(sizeof(struct custom_salt), MEM_ALIGN_WORD); p = strtok(ctcopy, "*"); for (i = 0; i < SALTLEN; i++) salt_struct->salt[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16 + atoi16[ARCH_INDEX(p[i * 2 + 1])]; p = strtok(NULL, "*"); for (i = 0; i < IVLEN; i++) salt_struct->iv[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16 + atoi16[ARCH_INDEX(p[i * 2 + 1])]; p = strtok(NULL, "*"); for (i = 0; i < CTLEN; i++) salt_struct->ct[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16 + atoi16[ARCH_INDEX(p[i * 2 + 1])]; free(keeptr); return (void *)salt_struct; }
static int valid(char *ciphertext, struct fmt_main *pFmt) { int length, count_base64, id, pw_length; char pw[PLAINTEXT_LENGTH + 1], *new_ciphertext; /* We assume that these are zero-initialized */ static char sup_length[BINARY_SIZE], sup_id[0x80]; length = count_base64 = 0; while (ciphertext[length]) { if (atoi64[ARCH_INDEX(ciphertext[length])] != 0x7F && (ciphertext[0] == '_' || length >= 2)) count_base64++; length++; } if (length < 13 || length >= BINARY_SIZE) return 0; id = 0; if (length == 13 && count_base64 == 11) id = 1; else if (length >= 13 && count_base64 >= length - 2 && /* allow for invalid salt */ (length - 2) % 11 == 0) id = 2; else if (length == 20 && count_base64 == 19 && ciphertext[0] == '_') id = 3; else if (ciphertext[0] == '$') { id = (unsigned char)ciphertext[1]; if (id <= 0x20 || id >= 0x80) id = 9; } else if (ciphertext[0] == '*' || ciphertext[0] == '!') /* likely locked */ id = 10; /* Previously detected as supported */ if (sup_length[length] > 0 && sup_id[id] > 0) return 1; /* Previously detected as unsupported */ if (sup_length[length] < 0 && sup_id[id] < 0) return 0; pw_length = ((length - 2) / 11) << 3; if (pw_length >= sizeof(pw)) pw_length = sizeof(pw) - 1; memcpy(pw, ciphertext, pw_length); /* reuse the string, why not? */ pw[pw_length] = 0; #if defined(_OPENMP) && defined(__GLIBC__) /* * Let's use crypt_r(3) just like we will in crypt_all() below. * It is possible that crypt(3) and crypt_r(3) differ in their supported hash * types on a given system. */ { struct crypt_data **data = &crypt_data[0]; if (!*data) { /* * **data is not exactly tiny, but we use mem_alloc_tiny() for its alignment * support and error checking. We do not need to free() this memory anyway. * * The page alignment is to keep different threads' data on different pages. */ *data = mem_alloc_tiny(sizeof(**data), MEM_ALIGN_PAGE); memset(*data, 0, sizeof(**data)); } new_ciphertext = crypt_r(pw, ciphertext, *data); } #else new_ciphertext = crypt(pw, ciphertext); #endif if (strlen(new_ciphertext) == length && !strncmp(new_ciphertext, ciphertext, 2)) { sup_length[length] = 1; sup_id[id] = 1; return 1; } if (id != 10 && !ldr_in_pot) #ifdef HAVE_MPI if (mpi_id == 0) #endif fprintf(stderr, "Generic crypt(3) module: " "hash encoding string length %d, type id %c%c\n" "appears to be unsupported on this system; " "will not load such hashes.\n", length, id > 0x20 ? '$' : '#', id > 0x20 ? id : '0' + id); if (!sup_length[length]) sup_length[length] = -1; if (!sup_id[id]) sup_id[id] = -1; return 0; }
static void *get_salt(char *ciphertext) { unsigned int i; size_t count; /* extract data from "salt" */ char *encoded_salt; char *saltcopy = strdup(ciphertext); char *keep_ptr = saltcopy; static rarfile rarfile; saltcopy += 7; /* skip over "$RAR3$*" */ rarfile.type = atoi(strtok(saltcopy, "*")); encoded_salt = strtok(NULL, "*"); for (i = 0; i < 8; i++) rarfile.salt[i] = atoi16[ARCH_INDEX(encoded_salt[i * 2])] * 16 + atoi16[ARCH_INDEX(encoded_salt[i * 2 + 1])]; if (rarfile.type == 0) { /* rar-hp mode */ char *encoded_ct = strtok(NULL, "*"); rarfile.raw_data = (unsigned char*)mem_alloc_tiny(16, MEM_ALIGN_WORD); for (i = 0; i < 16; i++) rarfile.raw_data[i] = atoi16[ARCH_INDEX(encoded_ct[i * 2])] * 16 + atoi16[ARCH_INDEX(encoded_ct[i * 2 + 1])]; } else { char *p = strtok(NULL, "*"); int inlined; for (i = 0; i < 4; i++) rarfile.crc.c[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16 + atoi16[ARCH_INDEX(p[i * 2 + 1])]; rarfile.pack_size = atoll(strtok(NULL, "*")); rarfile.unp_size = atoll(strtok(NULL, "*")); inlined = atoi(strtok(NULL, "*")); /* load ciphertext. We allocate and load all files here, and they don't get unloaded until program ends */ rarfile.raw_data = (unsigned char*)mem_alloc_tiny(rarfile.pack_size, MEM_ALIGN_WORD); if (inlined) { unsigned char *d = rarfile.raw_data; p = strtok(NULL, "*"); for (i = 0; i < rarfile.pack_size; i++) *d++ = atoi16[ARCH_INDEX(p[i * 2])] * 16 + atoi16[ARCH_INDEX(p[i * 2 + 1])]; } else { FILE *fp; rarfile.archive_name = strtok(NULL, "*"); rarfile.pos = atol(strtok(NULL, "*")); if (!(fp = fopen(rarfile.archive_name, "rb"))) { fprintf(stderr, "! %s: %s\n", rarfile.archive_name, strerror(errno)); error(); } fseek(fp, rarfile.pos, SEEK_SET); count = fread(rarfile.raw_data, 1, rarfile.pack_size, fp); if (count != rarfile.pack_size) { fprintf(stderr, "Error loading file from archive '%s', expected %llu bytes, got %zu. Archive possibly damaged.\n", rarfile.archive_name, rarfile.pack_size, count); exit(0); } fclose(fp); } p = strtok(NULL, "*"); rarfile.method = atoi16[ARCH_INDEX(p[0])] * 16 + atoi16[ARCH_INDEX(p[1])]; if (rarfile.method != 0x30) rarfile.crc.w = ~rarfile.crc.w; } MEM_FREE(keep_ptr); return (void*)&rarfile; }
static void *get_salt(char *ciphertext) { int i; my_salt salt, *psalt; static unsigned char *ptr; /* extract data from "ciphertext" */ u8 *copy_mem = (u8*)strdup(ciphertext); u8 *cp, *p; if (!ptr) ptr = mem_alloc_tiny(sizeof(my_salt*),sizeof(my_salt*)); p = copy_mem + TAG_LENGTH+1; /* skip over "$zip2$*" */ memset(&salt, 0, sizeof(salt)); p = pkz_GetFld(p, &cp); // type salt.v.type = atoi((const char*)cp); p = pkz_GetFld(p, &cp); // mode salt.v.mode = atoi((const char*)cp); p = pkz_GetFld(p, &cp); // file_magic enum (ignored) p = pkz_GetFld(p, &cp); // salt for (i = 0; i < SALT_LENGTH(salt.v.mode); i++) salt.salt[i] = (atoi16[ARCH_INDEX(cp[i<<1])]<<4) | atoi16[ARCH_INDEX(cp[(i<<1)+1])]; p = pkz_GetFld(p, &cp); // validator salt.passverify[0] = (atoi16[ARCH_INDEX(cp[0])]<<4) | atoi16[ARCH_INDEX(cp[1])]; salt.passverify[1] = (atoi16[ARCH_INDEX(cp[2])]<<4) | atoi16[ARCH_INDEX(cp[3])]; p = pkz_GetFld(p, &cp); // data len sscanf((const char *)cp, "%x", &salt.comp_len); // later we will store the data blob in our own static data structure, and place the 64 bit LSB of the // MD5 of the data blob into a field in the salt. For the first POC I store the entire blob and just // make sure all my test data is small enough to fit. p = pkz_GetFld(p, &cp); // data blob // Ok, now create the allocated salt record we are going to return back to John, using the dynamic // sized data buffer. psalt = (my_salt*)mem_calloc(1, sizeof(my_salt) + salt.comp_len); psalt->v.type = salt.v.type; psalt->v.mode = salt.v.mode; psalt->comp_len = salt.comp_len; psalt->dsalt.salt_alloc_needs_free = 1; // we used mem_calloc, so JtR CAN free our pointer when done with them. memcpy(psalt->salt, salt.salt, sizeof(salt.salt)); psalt->passverify[0] = salt.passverify[0]; psalt->passverify[1] = salt.passverify[1]; // set the JtR core linkage stuff for this dyna_salt psalt->dsalt.salt_cmp_offset = SALT_CMP_OFF(my_salt, comp_len); psalt->dsalt.salt_cmp_size = SALT_CMP_SIZE(my_salt, comp_len, datablob, psalt->comp_len); if (strcmp((const char*)cp, "ZFILE")) { for (i = 0; i < psalt->comp_len; i++) psalt->datablob[i] = (atoi16[ARCH_INDEX(cp[i<<1])]<<4) | atoi16[ARCH_INDEX(cp[(i<<1)+1])]; } else { u8 *Fn, *Oh, *Ob; long len; uint32_t id; FILE *fp; p = pkz_GetFld(p, &Fn); p = pkz_GetFld(p, &Oh); p = pkz_GetFld(p, &Ob); fp = fopen((const char*)Fn, "rb"); if (!fp) { psalt->v.type = 1; // this will tell the format to 'skip' this salt, it is garbage goto Bail; } sscanf((const char*)Oh, "%lx", &len); if (fseek(fp, len, SEEK_SET)) { fclose(fp); psalt->v.type = 1; goto Bail; } id = fget32LE(fp); if (id != 0x04034b50U) { fclose(fp); psalt->v.type = 1; goto Bail; } sscanf((const char*)Ob, "%lx", &len); if (fseek(fp, len, SEEK_SET)) { fclose(fp); psalt->v.type = 1; goto Bail; } if (fread(psalt->datablob, 1, psalt->comp_len, fp) != psalt->comp_len) { fclose(fp); psalt->v.type = 1; goto Bail; } fclose(fp); } Bail: MEM_FREE(copy_mem); memcpy(ptr, &psalt, sizeof(my_salt*)); return (void*)ptr; }
void rec_restore_args(int lock) { char line[LINE_BUFFER_SIZE]; int index, argc; char **argv; char *save_rec_name; rec_name_complete(); if (!(rec_file = fopen(path_expand(rec_name), "r+"))) { if (options.fork && !john_main_process && errno == ENOENT) { fprintf(stderr, "%u Session completed\n", options.node_min); if (options.flags & FLG_STATUS_CHK) return; log_event("No crash recovery file, terminating"); log_done(); exit(0); } pexit("fopen: %s", path_expand(rec_name)); } rec_fd = fileno(rec_file); if (lock) rec_lock(); if (!fgetl(line, sizeof(line), rec_file)) rec_format_error("fgets"); rec_version = 0; if (!strcmp(line, RECOVERY_V4)) rec_version = 4; else if (!strcmp(line, RECOVERY_V3)) rec_version = 3; else if (!strcmp(line, RECOVERY_V2)) rec_version = 2; else if (!strcmp(line, RECOVERY_V1)) rec_version = 1; else if (strcmp(line, RECOVERY_V0)) rec_format_error(NULL); if (fscanf(rec_file, "%d\n", &argc) != 1) rec_format_error("fscanf"); if (argc < 2) rec_format_error(NULL); argv = mem_alloc_tiny(sizeof(char *) * (argc + 1), MEM_ALIGN_WORD); argv[0] = "john"; for (index = 1; index < argc; index++) if (fgetl(line, sizeof(line), rec_file)) argv[index] = str_alloc_copy(line); else rec_format_error("fgets"); argv[argc] = NULL; save_rec_name = rec_name; opt_init(argv[0], argc, argv); rec_name = save_rec_name; rec_name_completed = 1; if (fscanf(rec_file, "%u\n%u\n%x\n%x\n", &status_restored_time, &status.guess_count, &status.combs.lo, &status.combs.hi) != 4) rec_format_error("fscanf"); if (!status_restored_time) status_restored_time = 1; if (rec_version >= 4) { if (fscanf(rec_file, "%x\n%x\n%x\n%x\n%x\n%d\n", &status.combs_ehi, &status.crypts.lo, &status.crypts.hi, &status.cands.lo, &status.cands.hi, &status.compat) != 6) rec_format_error("fscanf"); } else { /* Historically, we were reusing what became the combs field for candidates * count when in --stdout mode */ status.cands = status.combs; status.compat = 1; } if (rec_version == 0) { status.pass = 0; status.progress = -1; } else if (fscanf(rec_file, "%d\n%d\n", &status.pass, &status.progress) != 2) rec_format_error("fscanf"); if (status.pass < 0 || status.pass > 3) rec_format_error(NULL); if (rec_version < 3) rec_check = 0; else if (fscanf(rec_file, "%x\n", &rec_check) != 1) rec_format_error("fscanf"); rec_restoring_now = 1; }
void list_init(struct list_main **list) { *list = mem_alloc_tiny(sizeof(struct list_main), MEM_ALIGN_WORD); (*list)->tail = (*list)->head = NULL; (*list)->count = 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; }
static char *split(char *ciphertext, int index, struct fmt_main *pFmt) { #else static char *split(char *ciphertext, int index) { #endif static char out[8 + CIPHERTEXT_LENGTH + 1]; if (!strncmp(ciphertext, "$SHA256$", 8)) return ciphertext; memcpy(out, "$SHA256$", 8); memcpy(out + 8, ciphertext, CIPHERTEXT_LENGTH + 1); strlwr(out + 8); return out; } /* ------- To binary functions ------- */ static void * get_binary(char *ciphertext) { static unsigned char *out; uint32_t * b; char *p; int i; if (!out) out = mem_alloc_tiny(FULL_BINARY_SIZE, MEM_ALIGN_WORD); p = ciphertext + 8; for (i = 0; i < (FULL_BINARY_SIZE / 2); i++) { out[i] = (atoi16[ARCH_INDEX(*p)] << 4) | atoi16[ARCH_INDEX(p[1])]; p += 2; } b = (uint32_t *) out; b[0] = SWAP32(b[3]) - 0xa54ff53a; return out; } static void * get_full_binary(char *ciphertext) { static unsigned char *out; char *p; int i; if (!out) out = mem_alloc_tiny(FULL_BINARY_SIZE, MEM_ALIGN_WORD); p = ciphertext + 8; for (i = 0; i < FULL_BINARY_SIZE; i++) { out[i] = (atoi16[ARCH_INDEX(*p)] << 4) | atoi16[ARCH_INDEX(p[1])]; p += 2; } return out; } /* ------- Crypt function ------- */ static void crypt_all(int count) { //Send data to device. HANDLE_CLERROR(clEnqueueWriteBuffer(queue[ocl_gpu_id], pass_buffer, CL_FALSE, 0, sizeof(sha256_password) * global_work_size, plaintext, 0, NULL, NULL), "failed in clEnqueueWriteBuffer pass_buffer"); //Enqueue the kernel HANDLE_CLERROR(clEnqueueNDRangeKernel(queue[ocl_gpu_id], crypt_kernel, 1, NULL, &global_work_size, &local_work_size, 0, NULL, profilingEvent), "failed in clEnqueueNDRangeKernel"); //Read back hashes HANDLE_CLERROR(clEnqueueReadBuffer(queue[ocl_gpu_id], hash_buffer, CL_FALSE, 0, sizeof(uint32_t) * global_work_size, calculated_hash, 0, NULL, NULL), "failed in reading data back"); //Do the work HANDLE_CLERROR(clFinish(queue[ocl_gpu_id]), "failed in clFinish"); }
int dynamic_LOAD_PARSER_FUNCTIONS(int which, struct fmt_main *pFmt) { int ret, cnt; struct cfg_line *gen_line; nPreloadCnt = 0; nFuncCnt = 0; if (!dynamic_LOAD_PARSER_SIGNATURE(which)) { #ifdef HAVE_MPI if (mpi_id == 0) #endif fprintf(stderr, "Could not find section [List.Generic:dynamic_%d] in the john.ini/conf file\n", which); error(); } // Setup the 'default' format name sprintf(SetupName, "$dynamic_%d$", which); sprintf(SetupNameID, "dynamic_%d", which); Setup.szFORMAT_NAME = str_alloc_copy(SetupName); // allocate (and set null) enough file pointers cnt = Count_Items("Func="); Setup.pFuncs = mem_alloc_tiny((cnt+1)*sizeof(DYNAMIC_primitive_funcp), MEM_ALIGN_WORD); memset(Setup.pFuncs, 0, (cnt+1)*sizeof(DYNAMIC_primitive_funcp)); // allocate (and set null) enough Preloads cnt = Count_Items("Test="); cnt += Count_Items("TestU="); cnt += Count_Items("TestA="); Setup.pPreloads = mem_alloc_tiny((cnt+1)*sizeof(struct fmt_tests), MEM_ALIGN_WORD); memset(Setup.pPreloads, 0, (cnt+1)*sizeof(struct fmt_tests)); // allocate (and set null) enough constants (if we have 8, we still need a null to specify the end of the list) cnt = Count_Items("CONST"); Setup.pConstants = mem_alloc_tiny((cnt+1)*sizeof(DYNAMIC_Constants), MEM_ALIGN_WORD); memset(Setup.pConstants, 0, (cnt+1)*sizeof(DYNAMIC_Constants)); Setup.flags = 0; Setup.startFlags = 0; Setup.SaltLen = 0; Setup.MaxInputLen = 0; // Ok, now 'grind' through the data I do know know how to use // the config stuff too much, so will grind for now, and later // go back over this, and do it 'right', if there is a right way gen_line = gen_source->head; while (gen_line) { if (!dynamic_LOAD_PARSER_FUNCTIONS_LoadLINE(gen_line)) { #ifdef HAVE_MPI if (mpi_id == 0) #endif fprintf(stderr, "Error parsing section [List.Generic:dynamic_%d]\nError in line %d file is %s\n", which, gen_line->number, gen_line->cfg_name); error(); } gen_line = gen_line->next; } ret = dynamic_SETUP(&Setup, pFmt); return ret; }
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); } } }
static void log_file_flush(struct log_file *f) { int count; long int pos_b4 = 0; #if FCNTL_LOCKS struct flock lock; #endif if (f->fd < 0) return; count = f->ptr - f->buffer; if (count <= 0) return; #if OS_FLOCK || FCNTL_LOCKS #ifdef LOCK_DEBUG fprintf(stderr, "%s(%u): Locking %s...\n", __FUNCTION__, options.node_min, f->name); #endif #if FCNTL_LOCKS memset(&lock, 0, sizeof(lock)); lock.l_type = F_WRLCK; while (fcntl(f->fd, F_SETLKW, &lock)) { if (errno != EINTR) pexit("fcntl(F_WRLCK)"); } #else while (flock(f->fd, LOCK_EX)) { if (errno != EINTR) pexit("flock(LOCK_EX)"); } #endif #ifdef LOCK_DEBUG fprintf(stderr, "%s(%u): Locked %s exclusively\n", __FUNCTION__, options.node_min, f->name); #endif #endif if (f == &pot) { pos_b4 = (long int)lseek(f->fd, 0, SEEK_END); #if defined(LOCK_DEBUG) fprintf(stderr, "%s(%u): writing %d at %ld, ending at %ld to file %s\n", __FUNCTION__, options.node_min, count, pos_b4, pos_b4+count, f->name); #endif } if (write_loop(f->fd, f->buffer, count) < 0) pexit("write"); f->ptr = f->buffer; if (f == &pot && pos_b4 == crk_pot_pos) crk_pot_pos += count; #if OS_FLOCK || FCNTL_LOCKS #ifdef LOCK_DEBUG fprintf(stderr, "%s(%u): Unlocking %s\n", __FUNCTION__, options.node_min, f->name); #endif #if FCNTL_LOCKS lock.l_type = F_UNLCK; fcntl(f->fd, F_SETLK, &lock); #else if (flock(f->fd, LOCK_UN)) pexit("flock(LOCK_UN)"); #endif #endif #ifdef SIGUSR2 /* We don't really send a sync trigger "at crack" but after it's actually written to the pot file. That is, now. */ if (f == &pot && !event_abort && options.reload_at_crack) { #ifdef HAVE_MPI if (mpi_p > 1) { 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]); } } else #endif if (options.fork) raise(SIGUSR2); } #endif }
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); } } }
void MD5_std_init(void) { int index; MD5_pool *current; #if MD5_std_mt int t, n; if (!MD5_std_all_p) { n = omp_get_max_threads(); if (n < 1) n = 1; if (n > MD5_std_mt_max) n = MD5_std_mt_max; MD5_std_min_kpc = n * MD5_N; { int max = n * MD5_std_cpt; while (max > MD5_std_mt_max) max -= n; n = max; } MD5_std_max_kpc = n * MD5_N; /* * The array of MD5_std_all's is not exactly tiny, but we use mem_alloc_tiny() * for its alignment support and error checking. We do not need to free() this * memory anyway. */ MD5_std_all_p = mem_alloc_tiny(n * MD5_std_all_size, MEM_ALIGN_PAGE); MD5_std_nt = n; } #endif for_each_t(MD5_std_nt) { #if !MD5_IMM MD5_std_all.data = MD5_data_init; #endif current = pool; for (index = 0; index < MD5_N; index++) { #define init_line(line, init_even, init_odd) \ order[line][index].even = init_even; \ order[line][index].odd = init_odd; init_line(0, ¤t->e.p, ¤t->o.psp); init_line(1, ¤t->e.spp, ¤t->o.pp); init_line(2, ¤t->e.spp, ¤t->o.psp); init_line(3, ¤t->e.pp, ¤t->o.ps); init_line(4, ¤t->e.spp, ¤t->o.pp); init_line(5, ¤t->e.spp, ¤t->o.psp); init_line(6, ¤t->e.pp, ¤t->o.psp); init_line(7, ¤t->e.sp, ¤t->o.pp); init_line(8, ¤t->e.spp, ¤t->o.psp); init_line(9, ¤t->e.pp, ¤t->o.psp); init_line(10, ¤t->e.spp, ¤t->o.p); init_line(11, ¤t->e.spp, ¤t->o.psp); init_line(12, ¤t->e.pp, ¤t->o.psp); init_line(13, ¤t->e.spp, ¤t->o.pp); init_line(14, ¤t->e.sp, ¤t->o.psp); init_line(15, ¤t->e.pp, ¤t->o.psp); init_line(16, ¤t->e.spp, ¤t->o.pp); init_line(17, ¤t->e.spp, ¤t->o.ps); init_line(18, ¤t->e.pp, ¤t->o.psp); init_line(19, ¤t->e.spp, ¤t->o.pp); init_line(20, ¤t->e.spp, ¤t->o.psp); #undef init_line current++; } } }
static void ldr_show_pw_line(struct db_main *db, char *line) { int show; char source[LINE_BUFFER_SIZE]; struct fmt_main *format; char *(*split)(char *ciphertext, int index); int index, count, unify; char *login, *ciphertext, *gecos, *home; char *piece; int pass, found, chars; int hash; struct db_cracked *current; extern struct fmt_main fmt_mscash; extern struct fmt_main fmt_oracle; format = NULL; count = ldr_split_line(&login, &ciphertext, &gecos, &home, source, &format, db->options, line); if (!count) return; show = !(db->options->flags & DB_PLAINTEXTS); if (format) { split = format->methods.split; if(format == &fmt_mscash) { char * ciphertext2 = (char *) mem_alloc_tiny(strlen(login) + strlen(ciphertext) + 4, MEM_ALIGN_NONE); sprintf(ciphertext2, "M$%s#%s", login, ciphertext); ciphertext = ciphertext2; } if(format == &fmt_oracle) { char * ciphertext2 = (char *) mem_alloc_tiny(strlen(login) + strlen(ciphertext) + 4, MEM_ALIGN_NONE); sprintf(ciphertext2, "O$%s#%s", login, ciphertext); ciphertext = ciphertext2; } unify = format->params.flags & FMT_SPLIT_UNIFIES_CASE; } else { split = fmt_default_split; count = 1; unify = 0; } if (!*ciphertext) { found = 1; if (show) { if(mpi_id == 0) { printf("%s:NO PASSWORD", login); } } db->guess_count++; } else for (found = pass = 0; pass == 0 || (pass == 1 && found); pass++) for (index = 0; index < count; index++) { piece = split(ciphertext, index); if (unify) piece = strcpy(mem_alloc(strlen(piece) + 1), piece); hash = ldr_cracked_hash(piece); if ((current = db->cracked_hash[hash])) do { if (!strcmp(current->ciphertext, piece)) break; /* This extra check, along with ldr_cracked_hash() being case-insensitive, * is only needed for matching some pot file records produced by older * versions of John and contributed patches where split() didn't unify the * case of hex-encoded hashes. */ if (unify && format->methods.valid(current->ciphertext) == 1 && !strcmp(split(current->ciphertext, 0), piece)) break; } while ((current = current->next)); if (unify) MEM_FREE(piece); if (pass) { //modification by bartavelle, catches the no format bug /* if(format) chars = format->params.plaintext_length; else chars = 0; if (current && show && index < count - 1) if ((int)strlen(current->plaintext) != chars) current = NULL; */ chars = 0; if (show) { if (format) chars = format->params.plaintext_length; if (index < count - 1 && current && (int)strlen(current->plaintext) != chars) current = NULL; } if (current) { if (show) { if(mpi_id == 0) { printf("%s", current->plaintext); } } else list_add(db->plaintexts, current->plaintext); db->guess_count++; } else if (show) { if(mpi_id == 0) { do { putchar('?'); } while (--chars); } } } else if (current) { found = 1; if (show) { if(mpi_id == 0) { printf("%s:", login); } } break; } } if (found && show) { if(mpi_id == 0) { if (source[0]) printf(":%s", source); else putchar('\n'); } } if (format || found) db->password_count += count; }
void *mem_alloc_copy(size_t size, size_t align, void *src) { return memcpy(mem_alloc_tiny(size, align), src, size); }
void rec_restore_args(int lock) { char line[LINE_BUFFER_SIZE]; int index, argc; char **argv; char *save_rec_name; rec_name_complete(); if (!(rec_file = fopen(path_expand(rec_name), "r+"))) { #ifndef HAVE_MPI if (options.fork && !john_main_process && errno == ENOENT) { #else if (options.node_min > 1 && errno == ENOENT) { #endif fprintf(stderr, "%u Session completed\n", options.node_min); if (options.flags & FLG_STATUS_CHK) return; log_event("No crash recovery file, terminating"); log_done(); #ifdef HAVE_MPI mpi_teardown(); #endif exit(0); } #ifdef HAVE_MPI if (mpi_p > 1) { fprintf(stderr, "%u@%s: fopen: %s: %s\n", mpi_id + 1, mpi_name, path_expand(rec_name), strerror(errno)); error(); } #endif pexit("fopen: %s", path_expand(rec_name)); } rec_fd = fileno(rec_file); if (lock) rec_lock(lock); if (!fgetl(line, sizeof(line), rec_file)) rec_format_error("fgets"); rec_version = 0; if (!strcmp(line, RECOVERY_V4)) rec_version = 4; else if (!strcmp(line, RECOVERY_V3)) rec_version = 3; else if (!strcmp(line, RECOVERY_V2)) rec_version = 2; else if (!strcmp(line, RECOVERY_V1)) rec_version = 1; else if (strcmp(line, RECOVERY_V0)) rec_format_error(NULL); if (fscanf(rec_file, "%d\n", &argc) != 1) rec_format_error("fscanf"); if (argc < 2) rec_format_error(NULL); argv = mem_alloc_tiny(sizeof(char *) * (argc + 1), MEM_ALIGN_WORD); argv[0] = "john"; for (index = 1; index < argc; index++) if (fgetl(line, sizeof(line), rec_file)) argv[index] = str_alloc_copy(line); else rec_format_error("fgets"); argv[argc] = NULL; save_rec_name = rec_name; opt_init(argv[0], argc, argv, 0); rec_name = save_rec_name; rec_name_completed = 1; if (fscanf(rec_file, "%u\n%u\n%x\n%x\n", &status_restored_time, &status.guess_count, &status.combs.lo, &status.combs.hi) != 4) rec_format_error("fscanf"); if (!status_restored_time) status_restored_time = 1; if (rec_version >= 4) { if (fscanf(rec_file, "%x\n%x\n%x\n%x\n%x\n%d\n", &status.combs_ehi, &status.crypts.lo, &status.crypts.hi, &status.cands.lo, &status.cands.hi, &status.compat) != 6) rec_format_error("fscanf"); } else { /* Historically, we were reusing what became the combs field for candidates * count when in --stdout mode */ status.cands = status.combs; status.compat = 1; } if (rec_version == 0) { status.pass = 0; status.progress = -1; } else if (fscanf(rec_file, "%d\n%d\n", &status.pass, &status.progress) != 2) rec_format_error("fscanf"); if (status.pass < 0 || status.pass > 3) rec_format_error(NULL); if (rec_version < 3) rec_check = 0; else if (fscanf(rec_file, "%x\n", &rec_check) != 1) rec_format_error("fscanf"); rec_restoring_now = 1; } void rec_restore_mode(int (*restore_mode)(FILE *file)) { rec_name_complete(); if (!rec_file) return; if (restore_mode) if (restore_mode(rec_file)) rec_format_error("fscanf"); if (options.flags & FLG_MASK_STACKED) if (mask_restore_state(rec_file)) rec_format_error("fscanf"); /* * Unlocking the file explicitly is normally not necessary since we're about to * close it anyway (which would normally release the lock). However, when * we're the main process running with --fork, our newborn children may hold a * copy of the fd for a moment (until they close the fd themselves). Thus, if * we don't explicitly remove the lock, there may be a race condition between * our children closing the fd and us proceeding to re-open and re-lock it. */ rec_unlock(); if (fclose(rec_file)) pexit("fclose"); rec_file = NULL; rec_restoring_now = 0; }