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
|