static int ldr_check_shells(struct list_main *list, char *shell) { char *name; if (list->head) { if ((name = strrchr(shell, '/'))) name++; else name = shell; return ldr_check_list(list, shell, name); } return 0; }
static int ldr_split_line(char **login, char **ciphertext, char **gecos, char **home, char *source, struct fmt_main **format, struct db_options *options, char *line) { struct fmt_main *alt; char *fields[10], *uid, *gid, *shell; int i, retval; fields[0] = *login = ldr_get_field(&line); fields[1] = *ciphertext = ldr_get_field(&line); /* Check for NIS stuff */ if ((!strcmp(*login, "+") || !strncmp(*login, "+@", 2)) && strlen(*ciphertext) < 10 && strncmp(*ciphertext, "$dummy$", 7)) return 0; if (!**ciphertext && !line) { /* Possible hash on a line on its own (no colons) */ char *p = *login; /* Skip leading and trailing whitespace */ while (*p == ' ' || *p == '\t') p++; *ciphertext = p; p += strlen(p) - 1; while (p > *ciphertext && (*p == ' ' || *p == '\t')) p--; p++; /* Some valid dummy hashes may be shorter than 10 characters, so don't subject * them to the length checks. */ if (strncmp(*ciphertext, "$dummy$", 7) && p - *ciphertext != 10 /* not tripcode */) { /* Check for a special case: possibly a traditional crypt(3) hash with * whitespace in its invalid salt. Only support such hashes at the very start * of a line (no leading whitespace other than the invalid salt). */ if (p - *ciphertext == 11 && *ciphertext - *login == 2) (*ciphertext)--; if (p - *ciphertext == 12 && *ciphertext - *login == 1) (*ciphertext)--; if (p - *ciphertext < 13) return 0; } *p = 0; fields[0] = *login = no_username; fields[1] = *ciphertext; } if (source) strcpy(source, line ? line : ""); /* * This check is just a loader performance optimization, so that we can parse * fewer fields when we know we won't need the rest. It should be revised or * removed when there are formats that use higher-numbered fields in prepare(). */ if ((options->flags & DB_WORDS) || options->shells->head) { /* Parse all fields */ for (i = 2; i < 10; i++) fields[i] = ldr_get_field(&line); } else { /* Parse some fields only */ for (i = 2; i < 4; i++) fields[i] = ldr_get_field(&line); for (; i < 10; i++) fields[i] = "/"; } /* /etc/passwd */ uid = fields[2]; gid = fields[3]; *gecos = fields[4]; *home = fields[5]; shell = fields[6]; if (fields[5][0] != '/' && ((!strcmp(fields[5], "0") && !strcmp(fields[6], "0")) || fields[8][0] == '/' || fields[9][0] == '/')) { /* /etc/master.passwd */ *gecos = fields[7]; *home = fields[8]; shell = fields[9]; } else if (fields[3] - fields[2] == 32 + 1) { /* PWDUMP */ uid = fields[1]; *ciphertext = fields[2]; if (!strncmp(*ciphertext, "NO PASSWORD", 11)) *ciphertext = ""; gid = shell = ""; *gecos = fields[4]; *home = fields[5]; /* Re-introduce the previously removed uid field */ if (source) { int shift = strlen(uid); memmove(source + shift + 1, source, strlen(source) + 1); memcpy(source, uid, shift); source[shift] = ':'; } } if (ldr_check_list(options->users, *login, uid)) return 0; if (ldr_check_list(options->groups, gid, gid)) return 0; if (ldr_check_shells(options->shells, shell)) return 0; if (*format) { char *prepared; int valid; prepared = (*format)->methods.prepare(fields, *format); if (prepared) valid = (*format)->methods.valid(prepared, *format); else valid = 0; if (valid) { *ciphertext = prepared; return valid; } alt = fmt_list; do { if (alt == *format) continue; if (alt->params.flags & FMT_WARNED) continue; #ifdef HAVE_CRYPT if (alt == &fmt_crypt && #ifdef __sun strncmp(*ciphertext, "$md5$", 5) && strncmp(*ciphertext, "$md5,", 5) && #endif strncmp(*ciphertext, "$5$", 3) && strncmp(*ciphertext, "$6$", 3)) continue; #endif prepared = alt->methods.prepare(fields, alt); if (alt->methods.valid(prepared, alt)) { alt->params.flags |= FMT_WARNED; fprintf(stderr, "Warning: only loading hashes of type " "\"%s\", but also saw type \"%s\"\n" "Use the \"--format=%s\" option to force " "loading hashes of that type instead\n", (*format)->params.label, alt->params.label, alt->params.label); break; } } while ((alt = alt->next)); return 0; } retval = -1; if ((alt = fmt_list)) do { char *prepared; int valid; #ifdef HAVE_CRYPT /* * Only probe for support by the current system's crypt(3) if this is forced * from the command-line or/and if the hash encoding string looks like one of * those that are only supported in that way. Avoid the probe in other cases * because it may be slow and undesirable (false detection is possible). */ if (alt == &fmt_crypt && fmt_list != &fmt_crypt /* not forced */ && #ifdef __sun strncmp(*ciphertext, "$md5$", 5) && strncmp(*ciphertext, "$md5,", 5) && #endif strncmp(*ciphertext, "$5$", 3) && strncmp(*ciphertext, "$6$", 3)) continue; #endif prepared = alt->methods.prepare(fields, alt); if (!prepared) continue; valid = alt->methods.valid(prepared, alt); if (!valid) continue; if (retval < 0) { retval = valid; *ciphertext = prepared; fmt_init(*format = alt); #ifdef LDR_WARN_AMBIGUOUS if (!source) /* not --show */ continue; #endif break; } #ifdef LDR_WARN_AMBIGUOUS fprintf(stderr, "Warning: detected hash type \"%s\", but the string is " "also recognized as \"%s\"\n" "Use the \"--format=%s\" option to force loading these " "as that type instead\n", (*format)->params.label, alt->params.label, alt->params.label); #endif } while ((alt = alt->next)); return retval; }
static int ldr_split_line(char **login, char **ciphertext, char **gecos, char **home, char *source, struct fmt_main **format, struct db_options *db_options, char *line) { char *uid = NULL, *gid = NULL, *shell = NULL; char *tmp; int count; *login = ldr_get_field(&line); if (!strcmp(*login, "+") || !strncmp(*login, "+@", 2)) return 0; if (!*(*ciphertext = ldr_get_field(&line))) if (!line) return 0; if (source) strcpy(source, line ? line : ""); uid = ldr_get_field(&line); if (strlen(uid) == 32) { tmp = *ciphertext; *ciphertext = uid; uid = tmp; if (!strncmp(*ciphertext, "NO PASSWORD", 11)) *ciphertext = ""; /* NT loader hack starts here ! */ if (options.format && (strncmp(options.format, "nt", 2)==0)) { tmp = ldr_get_field(&line); *ciphertext = tmp; if (!strncmp(*ciphertext, "NO PASSWORD", 11)) *ciphertext = ""; else if(strlen(*ciphertext) == 32) { *ciphertext -= 4; strncpy(*ciphertext,"$NT$",4); } else { return 0; } } /* NT loader hack ends here ! */ if (source) sprintf(source, "%s:%s", uid, line); } if (db_options->flags & DB_WORDS || db_options->shells->head) { gid = ldr_get_field(&line); do { *gecos = ldr_get_field(&line); *home = ldr_get_field(&line); shell = ldr_get_field(&line); } while (!**gecos && !strcmp(*home, "0") && !strcmp(shell, "0")); } else if (db_options->groups->head) { gid = ldr_get_field(&line); } if (ldr_check_list(db_options->users, *login, uid)) return 0; if (ldr_check_list(db_options->groups, gid, gid)) return 0; if (ldr_check_shells(db_options->shells, shell)) return 0; if (*format) return (*format)->methods.valid(*ciphertext); if ((*format = fmt_list)) do { if ((count = (*format)->methods.valid(*ciphertext))) { fmt_init(*format); return count; } } while ((*format = (*format)->next)); return -1; }
static int ldr_split_line(char **login, char **ciphertext, char **gecos, char **home, char *source, struct fmt_main **format, struct db_options *db_options, char *line) { struct fmt_main *alt; char *uid = NULL, *gid = NULL, *shell = NULL; char *split_fields[10]; int i, retval, valid; // Note, only 7 are 'defined' in the passwd format. We load 10, so that // other formats can add specific extra stuff. for (i = 0; i < 10; ++i) { split_fields[i] = ldr_get_field(&line, db_options->field_sep_char); if (!line && i == 1 && split_fields[1][0] == 0) { /* Possible hash on a line on its own (no colons) */ char *p = split_fields[0]; /* Skip leading and trailing whitespace */ while (*p == ' ' || *p == '\t') p++; split_fields[1] = p; p += strlen(p) - 1; while (p > split_fields[1] && (*p == ' ' || *p == '\t')) p--; p++; /* Some valid dummy hashes may be shorter than 10 characters, so don't subject * them to the length checks. */ if (strncmp(split_fields[1], "$dummy$", 7) && p - split_fields[1] != 10 /* not tripcode */) { /* Check for a special case: possibly a traditional crypt(3) hash with * whitespace in its invalid salt. Only support such hashes at the very start * of a line (no leading whitespace other than the invalid salt). */ if (p - split_fields[1] == 11 && split_fields[1] - split_fields[0] == 2) split_fields[1]--; if (p - split_fields[1] == 12 && split_fields[1] - split_fields[0] == 1) split_fields[1]--; if (p - split_fields[1] < 13) return 0; } *p = 0; split_fields[0] = no_username; } if (i == 1 && source) strcpy(source, line ? line : ""); } *login = split_fields[0]; *ciphertext = split_fields[1]; /* Check for NIS stuff */ if ((!strcmp(*login, "+") || !strncmp(*login, "+@", 2)) && strlen(*ciphertext) < 10 && strncmp(*ciphertext, "$dummy$", 7)) return 0; /* SPLFLEN(n) is a macro equiv. of strlen(split_fields[n]) (but faster) */ if (SPLFLEN(1) > 0 && SPLFLEN(1) < 7 && (SPLFLEN(3) == 32 || SPLFLEN(2) == 32)) { /* uid for pwdump files. */ uid = split_fields[1]; gid = *gecos = *home = shell = ""; } else if (SPLFLEN(1) == 0 && SPLFLEN(3) >= 16 && SPLFLEN(4) >= 32 && SPLFLEN(5) >= 16) { /* l0phtcrack-style input */ uid = gid = *home = shell = ""; *gecos = split_fields[2]; // in case there's a domain name here } else { /* normal passwd-style input */ uid = split_fields[2]; gid = split_fields[3]; *gecos = split_fields[4]; *home = split_fields[5]; shell = split_fields[6]; } if (ldr_check_list(db_options->users, *login, uid)) return 0; if (ldr_check_list(db_options->groups, gid, gid)) return 0; if (ldr_check_shells(db_options->shells, shell)) return 0; if (*format) { *ciphertext = (*format)->methods.prepare(split_fields, *format); valid = (*format)->methods.valid(*ciphertext, *format); if (!valid) { alt = fmt_list; do { if (alt == *format) continue; if (alt->params.flags & FMT_WARNED) continue; #ifdef HAVE_CRYPT if (alt == &fmt_crypt && #ifdef __sun strncmp(*ciphertext, "$md5$", 5) && strncmp(*ciphertext, "$md5,", 5) && #endif strncmp(*ciphertext, "$5$", 3) && strncmp(*ciphertext, "$6$", 3)) continue; #endif if (alt->methods.valid(*ciphertext,alt)) { alt->params.flags |= FMT_WARNED; #ifdef HAVE_MPI if (mpi_id == 0) #endif fprintf(stderr, "Warning: only loading hashes " "of type \"%s\", but also saw " "type \"%s\"\n" "Use the " "\"--format=%s\" option to force " "loading hashes of that type " "instead\n", (*format)->params.label, alt->params.label, alt->params.label); break; } } while ((alt = alt->next)); } return valid; } retval = -1; if ((alt = fmt_list)) do { int valid; char *prepared_CT = alt->methods.prepare(split_fields, alt); if (!prepared_CT || !*prepared_CT) continue; #ifdef HAVE_CRYPT /* * Only probe for support by the current system's crypt(3) if this is forced * from the command-line or/and if the hash encoding string looks like one of * those that are only supported in that way. Avoid the probe in other cases * because it may be slow and undesirable (false detection is possible). */ if (alt == &fmt_crypt && fmt_list != &fmt_crypt /* not forced */ && #ifdef __sun strncmp(prepared_CT, "$md5$", 5) && strncmp(prepared_CT, "$md5,", 5) && #endif strncmp(prepared_CT, "$5$", 3) && strncmp(prepared_CT, "$6$", 3)) continue; #endif if (!(valid = alt->methods.valid(prepared_CT, alt))) continue; if (retval < 0) { fmt_init(*format = alt); retval = valid; *ciphertext = prepared_CT; #ifdef LDR_WARN_AMBIGUOUS if (!source) /* not --show */ continue; #endif break; } #ifdef LDR_WARN_AMBIGUOUS #ifdef HAVE_MPI if (mpi_id == 0) #endif fprintf(stderr, "Warning: detected hash type \"%s\", but the string is " "also recognized as \"%s\"\n" "Use the \"--format=%s\" option to force loading these " "as that type instead\n", (*format)->params.label, alt->params.label, alt->params.label); #endif } while ((alt = alt->next)); return retval; }