]> andersk Git - gssapi-openssh.git/blobdiff - openssh/session.c
merged OpenSSH 5.1p1 to trunk
[gssapi-openssh.git] / openssh / session.c
index ef308cdecbd258ec20d647d40234be6e47e7a92d..8066914434fee1d3522fd0c4732d4720c9e2b537 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.233 2008/03/26 21:28:14 djm Exp $ */
+/* $OpenBSD: session.c,v 1.241 2008/06/16 13:22:53 dtucker Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -59,6 +59,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "openbsd-compat/sys-queue.h"
 #include "xmalloc.h"
 #include "ssh.h"
 #include "ssh1.h"
 /* func */
 
 Session *session_new(void);
-void   session_set_fds(Session *, int, int, int);
+void   session_set_fds(Session *, int, int, int, int);
 void   session_pty_cleanup(Session *);
 void   session_proctitle(Session *);
 int    session_setup_x11fwd(Session *);
-void   do_exec_pty(Session *, const char *);
-void   do_exec_no_pty(Session *, const char *);
-void   do_exec(Session *, const char *);
+int    do_exec_pty(Session *, const char *);
+int    do_exec_no_pty(Session *, const char *);
+int    do_exec(Session *, const char *);
 void   do_login(Session *, const char *);
 #ifdef LOGIN_NEEDS_UTMPX
 static void    do_pre_login(Session *s);
@@ -136,8 +137,9 @@ extern Buffer loginmsg;
 const char *original_command = NULL;
 
 /* data */
-#define MAX_SESSIONS 20
-Session        sessions[MAX_SESSIONS];
+static int sessions_first_unused = -1;
+static int sessions_nalloc = 0;
+static Session *sessions = NULL;
 
 #define SUBSYSTEM_NONE         0
 #define SUBSYSTEM_EXT          1
@@ -171,7 +173,7 @@ static int
 auth_input_request_forwarding(struct passwd * pw)
 {
        Channel *nc;
-       int sock;
+       int sock = -1;
        struct sockaddr_un sunaddr;
 
        if (auth_sock_name != NULL) {
@@ -183,43 +185,48 @@ auth_input_request_forwarding(struct passwd * pw)
        temporarily_use_uid(pw);
 
        /* Allocate a buffer for the socket name, and format the name. */
-       auth_sock_name = xmalloc(MAXPATHLEN);
-       auth_sock_dir = xmalloc(MAXPATHLEN);
-       strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
+       auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
 
        /* Create private directory for socket */
        if (mkdtemp(auth_sock_dir) == NULL) {
                packet_send_debug("Agent forwarding disabled: "
                    "mkdtemp() failed: %.100s", strerror(errno));
                restore_uid();
-               xfree(auth_sock_name);
                xfree(auth_sock_dir);
-               auth_sock_name = NULL;
                auth_sock_dir = NULL;
-               return 0;
+               goto authsock_err;
        }
-       snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
-                auth_sock_dir, (long) getpid());
+
+       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)
-               packet_disconnect("socket: %.100s", strerror(errno));
+       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)
-               packet_disconnect("bind: %.100s", strerror(errno));
+       if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
+               error("bind: %.100s", strerror(errno));
+               restore_uid();
+               goto authsock_err;
+       }
 
        /* Restore the privileged uid. */
        restore_uid();
 
        /* Start listening on the socket. */
-       if (listen(sock, SSH_LISTEN_BACKLOG) < 0)
-               packet_disconnect("listen: %.100s", strerror(errno));
+       if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
+               error("listen: %.100s", strerror(errno));
+               goto authsock_err;
+       }
 
        /* Allocate a channel for the authentication agent socket. */
        /* this shouldn't matter if its hpn or not - cjr */
@@ -229,6 +236,19 @@ auth_input_request_forwarding(struct passwd * pw)
            0, "auth socket", 1);
        strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
        return 1;
+
+ authsock_err:
+       if (auth_sock_name != NULL)
+               xfree(auth_sock_name);
+       if (auth_sock_dir != NULL) {
+               rmdir(auth_sock_dir);
+               xfree(auth_sock_dir);
+       }
+       if (sock != -1)
+               close(sock);
+       auth_sock_name = NULL;
+       auth_sock_dir = NULL;
+       return 0;
 }
 
 static void
@@ -356,7 +376,8 @@ do_authenticated1(Authctxt *authctxt)
                        break;
 
                case SSH_CMSG_AGENT_REQUEST_FORWARDING:
-                       if (no_agent_forwarding_flag || compat13) {
+                       if (!options.allow_agent_forwarding ||
+                           no_agent_forwarding_flag || compat13) {
                                debug("Authentication agent forwarding not permitted for this authentication.");
                                break;
                        }
@@ -393,10 +414,14 @@ do_authenticated1(Authctxt *authctxt)
                        if (type == SSH_CMSG_EXEC_CMD) {
                                command = packet_get_string(&dlen);
                                debug("Exec command '%.500s'", command);
-                               do_exec(s, command);
+                               if (do_exec(s, command) != 0)
+                                       packet_disconnect(
+                                           "command execution failed");
                                xfree(command);
                        } else {
-                               do_exec(s, NULL);
+                               if (do_exec(s, NULL) != 0)
+                                       packet_disconnect(
+                                           "shell execution failed");
                        }
                        packet_check_eom();
                        session_close(s);
@@ -421,41 +446,84 @@ do_authenticated1(Authctxt *authctxt)
        }
 }
 
+#define USE_PIPES
 /*
  * 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
  * setting up file descriptors and such.
  */
-void
+int
 do_exec_no_pty(Session *s, const char *command)
 {
        pid_t pid;
 
 #ifdef USE_PIPES
        int pin[2], pout[2], perr[2];
+
        /* Allocate pipes for communicating with the program. */
-       if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
-               packet_disconnect("Could not create pipes: %.100s",
-                                 strerror(errno));
-#else /* USE_PIPES */
+       if (pipe(pin) < 0) {
+               error("%s: pipe in: %.100s", __func__, strerror(errno));
+               return -1;
+       }
+       if (pipe(pout) < 0) {
+               error("%s: pipe out: %.100s", __func__, strerror(errno));
+               close(pin[0]);
+               close(pin[1]);
+               return -1;
+       }
+       if (pipe(perr) < 0) {
+               error("%s: pipe err: %.100s", __func__, strerror(errno));
+               close(pin[0]);
+               close(pin[1]);
+               close(pout[0]);
+               close(pout[1]);
+               return -1;
+       }
+#else
        int inout[2], err[2];
+
        /* Uses socket pairs to communicate with the program. */
-       if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
-           socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
-               packet_disconnect("Could not create socket pairs: %.100s",
-                                 strerror(errno));
-#endif /* USE_PIPES */
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
+               error("%s: socketpair #1: %.100s", __func__, strerror(errno));
+               return -1;
+       }
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
+               error("%s: socketpair #2: %.100s", __func__, strerror(errno));
+               close(inout[0]);
+               close(inout[1]);
+               return -1;
+       }
+#endif
+
        if (s == NULL)
                fatal("do_exec_no_pty: no session");
 
        session_proctitle(s);
 
        /* Fork the child. */
-       if ((pid = fork()) == 0) {
+       switch ((pid = fork())) {
+       case -1:
+               error("%s: fork: %.100s", __func__, strerror(errno));
+#ifdef USE_PIPES
+               close(pin[0]);
+               close(pin[1]);
+               close(pout[0]);
+               close(pout[1]);
+               close(perr[0]);
+               close(perr[1]);
+#else
+               close(inout[0]);
+               close(inout[1]);
+               close(err[0]);
+               close(err[1]);
+#endif
+               return -1;
+       case 0:
                is_child = 1;
 
                /* Child.  Reinitialize the log since the pid has changed. */
-               log_init(__progname, options.log_level, options.log_facility, log_stderr);
+               log_init(__progname, options.log_level,
+                   options.log_facility, log_stderr);
 
                /*
                 * Create a new session and process group since the 4.4BSD
@@ -485,7 +553,7 @@ do_exec_no_pty(Session *s, const char *command)
                if (dup2(perr[1], 2) < 0)
                        perror("dup2 stderr");
                close(perr[1]);
-#else /* USE_PIPES */
+#else
                /*
                 * Redirect stdin, stdout, and stderr.  Stdin and stdout will
                 * use the same socket, as some programs (particularly rdist)
@@ -495,11 +563,14 @@ do_exec_no_pty(Session *s, const char *command)
                close(err[1]);
                if (dup2(inout[0], 0) < 0)      /* stdin */
                        perror("dup2 stdin");
-               if (dup2(inout[0], 1) < 0)      /* stdout.  Note: same socket as stdin. */
+               if (dup2(inout[0], 1) < 0)      /* stdout (same as stdin) */
                        perror("dup2 stdout");
+               close(inout[0]);
                if (dup2(err[0], 2) < 0)        /* stderr */
                        perror("dup2 stderr");
-#endif /* USE_PIPES */
+               close(err[0]);
+#endif
+
 
 #ifdef _UNICOS
                cray_init_job(s->pw); /* set up cray jid and tmpdir */
@@ -508,7 +579,10 @@ do_exec_no_pty(Session *s, const char *command)
                /* Do processing for the child (exec command etc). */
                do_child(s, command);
                /* NOTREACHED */
+       default:
+               break;
        }
+
 #ifdef _UNICOS
        signal(WJSIGNAL, cray_job_termination_handler);
 #endif /* _UNICOS */
@@ -516,11 +590,18 @@ do_exec_no_pty(Session *s, const char *command)
        if (is_winnt)
                cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
 #endif
-       if (pid < 0)
-               packet_disconnect("fork failed: %.100s", strerror(errno));
+
        s->pid = pid;
        /* Set interactive/non-interactive mode. */
        packet_set_interactive(s->display != NULL);
+
+       /*
+        * Clear loginmsg, since it's the child's responsibility to display
+        * it to the user, otherwise multiple sessions may accumulate
+        * multiple copies of the login messages.
+        */
+       buffer_clear(&loginmsg);
+
 #ifdef USE_PIPES
        /* We are the parent.  Close the child sides of the pipes. */
        close(pin[0]);
@@ -532,35 +613,32 @@ do_exec_no_pty(Session *s, const char *command)
                        close(perr[0]);
                        perr[0] = -1;
                }
-               session_set_fds(s, pin[1], pout[0], perr[0]);
+               session_set_fds(s, pin[1], pout[0], perr[0], 0);
        } else {
                /* Enter the interactive session. */
                server_loop(pid, pin[1], pout[0], perr[0]);
                /* server_loop has closed pin[1], pout[0], and perr[0]. */
        }
-#else /* USE_PIPES */
+#else
        /* We are the parent.  Close the child sides of the socket pairs. */
        close(inout[0]);
        close(err[0]);
 
-       /*
-        * Clear loginmsg, since it's the child's responsibility to display
-        * it to the user, otherwise multiple sessions may accumulate
-        * multiple copies of the login messages.
-        */
-       buffer_clear(&loginmsg);
-
        /*
         * Enter the interactive session.  Note: server_loop must be able to
         * handle the case that fdin and fdout are the same.
         */
        if (compat20) {
-               session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]);
+               session_set_fds(s, inout[1], inout[1],
+                   s->is_subsystem ? -1 : err[1], 0);
+               if (s->is_subsystem)
+                       close(err[1]);
        } else {
                server_loop(pid, inout[1], inout[1], err[1]);
                /* server_loop has closed inout[1] and err[1]. */
        }
-#endif /* USE_PIPES */
+#endif
+       return 0;
 }
 
 /*
@@ -569,7 +647,7 @@ do_exec_no_pty(Session *s, const char *command)
  * setting up file descriptors, controlling tty, updating wtmp, utmp,
  * lastlog, and other such operations.
  */
-void
+int
 do_exec_pty(Session *s, const char *command)
 {
        int fdout, ptyfd, ttyfd, ptymaster;
@@ -580,12 +658,46 @@ do_exec_pty(Session *s, const char *command)
        ptyfd = s->ptyfd;
        ttyfd = s->ttyfd;
 
+       /*
+        * Create another descriptor of the pty master side for use as the
+        * standard input.  We could use the original descriptor, but this
+        * simplifies code in server_loop.  The descriptor is bidirectional.
+        * Do this before forking (and cleanup in the child) so as to
+        * detect and gracefully fail out-of-fd conditions.
+        */
+       if ((fdout = dup(ptyfd)) < 0) {
+               error("%s: dup #1: %s", __func__, strerror(errno));
+               close(ttyfd);
+               close(ptyfd);
+               return -1;
+       }
+       /* we keep a reference to the pty master */
+       if ((ptymaster = dup(ptyfd)) < 0) {
+               error("%s: dup #2: %s", __func__, strerror(errno));
+               close(ttyfd);
+               close(ptyfd);
+               close(fdout);
+               return -1;
+       }
+
        /* Fork the child. */
-       if ((pid = fork()) == 0) {
+       switch ((pid = fork())) {
+       case -1:
+               error("%s: fork: %.100s", __func__, strerror(errno));
+               close(fdout);
+               close(ptymaster);
+               close(ttyfd);
+               close(ptyfd);
+               return -1;
+       case 0:
                is_child = 1;
 
+               close(fdout);
+               close(ptymaster);
+
                /* Child.  Reinitialize the log because the pid has changed. */
-               log_init(__progname, options.log_level, options.log_facility, log_stderr);
+               log_init(__progname, options.log_level,
+                   options.log_facility, log_stderr);
                /* Close the master side of the pseudo tty. */
                close(ptyfd);
 
@@ -616,11 +728,16 @@ do_exec_pty(Session *s, const char *command)
                        do_pre_login(s);
 # endif
 #endif
-
-               /* Do common processing for the child, such as execing the command. */
-               do_child(s, command);
-               /* NOTREACHED */
+               /*
+                * Do common processing for the child, such as execing
+                * the command.
+                */
+               do_child(s, command);
+               /* NOTREACHED */
+       default:
+               break;
        }
+
 #ifdef _UNICOS
        signal(WJSIGNAL, cray_job_termination_handler);
 #endif /* _UNICOS */
@@ -628,36 +745,22 @@ do_exec_pty(Session *s, const char *command)
        if (is_winnt)
                cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
 #endif
-       if (pid < 0)
-               packet_disconnect("fork failed: %.100s", strerror(errno));
+
        s->pid = pid;
 
        /* Parent.  Close the slave side of the pseudo tty. */
        close(ttyfd);
 
-       /*
-        * Create another descriptor of the pty master side for use as the
-        * standard input.  We could use the original descriptor, but this
-        * simplifies code in server_loop.  The descriptor is bidirectional.
-        */
-       fdout = dup(ptyfd);
-       if (fdout < 0)
-               packet_disconnect("dup #1 failed: %.100s", strerror(errno));
-
-       /* we keep a reference to the pty master */
-       ptymaster = dup(ptyfd);
-       if (ptymaster < 0)
-               packet_disconnect("dup #2 failed: %.100s", strerror(errno));
-       s->ptymaster = ptymaster;
-
        /* Enter interactive session. */
+       s->ptymaster = ptymaster;
        packet_set_interactive(1);
        if (compat20) {
-               session_set_fds(s, ptyfd, fdout, -1);
+               session_set_fds(s, ptyfd, fdout, -1, 1);
        } else {
                server_loop(pid, ptyfd, fdout, -1);
                /* server_loop _has_ closed ptyfd and fdout. */
        }
+       return 0;
 }
 
 #ifdef LOGIN_NEEDS_UTMPX
@@ -692,9 +795,11 @@ do_pre_login(Session *s)
  * This is called to fork and execute a command.  If another command is
  * to be forced, execute that instead.
  */
-void
+int
 do_exec(Session *s, const char *command)
 {
+       int ret;
+
        if (options.adm_forced_command) {
                original_command = command;
                command = options.adm_forced_command;
@@ -745,9 +850,9 @@ do_exec(Session *s, const char *command)
        }
 #endif
        if (s->ttyfd != -1)
-               do_exec_pty(s, command);
+               ret = do_exec_pty(s, command);
        else
-               do_exec_no_pty(s, command);
+               ret = do_exec_no_pty(s, command);
 
        original_command = NULL;
 
@@ -757,6 +862,8 @@ do_exec(Session *s, const char *command)
         * multiple copies of the login messages.
         */
        buffer_clear(&loginmsg);
+
+       return ret;
 }
 
 /* administrative, login(1)-like work */
@@ -1374,7 +1481,7 @@ 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 && 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)
@@ -1710,6 +1817,7 @@ do_child(Session *s, const char *command)
        char *argv[ARGV_MAX];
        const char *shell, *shell0, *hostname = NULL;
        struct passwd *pw = s->pw;
+       int r = 0;
 
 #ifdef AFS_KRB5
 /* Default place to look for aklog. */
@@ -1872,12 +1980,16 @@ do_child(Session *s, const char *command)
 
        /* Change current directory to the user's home directory. */
        if (chdir(pw->pw_dir) < 0) {
-               fprintf(stderr, "Could not chdir to home directory %s: %s\n",
-                   pw->pw_dir, strerror(errno));
+               /* Suppress missing homedir warning for chroot case */
 #ifdef HAVE_LOGIN_CAP
-               if (login_getcapbool(lc, "requirehome", 0))
-                       exit(1);
+               r = login_getcapbool(lc, "requirehome", 0);
 #endif
+               if (r || options.chroot_directory == NULL)
+                       fprintf(stderr, "Could not chdir to home "
+                           "directory %s: %s\n", pw->pw_dir,
+                           strerror(errno));
+               if (r)
+                       exit(1);
        }
 
        closefrom(STDERR_FILENO + 1);
@@ -1955,43 +2067,79 @@ do_child(Session *s, const char *command)
        exit(1);
 }
 
+void
+session_unused(int id)
+{
+       debug3("%s: session id %d unused", __func__, id);
+       if (id >= options.max_sessions ||
+           id >= sessions_nalloc) {
+               fatal("%s: insane session id %d (max %d nalloc %d)",
+                   __func__, id, options.max_sessions, sessions_nalloc);
+       }
+       bzero(&sessions[id], sizeof(*sessions));
+       sessions[id].self = id;
+       sessions[id].used = 0;
+       sessions[id].chanid = -1;
+       sessions[id].ptyfd = -1;
+       sessions[id].ttyfd = -1;
+       sessions[id].ptymaster = -1;
+       sessions[id].x11_chanids = NULL;
+       sessions[id].next_unused = sessions_first_unused;
+       sessions_first_unused = id;
+}
+
 Session *
 session_new(void)
 {
-       int i;
-       static int did_init = 0;
-       if (!did_init) {
-               debug("session_new: init");
-               for (i = 0; i < MAX_SESSIONS; i++) {
-                       sessions[i].used = 0;
+       Session *s, *tmp;
+
+       if (sessions_first_unused == -1) {
+               if (sessions_nalloc >= options.max_sessions)
+                       return NULL;
+               debug2("%s: allocate (allocated %d max %d)",
+                   __func__, sessions_nalloc, options.max_sessions);
+               tmp = xrealloc(sessions, sessions_nalloc + 1,
+                   sizeof(*sessions));
+               if (tmp == NULL) {
+                       error("%s: cannot allocate %d sessions",
+                           __func__, sessions_nalloc + 1);
+                       return NULL;
                }
-               did_init = 1;
+               sessions = tmp;
+               session_unused(sessions_nalloc++);
        }
-       for (i = 0; i < MAX_SESSIONS; i++) {
-               Session *s = &sessions[i];
-               if (! s->used) {
-                       memset(s, 0, sizeof(*s));
-                       s->chanid = -1;
-                       s->ptyfd = -1;
-                       s->ttyfd = -1;
-                       s->used = 1;
-                       s->self = i;
-                       s->x11_chanids = NULL;
-                       debug("session_new: session %d", i);
-                       return s;
-               }
+
+       if (sessions_first_unused >= sessions_nalloc ||
+           sessions_first_unused < 0) {
+               fatal("%s: insane first_unused %d max %d nalloc %d",
+                   __func__, sessions_first_unused, options.max_sessions,
+                   sessions_nalloc);
        }
-       return NULL;
+
+       s = &sessions[sessions_first_unused];
+       if (s->used) {
+               fatal("%s: session %d already used",
+                   __func__, sessions_first_unused);
+       }
+       sessions_first_unused = s->next_unused;
+       s->used = 1;
+       s->next_unused = -1;
+       debug("session_new: session %d", s->self);
+
+       return s;
 }
 
 static void
 session_dump(void)
 {
        int i;
-       for (i = 0; i < MAX_SESSIONS; i++) {
+       for (i = 0; i < sessions_nalloc; i++) {
                Session *s = &sessions[i];
-               debug("dump: used %d session %d %p channel %d pid %ld",
+
+               debug("dump: used %d next_unused %d session %d %p "
+                   "channel %d pid %ld",
                    s->used,
+                   s->next_unused,
                    s->self,
                    s,
                    s->chanid,
@@ -2021,7 +2169,7 @@ Session *
 session_by_tty(char *tty)
 {
        int i;
-       for (i = 0; i < MAX_SESSIONS; i++) {
+       for (i = 0; i < sessions_nalloc; i++) {
                Session *s = &sessions[i];
                if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
                        debug("session_by_tty: session %d tty %s", i, tty);
@@ -2037,10 +2185,11 @@ static Session *
 session_by_channel(int id)
 {
        int i;
-       for (i = 0; i < MAX_SESSIONS; i++) {
+       for (i = 0; i < sessions_nalloc; i++) {
                Session *s = &sessions[i];
                if (s->used && s->chanid == id) {
-                       debug("session_by_channel: session %d channel %d", i, id);
+                       debug("session_by_channel: session %d channel %d",
+                           i, id);
                        return s;
                }
        }
@@ -2054,7 +2203,7 @@ session_by_x11_channel(int id)
 {
        int i, j;
 
-       for (i = 0; i < MAX_SESSIONS; i++) {
+       for (i = 0; i < sessions_nalloc; i++) {
                Session *s = &sessions[i];
 
                if (s->x11_chanids == NULL || !s->used)
@@ -2077,7 +2226,7 @@ session_by_pid(pid_t pid)
 {
        int i;
        debug("session_by_pid: pid %ld", (long)pid);
-       for (i = 0; i < MAX_SESSIONS; i++) {
+       for (i = 0; i < sessions_nalloc; i++) {
                Session *s = &sessions[i];
                if (s->used && s->pid == pid)
                        return s;
@@ -2133,7 +2282,8 @@ session_pty_req(Session *s)
 
        /* Allocate a pty and open it. */
        debug("Allocating pty.");
-       if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {
+       if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
+           sizeof(s->tty)))) {
                if (s->term)
                        xfree(s->term);
                s->term = NULL;
@@ -2186,8 +2336,7 @@ session_subsystem_req(Session *s)
                                s->is_subsystem = SUBSYSTEM_EXT;
                        }
                        debug("subsystem: exec() %s", cmd);
-                       do_exec(s, cmd);
-                       success = 1;
+                       success = do_exec(s, cmd) == 0;
                        break;
                }
        }
@@ -2230,19 +2379,19 @@ static int
 session_shell_req(Session *s)
 {
        packet_check_eom();
-       do_exec(s, NULL);
-       return 1;
+       return do_exec(s, NULL) == 0;
 }
 
 static int
 session_exec_req(Session *s)
 {
-       u_int len;
+       u_int len, success;
+
        char *command = packet_get_string(&len);
        packet_check_eom();
-       do_exec(s, command);
+       success = do_exec(s, command) == 0;
        xfree(command);
-       return 1;
+       return success;
 }
 
 static int
@@ -2252,8 +2401,7 @@ session_break_req(Session *s)
        packet_get_int();       /* ignored */
        packet_check_eom();
 
-       if (s->ttyfd == -1 ||
-           tcsendbreak(s->ttyfd, 0) < 0)
+       if (s->ttyfd == -1 || tcsendbreak(s->ttyfd, 0) < 0)
                return 0;
        return 1;
 }
@@ -2298,7 +2446,7 @@ session_auth_agent_req(Session *s)
 {
        static int called = 0;
        packet_check_eom();
-       if (no_agent_forwarding_flag) {
+       if (no_agent_forwarding_flag || !options.allow_agent_forwarding) {
                debug("session_auth_agent_req: no_agent_forwarding_flag");
                return 0;
        }
@@ -2354,7 +2502,7 @@ session_input_channel_req(Channel *c, const char *rtype)
 }
 
 void
-session_set_fds(Session *s, int fdin, int fdout, int fderr)
+session_set_fds(Session *s, int fdin, int fdout, int fderr, int is_tty)
 {
        if (!compat20)
                fatal("session_set_fds: called for proto != 2.0");
@@ -2364,18 +2512,10 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
         */
        if (s->chanid == -1)
                fatal("no channel for session %d", s->self);
-       if(options.hpn_disabled) 
        channel_set_fds(s->chanid,
            fdout, fdin, fderr,
            fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
-           1,
-           CHAN_SES_WINDOW_DEFAULT);
-       else
-               channel_set_fds(s->chanid,
-                   fdout, fdin, fderr,
-                   fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
-                   1,
-                   options.hpn_buffer_size);
+           1, is_tty, CHAN_SES_WINDOW_DEFAULT);
 }
 
 /*
@@ -2407,8 +2547,9 @@ session_pty_cleanup2(Session *s)
         * the pty cleanup, so that another process doesn't get this pty
         * while we're still cleaning up.
         */
-       if (close(s->ptymaster) < 0)
-               error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno));
+       if (s->ptymaster != -1 && close(s->ptymaster) < 0)
+               error("close(s->ptymaster/%d): %s",
+                   s->ptymaster, strerror(errno));
 
        /* unlink pty from session */
        s->ttyfd = -1;
@@ -2568,7 +2709,6 @@ session_close(Session *s)
                xfree(s->auth_data);
        if (s->auth_proto)
                xfree(s->auth_proto);
-       s->used = 0;
        if (s->env != NULL) {
                for (i = 0; i < s->num_env; i++) {
                        xfree(s->env[i].name);
@@ -2577,6 +2717,7 @@ session_close(Session *s)
                xfree(s->env);
        }
        session_proctitle(s);
+       session_unused(s->self);
 }
 
 void
@@ -2640,7 +2781,7 @@ void
 session_destroy_all(void (*closefunc)(Session *))
 {
        int i;
-       for (i = 0; i < MAX_SESSIONS; i++) {
+       for (i = 0; i < sessions_nalloc; i++) {
                Session *s = &sessions[i];
                if (s->used) {
                        if (closefunc != NULL)
@@ -2659,7 +2800,7 @@ session_tty_list(void)
        char *cp;
 
        buf[0] = '\0';
-       for (i = 0; i < MAX_SESSIONS; i++) {
+       for (i = 0; i < sessions_nalloc; i++) {
                Session *s = &sessions[i];
                if (s->used && s->ttyfd != -1) {
 
This page took 0.066951 seconds and 4 git commands to generate.