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/session.c b/session.c
index 71466ff..9a15384 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.258 2010/11/25 04:10:09 djm Exp $ */
+/* $OpenBSD: session.c,v 1.277 2015/01/16 06:40:12 deraadt Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -49,6 +49,7 @@
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
+#include <netdb.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
@@ -59,6 +60,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
@@ -80,13 +82,14 @@
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
+#include "authfd.h"
#include "pathnames.h"
#include "log.h"
+#include "misc.h"
#include "servconf.h"
#include "sshlogin.h"
#include "serverloop.h"
#include "canohost.h"
-#include "misc.h"
#include "session.h"
#include "kex.h"
#include "monitor_wrap.h"
@@ -181,7 +184,6 @@
{
Channel *nc;
int sock = -1;
- struct sockaddr_un sunaddr;
if (auth_sock_name != NULL) {
error("authentication forwarding requested twice.");
@@ -199,7 +201,7 @@
packet_send_debug("Agent forwarding disabled: "
"mkdtemp() failed: %.100s", strerror(errno));
restore_uid();
- xfree(auth_sock_dir);
+ free(auth_sock_dir);
auth_sock_dir = NULL;
goto authsock_err;
}
@@ -207,33 +209,15 @@
xasprintf(&auth_sock_name, "%s/agent.%ld",
auth_sock_dir, (long) getpid());
- /* Create the socket. */
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- error("socket: %.100s", strerror(errno));
- restore_uid();
- goto authsock_err;
- }
-
- /* Bind it to the name. */
- memset(&sunaddr, 0, sizeof(sunaddr));
- sunaddr.sun_family = AF_UNIX;
- strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
-
- if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
- error("bind: %.100s", strerror(errno));
- restore_uid();
- goto authsock_err;
- }
+ /* Start a Unix listener on auth_sock_name. */
+ sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0);
/* Restore the privileged uid. */
restore_uid();
- /* Start listening on the socket. */
- if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
- error("listen: %.100s", strerror(errno));
+ /* Check for socket/bind/listen failure. */
+ if (sock < 0)
goto authsock_err;
- }
/* Allocate a channel for the authentication agent socket. */
nc = channel_new("auth socket",
@@ -244,11 +228,10 @@
return 1;
authsock_err:
- if (auth_sock_name != NULL)
- xfree(auth_sock_name);
+ free(auth_sock_name);
if (auth_sock_dir != NULL) {
rmdir(auth_sock_dir);
- xfree(auth_sock_dir);
+ free(auth_sock_dir);
}
if (sock != -1)
close(sock);
@@ -273,7 +256,11 @@
setproctitle("%s", authctxt->pw->pw_name);
/* setup the channel layer */
- if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
+ /* XXX - streamlocal? */
+ if (no_port_forwarding_flag ||
+ (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
+ channel_disable_adm_local_opens();
+ else
channel_permit_all_opens();
auth_debug_send();
@@ -361,8 +348,8 @@
packet_check_eom();
success = session_setup_x11fwd(s);
if (!success) {
- xfree(s->auth_proto);
- xfree(s->auth_data);
+ free(s->auth_proto);
+ free(s->auth_data);
s->auth_proto = NULL;
s->auth_data = NULL;
}
@@ -383,13 +370,13 @@
debug("Port forwarding not permitted for this authentication.");
break;
}
- if (!options.allow_tcp_forwarding) {
+ if (!(options.allow_tcp_forwarding & FORWARD_REMOTE)) {
debug("Port forwarding not permitted.");
break;
}
debug("Received TCP/IP port forwarding request.");
if (channel_input_port_forward_request(s->pw->pw_uid == 0,
- options.gateway_ports) < 0) {
+ &options.fwd_opts) < 0) {
debug("Port forwarding failed.");
break;
}
@@ -409,7 +396,7 @@
if (do_exec(s, command) != 0)
packet_disconnect(
"command execution failed");
- xfree(command);
+ free(command);
} else {
if (do_exec(s, NULL) != 0)
packet_disconnect(
@@ -438,7 +425,7 @@
}
}
-#define USE_PIPES
+#define USE_PIPES 1
/*
* This is called to fork and execute a command when we have no tty. This
* will call do_child from the child, and server_loop from the parent after
@@ -791,27 +778,50 @@
do_exec(Session *s, const char *command)
{
int ret;
+ const char *forced = NULL;
+ char session_type[1024], *tty = NULL;
if (options.adm_forced_command) {
original_command = command;
command = options.adm_forced_command;
- if (IS_INTERNAL_SFTP(command)) {
- s->is_subsystem = s->is_subsystem ?
- SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
- } else if (s->is_subsystem)
- s->is_subsystem = SUBSYSTEM_EXT;
- debug("Forced command (config) '%.900s'", command);
+ forced = "(config)";
} else if (forced_command) {
original_command = command;
command = forced_command;
+ forced = "(key-option)";
+ }
+ if (forced != NULL) {
if (IS_INTERNAL_SFTP(command)) {
s->is_subsystem = s->is_subsystem ?
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
} else if (s->is_subsystem)
s->is_subsystem = SUBSYSTEM_EXT;
- debug("Forced command (key option) '%.900s'", command);
+ snprintf(session_type, sizeof(session_type),
+ "forced-command %s '%.900s'", forced, command);
+ } else if (s->is_subsystem) {
+ snprintf(session_type, sizeof(session_type),
+ "subsystem '%.900s'", s->subsys);
+ } else if (command == NULL) {
+ snprintf(session_type, sizeof(session_type), "shell");
+ } else {
+ /* NB. we don't log unforced commands to preserve privacy */
+ snprintf(session_type, sizeof(session_type), "command");
}
+ if (s->ttyfd != -1) {
+ tty = s->tty;
+ if (strncmp(tty, "/dev/", 5) == 0)
+ tty += 5;
+ }
+
+ verbose("Starting session: %s%s%s for %s from %.200s port %d",
+ session_type,
+ tty == NULL ? "" : " on ",
+ tty == NULL ? "" : tty,
+ s->pw->pw_name,
+ get_remote_ipaddr(),
+ get_remote_port());
+
#ifdef SSH_AUDIT_EVENTS
if (command != NULL)
PRIVSEP(audit_run_command(command));
@@ -952,6 +962,11 @@
u_int envsize;
u_int i, namelen;
+ if (strchr(name, '=') != NULL) {
+ error("Invalid environment variable \"%.100s\"", name);
+ return;
+ }
+
/*
* If we're passed an uninitialized list, allocate a single null
* entry before continuing.
@@ -974,7 +989,7 @@
break;
if (env[i]) {
/* Reuse the slot. */
- xfree(env[i]);
+ free(env[i]);
} else {
/* New variable. Expand if necessary. */
envsize = *envsizep;
@@ -1090,8 +1105,8 @@
umask((mode_t)mask);
for (i = 0; tmpenv[i] != NULL; i++)
- xfree(tmpenv[i]);
- xfree(tmpenv);
+ free(tmpenv[i]);
+ free(tmpenv);
}
#endif /* HAVE_ETC_DEFAULT_LOGIN */
@@ -1107,7 +1122,7 @@
for(i = 0; source[i] != NULL; i++) {
var_name = xstrdup(source[i]);
if ((var_val = strstr(var_name, "=")) == NULL) {
- xfree(var_name);
+ free(var_name);
continue;
}
*var_val++ = '\0';
@@ -1115,7 +1130,7 @@
debug3("Copy environment: %s=%s", var_name, var_val);
child_set_env(env, envsize, var_name, var_val);
- xfree(var_name);
+ free(var_name);
}
}
@@ -1218,8 +1233,8 @@
child_set_env(&env, &envsize, str, str + i + 1);
}
custom_environment = ce->next;
- xfree(ce->s);
- xfree(ce);
+ free(ce->s);
+ free(ce);
}
}
@@ -1231,7 +1246,7 @@
laddr = get_local_ipaddr(packet_get_connection_in());
snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
- xfree(laddr);
+ free(laddr);
child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
if (s->ttyfd != -1)
@@ -1329,7 +1344,8 @@
/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
if (!s->is_subsystem && options.adm_forced_command == NULL &&
- !no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) {
+ !no_user_rc && options.permit_user_rc &&
+ stat(_PATH_SSH_USER_RC, &st) >= 0) {
snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
if (debug_flag)
@@ -1392,7 +1408,7 @@
struct stat sb;
#ifdef HAVE_LOGIN_CAP
- if (login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
+ if (login_getcapbool(lc, "ignorenologin", 0) || pw->pw_uid == 0)
return;
nl = login_getcapstr(lc, "nologin", def_nl, def_nl);
#else
@@ -1402,7 +1418,7 @@
#endif
if (stat(nl, &sb) == -1) {
if (nl != def_nl)
- xfree(nl);
+ free(nl);
return;
}
@@ -1424,7 +1440,7 @@
safely_chroot(const char *path, uid_t uid)
{
const char *cp;
- char component[MAXPATHLEN];
+ char component[PATH_MAX];
struct stat st;
if (*path != '/')
@@ -1476,6 +1492,9 @@
do_setusercontext(struct passwd *pw)
{
char *chroot_path, *tmp;
+#ifdef USE_LIBIAF
+ int doing_chroot = 0;
+#endif
platform_setusercontext(pw);
@@ -1498,8 +1517,7 @@
perror("initgroups");
exit(1);
}
-#ifndef ANDROID
- /* FIXME - Android doesn't have this */
+#if !defined(ANDROID)
endgrent();
#endif
#endif
@@ -1515,6 +1533,12 @@
safely_chroot(chroot_path, pw->pw_uid);
free(tmp);
free(chroot_path);
+ /* Make sure we don't attempt to chroot again */
+ free(options.chroot_directory);
+ options.chroot_directory = NULL;
+#ifdef USE_LIBIAF
+ doing_chroot = 1;
+#endif
}
#ifdef HAVE_LOGIN_CAP
@@ -1522,10 +1546,30 @@
perror("unable to set user context (setuser)");
exit(1);
}
+ /*
+ * FreeBSD's setusercontext() will not apply the user's
+ * own umask setting unless running with the user's UID.
+ */
+ (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUMASK);
#else
+# ifdef USE_LIBIAF
+/* In a chroot environment, the set_id() will always fail; typically
+ * because of the lack of necessary authentication services and runtime
+ * such as ./usr/lib/libiaf.so, ./usr/lib/libpam.so.1, and ./etc/passwd
+ * We skip it in the internal sftp chroot case.
+ * We'll lose auditing and ACLs but permanently_set_uid will
+ * take care of the rest.
+ */
+ if ((doing_chroot == 0) && set_id(pw->pw_name) != 0) {
+ fatal("set_id(%s) Failed", pw->pw_name);
+ }
+# endif /* USE_LIBIAF */
/* Permanently switch to the desired uid. */
permanently_set_uid(pw);
#endif
+ } else if (options.chroot_directory != NULL &&
+ strcasecmp(options.chroot_directory, "none") != 0) {
+ fatal("server lacks privileges to chroot to ChrootDirectory");
}
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
@@ -1581,6 +1625,13 @@
static void
child_close_fds(void)
{
+ extern int auth_sock;
+
+ if (auth_sock != -1) {
+ close(auth_sock);
+ auth_sock = -1;
+ }
+
if (packet_get_connection_in() == packet_get_connection_out())
close(packet_get_connection_in());
else {
@@ -1594,7 +1645,7 @@
/* XXX better use close-on-exec? -markus */
channel_close_all();
-#ifndef ANDROID
+#if !defined(ANDROID)
/*
* Close any extra file descriptors. Note that there may still be
* descriptors left by system functions. They will be closed later.
@@ -1847,7 +1898,7 @@
fatal("%s: insane session id %d (max %d nalloc %d)",
__func__, id, options.max_sessions, sessions_nalloc);
}
- bzero(&sessions[id], sizeof(*sessions));
+ memset(&sessions[id], 0, sizeof(*sessions));
sessions[id].self = id;
sessions[id].used = 0;
sessions[id].chanid = -1;
@@ -2025,7 +2076,7 @@
u_int len;
int n_bytes;
- if (no_pty_flag) {
+ if (no_pty_flag || !options.permit_tty) {
debug("Allocating a pty not permitted for this authentication.");
return 0;
}
@@ -2047,7 +2098,7 @@
s->ypixel = packet_get_int();
if (strcmp(s->term, "") == 0) {
- xfree(s->term);
+ free(s->term);
s->term = NULL;
}
@@ -2055,8 +2106,7 @@
debug("Allocating pty.");
if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
sizeof(s->tty)))) {
- if (s->term)
- xfree(s->term);
+ free(s->term);
s->term = NULL;
s->ptyfd = -1;
s->ttyfd = -1;
@@ -2087,15 +2137,16 @@
struct stat st;
u_int len;
int success = 0;
- char *prog, *cmd, *subsys = packet_get_string(&len);
+ char *prog, *cmd;
u_int i;
+ s->subsys = packet_get_string(&len);
packet_check_eom();
- logit("subsystem request for %.100s by user %s", subsys,
+ debug2("subsystem request for %.100s by user %s", s->subsys,
s->pw->pw_name);
for (i = 0; i < options.num_subsystems; i++) {
- if (strcmp(subsys, options.subsystem_name[i]) == 0) {
+ if (strcmp(s->subsys, options.subsystem_name[i]) == 0) {
prog = options.subsystem_command[i];
cmd = options.subsystem_args[i];
if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) {
@@ -2114,10 +2165,9 @@
}
if (!success)
- logit("subsystem request for %.100s failed, subsystem not found",
- subsys);
+ logit("subsystem request for %.100s by user %s failed, "
+ "subsystem not found", s->subsys, s->pw->pw_name);
- xfree(subsys);
return success;
}
@@ -2139,8 +2189,8 @@
success = session_setup_x11fwd(s);
if (!success) {
- xfree(s->auth_proto);
- xfree(s->auth_data);
+ free(s->auth_proto);
+ free(s->auth_data);
s->auth_proto = NULL;
s->auth_data = NULL;
}
@@ -2162,7 +2212,7 @@
char *command = packet_get_string(&len);
packet_check_eom();
success = do_exec(s, command) == 0;
- xfree(command);
+ free(command);
return success;
}
@@ -2173,7 +2223,7 @@
packet_get_int(); /* ignored */
packet_check_eom();
- if (s->ttyfd == -1 || tcsendbreak(s->ttyfd, 0) < 0)
+ if (s->ptymaster == -1 || tcsendbreak(s->ptymaster, 0) < 0)
return 0;
return 1;
}
@@ -2184,8 +2234,8 @@
char *name, *val;
u_int name_len, val_len, i;
- name = packet_get_string(&name_len);
- val = packet_get_string(&val_len);
+ name = packet_get_cstring(&name_len);
+ val = packet_get_cstring(&val_len);
packet_check_eom();
/* Don't set too many environment variables */
@@ -2208,8 +2258,8 @@
debug2("Ignoring env request %s: disallowed name", name);
fail:
- xfree(name);
- xfree(val);
+ free(name);
+ free(val);
return (0);
}
@@ -2391,24 +2441,16 @@
if (s->x11_chanids[i] != id)
session_close_x11(s->x11_chanids[i]);
}
- xfree(s->x11_chanids);
+ free(s->x11_chanids);
s->x11_chanids = NULL;
- if (s->display) {
- xfree(s->display);
- s->display = NULL;
- }
- if (s->auth_proto) {
- xfree(s->auth_proto);
- s->auth_proto = NULL;
- }
- if (s->auth_data) {
- xfree(s->auth_data);
- s->auth_data = NULL;
- }
- if (s->auth_display) {
- xfree(s->auth_display);
- s->auth_display = NULL;
- }
+ free(s->display);
+ s->display = NULL;
+ free(s->auth_proto);
+ s->auth_proto = NULL;
+ free(s->auth_data);
+ s->auth_data = NULL;
+ free(s->auth_display);
+ s->auth_display = NULL;
}
static void
@@ -2470,24 +2512,19 @@
debug("session_close: session %d pid %ld", s->self, (long)s->pid);
if (s->ttyfd != -1)
session_pty_cleanup(s);
- if (s->term)
- xfree(s->term);
- if (s->display)
- xfree(s->display);
- if (s->x11_chanids)
- xfree(s->x11_chanids);
- if (s->auth_display)
- xfree(s->auth_display);
- if (s->auth_data)
- xfree(s->auth_data);
- if (s->auth_proto)
- xfree(s->auth_proto);
+ free(s->term);
+ free(s->display);
+ free(s->x11_chanids);
+ free(s->auth_display);
+ free(s->auth_data);
+ free(s->auth_proto);
+ free(s->subsys);
if (s->env != NULL) {
for (i = 0; i < s->num_env; i++) {
- xfree(s->env[i].name);
- xfree(s->env[i].val);
+ free(s->env[i].name);
+ free(s->env[i].val);
}
- xfree(s->env);
+ free(s->env);
}
session_proctitle(s);
session_unused(s->self);
@@ -2607,7 +2644,7 @@
{
struct stat st;
char display[512], auth_display[512];
- char hostname[MAXHOSTNAMELEN];
+ char hostname[NI_MAXHOST];
u_int i;
if (no_x11_forwarding_flag) {
@@ -2618,7 +2655,7 @@
debug("X11 forwarding disabled in server configuration file.");
return 0;
}
- if (!options.xauth_location ||
+ if (options.xauth_location == NULL ||
(stat(options.xauth_location, &st) == -1)) {
packet_send_debug("No xauth program; cannot forward with spoofing.");
return 0;