Print this page
OS-2204 SunSSH has a maximum of 10 multiplexed sessions


  18  *    notice, this list of conditions and the following disclaimer.
  19  * 2. Redistributions in binary form must reproduce the above copyright
  20  *    notice, this list of conditions and the following disclaimer in the
  21  *    documentation and/or other materials provided with the distribution.
  22  *
  23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33  */
  34 /*
  35  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  36  * Use is subject to license terms.
  37  */



  38 
  39 #include "includes.h"
  40 RCSID("$OpenBSD: session.c,v 1.150 2002/09/16 19:55:33 stevesk Exp $");
  41 
  42 #ifdef HAVE_DEFOPEN
  43 #include <deflt.h>
  44 #include <ulimit.h>
  45 #endif /* HAVE_DEFOPEN */
  46 
  47 #ifdef HAVE_LIBGEN_H
  48 #include <libgen.h>
  49 #endif
  50 
  51 #include <priv.h>
  52 
  53 #include "ssh.h"
  54 #include "ssh1.h"
  55 #include "ssh2.h"
  56 #include "xmalloc.h"

  57 #include "sshpty.h"
  58 #include "packet.h"
  59 #include "buffer.h"
  60 #include "mpaux.h"
  61 #include "uidswap.h"
  62 #include "compat.h"
  63 #include "channels.h"
  64 #include "bufaux.h"
  65 #include "auth.h"
  66 #include "auth-options.h"
  67 #include "pathnames.h"
  68 #include "log.h"
  69 #include "servconf.h"
  70 #include "sshlogin.h"
  71 #include "serverloop.h"
  72 #include "canohost.h"
  73 #include "session.h"
  74 #include "tildexpand.h"
  75 #include "misc.h"
  76 #include "sftp.h"


 122 static void session_do_pam(Session *, int);
 123 #endif /* USE_PAM */
 124 
 125 /* import */
 126 extern ServerOptions options;
 127 extern char *__progname;
 128 extern int log_stderr;
 129 extern int debug_flag;
 130 extern u_int utmp_len;
 131 extern void destroy_sensitive_data(void);
 132 
 133 #ifdef GSSAPI
 134 extern Gssctxt *xxx_gssctxt;
 135 #endif /* GSSAPI */
 136 
 137 /* original command from peer. */
 138 const char *original_command = NULL;
 139 
 140 /* data */
 141 #define MAX_SESSIONS 10
 142 Session sessions[MAX_SESSIONS];


 143 
 144 #define SUBSYSTEM_NONE          0
 145 #define SUBSYSTEM_EXT           1
 146 #define SUBSYSTEM_INT_SFTP      2
 147 
 148 #ifdef HAVE_LOGIN_CAP
 149 login_cap_t *lc;
 150 #endif
 151 
 152 /* Name and directory of socket for authentication agent forwarding. */
 153 static char *auth_sock_name = NULL;
 154 static char *auth_sock_dir = NULL;
 155 
 156 /* removes the agent forwarding socket */
 157 
 158 static void
 159 auth_sock_cleanup_proc(void *_pw)
 160 {
 161         struct passwd *pw = _pw;
 162 


1510                 /* Executing the shell failed. */
1511                 perror(shell);
1512                 exit(1);
1513         }
1514         /*
1515          * Execute the command using the user's shell.  This uses the -c
1516          * option to execute the command.
1517          */
1518         argv[0] = (char *) shell0;
1519         argv[1] = "-c";
1520         argv[2] = (char *) command;
1521         argv[3] = NULL;
1522         execve(shell, argv, env);
1523         perror(shell);
1524         exit(1);
1525 }
1526 
1527 Session *
1528 session_new(void)
1529 {
1530         int i;
1531         static int did_init = 0;
1532         if (!did_init) {
1533                 debug("session_new: init");
1534                 for (i = 0; i < MAX_SESSIONS; i++) {
1535                         sessions[i].used = 0;
1536                 }
1537                 did_init = 1;
1538         }
1539         for (i = 0; i < MAX_SESSIONS; i++) {
1540                 Session *s = &sessions[i];
1541                 if (! s->used) {
1542                         memset(s, 0, sizeof(*s));
1543                         s->chanid = -1;
1544                         s->ptyfd = -1;
1545                         s->ttyfd = -1;
1546                         s->used = 1;
1547                         s->self = i;
1548                         s->env = NULL;
1549                         debug("session_new: session %d", i);
1550                         return s;
1551                 }
1552         }
1553         return NULL;
1554 }
1555 
1556 static void
1557 session_dump(void)
1558 {
1559         int i;
1560         for (i = 0; i < MAX_SESSIONS; i++) {
1561                 Session *s = &sessions[i];
1562                 debug("dump: used %d session %d %p channel %d pid %ld",
1563                     s->used,
1564                     s->self,
1565                     s,
1566                     s->chanid,
1567                     (long)s->pid);
1568         }
1569 }
1570 
1571 int
1572 session_open(Authctxt *authctxt, int chanid)
1573 {
1574         Session *s = session_new();
1575         debug("session_open: channel %d", chanid);
1576         if (s == NULL) {
1577                 error("no more sessions");
1578                 return 0;
1579         }
1580         s->authctxt = authctxt;
1581         s->pw = authctxt->pw;
1582         if (s->pw == NULL)
1583                 fatal("no user for session %d", s->self);
1584         debug("session_open: session %d: link with channel %d", s->self, chanid);
1585         s->chanid = chanid;
1586         return 1;
1587 }
1588 
1589 #ifndef lint
1590 Session *
1591 session_by_tty(char *tty)
1592 {
1593         int i;
1594         for (i = 0; i < MAX_SESSIONS; i++) {
1595                 Session *s = &sessions[i];
1596                 if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
1597                         debug("session_by_tty: session %d tty %s", i, tty);
1598                         return s;
1599                 }
1600         }
1601         debug("session_by_tty: unknown tty %.100s", tty);
1602         session_dump();
1603         return NULL;
1604 }
1605 #endif /* lint */
1606 
1607 static Session *
1608 session_by_channel(int id)
1609 {
1610         int i;
1611         for (i = 0; i < MAX_SESSIONS; i++) {
1612                 Session *s = &sessions[i];
1613                 if (s->used && s->chanid == id) {
1614                         debug("session_by_channel: session %d channel %d", i, id);
1615                         return s;
1616                 }
1617         }
1618         debug("session_by_channel: unknown channel %d", id);
1619         session_dump();
1620         return NULL;
1621 }
1622 
1623 static Session *
1624 session_by_pid(pid_t pid)
1625 {
1626         int i;
1627         debug("session_by_pid: pid %ld", (long)pid);
1628         for (i = 0; i < MAX_SESSIONS; i++) {
1629                 Session *s = &sessions[i];
1630                 if (s->used && s->pid == pid)
1631                         return s;
1632         }
1633         error("session_by_pid: unknown pid %ld", (long)pid);
1634         session_dump();
1635         return NULL;
1636 }
1637 
1638 static int
1639 session_window_change_req(Session *s)
1640 {
1641         s->col = packet_get_int();
1642         s->row = packet_get_int();
1643         s->xpixel = packet_get_int();
1644         s->ypixel = packet_get_int();
1645         packet_check_eom();
1646         pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1647         return 1;
1648 }
1649 
1650 static int


2270                 session_pty_cleanup(s);
2271         }
2272         if (s->auth_file != NULL) {
2273                 fatal_remove_cleanup(session_xauthfile_cleanup, (void *)s);
2274                 session_xauthfile_cleanup(s);
2275                 xfree(s->auth_file);
2276         }
2277         if (s->term)
2278                 xfree(s->term);
2279         if (s->display)
2280                 xfree(s->display);
2281         if (s->auth_display)
2282                 xfree(s->auth_display);
2283         if (s->auth_data)
2284                 xfree(s->auth_data);
2285         if (s->auth_proto)
2286                 xfree(s->auth_proto);
2287         if (s->command)
2288                 xfree(s->command);
2289         session_free_env(&s->env);
2290         s->used = 0;

2291         session_proctitle(s);

2292 }
2293 
2294 void
2295 session_close_by_pid(pid_t pid, int status)
2296 {
2297         Session *s = session_by_pid(pid);
2298         if (s == NULL) {
2299                 debug("session_close_by_pid: no session for pid %ld",
2300                     (long)pid);
2301                 return;
2302         }
2303         if (s->chanid != -1)
2304                 session_exit_message(s, status);
2305         session_close(s);
2306 }
2307 
2308 /*
2309  * This is called when a channel dies before the session 'child' itself dies.
2310  * It can happen for example if we exit from an interactive shell before we
2311  * exit from forwarded X11 applications.


2324                 debug("session_close_by_channel: channel %d: has child", id);
2325                 /*
2326                  * delay detach of session, but release pty, since
2327                  * the fd's to the child are already closed
2328                  */
2329                 if (s->ttyfd != -1) {
2330                         fatal_remove_cleanup(session_pty_cleanup, (void *)s);
2331                         session_pty_cleanup(s);
2332                 }
2333                 return;
2334         }
2335         /* detach by removing callback */
2336         channel_cancel_cleanup(s->chanid);
2337         s->chanid = -1;
2338         session_close(s);
2339 }
2340 
2341 void
2342 session_destroy_all(void (*closefunc)(Session *))
2343 {
2344         int i;
2345         for (i = 0; i < MAX_SESSIONS; i++) {
2346                 Session *s = &sessions[i];
2347                 if (s->used) {
2348                         if (closefunc != NULL)
2349                                 closefunc(s);
2350                         else
2351                                 session_close(s);
2352                 }
2353         }
2354 }
2355 
2356 static char *
2357 session_tty_list(void)
2358 {

2359         static char buf[1024];
2360         int i;
2361         buf[0] = '\0';
2362         for (i = 0; i < MAX_SESSIONS; i++) {
2363                 Session *s = &sessions[i];
2364                 if (s->used && s->ttyfd != -1) {
2365                         if (buf[0] != '\0')
2366                                 strlcat(buf, ",", sizeof buf);
2367                         strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf);
2368                 }
2369         }
2370         if (buf[0] == '\0')
2371                 strlcpy(buf, "notty", sizeof buf);
2372         return buf;
2373 }
2374 
2375 void
2376 session_proctitle(Session *s)
2377 {
2378         if (s->pw == NULL)
2379                 error("no user for session %d", s->self);
2380         else
2381                 setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
2382 }
2383 
2384 int




  18  *    notice, this list of conditions and the following disclaimer.
  19  * 2. Redistributions in binary form must reproduce the above copyright
  20  *    notice, this list of conditions and the following disclaimer in the
  21  *    documentation and/or other materials provided with the distribution.
  22  *
  23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33  */
  34 /*
  35  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  36  * Use is subject to license terms.
  37  */
  38 /*
  39  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  40  */
  41 
  42 #include "includes.h"
  43 RCSID("$OpenBSD: session.c,v 1.150 2002/09/16 19:55:33 stevesk Exp $");
  44 
  45 #ifdef HAVE_DEFOPEN
  46 #include <deflt.h>
  47 #include <ulimit.h>
  48 #endif /* HAVE_DEFOPEN */
  49 
  50 #ifdef HAVE_LIBGEN_H
  51 #include <libgen.h>
  52 #endif
  53 
  54 #include <priv.h>
  55 
  56 #include "ssh.h"
  57 #include "ssh1.h"
  58 #include "ssh2.h"
  59 #include "xmalloc.h"
  60 #include "sys-queue.h"
  61 #include "sshpty.h"
  62 #include "packet.h"
  63 #include "buffer.h"
  64 #include "mpaux.h"
  65 #include "uidswap.h"
  66 #include "compat.h"
  67 #include "channels.h"
  68 #include "bufaux.h"
  69 #include "auth.h"
  70 #include "auth-options.h"
  71 #include "pathnames.h"
  72 #include "log.h"
  73 #include "servconf.h"
  74 #include "sshlogin.h"
  75 #include "serverloop.h"
  76 #include "canohost.h"
  77 #include "session.h"
  78 #include "tildexpand.h"
  79 #include "misc.h"
  80 #include "sftp.h"


 126 static void session_do_pam(Session *, int);
 127 #endif /* USE_PAM */
 128 
 129 /* import */
 130 extern ServerOptions options;
 131 extern char *__progname;
 132 extern int log_stderr;
 133 extern int debug_flag;
 134 extern u_int utmp_len;
 135 extern void destroy_sensitive_data(void);
 136 
 137 #ifdef GSSAPI
 138 extern Gssctxt *xxx_gssctxt;
 139 #endif /* GSSAPI */
 140 
 141 /* original command from peer. */
 142 const char *original_command = NULL;
 143 
 144 /* data */
 145 #define MAX_SESSIONS 10
 146 static int sessions_next_id = 0;
 147 static LIST_HEAD(sessions_head, Session) sessions =
 148     LIST_HEAD_INITIALIZER(sessions);
 149 
 150 #define SUBSYSTEM_NONE          0
 151 #define SUBSYSTEM_EXT           1
 152 #define SUBSYSTEM_INT_SFTP      2
 153 
 154 #ifdef HAVE_LOGIN_CAP
 155 login_cap_t *lc;
 156 #endif
 157 
 158 /* Name and directory of socket for authentication agent forwarding. */
 159 static char *auth_sock_name = NULL;
 160 static char *auth_sock_dir = NULL;
 161 
 162 /* removes the agent forwarding socket */
 163 
 164 static void
 165 auth_sock_cleanup_proc(void *_pw)
 166 {
 167         struct passwd *pw = _pw;
 168 


1516                 /* Executing the shell failed. */
1517                 perror(shell);
1518                 exit(1);
1519         }
1520         /*
1521          * Execute the command using the user's shell.  This uses the -c
1522          * option to execute the command.
1523          */
1524         argv[0] = (char *) shell0;
1525         argv[1] = "-c";
1526         argv[2] = (char *) command;
1527         argv[3] = NULL;
1528         execve(shell, argv, env);
1529         perror(shell);
1530         exit(1);
1531 }
1532 
1533 Session *
1534 session_new(void)
1535 {
1536         Session *s;
1537 

1538         debug("session_new: init");
1539 
1540         s = xmalloc(sizeof (*s));






1541         memset(s, 0, sizeof(*s));
1542         s->chanid = -1;
1543         s->ptyfd = -1;
1544         s->ttyfd = -1;
1545         s->self = sessions_next_id++;

1546         s->env = NULL;
1547         LIST_INSERT_HEAD(&sessions, s, list_entry);
1548 
1549         debug("session_new: session %d", s->self);
1550 
1551         return (s);
1552 }
1553 
1554 static void
1555 session_dump(void)
1556 {
1557         Session *s;
1558         LIST_FOREACH(s, &sessions, list_entry) {
1559                 debug("dump: session %d %p channel %d pid %ld",


1560                     s->self,
1561                     s,
1562                     s->chanid,
1563                     (long)s->pid);
1564         }
1565 }
1566 
1567 int
1568 session_open(Authctxt *authctxt, int chanid)
1569 {
1570         Session *s = session_new();
1571         debug("session_open: channel %d", chanid);
1572         if (s == NULL) {
1573                 error("no more sessions");
1574                 return 0;
1575         }
1576         s->authctxt = authctxt;
1577         s->pw = authctxt->pw;
1578         if (s->pw == NULL)
1579                 fatal("no user for session %d", s->self);
1580         debug("session_open: session %d: link with channel %d", s->self, chanid);
1581         s->chanid = chanid;
1582         return 1;
1583 }
1584 
1585 #ifndef lint
1586 Session *
1587 session_by_tty(char *tty)
1588 {
1589         Session *s;
1590         LIST_FOREACH(s, &sessions, list_entry) {
1591                 if (s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
1592                         debug("session_by_tty: session %d tty %s", s->self, tty);

1593                         return s;
1594                 }
1595         }
1596         debug("session_by_tty: unknown tty %.100s", tty);
1597         session_dump();
1598         return NULL;
1599 }
1600 #endif /* lint */
1601 
1602 static Session *
1603 session_by_channel(int id)
1604 {
1605         Session *s;
1606         LIST_FOREACH(s, &sessions, list_entry) {
1607                 if (s->chanid == id) {
1608                         debug("session_by_channel: session %d channel %d", s->self, id);

1609                         return s;
1610                 }
1611         }
1612         debug("session_by_channel: unknown channel %d", id);
1613         session_dump();
1614         return NULL;
1615 }
1616 
1617 static Session *
1618 session_by_pid(pid_t pid)
1619 {
1620         Session *s;
1621         debug("session_by_pid: pid %ld", (long)pid);
1622         LIST_FOREACH(s, &sessions, list_entry) {
1623                 if (s->pid == pid)

1624                         return s;
1625         }
1626         error("session_by_pid: unknown pid %ld", (long)pid);
1627         session_dump();
1628         return NULL;
1629 }
1630 
1631 static int
1632 session_window_change_req(Session *s)
1633 {
1634         s->col = packet_get_int();
1635         s->row = packet_get_int();
1636         s->xpixel = packet_get_int();
1637         s->ypixel = packet_get_int();
1638         packet_check_eom();
1639         pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1640         return 1;
1641 }
1642 
1643 static int


2263                 session_pty_cleanup(s);
2264         }
2265         if (s->auth_file != NULL) {
2266                 fatal_remove_cleanup(session_xauthfile_cleanup, (void *)s);
2267                 session_xauthfile_cleanup(s);
2268                 xfree(s->auth_file);
2269         }
2270         if (s->term)
2271                 xfree(s->term);
2272         if (s->display)
2273                 xfree(s->display);
2274         if (s->auth_display)
2275                 xfree(s->auth_display);
2276         if (s->auth_data)
2277                 xfree(s->auth_data);
2278         if (s->auth_proto)
2279                 xfree(s->auth_proto);
2280         if (s->command)
2281                 xfree(s->command);
2282         session_free_env(&s->env);
2283 
2284         LIST_REMOVE(s, list_entry);
2285         session_proctitle(s);
2286         xfree(s);
2287 }
2288 
2289 void
2290 session_close_by_pid(pid_t pid, int status)
2291 {
2292         Session *s = session_by_pid(pid);
2293         if (s == NULL) {
2294                 debug("session_close_by_pid: no session for pid %ld",
2295                     (long)pid);
2296                 return;
2297         }
2298         if (s->chanid != -1)
2299                 session_exit_message(s, status);
2300         session_close(s);
2301 }
2302 
2303 /*
2304  * This is called when a channel dies before the session 'child' itself dies.
2305  * It can happen for example if we exit from an interactive shell before we
2306  * exit from forwarded X11 applications.


2319                 debug("session_close_by_channel: channel %d: has child", id);
2320                 /*
2321                  * delay detach of session, but release pty, since
2322                  * the fd's to the child are already closed
2323                  */
2324                 if (s->ttyfd != -1) {
2325                         fatal_remove_cleanup(session_pty_cleanup, (void *)s);
2326                         session_pty_cleanup(s);
2327                 }
2328                 return;
2329         }
2330         /* detach by removing callback */
2331         channel_cancel_cleanup(s->chanid);
2332         s->chanid = -1;
2333         session_close(s);
2334 }
2335 
2336 void
2337 session_destroy_all(void (*closefunc)(Session *))
2338 {
2339         Session *s;
2340         LIST_FOREACH(s, &sessions, list_entry) {


2341                 if (closefunc != NULL)
2342                         closefunc(s);
2343                 else
2344                         session_close(s);
2345         }

2346 }
2347 
2348 static char *
2349 session_tty_list(void)
2350 {
2351         Session *s;
2352         static char buf[1024];

2353         buf[0] = '\0';
2354         LIST_FOREACH(s, &sessions, list_entry) {
2355                 if (s->ttyfd != -1) {

2356                         if (buf[0] != '\0')
2357                                 strlcat(buf, ",", sizeof buf);
2358                         strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf);
2359                 }
2360         }
2361         if (buf[0] == '\0')
2362                 strlcpy(buf, "notty", sizeof buf);
2363         return buf;
2364 }
2365 
2366 void
2367 session_proctitle(Session *s)
2368 {
2369         if (s->pw == NULL)
2370                 error("no user for session %d", s->self);
2371         else
2372                 setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
2373 }
2374 
2375 int