Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Fri, 20 Jan 2012 03:49:35 +0100
From: magnum <john.magnum@...hmail.com>
To: john-dev@...ts.openwall.com
Subject: Jumbo patch breaks "--users=<uid>" for pwdump [was: john-users]

On 01/19/2012 09:23 PM, magnum wrote:
> On 01/19/2012 08:50 PM, Kurt Grutzmacher wrote:
>> During testing we noticed a little oddity today between the 
>> standard John release and the -jumbo release when requesting UID 
>> vs. Username in the --user option with PWDUMP files. For example:
> 
> Thank you for reporting! This was just on oversight, easy fix and 
> will work correctly in next Jumbo for both LM and NT

This, and more, is now fixed. I need a second opinion on this patch so I
did not screw anything up.

The logic is that if field 1 (normally the hash) is between 1 and 7
characters, and field 3 and/or 4 are 32 characters, we assume pwdump.

> (and other formats that support non-standard input files, likely 
> NETNTLM and the likes).

Furthermore, if field 1 is empty and fields 3-5 are of certain lengths,
we assume l0phtcrack. The NETNTLM formats was not affected, they do not
have any uid. But there was another problem: when loading l0phtcrack
style input, we got large hashes in the "gecos" field, resulting in lots
of crap candidates in single mode. I now mute that

The rest of the patch is just an attempt to make these strlens faster. I
change the field split so for trailing empty fields, it returns the
input's last zero byte instead of a constant "". This let me safely use
the SPLFLEN(f) macro (pointer subtraction) instead of
strlen(split_fields[f]). It did not end up that much faster though the
gain may be larger on a system lacking SSE strlen. Maybe this whole
thing was just silly :-)

magnum

diff --git a/src/loader.c b/src/loader.c
index 94fa0eb..dfbce65 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -44,6 +44,11 @@ int ldr_in_pot = 0;
 #define RF_ALLOW_MISSING		1
 #define RF_ALLOW_DIR			2
 
+/*
+ * Fast "Strlen" for split_fields[f]
+ */
+#define SPLFLEN(f)	(split_fields[f][0] ? split_fields[f+1] - split_fields[f] - 1 : 0)
+
 static char *no_username = "?";
 
 static void read_file(struct db_main *db, char *name, int flags,
@@ -146,9 +151,10 @@ static void ldr_init_password_hash(struct db_main *db)
 
 static char *ldr_get_field(char **ptr, char field_sep_char)
 {
+	static char *last;
 	char *res, *pos;
 
-	if (!*ptr) return "";
+	if (!*ptr) return last;
 
 	if ((pos = strchr(res = *ptr, field_sep_char))) {
 		*pos++ = 0; *ptr = pos;
@@ -157,6 +163,7 @@ static char *ldr_get_field(char **ptr, char field_sep_char)
 		do {
 			if (*pos == '\r' || *pos == '\n') *pos = 0;
 		} while (*pos++);
+		last = pos - 1;
 		*ptr = NULL;
 	}
 
@@ -262,12 +269,27 @@ static int ldr_split_line(char **login, char **ciphertext,
 	    strlen(*ciphertext) < 10 && strncmp(*ciphertext, "$dummy$", 7))
 		return 0;
 
-	uid = split_fields[2];
-	gid = split_fields[3];
-
-	*gecos = split_fields[4];
-	*home = split_fields[5];
-	shell = split_fields[6];
+/* 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;

Powered by blists - more mailing lists

Your e-mail address:

Powered by Openwall GNU/*/Linux - Powered by OpenVZ