Please grep through the source and look for 'ISSUE' comments and verify
that I was able to get all the portable bits in the right location.  As for
the SKEY comment there is an email out to Markus as to how it should be
resolved.  Until then I just #ifdef SKEY/#endif out the whole block.

 - (bal) OpenBSD Resync
   - markus@cvs.openbsd.org 2001/01/18 16:20:21
     [log-client.c log-server.c log.c readconf.c servconf.c ssh.1 ssh.h
      sshd.8 sshd.c]
     log() is at pri=LOG_INFO, since LOG_NOTICE goes to /dev/console on many
     systems
   - markus@cvs.openbsd.org 2001/01/18 16:59:59
     [auth-passwd.c auth.c auth.h auth1.c auth2.c serverloop.c session.c
      session.h sshconnect1.c]
     1) removes fake skey from sshd, since this will be much
        harder with /usr/libexec/auth/login_XXX
     2) share/unify code used in ssh-1 and ssh-2 authentication (server side)
     3) make addition of BSD_AUTH and other challenge reponse methods
        easier.
   - markus@cvs.openbsd.org 2001/01/18 17:12:43
     [auth-chall.c auth2-chall.c]
     rename *-skey.c *-chall.c since the files are not skey specific
diff --git a/auth1.c b/auth1.c
index 51ed8f7..0f21c4c 100644
--- a/auth1.c
+++ b/auth1.c
@@ -10,7 +10,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth1.c,v 1.10 2001/01/07 19:06:25 markus Exp $");
+RCSID("$OpenBSD: auth1.c,v 1.11 2001/01/18 16:59:59 markus Exp $");
 
 #ifdef HAVE_OSF_SIA
 # include <sia.h>
@@ -56,41 +56,53 @@
 		return "rhosts-rsa";
 	case SSH_CMSG_AUTH_RHOSTS:
 		return "rhosts";
+	case SSH_CMSG_AUTH_TIS:
+	case SSH_CMSG_AUTH_TIS_RESPONSE:
+		return "challenge-response";
 #ifdef KRB4
 	case SSH_CMSG_AUTH_KERBEROS:
 		return "kerberos";
 #endif
-#ifdef SKEY
-	case SSH_CMSG_AUTH_TIS_RESPONSE:
-		return "s/key";
-#endif
 	}
 	snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
 	return buf;
 }
 
 /*
- * read packets and try to authenticate local user 'luser'.
- * return if authentication is successful. not that pw == NULL
- * if the user does not exists or is not allowed to login.
- * each auth method has to 'fake' authentication for nonexisting
- * users.
+ * read packets, try to authenticate the user and
+ * return only if authentication is successful
  */
 void
-do_authloop(struct passwd * pw, char *luser)
+do_authloop(Authctxt *authctxt)
 {
 	int authenticated = 0;
-	int attempt = 0;
 	u_int bits;
 	RSA *client_host_key;
 	BIGNUM *n;
 	char *client_user, *password;
-	char user[1024];
+	char info[1024];
 	u_int dlen;
 	int plen, nlen, elen;
 	u_int ulen;
 	int type = 0;
-	void (*authlog) (const char *fmt,...) = verbose;
+	struct passwd *pw = authctxt->pw;
+
+	debug("Attempting authentication for %s%.100s.",
+	     authctxt->valid ? "" : "illegal user ", authctxt->user);
+
+	/* If the user has no password, accept authentication immediately. */
+	if (options.password_authentication &&
+#ifdef KRB4
+	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
+#endif
+#ifdef USE_PAM				/* ISSUE: Right?? */
+	    auth_pam_password(pw, password)) {
+#else
+	    auth_password(pw, "")) {
+#endif
+		auth_log(authctxt, 1, "without authentication", "");
+		return;
+	}
 
 	/* Indicate that authentication is needed. */
 	packet_start(SSH_SMSG_FAILURE);
@@ -99,11 +111,11 @@
 
 	client_user = NULL;
 
-	for (attempt = 1;; attempt++) {
+	for (;;) {
 		/* default to fail */
 		authenticated = 0;
 
-		strlcpy(user, "", sizeof user);
+		info[0] = '\0';
 
 		/* Get a packet from the client. */
 		type = packet_read(&plen);
@@ -120,7 +132,7 @@
 				char *tgt = packet_get_string(&dlen);
 				packet_integrity_check(plen, 4 + dlen, type);
 				if (!auth_kerberos_tgt(pw, tgt))
-					verbose("Kerberos tgt REFUSED for %.100s", luser);
+					verbose("Kerberos tgt REFUSED for %.100s", authctxt->user);
 				xfree(tgt);
 			}
 			continue;
@@ -134,7 +146,7 @@
 				char *token_string = packet_get_string(&dlen);
 				packet_integrity_check(plen, 4 + dlen, type);
 				if (!auth_afs_token(pw, token_string))
-					verbose("AFS token REFUSED for %.100s", luser);
+					verbose("AFS token REFUSED for %.100s", authctxt->user);
 				xfree(token_string);
 			}
 			continue;
@@ -142,7 +154,6 @@
 #ifdef KRB4
 		case SSH_CMSG_AUTH_KERBEROS:
 			if (!options.kerberos_authentication) {
-				/* packet_get_all(); */
 				verbose("Kerberos authentication disabled.");
 				break;
 			} else {
@@ -152,17 +163,17 @@
 				char *kdata = packet_get_string((u_int *) &auth.length);
 				packet_integrity_check(plen, 4 + auth.length, type);
 
-				if (auth.length < MAX_KTXT_LEN)
-					memcpy(auth.dat, kdata, auth.length);
-				xfree(kdata);
-
-				if (pw != NULL) {
+				if (authctxt->valid) {
+					if (auth.length < MAX_KTXT_LEN)
+						memcpy(auth.dat, kdata, auth.length);
 					authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
 					if (authenticated) {
-						snprintf(user, sizeof user, " tktuser %s", tkt_user);
+						snprintf(info, sizeof info,
+						    " tktuser %.100s", tkt_user);
 						xfree(tkt_user);
 					}
 				}
+				xfree(kdata);
 			}
 			break;
 #endif /* KRB4 */
@@ -184,7 +195,7 @@
 			/* Try to authenticate using /etc/hosts.equiv and .rhosts. */
 			authenticated = auth_rhosts(pw, client_user);
 
-			snprintf(user, sizeof user, " ruser %s", client_user);
+			snprintf(info, sizeof info, " ruser %.100s", client_user);
 			break;
 
 		case SSH_CMSG_AUTH_RHOSTS_RSA:
@@ -219,7 +230,7 @@
 			authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
 			RSA_free(client_host_key);
 
-			snprintf(user, sizeof user, " ruser %s", client_user);
+			snprintf(info, sizeof info, " ruser %.100s", client_user);
 			break;
 
 		case SSH_CMSG_AUTH_RSA:
@@ -267,22 +278,19 @@
 			xfree(password);
 			break;
 
-#ifdef SKEY
+#ifdef SKEY			/* ISSUE: Is this right?  we don't define
+					having skey_authentication in
+					servconf.h by default so I assume
+					we need to deal with this via #ifdef
+					in some reasonable way */
 		case SSH_CMSG_AUTH_TIS:
 			debug("rcvd SSH_CMSG_AUTH_TIS");
 			if (options.skey_authentication == 1) {
-				char *skeyinfo = NULL;
-				if (pw != NULL)
-					skeyinfo = skey_keyinfo(pw->pw_name);
-				if (skeyinfo == NULL) {
-					debug("generating fake skeyinfo for %.100s.", luser);
-					skeyinfo = skey_fake_keyinfo(luser);
-				}
-				if (skeyinfo != NULL) {
-					/* we send our s/key- in tis-challenge messages */
-					debug("sending challenge '%s'", skeyinfo);
+				char *challenge = get_challenge(authctxt, authctxt->style);
+				if (challenge != NULL) {
+					debug("sending challenge '%s'", challenge);
 					packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
-					packet_put_cstring(skeyinfo);
+					packet_put_cstring(challenge);
 					packet_send();
 					packet_write_wait();
 					continue;
@@ -293,20 +301,14 @@
 			debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
 			if (options.skey_authentication == 1) {
 				char *response = packet_get_string(&dlen);
-				debug("skey response == '%s'", response);
+				debug("got response '%s'", response);
 				packet_integrity_check(plen, 4 + dlen, type);
-				authenticated = (pw != NULL &&
-				    skey_haskey(pw->pw_name) == 0 &&
-				    skey_passcheck(pw->pw_name, response) != -1);
+				authenticated = verify_response(authctxt, response);
+				memset(response, 'r', dlen);
 				xfree(response);
 			}
 			break;
-#else
-		case SSH_CMSG_AUTH_TIS:
-			/* TIS Authentication is unsupported */
-			log("TIS authentication unsupported.");
-			break;
-#endif
+#endif					/* ISSUE: End of wrong SKEY defines */
 
 		default:
 			/*
@@ -316,10 +318,11 @@
 			log("Unknown message during authentication: type %d", type);
 			break;
 		}
-		if (authenticated && pw == NULL)
-			fatal("internal error: authenticated for pw == NULL");
+		if (!authctxt->valid && authenticated)
+			fatal("INTERNAL ERROR: authenticated invalid user %s",
+			    authctxt->user);
 
-#ifdef HAVE_CYGWIN
+#ifdef HAVE_CYGWIN		/* ISSUE: Right place? */
 		if (authenticated && 
 		    !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) {
 			packet_disconnect("Authentication rejected for uid %d.",
@@ -328,41 +331,18 @@
 		}
 #endif
 
-		/*
-		 * Check if the user is logging in as root and root logins
-		 * are disallowed.
-		 * Note that root login is allowed for forced commands.
-		 */
-		if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
-			if (forced_command) {
-				log("Root login accepted for forced command.");
-			} else {
-				authenticated = 0;
-				log("ROOT LOGIN REFUSED FROM %.200s",
-				    get_canonical_hostname());
-			}
-		}
+		/* Special handling for root */
+		if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed())
+			authenticated = 0;
 
-		/* Raise logging level */
-		if (authenticated ||
-		    attempt == AUTH_FAIL_LOG ||
-		    type == SSH_CMSG_AUTH_PASSWORD)
-			authlog = log;
-
-		authlog("%s %s for %s%.100s from %.200s port %d%s",
-			authenticated ? "Accepted" : "Failed",
-			get_authname(type),
-			pw ? "" : "illegal user ",
-			pw && pw->pw_uid == 0 ? "ROOT" : luser,
-			get_remote_ipaddr(),
-			get_remote_port(),
-			user);
-
-#ifdef USE_PAM
+#ifdef USE_PAM			/* ISSUE: Right place? */
 		if (authenticated && !do_pam_account(pw->pw_name, client_user))
 			authenticated = 0;
 #endif
 
+		/* Log before sending the reply */
+		auth_log(authctxt, authenticated, get_authname(type), info);
+
 		if (client_user != NULL) {
 			xfree(client_user);
 			client_user = NULL;
@@ -371,14 +351,13 @@
 		if (authenticated)
 			return;
 
-		if (attempt > AUTH_FAIL_MAX) {
+	if (authctxt->failures++ > AUTH_FAIL_MAX) {
 #ifdef WITH_AIXAUTHENTICATE 
 			loginfailed(user,get_canonical_hostname(),"ssh");
 #endif /* WITH_AIXAUTHENTICATE */
-			packet_disconnect(AUTH_FAIL_MSG, luser);
+			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
 		}
 
-		/* Send a message indicating that the authentication attempt failed. */
 		packet_start(SSH_SMSG_FAILURE);
 		packet_send();
 		packet_write_wait();
@@ -392,10 +371,11 @@
 void
 do_authentication()
 {
-	struct passwd *pw, pwcopy;
+	Authctxt *authctxt;
+	struct passwd *pw;
 	int plen;
 	u_int ulen;
-	char *user;
+	char *user, *style = NULL;
 
 	/* Get the name of the user that we wish to log in as. */
 	packet_read_expect(&plen, SSH_CMSG_USER);
@@ -404,6 +384,13 @@
 	user = packet_get_string(&ulen);
 	packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
 
+	if ((style = strchr(user, ':')) != NULL)
+		*style++ = 0;
+
+	authctxt = authctxt_new();
+	authctxt->user = user;
+	authctxt->style = style;
+
 	setproctitle("%s", user);
 
 #ifdef AFS
@@ -417,21 +404,13 @@
 	/* Verify that the user is a valid user. */
 	pw = getpwnam(user);
 	if (pw && allowed_user(pw)) {
-		/* Take a copy of the returned structure. */
-		memset(&pwcopy, 0, sizeof(pwcopy));
-		pwcopy.pw_name = xstrdup(pw->pw_name);
-		pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
-		pwcopy.pw_uid = pw->pw_uid;
-		pwcopy.pw_gid = pw->pw_gid;
-#ifdef HAVE_PW_CLASS_IN_PASSWD
-		pwcopy.pw_class = xstrdup(pw->pw_class);
-#endif
-		pwcopy.pw_dir = xstrdup(pw->pw_dir);
-		pwcopy.pw_shell = xstrdup(pw->pw_shell);
-		pw = &pwcopy;
+		authctxt->valid = 1;
+		pw = pwcopy(pw);
 	} else {
+		debug("do_authentication: illegal user %s", user);
 		pw = NULL;
 	}
+	authctxt->pw = pw;
 
 #ifdef USE_PAM
 	if (pw)
@@ -447,44 +426,25 @@
 		packet_disconnect("Cannot change user when server not running as root.");
 #endif
 
-	debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user);
-
-	/* If the user has no password, accept authentication immediately. */
-	if (options.password_authentication &&
-#ifdef KRB4
-	    (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
-#endif /* KRB4 */
-#ifdef USE_PAM
-	    auth_pam_password(pw, "")) {
-#elif defined(HAVE_OSF_SIA)
-	    (sia_validate_user(NULL, saved_argc, saved_argv, 
-	    get_canonical_hostname(), pw->pw_name, NULL, 0, 
-		 NULL, "") == SIASUCCESS)) {
-#else /* !HAVE_OSF_SIA && !USE_PAM */
- 	    auth_password(pw, "")) {
-#endif /* USE_PAM */
-		/* Authentication with empty password succeeded. */
-		log("Login for user %s from %.100s, accepted without authentication.",
-		    user, get_remote_ipaddr());
-	} else {
-		/* Loop until the user has been authenticated or the
-		   connection is closed, do_authloop() returns only if
-		   authentication is successful */
-		do_authloop(pw, user);
-	}
-	if (pw == NULL)
-		fatal("internal error, authentication successful for user '%.100s'", user);
+	/*
+         * Loop until the user has been authenticated or the connection is
+         * closed, do_authloop() returns only if authentication is successful
+         */
+	do_authloop(authctxt);
 
 	/* The user has been authenticated and accepted. */
 	packet_start(SSH_SMSG_SUCCESS);
 	packet_send();
 	packet_write_wait();
+
 #ifdef WITH_AIXAUTHENTICATE
 	/* We don't have a pty yet, so just label the line as "ssh" */
-	if (loginsuccess(user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0)
+	if (loginsuccess(authctxt->user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0)
 		aixloginmsg = NULL;
 #endif /* WITH_AIXAUTHENTICATE */
-	xfree(user);
+
+	xfree(authctxt->user);
+	xfree(authctxt);
 
 	/* Perform session preparation. */
 	do_authenticated(pw);