summaryrefslogtreecommitdiff
path: root/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'session.c')
-rw-r--r--session.c578
1 files changed, 407 insertions, 171 deletions
diff --git a/session.c b/session.c
index 997ee5fa9..93babf957 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.c,v 1.221 2007/01/21 01:41:54 stevesk Exp $ */ 1/* $OpenBSD: session.c,v 1.241 2008/06/16 13:22:53 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -59,6 +59,7 @@
59#include <string.h> 59#include <string.h>
60#include <unistd.h> 60#include <unistd.h>
61 61
62#include "openbsd-compat/sys-queue.h"
62#include "xmalloc.h" 63#include "xmalloc.h"
63#include "ssh.h" 64#include "ssh.h"
64#include "ssh1.h" 65#include "ssh1.h"
@@ -84,9 +85,11 @@
84#include "sshlogin.h" 85#include "sshlogin.h"
85#include "serverloop.h" 86#include "serverloop.h"
86#include "canohost.h" 87#include "canohost.h"
88#include "misc.h"
87#include "session.h" 89#include "session.h"
88#include "kex.h" 90#include "kex.h"
89#include "monitor_wrap.h" 91#include "monitor_wrap.h"
92#include "sftp.h"
90 93
91#if defined(KRB5) && defined(USE_AFS) 94#if defined(KRB5) && defined(USE_AFS)
92#include <kafs.h> 95#include <kafs.h>
@@ -95,13 +98,13 @@
95/* func */ 98/* func */
96 99
97Session *session_new(void); 100Session *session_new(void);
98void session_set_fds(Session *, int, int, int); 101void session_set_fds(Session *, int, int, int, int);
99void session_pty_cleanup(Session *); 102void session_pty_cleanup(Session *);
100void session_proctitle(Session *); 103void session_proctitle(Session *);
101int session_setup_x11fwd(Session *); 104int session_setup_x11fwd(Session *);
102void do_exec_pty(Session *, const char *); 105int do_exec_pty(Session *, const char *);
103void do_exec_no_pty(Session *, const char *); 106int do_exec_no_pty(Session *, const char *);
104void do_exec(Session *, const char *); 107int do_exec(Session *, const char *);
105void do_login(Session *, const char *); 108void do_login(Session *, const char *);
106#ifdef LOGIN_NEEDS_UTMPX 109#ifdef LOGIN_NEEDS_UTMPX
107static void do_pre_login(Session *s); 110static void do_pre_login(Session *s);
@@ -129,8 +132,13 @@ extern Buffer loginmsg;
129const char *original_command = NULL; 132const char *original_command = NULL;
130 133
131/* data */ 134/* data */
132#define MAX_SESSIONS 64 135static int sessions_first_unused = -1;
133Session sessions[MAX_SESSIONS]; 136static int sessions_nalloc = 0;
137static Session *sessions = NULL;
138
139#define SUBSYSTEM_NONE 0
140#define SUBSYSTEM_EXT 1
141#define SUBSYSTEM_INT_SFTP 2
134 142
135#ifdef HAVE_LOGIN_CAP 143#ifdef HAVE_LOGIN_CAP
136login_cap_t *lc; 144login_cap_t *lc;
@@ -160,7 +168,7 @@ static int
160auth_input_request_forwarding(struct passwd * pw) 168auth_input_request_forwarding(struct passwd * pw)
161{ 169{
162 Channel *nc; 170 Channel *nc;
163 int sock; 171 int sock = -1;
164 struct sockaddr_un sunaddr; 172 struct sockaddr_un sunaddr;
165 173
166 if (auth_sock_name != NULL) { 174 if (auth_sock_name != NULL) {
@@ -172,43 +180,48 @@ auth_input_request_forwarding(struct passwd * pw)
172 temporarily_use_uid(pw); 180 temporarily_use_uid(pw);
173 181
174 /* Allocate a buffer for the socket name, and format the name. */ 182 /* Allocate a buffer for the socket name, and format the name. */
175 auth_sock_name = xmalloc(MAXPATHLEN); 183 auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
176 auth_sock_dir = xmalloc(MAXPATHLEN);
177 strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
178 184
179 /* Create private directory for socket */ 185 /* Create private directory for socket */
180 if (mkdtemp(auth_sock_dir) == NULL) { 186 if (mkdtemp(auth_sock_dir) == NULL) {
181 packet_send_debug("Agent forwarding disabled: " 187 packet_send_debug("Agent forwarding disabled: "
182 "mkdtemp() failed: %.100s", strerror(errno)); 188 "mkdtemp() failed: %.100s", strerror(errno));
183 restore_uid(); 189 restore_uid();
184 xfree(auth_sock_name);
185 xfree(auth_sock_dir); 190 xfree(auth_sock_dir);
186 auth_sock_name = NULL;
187 auth_sock_dir = NULL; 191 auth_sock_dir = NULL;
188 return 0; 192 goto authsock_err;
189 } 193 }
190 snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld", 194
191 auth_sock_dir, (long) getpid()); 195 xasprintf(&auth_sock_name, "%s/agent.%ld",
196 auth_sock_dir, (long) getpid());
192 197
193 /* Create the socket. */ 198 /* Create the socket. */
194 sock = socket(AF_UNIX, SOCK_STREAM, 0); 199 sock = socket(AF_UNIX, SOCK_STREAM, 0);
195 if (sock < 0) 200 if (sock < 0) {
196 packet_disconnect("socket: %.100s", strerror(errno)); 201 error("socket: %.100s", strerror(errno));
202 restore_uid();
203 goto authsock_err;
204 }
197 205
198 /* Bind it to the name. */ 206 /* Bind it to the name. */
199 memset(&sunaddr, 0, sizeof(sunaddr)); 207 memset(&sunaddr, 0, sizeof(sunaddr));
200 sunaddr.sun_family = AF_UNIX; 208 sunaddr.sun_family = AF_UNIX;
201 strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); 209 strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
202 210
203 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) 211 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
204 packet_disconnect("bind: %.100s", strerror(errno)); 212 error("bind: %.100s", strerror(errno));
213 restore_uid();
214 goto authsock_err;
215 }
205 216
206 /* Restore the privileged uid. */ 217 /* Restore the privileged uid. */
207 restore_uid(); 218 restore_uid();
208 219
209 /* Start listening on the socket. */ 220 /* Start listening on the socket. */
210 if (listen(sock, SSH_LISTEN_BACKLOG) < 0) 221 if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
211 packet_disconnect("listen: %.100s", strerror(errno)); 222 error("listen: %.100s", strerror(errno));
223 goto authsock_err;
224 }
212 225
213 /* Allocate a channel for the authentication agent socket. */ 226 /* Allocate a channel for the authentication agent socket. */
214 nc = channel_new("auth socket", 227 nc = channel_new("auth socket",
@@ -217,6 +230,19 @@ auth_input_request_forwarding(struct passwd * pw)
217 0, "auth socket", 1); 230 0, "auth socket", 1);
218 strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); 231 strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
219 return 1; 232 return 1;
233
234 authsock_err:
235 if (auth_sock_name != NULL)
236 xfree(auth_sock_name);
237 if (auth_sock_dir != NULL) {
238 rmdir(auth_sock_dir);
239 xfree(auth_sock_dir);
240 }
241 if (sock != -1)
242 close(sock);
243 auth_sock_name = NULL;
244 auth_sock_dir = NULL;
245 return 0;
220} 246}
221 247
222static void 248static void
@@ -329,7 +355,8 @@ do_authenticated1(Authctxt *authctxt)
329 break; 355 break;
330 356
331 case SSH_CMSG_AGENT_REQUEST_FORWARDING: 357 case SSH_CMSG_AGENT_REQUEST_FORWARDING:
332 if (no_agent_forwarding_flag || compat13) { 358 if (!options.allow_agent_forwarding ||
359 no_agent_forwarding_flag || compat13) {
333 debug("Authentication agent forwarding not permitted for this authentication."); 360 debug("Authentication agent forwarding not permitted for this authentication.");
334 break; 361 break;
335 } 362 }
@@ -365,10 +392,14 @@ do_authenticated1(Authctxt *authctxt)
365 if (type == SSH_CMSG_EXEC_CMD) { 392 if (type == SSH_CMSG_EXEC_CMD) {
366 command = packet_get_string(&dlen); 393 command = packet_get_string(&dlen);
367 debug("Exec command '%.500s'", command); 394 debug("Exec command '%.500s'", command);
368 do_exec(s, command); 395 if (do_exec(s, command) != 0)
396 packet_disconnect(
397 "command execution failed");
369 xfree(command); 398 xfree(command);
370 } else { 399 } else {
371 do_exec(s, NULL); 400 if (do_exec(s, NULL) != 0)
401 packet_disconnect(
402 "shell execution failed");
372 } 403 }
373 packet_check_eom(); 404 packet_check_eom();
374 session_close(s); 405 session_close(s);
@@ -393,46 +424,84 @@ do_authenticated1(Authctxt *authctxt)
393 } 424 }
394} 425}
395 426
427#define USE_PIPES
396/* 428/*
397 * This is called to fork and execute a command when we have no tty. This 429 * This is called to fork and execute a command when we have no tty. This
398 * will call do_child from the child, and server_loop from the parent after 430 * will call do_child from the child, and server_loop from the parent after
399 * setting up file descriptors and such. 431 * setting up file descriptors and such.
400 */ 432 */
401void 433int
402do_exec_no_pty(Session *s, const char *command) 434do_exec_no_pty(Session *s, const char *command)
403{ 435{
404 pid_t pid; 436 pid_t pid;
405 437
406#ifdef USE_PIPES 438#ifdef USE_PIPES
407 int pin[2], pout[2], perr[2]; 439 int pin[2], pout[2], perr[2];
440
408 /* Allocate pipes for communicating with the program. */ 441 /* Allocate pipes for communicating with the program. */
409 if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0) 442 if (pipe(pin) < 0) {
410 packet_disconnect("Could not create pipes: %.100s", 443 error("%s: pipe in: %.100s", __func__, strerror(errno));
411 strerror(errno)); 444 return -1;
412#else /* USE_PIPES */ 445 }
446 if (pipe(pout) < 0) {
447 error("%s: pipe out: %.100s", __func__, strerror(errno));
448 close(pin[0]);
449 close(pin[1]);
450 return -1;
451 }
452 if (pipe(perr) < 0) {
453 error("%s: pipe err: %.100s", __func__, strerror(errno));
454 close(pin[0]);
455 close(pin[1]);
456 close(pout[0]);
457 close(pout[1]);
458 return -1;
459 }
460#else
413 int inout[2], err[2]; 461 int inout[2], err[2];
462
414 /* Uses socket pairs to communicate with the program. */ 463 /* Uses socket pairs to communicate with the program. */
415 if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 || 464 if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
416 socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) 465 error("%s: socketpair #1: %.100s", __func__, strerror(errno));
417 packet_disconnect("Could not create socket pairs: %.100s", 466 return -1;
418 strerror(errno)); 467 }
419#endif /* USE_PIPES */ 468 if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
469 error("%s: socketpair #2: %.100s", __func__, strerror(errno));
470 close(inout[0]);
471 close(inout[1]);
472 return -1;
473 }
474#endif
475
420 if (s == NULL) 476 if (s == NULL)
421 fatal("do_exec_no_pty: no session"); 477 fatal("do_exec_no_pty: no session");
422 478
423 session_proctitle(s); 479 session_proctitle(s);
424 480
425#if defined(USE_PAM)
426 if (options.use_pam && !use_privsep)
427 do_pam_setcred(1);
428#endif /* USE_PAM */
429
430 /* Fork the child. */ 481 /* Fork the child. */
431 if ((pid = fork()) == 0) { 482 switch ((pid = fork())) {
483 case -1:
484 error("%s: fork: %.100s", __func__, strerror(errno));
485#ifdef USE_PIPES
486 close(pin[0]);
487 close(pin[1]);
488 close(pout[0]);
489 close(pout[1]);
490 close(perr[0]);
491 close(perr[1]);
492#else
493 close(inout[0]);
494 close(inout[1]);
495 close(err[0]);
496 close(err[1]);
497#endif
498 return -1;
499 case 0:
432 is_child = 1; 500 is_child = 1;
433 501
434 /* Child. Reinitialize the log since the pid has changed. */ 502 /* Child. Reinitialize the log since the pid has changed. */
435 log_init(__progname, options.log_level, options.log_facility, log_stderr); 503 log_init(__progname, options.log_level,
504 options.log_facility, log_stderr);
436 505
437 /* 506 /*
438 * Create a new session and process group since the 4.4BSD 507 * Create a new session and process group since the 4.4BSD
@@ -462,7 +531,7 @@ do_exec_no_pty(Session *s, const char *command)
462 if (dup2(perr[1], 2) < 0) 531 if (dup2(perr[1], 2) < 0)
463 perror("dup2 stderr"); 532 perror("dup2 stderr");
464 close(perr[1]); 533 close(perr[1]);
465#else /* USE_PIPES */ 534#else
466 /* 535 /*
467 * Redirect stdin, stdout, and stderr. Stdin and stdout will 536 * Redirect stdin, stdout, and stderr. Stdin and stdout will
468 * use the same socket, as some programs (particularly rdist) 537 * use the same socket, as some programs (particularly rdist)
@@ -472,11 +541,14 @@ do_exec_no_pty(Session *s, const char *command)
472 close(err[1]); 541 close(err[1]);
473 if (dup2(inout[0], 0) < 0) /* stdin */ 542 if (dup2(inout[0], 0) < 0) /* stdin */
474 perror("dup2 stdin"); 543 perror("dup2 stdin");
475 if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */ 544 if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */
476 perror("dup2 stdout"); 545 perror("dup2 stdout");
546 close(inout[0]);
477 if (dup2(err[0], 2) < 0) /* stderr */ 547 if (dup2(err[0], 2) < 0) /* stderr */
478 perror("dup2 stderr"); 548 perror("dup2 stderr");
479#endif /* USE_PIPES */ 549 close(err[0]);
550#endif
551
480 552
481#ifdef _UNICOS 553#ifdef _UNICOS
482 cray_init_job(s->pw); /* set up cray jid and tmpdir */ 554 cray_init_job(s->pw); /* set up cray jid and tmpdir */
@@ -485,7 +557,10 @@ do_exec_no_pty(Session *s, const char *command)
485 /* Do processing for the child (exec command etc). */ 557 /* Do processing for the child (exec command etc). */
486 do_child(s, command); 558 do_child(s, command);
487 /* NOTREACHED */ 559 /* NOTREACHED */
560 default:
561 break;
488 } 562 }
563
489#ifdef _UNICOS 564#ifdef _UNICOS
490 signal(WJSIGNAL, cray_job_termination_handler); 565 signal(WJSIGNAL, cray_job_termination_handler);
491#endif /* _UNICOS */ 566#endif /* _UNICOS */
@@ -493,11 +568,18 @@ do_exec_no_pty(Session *s, const char *command)
493 if (is_winnt) 568 if (is_winnt)
494 cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); 569 cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
495#endif 570#endif
496 if (pid < 0) 571
497 packet_disconnect("fork failed: %.100s", strerror(errno));
498 s->pid = pid; 572 s->pid = pid;
499 /* Set interactive/non-interactive mode. */ 573 /* Set interactive/non-interactive mode. */
500 packet_set_interactive(s->display != NULL); 574 packet_set_interactive(s->display != NULL);
575
576 /*
577 * Clear loginmsg, since it's the child's responsibility to display
578 * it to the user, otherwise multiple sessions may accumulate
579 * multiple copies of the login messages.
580 */
581 buffer_clear(&loginmsg);
582
501#ifdef USE_PIPES 583#ifdef USE_PIPES
502 /* We are the parent. Close the child sides of the pipes. */ 584 /* We are the parent. Close the child sides of the pipes. */
503 close(pin[0]); 585 close(pin[0]);
@@ -509,35 +591,32 @@ do_exec_no_pty(Session *s, const char *command)
509 close(perr[0]); 591 close(perr[0]);
510 perr[0] = -1; 592 perr[0] = -1;
511 } 593 }
512 session_set_fds(s, pin[1], pout[0], perr[0]); 594 session_set_fds(s, pin[1], pout[0], perr[0], 0);
513 } else { 595 } else {
514 /* Enter the interactive session. */ 596 /* Enter the interactive session. */
515 server_loop(pid, pin[1], pout[0], perr[0]); 597 server_loop(pid, pin[1], pout[0], perr[0]);
516 /* server_loop has closed pin[1], pout[0], and perr[0]. */ 598 /* server_loop has closed pin[1], pout[0], and perr[0]. */
517 } 599 }
518#else /* USE_PIPES */ 600#else
519 /* We are the parent. Close the child sides of the socket pairs. */ 601 /* We are the parent. Close the child sides of the socket pairs. */
520 close(inout[0]); 602 close(inout[0]);
521 close(err[0]); 603 close(err[0]);
522 604
523 /* 605 /*
524 * Clear loginmsg, since it's the child's responsibility to display
525 * it to the user, otherwise multiple sessions may accumulate
526 * multiple copies of the login messages.
527 */
528 buffer_clear(&loginmsg);
529
530 /*
531 * Enter the interactive session. Note: server_loop must be able to 606 * Enter the interactive session. Note: server_loop must be able to
532 * handle the case that fdin and fdout are the same. 607 * handle the case that fdin and fdout are the same.
533 */ 608 */
534 if (compat20) { 609 if (compat20) {
535 session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]); 610 session_set_fds(s, inout[1], inout[1],
611 s->is_subsystem ? -1 : err[1], 0);
612 if (s->is_subsystem)
613 close(err[1]);
536 } else { 614 } else {
537 server_loop(pid, inout[1], inout[1], err[1]); 615 server_loop(pid, inout[1], inout[1], err[1]);
538 /* server_loop has closed inout[1] and err[1]. */ 616 /* server_loop has closed inout[1] and err[1]. */
539 } 617 }
540#endif /* USE_PIPES */ 618#endif
619 return 0;
541} 620}
542 621
543/* 622/*
@@ -546,7 +625,7 @@ do_exec_no_pty(Session *s, const char *command)
546 * setting up file descriptors, controlling tty, updating wtmp, utmp, 625 * setting up file descriptors, controlling tty, updating wtmp, utmp,
547 * lastlog, and other such operations. 626 * lastlog, and other such operations.
548 */ 627 */
549void 628int
550do_exec_pty(Session *s, const char *command) 629do_exec_pty(Session *s, const char *command)
551{ 630{
552 int fdout, ptyfd, ttyfd, ptymaster; 631 int fdout, ptyfd, ttyfd, ptymaster;
@@ -557,20 +636,46 @@ do_exec_pty(Session *s, const char *command)
557 ptyfd = s->ptyfd; 636 ptyfd = s->ptyfd;
558 ttyfd = s->ttyfd; 637 ttyfd = s->ttyfd;
559 638
560#if defined(USE_PAM) 639 /*
561 if (options.use_pam) { 640 * Create another descriptor of the pty master side for use as the
562 do_pam_set_tty(s->tty); 641 * standard input. We could use the original descriptor, but this
563 if (!use_privsep) 642 * simplifies code in server_loop. The descriptor is bidirectional.
564 do_pam_setcred(1); 643 * Do this before forking (and cleanup in the child) so as to
644 * detect and gracefully fail out-of-fd conditions.
645 */
646 if ((fdout = dup(ptyfd)) < 0) {
647 error("%s: dup #1: %s", __func__, strerror(errno));
648 close(ttyfd);
649 close(ptyfd);
650 return -1;
651 }
652 /* we keep a reference to the pty master */
653 if ((ptymaster = dup(ptyfd)) < 0) {
654 error("%s: dup #2: %s", __func__, strerror(errno));
655 close(ttyfd);
656 close(ptyfd);
657 close(fdout);
658 return -1;
565 } 659 }
566#endif
567 660
568 /* Fork the child. */ 661 /* Fork the child. */
569 if ((pid = fork()) == 0) { 662 switch ((pid = fork())) {
663 case -1:
664 error("%s: fork: %.100s", __func__, strerror(errno));
665 close(fdout);
666 close(ptymaster);
667 close(ttyfd);
668 close(ptyfd);
669 return -1;
670 case 0:
570 is_child = 1; 671 is_child = 1;
571 672
673 close(fdout);
674 close(ptymaster);
675
572 /* Child. Reinitialize the log because the pid has changed. */ 676 /* Child. Reinitialize the log because the pid has changed. */
573 log_init(__progname, options.log_level, options.log_facility, log_stderr); 677 log_init(__progname, options.log_level,
678 options.log_facility, log_stderr);
574 /* Close the master side of the pseudo tty. */ 679 /* Close the master side of the pseudo tty. */
575 close(ptyfd); 680 close(ptyfd);
576 681
@@ -601,11 +706,16 @@ do_exec_pty(Session *s, const char *command)
601 do_pre_login(s); 706 do_pre_login(s);
602# endif 707# endif
603#endif 708#endif
604 709 /*
605 /* Do common processing for the child, such as execing the command. */ 710 * Do common processing for the child, such as execing
606 do_child(s, command); 711 * the command.
607 /* NOTREACHED */ 712 */
713 do_child(s, command);
714 /* NOTREACHED */
715 default:
716 break;
608 } 717 }
718
609#ifdef _UNICOS 719#ifdef _UNICOS
610 signal(WJSIGNAL, cray_job_termination_handler); 720 signal(WJSIGNAL, cray_job_termination_handler);
611#endif /* _UNICOS */ 721#endif /* _UNICOS */
@@ -613,36 +723,22 @@ do_exec_pty(Session *s, const char *command)
613 if (is_winnt) 723 if (is_winnt)
614 cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); 724 cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
615#endif 725#endif
616 if (pid < 0) 726
617 packet_disconnect("fork failed: %.100s", strerror(errno));
618 s->pid = pid; 727 s->pid = pid;
619 728
620 /* Parent. Close the slave side of the pseudo tty. */ 729 /* Parent. Close the slave side of the pseudo tty. */
621 close(ttyfd); 730 close(ttyfd);
622 731
623 /*
624 * Create another descriptor of the pty master side for use as the
625 * standard input. We could use the original descriptor, but this
626 * simplifies code in server_loop. The descriptor is bidirectional.
627 */
628 fdout = dup(ptyfd);
629 if (fdout < 0)
630 packet_disconnect("dup #1 failed: %.100s", strerror(errno));
631
632 /* we keep a reference to the pty master */
633 ptymaster = dup(ptyfd);
634 if (ptymaster < 0)
635 packet_disconnect("dup #2 failed: %.100s", strerror(errno));
636 s->ptymaster = ptymaster;
637
638 /* Enter interactive session. */ 732 /* Enter interactive session. */
733 s->ptymaster = ptymaster;
639 packet_set_interactive(1); 734 packet_set_interactive(1);
640 if (compat20) { 735 if (compat20) {
641 session_set_fds(s, ptyfd, fdout, -1); 736 session_set_fds(s, ptyfd, fdout, -1, 1);
642 } else { 737 } else {
643 server_loop(pid, ptyfd, fdout, -1); 738 server_loop(pid, ptyfd, fdout, -1);
644 /* server_loop _has_ closed ptyfd and fdout. */ 739 /* server_loop _has_ closed ptyfd and fdout. */
645 } 740 }
741 return 0;
646} 742}
647 743
648#ifdef LOGIN_NEEDS_UTMPX 744#ifdef LOGIN_NEEDS_UTMPX
@@ -677,16 +773,26 @@ do_pre_login(Session *s)
677 * This is called to fork and execute a command. If another command is 773 * This is called to fork and execute a command. If another command is
678 * to be forced, execute that instead. 774 * to be forced, execute that instead.
679 */ 775 */
680void 776int
681do_exec(Session *s, const char *command) 777do_exec(Session *s, const char *command)
682{ 778{
779 int ret;
780
683 if (options.adm_forced_command) { 781 if (options.adm_forced_command) {
684 original_command = command; 782 original_command = command;
685 command = options.adm_forced_command; 783 command = options.adm_forced_command;
784 if (strcmp(INTERNAL_SFTP_NAME, command) == 0)
785 s->is_subsystem = SUBSYSTEM_INT_SFTP;
786 else if (s->is_subsystem)
787 s->is_subsystem = SUBSYSTEM_EXT;
686 debug("Forced command (config) '%.900s'", command); 788 debug("Forced command (config) '%.900s'", command);
687 } else if (forced_command) { 789 } else if (forced_command) {
688 original_command = command; 790 original_command = command;
689 command = forced_command; 791 command = forced_command;
792 if (strcmp(INTERNAL_SFTP_NAME, command) == 0)
793 s->is_subsystem = SUBSYSTEM_INT_SFTP;
794 else if (s->is_subsystem)
795 s->is_subsystem = SUBSYSTEM_EXT;
690 debug("Forced command (key option) '%.900s'", command); 796 debug("Forced command (key option) '%.900s'", command);
691 } 797 }
692 798
@@ -701,11 +807,10 @@ do_exec(Session *s, const char *command)
701 PRIVSEP(audit_run_command(shell)); 807 PRIVSEP(audit_run_command(shell));
702 } 808 }
703#endif 809#endif
704
705 if (s->ttyfd != -1) 810 if (s->ttyfd != -1)
706 do_exec_pty(s, command); 811 ret = do_exec_pty(s, command);
707 else 812 else
708 do_exec_no_pty(s, command); 813 ret = do_exec_no_pty(s, command);
709 814
710 original_command = NULL; 815 original_command = NULL;
711 816
@@ -715,6 +820,8 @@ do_exec(Session *s, const char *command)
715 * multiple copies of the login messages. 820 * multiple copies of the login messages.
716 */ 821 */
717 buffer_clear(&loginmsg); 822 buffer_clear(&loginmsg);
823
824 return ret;
718} 825}
719 826
720/* administrative, login(1)-like work */ 827/* administrative, login(1)-like work */
@@ -897,8 +1004,9 @@ read_environment_file(char ***env, u_int *envsize,
897 ; 1004 ;
898 if (!*cp || *cp == '#' || *cp == '\n') 1005 if (!*cp || *cp == '#' || *cp == '\n')
899 continue; 1006 continue;
900 if (strchr(cp, '\n')) 1007
901 *strchr(cp, '\n') = '\0'; 1008 cp[strcspn(cp, "\n")] = '\0';
1009
902 value = strchr(cp, '='); 1010 value = strchr(cp, '=');
903 if (value == NULL) { 1011 if (value == NULL) {
904 fprintf(stderr, "Bad line %u in %.100s\n", lineno, 1012 fprintf(stderr, "Bad line %u in %.100s\n", lineno,
@@ -1203,7 +1311,7 @@ do_rc_files(Session *s, const char *shell)
1203 1311
1204 /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */ 1312 /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
1205 if (!s->is_subsystem && options.adm_forced_command == NULL && 1313 if (!s->is_subsystem && options.adm_forced_command == NULL &&
1206 !no_user_rc && (stat(_PATH_SSH_USER_RC, &st) >= 0)) { 1314 !no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) {
1207 snprintf(cmd, sizeof cmd, "%s -c '%s %s'", 1315 snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
1208 shell, _PATH_BSHELL, _PATH_SSH_USER_RC); 1316 shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
1209 if (debug_flag) 1317 if (debug_flag)
@@ -1284,10 +1392,72 @@ do_nologin(struct passwd *pw)
1284 } 1392 }
1285} 1393}
1286 1394
1395/*
1396 * Chroot into a directory after checking it for safety: all path components
1397 * must be root-owned directories with strict permissions.
1398 */
1399static void
1400safely_chroot(const char *path, uid_t uid)
1401{
1402 const char *cp;
1403 char component[MAXPATHLEN];
1404 struct stat st;
1405
1406 if (*path != '/')
1407 fatal("chroot path does not begin at root");
1408 if (strlen(path) >= sizeof(component))
1409 fatal("chroot path too long");
1410
1411 /*
1412 * Descend the path, checking that each component is a
1413 * root-owned directory with strict permissions.
1414 */
1415 for (cp = path; cp != NULL;) {
1416 if ((cp = strchr(cp, '/')) == NULL)
1417 strlcpy(component, path, sizeof(component));
1418 else {
1419 cp++;
1420 memcpy(component, path, cp - path);
1421 component[cp - path] = '\0';
1422 }
1423
1424 debug3("%s: checking '%s'", __func__, component);
1425
1426 if (stat(component, &st) != 0)
1427 fatal("%s: stat(\"%s\"): %s", __func__,
1428 component, strerror(errno));
1429 if (st.st_uid != 0 || (st.st_mode & 022) != 0)
1430 fatal("bad ownership or modes for chroot "
1431 "directory %s\"%s\"",
1432 cp == NULL ? "" : "component ", component);
1433 if (!S_ISDIR(st.st_mode))
1434 fatal("chroot path %s\"%s\" is not a directory",
1435 cp == NULL ? "" : "component ", component);
1436
1437 }
1438
1439 if (chdir(path) == -1)
1440 fatal("Unable to chdir to chroot path \"%s\": "
1441 "%s", path, strerror(errno));
1442 if (chroot(path) == -1)
1443 fatal("chroot(\"%s\"): %s", path, strerror(errno));
1444 if (chdir("/") == -1)
1445 fatal("%s: chdir(/) after chroot: %s",
1446 __func__, strerror(errno));
1447 verbose("Changed root directory to \"%s\"", path);
1448}
1449
1287/* Set login name, uid, gid, and groups. */ 1450/* Set login name, uid, gid, and groups. */
1288void 1451void
1289do_setusercontext(struct passwd *pw) 1452do_setusercontext(struct passwd *pw)
1290{ 1453{
1454 char *chroot_path, *tmp;
1455
1456#ifdef WITH_SELINUX
1457 /* Cache selinux status for later use */
1458 (void)ssh_selinux_enabled();
1459#endif
1460
1291#ifndef HAVE_CYGWIN 1461#ifndef HAVE_CYGWIN
1292 if (getuid() == 0 || geteuid() == 0) 1462 if (getuid() == 0 || geteuid() == 0)
1293#endif /* HAVE_CYGWIN */ 1463#endif /* HAVE_CYGWIN */
@@ -1301,21 +1471,13 @@ do_setusercontext(struct passwd *pw)
1301# ifdef __bsdi__ 1471# ifdef __bsdi__
1302 setpgid(0, 0); 1472 setpgid(0, 0);
1303# endif 1473# endif
1304#ifdef GSSAPI
1305 if (options.gss_authentication) {
1306 temporarily_use_uid(pw);
1307 ssh_gssapi_storecreds();
1308 restore_uid();
1309 }
1310#endif
1311# ifdef USE_PAM 1474# ifdef USE_PAM
1312 if (options.use_pam) { 1475 if (options.use_pam) {
1313 do_pam_session();
1314 do_pam_setcred(use_privsep); 1476 do_pam_setcred(use_privsep);
1315 } 1477 }
1316# endif /* USE_PAM */ 1478# endif /* USE_PAM */
1317 if (setusercontext(lc, pw, pw->pw_uid, 1479 if (setusercontext(lc, pw, pw->pw_uid,
1318 (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { 1480 (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
1319 perror("unable to set user context"); 1481 perror("unable to set user context");
1320 exit(1); 1482 exit(1);
1321 } 1483 }
@@ -1338,13 +1500,6 @@ do_setusercontext(struct passwd *pw)
1338 exit(1); 1500 exit(1);
1339 } 1501 }
1340 endgrent(); 1502 endgrent();
1341#ifdef GSSAPI
1342 if (options.gss_authentication) {
1343 temporarily_use_uid(pw);
1344 ssh_gssapi_storecreds();
1345 restore_uid();
1346 }
1347#endif
1348# ifdef USE_PAM 1503# ifdef USE_PAM
1349 /* 1504 /*
1350 * PAM credentials may take the form of supplementary groups. 1505 * PAM credentials may take the form of supplementary groups.
@@ -1352,21 +1507,39 @@ do_setusercontext(struct passwd *pw)
1352 * Reestablish them here. 1507 * Reestablish them here.
1353 */ 1508 */
1354 if (options.use_pam) { 1509 if (options.use_pam) {
1355 do_pam_session();
1356 do_pam_setcred(use_privsep); 1510 do_pam_setcred(use_privsep);
1357 } 1511 }
1358# endif /* USE_PAM */ 1512# endif /* USE_PAM */
1359# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) 1513# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)
1360 irix_setusercontext(pw); 1514 irix_setusercontext(pw);
1361# endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ 1515# endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
1362# ifdef _AIX 1516# ifdef _AIX
1363 aix_usrinfo(pw); 1517 aix_usrinfo(pw);
1364# endif /* _AIX */ 1518# endif /* _AIX */
1365#ifdef USE_LIBIAF 1519# ifdef USE_LIBIAF
1366 if (set_id(pw->pw_name) != 0) { 1520 if (set_id(pw->pw_name) != 0) {
1367 exit(1); 1521 exit(1);
1368 } 1522 }
1369#endif /* USE_LIBIAF */ 1523# endif /* USE_LIBIAF */
1524#endif
1525
1526 if (options.chroot_directory != NULL &&
1527 strcasecmp(options.chroot_directory, "none") != 0) {
1528 tmp = tilde_expand_filename(options.chroot_directory,
1529 pw->pw_uid);
1530 chroot_path = percent_expand(tmp, "h", pw->pw_dir,
1531 "u", pw->pw_name, (char *)NULL);
1532 safely_chroot(chroot_path, pw->pw_uid);
1533 free(tmp);
1534 free(chroot_path);
1535 }
1536
1537#ifdef HAVE_LOGIN_CAP
1538 if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) {
1539 perror("unable to set user context (setuser)");
1540 exit(1);
1541 }
1542#else
1370 /* Permanently switch to the desired uid. */ 1543 /* Permanently switch to the desired uid. */
1371 permanently_set_uid(pw); 1544 permanently_set_uid(pw);
1372#endif 1545#endif
@@ -1465,14 +1638,16 @@ child_close_fds(void)
1465 * environment, closing extra file descriptors, setting the user and group 1638 * environment, closing extra file descriptors, setting the user and group
1466 * ids, and executing the command or shell. 1639 * ids, and executing the command or shell.
1467 */ 1640 */
1641#define ARGV_MAX 10
1468void 1642void
1469do_child(Session *s, const char *command) 1643do_child(Session *s, const char *command)
1470{ 1644{
1471 extern char **environ; 1645 extern char **environ;
1472 char **env; 1646 char **env;
1473 char *argv[10]; 1647 char *argv[ARGV_MAX];
1474 const char *shell, *shell0, *hostname = NULL; 1648 const char *shell, *shell0, *hostname = NULL;
1475 struct passwd *pw = s->pw; 1649 struct passwd *pw = s->pw;
1650 int r = 0;
1476 1651
1477 /* remove hostkey from the child's memory */ 1652 /* remove hostkey from the child's memory */
1478 destroy_sensitive_data(); 1653 destroy_sensitive_data();
@@ -1588,20 +1763,42 @@ do_child(Session *s, const char *command)
1588 1763
1589 /* Change current directory to the user's home directory. */ 1764 /* Change current directory to the user's home directory. */
1590 if (chdir(pw->pw_dir) < 0) { 1765 if (chdir(pw->pw_dir) < 0) {
1591 fprintf(stderr, "Could not chdir to home directory %s: %s\n", 1766 /* Suppress missing homedir warning for chroot case */
1592 pw->pw_dir, strerror(errno));
1593#ifdef HAVE_LOGIN_CAP 1767#ifdef HAVE_LOGIN_CAP
1594 if (login_getcapbool(lc, "requirehome", 0)) 1768 r = login_getcapbool(lc, "requirehome", 0);
1595 exit(1);
1596#endif 1769#endif
1770 if (r || options.chroot_directory == NULL)
1771 fprintf(stderr, "Could not chdir to home "
1772 "directory %s: %s\n", pw->pw_dir,
1773 strerror(errno));
1774 if (r)
1775 exit(1);
1597 } 1776 }
1598 1777
1778 closefrom(STDERR_FILENO + 1);
1779
1599 if (!options.use_login) 1780 if (!options.use_login)
1600 do_rc_files(s, shell); 1781 do_rc_files(s, shell);
1601 1782
1602 /* restore SIGPIPE for child */ 1783 /* restore SIGPIPE for child */
1603 signal(SIGPIPE, SIG_DFL); 1784 signal(SIGPIPE, SIG_DFL);
1604 1785
1786 if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {
1787 extern int optind, optreset;
1788 int i;
1789 char *p, *args;
1790
1791 setproctitle("%s@internal-sftp-server", s->pw->pw_name);
1792 args = strdup(command ? command : "sftp-server");
1793 for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " ")))
1794 if (i < ARGV_MAX - 1)
1795 argv[i++] = p;
1796 argv[i] = NULL;
1797 optind = optreset = 1;
1798 __progname = argv[0];
1799 exit(sftp_server_main(i, argv, s->pw));
1800 }
1801
1605 if (options.use_login) { 1802 if (options.use_login) {
1606 launch_login(pw, hostname); 1803 launch_login(pw, hostname);
1607 /* NEVERREACHED */ 1804 /* NEVERREACHED */
@@ -1653,43 +1850,79 @@ do_child(Session *s, const char *command)
1653 exit(1); 1850 exit(1);
1654} 1851}
1655 1852
1853void
1854session_unused(int id)
1855{
1856 debug3("%s: session id %d unused", __func__, id);
1857 if (id >= options.max_sessions ||
1858 id >= sessions_nalloc) {
1859 fatal("%s: insane session id %d (max %d nalloc %d)",
1860 __func__, id, options.max_sessions, sessions_nalloc);
1861 }
1862 bzero(&sessions[id], sizeof(*sessions));
1863 sessions[id].self = id;
1864 sessions[id].used = 0;
1865 sessions[id].chanid = -1;
1866 sessions[id].ptyfd = -1;
1867 sessions[id].ttyfd = -1;
1868 sessions[id].ptymaster = -1;
1869 sessions[id].x11_chanids = NULL;
1870 sessions[id].next_unused = sessions_first_unused;
1871 sessions_first_unused = id;
1872}
1873
1656Session * 1874Session *
1657session_new(void) 1875session_new(void)
1658{ 1876{
1659 int i; 1877 Session *s, *tmp;
1660 static int did_init = 0; 1878
1661 if (!did_init) { 1879 if (sessions_first_unused == -1) {
1662 debug("session_new: init"); 1880 if (sessions_nalloc >= options.max_sessions)
1663 for (i = 0; i < MAX_SESSIONS; i++) { 1881 return NULL;
1664 sessions[i].used = 0; 1882 debug2("%s: allocate (allocated %d max %d)",
1883 __func__, sessions_nalloc, options.max_sessions);
1884 tmp = xrealloc(sessions, sessions_nalloc + 1,
1885 sizeof(*sessions));
1886 if (tmp == NULL) {
1887 error("%s: cannot allocate %d sessions",
1888 __func__, sessions_nalloc + 1);
1889 return NULL;
1665 } 1890 }
1666 did_init = 1; 1891 sessions = tmp;
1892 session_unused(sessions_nalloc++);
1667 } 1893 }
1668 for (i = 0; i < MAX_SESSIONS; i++) { 1894
1669 Session *s = &sessions[i]; 1895 if (sessions_first_unused >= sessions_nalloc ||
1670 if (! s->used) { 1896 sessions_first_unused < 0) {
1671 memset(s, 0, sizeof(*s)); 1897 fatal("%s: insane first_unused %d max %d nalloc %d",
1672 s->chanid = -1; 1898 __func__, sessions_first_unused, options.max_sessions,
1673 s->ptyfd = -1; 1899 sessions_nalloc);
1674 s->ttyfd = -1;
1675 s->used = 1;
1676 s->self = i;
1677 s->x11_chanids = NULL;
1678 debug("session_new: session %d", i);
1679 return s;
1680 }
1681 } 1900 }
1682 return NULL; 1901
1902 s = &sessions[sessions_first_unused];
1903 if (s->used) {
1904 fatal("%s: session %d already used",
1905 __func__, sessions_first_unused);
1906 }
1907 sessions_first_unused = s->next_unused;
1908 s->used = 1;
1909 s->next_unused = -1;
1910 debug("session_new: session %d", s->self);
1911
1912 return s;
1683} 1913}
1684 1914
1685static void 1915static void
1686session_dump(void) 1916session_dump(void)
1687{ 1917{
1688 int i; 1918 int i;
1689 for (i = 0; i < MAX_SESSIONS; i++) { 1919 for (i = 0; i < sessions_nalloc; i++) {
1690 Session *s = &sessions[i]; 1920 Session *s = &sessions[i];
1691 debug("dump: used %d session %d %p channel %d pid %ld", 1921
1922 debug("dump: used %d next_unused %d session %d %p "
1923 "channel %d pid %ld",
1692 s->used, 1924 s->used,
1925 s->next_unused,
1693 s->self, 1926 s->self,
1694 s, 1927 s,
1695 s->chanid, 1928 s->chanid,
@@ -1719,7 +1952,7 @@ Session *
1719session_by_tty(char *tty) 1952session_by_tty(char *tty)
1720{ 1953{
1721 int i; 1954 int i;
1722 for (i = 0; i < MAX_SESSIONS; i++) { 1955 for (i = 0; i < sessions_nalloc; i++) {
1723 Session *s = &sessions[i]; 1956 Session *s = &sessions[i];
1724 if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) { 1957 if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
1725 debug("session_by_tty: session %d tty %s", i, tty); 1958 debug("session_by_tty: session %d tty %s", i, tty);
@@ -1735,10 +1968,11 @@ static Session *
1735session_by_channel(int id) 1968session_by_channel(int id)
1736{ 1969{
1737 int i; 1970 int i;
1738 for (i = 0; i < MAX_SESSIONS; i++) { 1971 for (i = 0; i < sessions_nalloc; i++) {
1739 Session *s = &sessions[i]; 1972 Session *s = &sessions[i];
1740 if (s->used && s->chanid == id) { 1973 if (s->used && s->chanid == id) {
1741 debug("session_by_channel: session %d channel %d", i, id); 1974 debug("session_by_channel: session %d channel %d",
1975 i, id);
1742 return s; 1976 return s;
1743 } 1977 }
1744 } 1978 }
@@ -1752,7 +1986,7 @@ session_by_x11_channel(int id)
1752{ 1986{
1753 int i, j; 1987 int i, j;
1754 1988
1755 for (i = 0; i < MAX_SESSIONS; i++) { 1989 for (i = 0; i < sessions_nalloc; i++) {
1756 Session *s = &sessions[i]; 1990 Session *s = &sessions[i];
1757 1991
1758 if (s->x11_chanids == NULL || !s->used) 1992 if (s->x11_chanids == NULL || !s->used)
@@ -1775,7 +2009,7 @@ session_by_pid(pid_t pid)
1775{ 2009{
1776 int i; 2010 int i;
1777 debug("session_by_pid: pid %ld", (long)pid); 2011 debug("session_by_pid: pid %ld", (long)pid);
1778 for (i = 0; i < MAX_SESSIONS; i++) { 2012 for (i = 0; i < sessions_nalloc; i++) {
1779 Session *s = &sessions[i]; 2013 Session *s = &sessions[i];
1780 if (s->used && s->pid == pid) 2014 if (s->used && s->pid == pid)
1781 return s; 2015 return s;
@@ -1831,7 +2065,8 @@ session_pty_req(Session *s)
1831 2065
1832 /* Allocate a pty and open it. */ 2066 /* Allocate a pty and open it. */
1833 debug("Allocating pty."); 2067 debug("Allocating pty.");
1834 if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) { 2068 if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
2069 sizeof(s->tty)))) {
1835 if (s->term) 2070 if (s->term)
1836 xfree(s->term); 2071 xfree(s->term);
1837 s->term = NULL; 2072 s->term = NULL;
@@ -1874,15 +2109,17 @@ session_subsystem_req(Session *s)
1874 if (strcmp(subsys, options.subsystem_name[i]) == 0) { 2109 if (strcmp(subsys, options.subsystem_name[i]) == 0) {
1875 prog = options.subsystem_command[i]; 2110 prog = options.subsystem_command[i];
1876 cmd = options.subsystem_args[i]; 2111 cmd = options.subsystem_args[i];
1877 if (stat(prog, &st) < 0) { 2112 if (!strcmp(INTERNAL_SFTP_NAME, prog)) {
2113 s->is_subsystem = SUBSYSTEM_INT_SFTP;
2114 } else if (stat(prog, &st) < 0) {
1878 error("subsystem: cannot stat %s: %s", prog, 2115 error("subsystem: cannot stat %s: %s", prog,
1879 strerror(errno)); 2116 strerror(errno));
1880 break; 2117 break;
2118 } else {
2119 s->is_subsystem = SUBSYSTEM_EXT;
1881 } 2120 }
1882 debug("subsystem: exec() %s", cmd); 2121 debug("subsystem: exec() %s", cmd);
1883 s->is_subsystem = 1; 2122 success = do_exec(s, cmd) == 0;
1884 do_exec(s, cmd);
1885 success = 1;
1886 break; 2123 break;
1887 } 2124 }
1888 } 2125 }
@@ -1925,19 +2162,19 @@ static int
1925session_shell_req(Session *s) 2162session_shell_req(Session *s)
1926{ 2163{
1927 packet_check_eom(); 2164 packet_check_eom();
1928 do_exec(s, NULL); 2165 return do_exec(s, NULL) == 0;
1929 return 1;
1930} 2166}
1931 2167
1932static int 2168static int
1933session_exec_req(Session *s) 2169session_exec_req(Session *s)
1934{ 2170{
1935 u_int len; 2171 u_int len, success;
2172
1936 char *command = packet_get_string(&len); 2173 char *command = packet_get_string(&len);
1937 packet_check_eom(); 2174 packet_check_eom();
1938 do_exec(s, command); 2175 success = do_exec(s, command) == 0;
1939 xfree(command); 2176 xfree(command);
1940 return 1; 2177 return success;
1941} 2178}
1942 2179
1943static int 2180static int
@@ -1947,8 +2184,7 @@ session_break_req(Session *s)
1947 packet_get_int(); /* ignored */ 2184 packet_get_int(); /* ignored */
1948 packet_check_eom(); 2185 packet_check_eom();
1949 2186
1950 if (s->ttyfd == -1 || 2187 if (s->ttyfd == -1 || tcsendbreak(s->ttyfd, 0) < 0)
1951 tcsendbreak(s->ttyfd, 0) < 0)
1952 return 0; 2188 return 0;
1953 return 1; 2189 return 1;
1954} 2190}
@@ -1993,7 +2229,7 @@ session_auth_agent_req(Session *s)
1993{ 2229{
1994 static int called = 0; 2230 static int called = 0;
1995 packet_check_eom(); 2231 packet_check_eom();
1996 if (no_agent_forwarding_flag) { 2232 if (no_agent_forwarding_flag || !options.allow_agent_forwarding) {
1997 debug("session_auth_agent_req: no_agent_forwarding_flag"); 2233 debug("session_auth_agent_req: no_agent_forwarding_flag");
1998 return 0; 2234 return 0;
1999 } 2235 }
@@ -2049,7 +2285,7 @@ session_input_channel_req(Channel *c, const char *rtype)
2049} 2285}
2050 2286
2051void 2287void
2052session_set_fds(Session *s, int fdin, int fdout, int fderr) 2288session_set_fds(Session *s, int fdin, int fdout, int fderr, int is_tty)
2053{ 2289{
2054 if (!compat20) 2290 if (!compat20)
2055 fatal("session_set_fds: called for proto != 2.0"); 2291 fatal("session_set_fds: called for proto != 2.0");
@@ -2062,8 +2298,7 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
2062 channel_set_fds(s->chanid, 2298 channel_set_fds(s->chanid,
2063 fdout, fdin, fderr, 2299 fdout, fdin, fderr,
2064 fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, 2300 fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
2065 1, 2301 1, is_tty, CHAN_SES_WINDOW_DEFAULT);
2066 CHAN_SES_WINDOW_DEFAULT);
2067} 2302}
2068 2303
2069/* 2304/*
@@ -2095,8 +2330,9 @@ session_pty_cleanup2(Session *s)
2095 * the pty cleanup, so that another process doesn't get this pty 2330 * the pty cleanup, so that another process doesn't get this pty
2096 * while we're still cleaning up. 2331 * while we're still cleaning up.
2097 */ 2332 */
2098 if (close(s->ptymaster) < 0) 2333 if (s->ptymaster != -1 && close(s->ptymaster) < 0)
2099 error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); 2334 error("close(s->ptymaster/%d): %s",
2335 s->ptymaster, strerror(errno));
2100 2336
2101 /* unlink pty from session */ 2337 /* unlink pty from session */
2102 s->ttyfd = -1; 2338 s->ttyfd = -1;
@@ -2204,7 +2440,7 @@ session_exit_message(Session *s, int status)
2204 channel_request_start(s->chanid, "exit-signal", 0); 2440 channel_request_start(s->chanid, "exit-signal", 0);
2205 packet_put_cstring(sig2name(WTERMSIG(status))); 2441 packet_put_cstring(sig2name(WTERMSIG(status)));
2206#ifdef WCOREDUMP 2442#ifdef WCOREDUMP
2207 packet_put_char(WCOREDUMP(status)); 2443 packet_put_char(WCOREDUMP(status)? 1 : 0);
2208#else /* WCOREDUMP */ 2444#else /* WCOREDUMP */
2209 packet_put_char(0); 2445 packet_put_char(0);
2210#endif /* WCOREDUMP */ 2446#endif /* WCOREDUMP */
@@ -2256,7 +2492,6 @@ session_close(Session *s)
2256 xfree(s->auth_data); 2492 xfree(s->auth_data);
2257 if (s->auth_proto) 2493 if (s->auth_proto)
2258 xfree(s->auth_proto); 2494 xfree(s->auth_proto);
2259 s->used = 0;
2260 if (s->env != NULL) { 2495 if (s->env != NULL) {
2261 for (i = 0; i < s->num_env; i++) { 2496 for (i = 0; i < s->num_env; i++) {
2262 xfree(s->env[i].name); 2497 xfree(s->env[i].name);
@@ -2265,6 +2500,7 @@ session_close(Session *s)
2265 xfree(s->env); 2500 xfree(s->env);
2266 } 2501 }
2267 session_proctitle(s); 2502 session_proctitle(s);
2503 session_unused(s->self);
2268} 2504}
2269 2505
2270void 2506void
@@ -2328,7 +2564,7 @@ void
2328session_destroy_all(void (*closefunc)(Session *)) 2564session_destroy_all(void (*closefunc)(Session *))
2329{ 2565{
2330 int i; 2566 int i;
2331 for (i = 0; i < MAX_SESSIONS; i++) { 2567 for (i = 0; i < sessions_nalloc; i++) {
2332 Session *s = &sessions[i]; 2568 Session *s = &sessions[i];
2333 if (s->used) { 2569 if (s->used) {
2334 if (closefunc != NULL) 2570 if (closefunc != NULL)
@@ -2347,7 +2583,7 @@ session_tty_list(void)
2347 char *cp; 2583 char *cp;
2348 2584
2349 buf[0] = '\0'; 2585 buf[0] = '\0';
2350 for (i = 0; i < MAX_SESSIONS; i++) { 2586 for (i = 0; i < sessions_nalloc; i++) {
2351 Session *s = &sessions[i]; 2587 Session *s = &sessions[i];
2352 if (s->used && s->ttyfd != -1) { 2588 if (s->used && s->ttyfd != -1) {
2353 2589