- Use the MD4_SUM_LENGTH define in place of some hard-wired values.
- Pass the hostname in to auth_server().
- Generate a unique error for each failure type in auth_server() so
  that the log-file contains why the authorization failed.
- Don't use sscanf() to parse the client's auth-challenge response.
diff --git a/authenticate.c b/authenticate.c
index ff24028..25d2ded 100644
--- a/authenticate.c
+++ b/authenticate.c
@@ -51,7 +51,7 @@
 	}
 }
 
-/* create a 16 byte challenge buffer */
+/* Create a 16-byte challenge buffer. */
 static void gen_challenge(char *addr, char *challenge)
 {
 	char input[32];
@@ -195,17 +195,17 @@
 	return NULL;
 }
 
-/* generate a 16 byte hash from a password and challenge */
+/* Generate a 16-byte hash from a password and challenge. */
 static void generate_hash(char *in, char *challenge, char *out)
 {
-	char buf[16];
+	char buf[MD4_SUM_LENGTH];
 
 	sum_init(0);
 	sum_update(in, strlen(in));
 	sum_update(challenge, strlen(challenge));
 	sum_end(buf);
 
-	base64_encode(buf, 16, out);
+	base64_encode(buf, MD4_SUM_LENGTH, out);
 }
 
 /* Possibly negotiate authentication with the client.  Use "leader" to
@@ -214,17 +214,16 @@
  * Return NULL if authentication failed.  Return "" if anonymous access.
  * Otherwise return username.
  */
-char *auth_server(int f_in, int f_out, int module, char *addr, char *leader)
+char *auth_server(int f_in, int f_out, int module, char *host, char *addr,
+		  char *leader)
 {
 	char *users = lp_auth_users(module);
-	char challenge[16];
-	char b64_challenge[30];
+	char challenge[MD4_SUM_LENGTH];
+	char b64_challenge[MD4_SUM_LENGTH*2];
 	char line[MAXPATHLEN];
-	static char user[100];
-	char secret[100];
-	char pass[30];
-	char pass2[30];
-	char *tok;
+	char secret[512];
+	char pass2[MD4_SUM_LENGTH*2];
+	char *tok, *pass;
 
 	/* if no auth list then allow anyone in! */
 	if (!users || !*users)
@@ -232,52 +231,62 @@
 
 	gen_challenge(addr, challenge);
 
-	base64_encode(challenge, 16, b64_challenge);
+	base64_encode(challenge, MD4_SUM_LENGTH, b64_challenge);
 
 	io_printf(f_out, "%s%s\n", leader, b64_challenge);
 
-	if (!read_line(f_in, line, sizeof line - 1))
+	if (!read_line(f_in, line, sizeof line - 1)
+	 || (pass = strchr(line, ' ')) == NULL) {
+		rprintf(FLOG, "auth failed on module %s from %s (%s): "
+			"invalid challenge response\n",
+			lp_name(module), host, addr);
 		return NULL;
+	}
+	*pass++ = '\0';
 
-	memset(user, 0, sizeof user);
-	memset(pass, 0, sizeof pass);
+	if (!(users = strdup(users)))
+		out_of_memory("auth_server");
 
-	if (sscanf(line,"%99s %29s", user, pass) != 2)
-		return NULL;
-
-	users = strdup(users);
-	if (!users)
-		return NULL;
-
-	for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
-		if (wildmatch(tok, user))
+	for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
+		if (wildmatch(tok, line))
 			break;
 	}
 	free(users);
 
-	if (!tok)
+	if (!tok) {
+		rprintf(FLOG, "auth failed on module %s from %s (%s): "
+			"unauthorized user\n",
+			lp_name(module), host, addr);
 		return NULL;
+	}
 
 	memset(secret, 0, sizeof secret);
-	if (!get_secret(module, user, secret, sizeof secret - 1)) {
+	if (!get_secret(module, line, secret, sizeof secret - 1)) {
 		memset(secret, 0, sizeof secret);
+		rprintf(FLOG, "auth failed on module %s from %s (%s): "
+			"missing secret for user \"%s\"\n",
+			lp_name(module), host, addr, line);
 		return NULL;
 	}
 
 	generate_hash(secret, b64_challenge, pass2);
 	memset(secret, 0, sizeof secret);
 
-	if (strcmp(pass, pass2) == 0)
-		return user;
+	if (strcmp(pass, pass2) != 0) {
+		rprintf(FLOG, "auth failed on module %s from %s (%s): "
+			"password mismatch\n",
+			lp_name(module), host, addr);
+		return NULL;
+	}
 
-	return NULL;
+	return strdup(line);
 }
 
 
 void auth_client(int fd, char *user, char *challenge)
 {
 	char *pass;
-	char pass2[30];
+	char pass2[MD4_SUM_LENGTH*2];
 
 	if (!user || !*user)
 		user = "nobody";