external/openssh: update to 6.8p1.

In preparation for some updates to external/openssh to make it work with
BoringSSL, this change updates the code to a recent version. The current
version (5.9p1) is coming up on four years old now.

  * Confirmed that f5c67b478bef9992de9e9ec91ce10af4f6205e0d matches
    OpenSSH 5.9p1 exactly (save for the removal of the scard
    subdirectory).

  * Downloaded openssh-6.8p1.tar.gz (SHA256:
    3ff64ce73ee124480b5bf767b9830d7d3c03bbcb6abe716b78f0192c37ce160e)
    and verified with PGP signature. (I've verified Damien's key in
    person previously.)

  * Applied changes between f5c67b478bef9992de9e9ec91ce10af4f6205e0d and
    OpenSSH 5.9p1 to 6.8p1 and updated the build as best I can. The
    ugliest change is probably the duplication of umac.c to umac128.c
    because Android conditionally compiles that file twice. See the
    comment in those files.

Change-Id: I63cb07a8118afb5a377f116087a0882914cea486
diff --git a/auth.c b/auth.c
index a15b306..25ed53d 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.94 2011/05/23 03:33:38 djm Exp $ */
+/* $OpenBSD: auth.c,v 1.110 2015/02/25 17:29:38 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -27,7 +27,6 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/param.h>
 
 #include <netinet/in.h>
 
@@ -50,12 +49,14 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <limits.h>
 
 #include "xmalloc.h"
 #include "match.h"
 #include "groupaccess.h"
 #include "log.h"
 #include "buffer.h"
+#include "misc.h"
 #include "servconf.h"
 #include "key.h"
 #include "hostfile.h"
@@ -63,7 +64,6 @@
 #include "auth-options.h"
 #include "canohost.h"
 #include "uidswap.h"
-#include "misc.h"
 #include "packet.h"
 #include "loginrec.h"
 #ifdef GSSAPI
@@ -71,6 +71,9 @@
 #endif
 #include "authfile.h"
 #include "monitor_wrap.h"
+#include "authfile.h"
+#include "ssherr.h"
+#include "compat.h"
 
 /* import */
 extern ServerOptions options;
@@ -164,17 +167,17 @@
 		if (stat(shell, &st) != 0) {
 			logit("User %.100s not allowed because shell %.100s "
 			    "does not exist", pw->pw_name, shell);
-			xfree(shell);
+			free(shell);
 			return 0;
 		}
 		if (S_ISREG(st.st_mode) == 0 ||
 		    (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
 			logit("User %.100s not allowed because shell %.100s "
 			    "is not executable", pw->pw_name, shell);
-			xfree(shell);
+			free(shell);
 			return 0;
 		}
-		xfree(shell);
+		free(shell);
 	}
 
 	if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
@@ -251,7 +254,25 @@
 }
 
 void
-auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
+auth_info(Authctxt *authctxt, const char *fmt, ...)
+{
+	va_list ap;
+        int i;
+
+	free(authctxt->info);
+	authctxt->info = NULL;
+
+	va_start(ap, fmt);
+	i = vasprintf(&authctxt->info, fmt, ap);
+	va_end(ap);
+
+	if (i < 0 || authctxt->info == NULL)
+		fatal("vasprintf failed");
+}
+
+void
+auth_log(Authctxt *authctxt, int authenticated, int partial,
+    const char *method, const char *submethod)
 {
 	void (*authlog) (const char *fmt,...) = verbose;
 	char *authmsg;
@@ -268,17 +289,24 @@
 
 	if (authctxt->postponed)
 		authmsg = "Postponed";
+	else if (partial)
+		authmsg = "Partial";
 	else
 		authmsg = authenticated ? "Accepted" : "Failed";
 
-	authlog("%s %s for %s%.100s from %.200s port %d%s",
+	authlog("%s %s%s%s for %s%.100s from %.200s port %d %s%s%s",
 	    authmsg,
 	    method,
+	    submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
 	    authctxt->valid ? "" : "invalid user ",
 	    authctxt->user,
 	    get_remote_ipaddr(),
 	    get_remote_port(),
-	    info);
+	    compat20 ? "ssh2" : "ssh1",
+	    authctxt->info != NULL ? ": " : "",
+	    authctxt->info != NULL ? authctxt->info : "");
+	free(authctxt->info);
+	authctxt->info = NULL;
 
 #ifdef CUSTOM_FAILED_LOGIN
 	if (authenticated == 0 && !authctxt->postponed &&
@@ -299,11 +327,26 @@
 #endif
 }
 
+
+void
+auth_maxtries_exceeded(Authctxt *authctxt)
+{
+	error("maximum authentication attempts exceeded for "
+	    "%s%.100s from %.200s port %d %s",
+	    authctxt->valid ? "" : "invalid user ",
+	    authctxt->user,
+	    get_remote_ipaddr(),
+	    get_remote_port(),
+	    compat20 ? "ssh2" : "ssh1");
+	packet_disconnect("Too many authentication failures");
+	/* NOTREACHED */
+}
+
 /*
  * Check whether root logins are disallowed.
  */
 int
-auth_root_allowed(char *method)
+auth_root_allowed(const char *method)
 {
 	switch (options.permit_root_login) {
 	case PERMIT_YES:
@@ -334,7 +377,7 @@
 char *
 expand_authorized_keys(const char *filename, struct passwd *pw)
 {
-	char *file, ret[MAXPATHLEN];
+	char *file, ret[PATH_MAX];
 	int i;
 
 	file = percent_expand(filename, "h", pw->pw_dir,
@@ -350,14 +393,15 @@
 	i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
 	if (i < 0 || (size_t)i >= sizeof(ret))
 		fatal("expand_authorized_keys: path too long");
-	xfree(file);
+	free(file);
 	return (xstrdup(ret));
 }
 
 char *
 authorized_principals_file(struct passwd *pw)
 {
-	if (options.authorized_principals_file == NULL)
+	if (options.authorized_principals_file == NULL ||
+	    strcasecmp(options.authorized_principals_file, "none") == 0)
 		return NULL;
 	return expand_authorized_keys(options.authorized_principals_file, pw);
 }
@@ -391,7 +435,7 @@
 			load_hostkeys(hostkeys, host, user_hostfile);
 			restore_uid();
 		}
-		xfree(user_hostfile);
+		free(user_hostfile);
 	}
 	host_status = check_key_in_hostkeys(hostkeys, key, &found);
 	if (host_status == HOST_REVOKED)
@@ -408,49 +452,50 @@
 	return host_status;
 }
 
-
 /*
- * Check a given file for security. This is defined as all components
+ * Check a given path for security. This is defined as all components
  * of the path to the file must be owned by either the owner of
  * of the file or root and no directories must be group or world writable.
  *
  * XXX Should any specific check be done for sym links ?
  *
- * Takes an open file descriptor, the file name, a uid and and
+ * Takes a file name, its stat information (preferably from fstat() to
+ * avoid races), the uid of the expected owner, their home directory and an
  * error buffer plus max size as arguments.
  *
  * Returns 0 on success and -1 on failure
  */
-static int
-secure_filename(FILE *f, const char *file, struct passwd *pw,
-    char *err, size_t errlen)
+int
+auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
+    uid_t uid, char *err, size_t errlen)
 {
-	uid_t uid = pw->pw_uid;
-	char buf[MAXPATHLEN], homedir[MAXPATHLEN];
+	char buf[PATH_MAX], homedir[PATH_MAX];
 	char *cp;
 	int comparehome = 0;
 	struct stat st;
 
-	if (realpath(file, buf) == NULL) {
-		snprintf(err, errlen, "realpath %s failed: %s", file,
+	if (realpath(name, buf) == NULL) {
+		snprintf(err, errlen, "realpath %s failed: %s", name,
 		    strerror(errno));
 		return -1;
 	}
-	if (realpath(pw->pw_dir, homedir) != NULL)
+	if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
 		comparehome = 1;
 
-	/* check the open file to avoid races */
-	if (fstat(fileno(f), &st) < 0 ||
-	    (st.st_uid != 0 && st.st_uid != uid) ||
-	    (st.st_mode & 022) != 0) {
-#ifdef ANDROID
-		/* needed to allow root login on android */
+	if (!S_ISREG(stp->st_mode)) {
+		snprintf(err, errlen, "%s is not a regular file", buf);
+		return -1;
+	}
+	if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
+	    (stp->st_mode & 022) != 0) {
+#if defined(ANDROID)
+		/* needed to allow root login on Android. */
 		if (getuid() != 0)
 #endif
-	    {
-			snprintf(err, errlen, "bad ownership or modes for file %s",
-				buf);
-			return -1;
+		{
+		snprintf(err, errlen, "bad ownership or modes for file %s",
+		    buf);
+		return -1;
 		}
 	}
 
@@ -462,16 +507,17 @@
 		}
 		strlcpy(buf, cp, sizeof(buf));
 
-#ifndef ANDROID
-	    /* /data is owned by system user, which causes this check to fail */
+#if !defined(ANDROID)
+		/* /data is owned by system user, which causes this check to fail */
 		if (stat(buf, &st) < 0 ||
-		    (st.st_uid != 0 && st.st_uid != uid) ||
+		    (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
 		    (st.st_mode & 022) != 0) {
 			snprintf(err, errlen,
 			    "bad ownership or modes for directory %s", buf);
 			return -1;
 		}
 #endif
+
 		/* If are past the homedir then we can stop */
 		if (comparehome && strcmp(homedir, buf) == 0)
 			break;
@@ -486,6 +532,27 @@
 	return 0;
 }
 
+/*
+ * Version of secure_path() that accepts an open file descriptor to
+ * avoid races.
+ *
+ * Returns 0 on success and -1 on failure
+ */
+static int
+secure_filename(FILE *f, const char *file, struct passwd *pw,
+    char *err, size_t errlen)
+{
+	struct stat st;
+
+	/* check the open file to avoid races */
+	if (fstat(fileno(f), &st) < 0) {
+		snprintf(err, errlen, "cannot stat file %s: %s",
+		    file, strerror(errno));
+		return -1;
+	}
+	return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
+}
+
 static FILE *
 auth_openfile(const char *file, struct passwd *pw, int strict_modes,
     int log_missing, char *file_type)
@@ -552,9 +619,10 @@
 #endif
 #endif
 	struct passwd *pw;
+	struct connection_info *ci = get_connection_info(1, options.use_dns);
 
-	parse_server_match_config(&options, user,
-	    get_canonical_hostname(options.use_dns), get_remote_ipaddr());
+	ci->user = user;
+	parse_server_match_config(&options, ci);
 
 #if defined(_AIX) && defined(HAVE_SETAUTHDB)
 	aix_setauthdb(user);
@@ -616,29 +684,39 @@
 int
 auth_key_is_revoked(Key *key)
 {
-	char *key_fp;
+	char *fp = NULL;
+	int r;
 
 	if (options.revoked_keys_file == NULL)
 		return 0;
-
-	switch (key_in_file(key, options.revoked_keys_file, 0)) {
-	case 0:
-		/* key not revoked */
-		return 0;
-	case -1:
-		/* Error opening revoked_keys_file: refuse all keys */
-		error("Revoked keys file is unreadable: refusing public key "
-		    "authentication");
-		return 1;
-	case 1:
-		/* Key revoked */
-		key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
-		error("WARNING: authentication attempt with a revoked "
-		    "%s key %s ", key_type(key), key_fp);
-		xfree(key_fp);
-		return 1;
+	if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
+	    SSH_FP_DEFAULT)) == NULL) {
+		r = SSH_ERR_ALLOC_FAIL;
+		error("%s: fingerprint key: %s", __func__, ssh_err(r));
+		goto out;
 	}
-	fatal("key_in_file returned junk");
+
+	r = sshkey_check_revoked(key, options.revoked_keys_file);
+	switch (r) {
+	case 0:
+		break; /* not revoked */
+	case SSH_ERR_KEY_REVOKED:
+		error("Authentication key %s %s revoked by file %s",
+		    sshkey_type(key), fp, options.revoked_keys_file);
+		goto out;
+	default:
+		error("Error checking authentication key %s %s in "
+		    "revoked keys file %s: %s", sshkey_type(key), fp,
+		    options.revoked_keys_file, ssh_err(r));
+		goto out;
+	}
+
+	/* Success */
+	r = 0;
+
+ out:
+	free(fp);
+	return r == 0 ? 0 : 1;
 }
 
 void
@@ -666,7 +744,7 @@
 	while (buffer_len(&auth_debug)) {
 		msg = buffer_get_string(&auth_debug, NULL);
 		packet_send_debug("%s", msg);
-		xfree(msg);
+		free(msg);
 	}
 }
 
@@ -690,12 +768,12 @@
 	fake.pw_name = "NOUSER";
 	fake.pw_passwd =
 	    "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK";
-#ifdef HAVE_PW_GECOS_IN_PASSWD
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
 	fake.pw_gecos = "NOUSER";
 #endif
 	fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid;
 	fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid;
-#ifdef HAVE_PW_CLASS_IN_PASSWD
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
 	fake.pw_class = "";
 #endif
 	fake.pw_dir = "/nonexist";