diff options
| author | Adam Langley <agl@google.com> | 2015-03-30 14:49:51 -0700 |
|---|---|---|
| committer | Adam Langley <agl@google.com> | 2015-04-07 17:50:50 -0700 |
| commit | d059297112922cabb0c674840589be8db821fd9a (patch) | |
| tree | 9c2045d28ec1c8594090f38bc32e9f523dc6c68d /session.c | |
| parent | f5c67b478bef9992de9e9ec91ce10af4f6205e0d (diff) | |
| download | platform_external_openssh-d059297112922cabb0c674840589be8db821fd9a.tar.gz platform_external_openssh-d059297112922cabb0c674840589be8db821fd9a.tar.bz2 platform_external_openssh-d059297112922cabb0c674840589be8db821fd9a.zip | |
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
Diffstat (limited to 'session.c')
| -rw-r--r-- | session.c | 259 |
1 files changed, 148 insertions, 111 deletions
@@ -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 @@ auth_input_request_forwarding(struct passwd * pw) { Channel *nc; int sock = -1; - struct sockaddr_un sunaddr; if (auth_sock_name != NULL) { error("authentication forwarding requested twice."); @@ -199,7 +201,7 @@ auth_input_request_forwarding(struct passwd * pw) 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 @@ auth_input_request_forwarding(struct passwd * pw) 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 @@ auth_input_request_forwarding(struct passwd * pw) 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 @@ do_authenticated(Authctxt *authctxt) 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 @@ do_authenticated1(Authctxt *authctxt) 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 @@ do_authenticated1(Authctxt *authctxt) 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 @@ do_authenticated1(Authctxt *authctxt) 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 @@ do_authenticated1(Authctxt *authctxt) } } -#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 @@ int 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 @@ child_set_env(char ***envp, u_int *envsizep, const char *name, 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 @@ child_set_env(char ***envp, u_int *envsizep, const char *name, 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 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid) 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 @@ copy_environment(char **source, char ***env, u_int *envsize) 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 @@ copy_environment(char **source, char ***env, u_int *envsize) 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 @@ do_setup_env(Session *s, const char *shell) 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 @@ do_setup_env(Session *s, const char *shell) 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 @@ do_rc_files(Session *s, const char *shell) /* 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 @@ do_nologin(struct passwd *pw) 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 @@ do_nologin(struct passwd *pw) #endif if (stat(nl, &sb) == -1) { if (nl != def_nl) - xfree(nl); + free(nl); return; } @@ -1424,7 +1440,7 @@ static void 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 @@ void do_setusercontext(struct passwd *pw) { char *chroot_path, *tmp; +#ifdef USE_LIBIAF + int doing_chroot = 0; +#endif platform_setusercontext(pw); @@ -1498,8 +1517,7 @@ do_setusercontext(struct passwd *pw) perror("initgroups"); exit(1); } -#ifndef ANDROID - /* FIXME - Android doesn't have this */ +#if !defined(ANDROID) endgrent(); #endif #endif @@ -1515,6 +1533,12 @@ do_setusercontext(struct passwd *pw) 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 @@ do_setusercontext(struct passwd *pw) 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 @@ launch_login(struct passwd *pw, const char *hostname) 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 @@ child_close_fds(void) /* 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 @@ session_unused(int id) 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 @@ session_pty_req(Session *s) 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 @@ session_pty_req(Session *s) s->ypixel = packet_get_int(); if (strcmp(s->term, "") == 0) { - xfree(s->term); + free(s->term); s->term = NULL; } @@ -2055,8 +2106,7 @@ session_pty_req(Session *s) 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 @@ session_subsystem_req(Session *s) 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 @@ session_subsystem_req(Session *s) } 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 @@ session_x11_req(Session *s) 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 @@ session_exec_req(Session *s) 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 @@ session_break_req(Session *s) 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 @@ session_env_req(Session *s) 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 @@ session_env_req(Session *s) debug2("Ignoring env request %s: disallowed name", name); fail: - xfree(name); - xfree(val); + free(name); + free(val); return (0); } @@ -2391,24 +2441,16 @@ session_close_single_x11(int id, void *arg) 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 @@ session_close(Session *s) 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 @@ session_setup_x11fwd(Session *s) { 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 @@ session_setup_x11fwd(Session *s) 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; |
