session.c 66.3 KB
Newer Older
1
/* $OpenBSD: session.c,v 1.269 2014/01/18 09:36:26 dtucker Exp $ */
2 3 4
/*
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 *                    All rights reserved
5 6 7 8 9 10 11
 *
 * As far as I am concerned, the code I have written for this software
 * can be used freely for any purpose.  Any derived versions of this
 * software must be clearly marked as such, and if the derived work is
 * incompatible with the protocol description in the RFC file, it must be
 * called by a name other than "ssh" or "Secure Shell".
 *
12
 * SSH2 support by Markus Friedl.
13
 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
 */
35 36

#include "includes.h"
37 38

#include <sys/types.h>
39
#include <sys/param.h>
40 41 42
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
43
#include <sys/socket.h>
44
#include <sys/un.h>
45
#include <sys/wait.h>
46

47 48
#include <arpa/inet.h>

49
#include <errno.h>
50
#include <fcntl.h>
51
#include <grp.h>
52
#ifdef HAVE_PATHS_H
53
#include <paths.h>
54
#endif
55
#include <pwd.h>
56
#include <signal.h>
57
#include <stdarg.h>
58
#include <stdio.h>
59
#include <stdlib.h>
60
#include <string.h>
61
#include <unistd.h>
62

63
#include "openbsd-compat/sys-queue.h"
64
#include "xmalloc.h"
65
#include "ssh.h"
66 67
#include "ssh1.h"
#include "ssh2.h"
68
#include "sshpty.h"
69 70
#include "packet.h"
#include "buffer.h"
71
#include "match.h"
72 73
#include "uidswap.h"
#include "compat.h"
74
#include "channels.h"
75 76 77 78 79 80
#include "key.h"
#include "cipher.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "hostfile.h"
81
#include "auth.h"
82
#include "auth-options.h"
83
#include "authfd.h"
84 85 86
#include "pathnames.h"
#include "log.h"
#include "servconf.h"
87
#include "sshlogin.h"
88 89
#include "serverloop.h"
#include "canohost.h"
90
#include "misc.h"
91
#include "session.h"
92
#include "kex.h"
93
#include "monitor_wrap.h"
94
#include "sftp.h"
95

96
#if defined(KRB5) && defined(USE_AFS)
97 98 99
#include <kafs.h>
#endif

100 101 102 103
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif

104 105 106 107 108 109
#define IS_INTERNAL_SFTP(c) \
	(!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
	 (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
	  c[sizeof(INTERNAL_SFTP_NAME) - 1] == ' ' || \
	  c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t'))

110 111 112
/* func */

Session *session_new(void);
113
void	session_set_fds(Session *, int, int, int, int, int);
114
void	session_pty_cleanup(Session *);
115 116
void	session_proctitle(Session *);
int	session_setup_x11fwd(Session *);
117 118 119
int	do_exec_pty(Session *, const char *);
int	do_exec_no_pty(Session *, const char *);
int	do_exec(Session *, const char *);
120
void	do_login(Session *, const char *);
121 122 123
#ifdef LOGIN_NEEDS_UTMPX
static void	do_pre_login(Session *s);
#endif
124
void	do_child(Session *, const char *);
125
void	do_motd(void);
126
int	check_quietlogin(Session *, const char *);
127

128 129
static void do_authenticated1(Authctxt *);
static void do_authenticated2(Authctxt *);
130

131
static int session_pty_req(Session *);
132

133 134 135 136 137
/* import */
extern ServerOptions options;
extern char *__progname;
extern int log_stderr;
extern int debug_flag;
138
extern u_int utmp_len;
139
extern int startup_pipe;
140
extern void destroy_sensitive_data(void);
141
extern Buffer loginmsg;
142

Damien Miller's avatar
Damien Miller committed
143
/* original command from peer. */
144
const char *original_command = NULL;
Damien Miller's avatar
Damien Miller committed
145

146
/* data */
147 148 149
static int sessions_first_unused = -1;
static int sessions_nalloc = 0;
static Session *sessions = NULL;
150

151 152 153 154
#define SUBSYSTEM_NONE			0
#define SUBSYSTEM_EXT			1
#define SUBSYSTEM_INT_SFTP		2
#define SUBSYSTEM_INT_SFTP_ERROR	3
155

156
#ifdef HAVE_LOGIN_CAP
157
login_cap_t *lc;
158 159
#endif

160 161
static int is_child = 0;

162 163 164 165 166 167 168
/* Name and directory of socket for authentication agent forwarding. */
static char *auth_sock_name = NULL;
static char *auth_sock_dir = NULL;

/* removes the agent forwarding socket */

static void
169
auth_sock_cleanup_proc(struct passwd *pw)
170 171 172 173 174 175 176 177 178 179 180 181 182 183
{
	if (auth_sock_name != NULL) {
		temporarily_use_uid(pw);
		unlink(auth_sock_name);
		rmdir(auth_sock_dir);
		auth_sock_name = NULL;
		restore_uid();
	}
}

static int
auth_input_request_forwarding(struct passwd * pw)
{
	Channel *nc;
184
	int sock = -1;
185 186 187 188 189 190 191 192 193 194 195
	struct sockaddr_un sunaddr;

	if (auth_sock_name != NULL) {
		error("authentication forwarding requested twice.");
		return 0;
	}

	/* Temporarily drop privileged uid for mkdir/bind. */
	temporarily_use_uid(pw);

	/* Allocate a buffer for the socket name, and format the name. */
196
	auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
197 198 199 200 201 202

	/* Create private directory for socket */
	if (mkdtemp(auth_sock_dir) == NULL) {
		packet_send_debug("Agent forwarding disabled: "
		    "mkdtemp() failed: %.100s", strerror(errno));
		restore_uid();
203
		free(auth_sock_dir);
204
		auth_sock_dir = NULL;
205
		goto authsock_err;
206
	}
207 208 209

	xasprintf(&auth_sock_name, "%s/agent.%ld",
	    auth_sock_dir, (long) getpid());
210 211 212

	/* Create the socket. */
	sock = socket(AF_UNIX, SOCK_STREAM, 0);
213 214 215 216 217
	if (sock < 0) {
		error("socket: %.100s", strerror(errno));
		restore_uid();
		goto authsock_err;
	}
218 219 220 221 222 223

	/* 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));

224 225 226 227 228
	if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
		error("bind: %.100s", strerror(errno));
		restore_uid();
		goto authsock_err;
	}
229 230 231 232 233

	/* Restore the privileged uid. */
	restore_uid();

	/* Start listening on the socket. */
234 235 236 237
	if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
		error("listen: %.100s", strerror(errno));
		goto authsock_err;
	}
238 239 240 241 242

	/* Allocate a channel for the authentication agent socket. */
	nc = channel_new("auth socket",
	    SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
	    CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
243
	    0, "auth socket", 1);
244
	nc->path = xstrdup(auth_sock_name);
245
	return 1;
246 247

 authsock_err:
248
	free(auth_sock_name);
249 250
	if (auth_sock_dir != NULL) {
		rmdir(auth_sock_dir);
251
		free(auth_sock_dir);
252 253 254 255 256 257
	}
	if (sock != -1)
		close(sock);
	auth_sock_name = NULL;
	auth_sock_dir = NULL;
	return 0;
258 259
}

260 261 262
static void
display_loginmsg(void)
{
263 264 265 266 267
	if (buffer_len(&loginmsg) > 0) {
		buffer_append(&loginmsg, "\0", 1);
		printf("%s", (char *)buffer_ptr(&loginmsg));
		buffer_clear(&loginmsg);
	}
268
}
269

270 271 272
void
do_authenticated(Authctxt *authctxt)
{
273 274
	setproctitle("%s", authctxt->pw->pw_name);

275
	/* setup the channel layer */
276 277 278 279
	if (no_port_forwarding_flag ||
	    (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
		channel_disable_adm_local_opens();
	else
280 281
		channel_permit_all_opens();

282 283
	auth_debug_send();

284 285 286 287
	if (compat20)
		do_authenticated2(authctxt);
	else
		do_authenticated1(authctxt);
288

289
	do_cleanup(authctxt);
290 291
}

292 293 294 295 296 297
/*
 * Prepares for an interactive session.  This is called after the user has
 * been successfully authenticated.  During this message exchange, pseudo
 * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
 * are requested, etc.
 */
298
static void
299
do_authenticated1(Authctxt *authctxt)
300 301 302
{
	Session *s;
	char *command;
303
	int success, type, screen_flag;
304 305
	int enable_compression_after_reply = 0;
	u_int proto_len, data_len, dlen, compression_level = 0;
306 307

	s = session_new();
308 309 310 311
	if (s == NULL) {
		error("no more sessions");
		return;
	}
312
	s->authctxt = authctxt;
313
	s->pw = authctxt->pw;
314

315 316 317 318 319
	/*
	 * We stay in this loop until the client requests to execute a shell
	 * or a command.
	 */
	for (;;) {
320
		success = 0;
321 322

		/* Get a packet from the client. */
323
		type = packet_read();
324 325 326 327 328

		/* Process the packet. */
		switch (type) {
		case SSH_CMSG_REQUEST_COMPRESSION:
			compression_level = packet_get_int();
329
			packet_check_eom();
330
			if (compression_level < 1 || compression_level > 9) {
331
				packet_send_debug("Received invalid compression level %d.",
332
				    compression_level);
333 334
				break;
			}
335
			if (options.compression == COMP_NONE) {
336 337 338
				debug2("compression disabled");
				break;
			}
339 340 341 342 343 344
			/* Enable compression after we have responded with SUCCESS. */
			enable_compression_after_reply = 1;
			success = 1;
			break;

		case SSH_CMSG_REQUEST_PTY:
345
			success = session_pty_req(s);
346 347 348 349 350 351
			break;

		case SSH_CMSG_X11_REQUEST_FORWARDING:
			s->auth_proto = packet_get_string(&proto_len);
			s->auth_data = packet_get_string(&data_len);

352 353 354 355 356 357 358 359
			screen_flag = packet_get_protocol_flags() &
			    SSH_PROTOFLAG_SCREEN_NUMBER;
			debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);

			if (packet_remaining() == 4) {
				if (!screen_flag)
					debug2("Buggy client: "
					    "X11 screen flag missing");
360
				s->screen = packet_get_int();
361
			} else {
362
				s->screen = 0;
363
			}
364
			packet_check_eom();
365 366
			success = session_setup_x11fwd(s);
			if (!success) {
367 368
				free(s->auth_proto);
				free(s->auth_data);
369 370
				s->auth_proto = NULL;
				s->auth_data = NULL;
371 372 373 374
			}
			break;

		case SSH_CMSG_AGENT_REQUEST_FORWARDING:
375 376
			if (!options.allow_agent_forwarding ||
			    no_agent_forwarding_flag || compat13) {
377 378 379 380
				debug("Authentication agent forwarding not permitted for this authentication.");
				break;
			}
			debug("Received authentication agent forwarding request.");
381
			success = auth_input_request_forwarding(s->pw);
382 383 384 385 386 387 388
			break;

		case SSH_CMSG_PORT_FORWARD_REQUEST:
			if (no_port_forwarding_flag) {
				debug("Port forwarding not permitted for this authentication.");
				break;
			}
389
			if (!(options.allow_tcp_forwarding & FORWARD_REMOTE)) {
390 391 392
				debug("Port forwarding not permitted.");
				break;
			}
393
			debug("Received TCP/IP port forwarding request.");
394 395 396 397 398
			if (channel_input_port_forward_request(s->pw->pw_uid == 0,
			    options.gateway_ports) < 0) {
				debug("Port forwarding failed.");
				break;
			}
399 400 401 402 403 404 405
			success = 1;
			break;

		case SSH_CMSG_MAX_PACKET_SIZE:
			if (packet_set_maxsize(packet_get_int()) > 0)
				success = 1;
			break;
406

407 408 409 410 411
		case SSH_CMSG_EXEC_SHELL:
		case SSH_CMSG_EXEC_CMD:
			if (type == SSH_CMSG_EXEC_CMD) {
				command = packet_get_string(&dlen);
				debug("Exec command '%.500s'", command);
412 413 414
				if (do_exec(s, command) != 0)
					packet_disconnect(
					    "command execution failed");
415
				free(command);
416
			} else {
417 418 419
				if (do_exec(s, NULL) != 0)
					packet_disconnect(
					    "shell execution failed");
420
			}
421
			packet_check_eom();
422
			session_close(s);
423 424 425 426 427 428 429
			return;

		default:
			/*
			 * Any unknown messages in this phase are ignored,
			 * and a failure message is returned.
			 */
430
			logit("Unknown packet type received after authentication: %d", type);
431 432 433 434 435 436 437 438 439 440 441 442 443
		}
		packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
		packet_send();
		packet_write_wait();

		/* Enable compression now that we have replied if appropriate. */
		if (enable_compression_after_reply) {
			enable_compression_after_reply = 0;
			packet_start_compression(compression_level);
		}
	}
}

444
#define USE_PIPES 1
445 446 447 448 449
/*
 * 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.
 */
450
int
451
do_exec_no_pty(Session *s, const char *command)
452
{
453
	pid_t pid;
454 455 456

#ifdef USE_PIPES
	int pin[2], pout[2], perr[2];
457

458 459 460
	if (s == NULL)
		fatal("do_exec_no_pty: no session");

461
	/* Allocate pipes for communicating with the program. */
462 463 464 465 466 467 468 469 470 471
	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;
	}
472 473 474 475 476 477 478 479
	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;
480 481
	}
#else
482
	int inout[2], err[2];
483

484 485 486
	if (s == NULL)
		fatal("do_exec_no_pty: no session");

487
	/* Uses socket pairs to communicate with the program. */
488 489 490 491
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
		error("%s: socketpair #1: %.100s", __func__, strerror(errno));
		return -1;
	}
492 493 494 495 496 497
	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;
498 499 500
	}
#endif

501
	session_proctitle(s);
502 503

	/* Fork the child. */
504 505 506 507 508 509 510 511
	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]);
512
		close(perr[0]);
513 514 515 516 517
		close(perr[1]);
#else
		close(inout[0]);
		close(inout[1]);
		close(err[0]);
518
		close(err[1]);
519 520 521
#endif
		return -1;
	case 0:
522
		is_child = 1;
523

524
		/* Child.  Reinitialize the log since the pid has changed. */
525 526
		log_init(__progname, options.log_level,
		    options.log_facility, log_stderr);
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551

		/*
		 * Create a new session and process group since the 4.4BSD
		 * setlogin() affects the entire process group.
		 */
		if (setsid() < 0)
			error("setsid failed: %.100s", strerror(errno));

#ifdef USE_PIPES
		/*
		 * Redirect stdin.  We close the parent side of the socket
		 * pair, and make the child side the standard input.
		 */
		close(pin[1]);
		if (dup2(pin[0], 0) < 0)
			perror("dup2 stdin");
		close(pin[0]);

		/* Redirect stdout. */
		close(pout[0]);
		if (dup2(pout[1], 1) < 0)
			perror("dup2 stdout");
		close(pout[1]);

		/* Redirect stderr. */
552
		close(perr[0]);
553 554 555
		if (dup2(perr[1], 2) < 0)
			perror("dup2 stderr");
		close(perr[1]);
556
#else
557 558 559 560 561 562
		/*
		 * Redirect stdin, stdout, and stderr.  Stdin and stdout will
		 * use the same socket, as some programs (particularly rdist)
		 * seem to depend on it.
		 */
		close(inout[1]);
563
		close(err[1]);
564 565
		if (dup2(inout[0], 0) < 0)	/* stdin */
			perror("dup2 stdin");
566
		if (dup2(inout[0], 1) < 0)	/* stdout (same as stdin) */
567
			perror("dup2 stdout");
568
		close(inout[0]);
569 570
		if (dup2(err[0], 2) < 0)	/* stderr */
			perror("dup2 stderr");
571 572 573
		close(err[0]);
#endif

574

575 576 577 578
#ifdef _UNICOS
		cray_init_job(s->pw); /* set up cray jid and tmpdir */
#endif

579
		/* Do processing for the child (exec command etc). */
580
		do_child(s, command);
581
		/* NOTREACHED */
582 583
	default:
		break;
584
	}
585

586 587 588
#ifdef _UNICOS
	signal(WJSIGNAL, cray_job_termination_handler);
#endif /* _UNICOS */
589
#ifdef HAVE_CYGWIN
590
	cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
591
#endif
592

593
	s->pid = pid;
594
	/* Set interactive/non-interactive mode. */
595 596
	packet_set_interactive(s->display != NULL,
	    options.ip_qos_interactive, options.ip_qos_bulk);
597 598 599 600 601 602 603 604

	/*
	 * 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);

605 606 607 608 609 610
#ifdef USE_PIPES
	/* We are the parent.  Close the child sides of the pipes. */
	close(pin[0]);
	close(pout[1]);
	close(perr[1]);

611
	if (compat20) {
612 613
		session_set_fds(s, pin[1], pout[0], perr[0],
		    s->is_subsystem, 0);
614 615 616
	} else {
		/* Enter the interactive session. */
		server_loop(pid, pin[1], pout[0], perr[0]);
617
		/* server_loop has closed pin[1], pout[0], and perr[0]. */
618
	}
619
#else
620 621 622 623 624 625 626 627
	/* We are the parent.  Close the child sides of the socket pairs. */
	close(inout[0]);
	close(err[0]);

	/*
	 * Enter the interactive session.  Note: server_loop must be able to
	 * handle the case that fdin and fdout are the same.
	 */
628
	if (compat20) {
629 630
		session_set_fds(s, inout[1], inout[1], err[1],
		    s->is_subsystem, 0);
631 632 633 634
	} else {
		server_loop(pid, inout[1], inout[1], err[1]);
		/* server_loop has closed inout[1] and err[1]. */
	}
635 636
#endif
	return 0;
637 638 639 640 641 642 643 644
}

/*
 * This is called to fork and execute a command when we have a tty.  This
 * will call do_child from the child, and server_loop from the parent after
 * setting up file descriptors, controlling tty, updating wtmp, utmp,
 * lastlog, and other such operations.
 */
645
int
646
do_exec_pty(Session *s, const char *command)
647 648 649 650 651 652 653 654 655
{
	int fdout, ptyfd, ttyfd, ptymaster;
	pid_t pid;

	if (s == NULL)
		fatal("do_exec_pty: no session");
	ptyfd = s->ptyfd;
	ttyfd = s->ttyfd;

656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
	/*
	 * 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;
	}

678
	/* Fork the child. */
679 680 681 682 683 684 685 686 687
	switch ((pid = fork())) {
	case -1:
		error("%s: fork: %.100s", __func__, strerror(errno));
		close(fdout);
		close(ptymaster);
		close(ttyfd);
		close(ptyfd);
		return -1;
	case 0:
688
		is_child = 1;
689

690 691 692
		close(fdout);
		close(ptymaster);

693
		/* Child.  Reinitialize the log because the pid has changed. */
694 695
		log_init(__progname, options.log_level,
		    options.log_facility, log_stderr);
696 697 698 699 700 701
		/* Close the master side of the pseudo tty. */
		close(ptyfd);

		/* Make the pseudo tty our controlling tty. */
		pty_make_controlling_tty(&ttyfd, s->tty);

702 703 704 705 706 707 708
		/* Redirect stdin/stdout/stderr from the pseudo tty. */
		if (dup2(ttyfd, 0) < 0)
			error("dup2 stdin: %s", strerror(errno));
		if (dup2(ttyfd, 1) < 0)
			error("dup2 stdout: %s", strerror(errno));
		if (dup2(ttyfd, 2) < 0)
			error("dup2 stderr: %s", strerror(errno));
709 710 711 712

		/* Close the extra descriptor for the pseudo tty. */
		close(ttyfd);

713
		/* record login, etc. similar to login(1) */
714
#ifndef HAVE_OSF_SIA
715 716 717 718
		if (!(options.use_login && command == NULL)) {
#ifdef _UNICOS
			cray_init_job(s->pw); /* set up cray jid and tmpdir */
#endif /* _UNICOS */
719
			do_login(s, command);
720
		}
721 722 723 724
# ifdef LOGIN_NEEDS_UTMPX
		else
			do_pre_login(s);
# endif
725
#endif
726 727 728 729
		/*
		 * Do common processing for the child, such as execing
		 * the command.
		 */
730 731
		do_child(s, command);
		/* NOTREACHED */
732 733
	default:
		break;
734
	}
735

736 737 738
#ifdef _UNICOS
	signal(WJSIGNAL, cray_job_termination_handler);
#endif /* _UNICOS */
739
#ifdef HAVE_CYGWIN
740
	cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
741
#endif
742

743 744 745 746 747 748
	s->pid = pid;

	/* Parent.  Close the slave side of the pseudo tty. */
	close(ttyfd);

	/* Enter interactive session. */
749
	s->ptymaster = ptymaster;
750 751
	packet_set_interactive(1, 
	    options.ip_qos_interactive, options.ip_qos_bulk);
752
	if (compat20) {
753
		session_set_fds(s, ptyfd, fdout, -1, 1, 1);
754 755 756 757
	} else {
		server_loop(pid, ptyfd, fdout, -1);
		/* server_loop _has_ closed ptyfd and fdout. */
	}
758
	return 0;
759 760
}

761
#ifdef LOGIN_NEEDS_UTMPX
762
static void
763 764 765 766 767 768 769 770 771 772 773
do_pre_login(Session *s)
{
	socklen_t fromlen;
	struct sockaddr_storage from;
	pid_t pid = getpid();

	/*
	 * Get IP address of client. If the connection is not a socket, let
	 * the address be 0.0.0.0.
	 */
	memset(&from, 0, sizeof(from));
774
	fromlen = sizeof(from);
775 776
	if (packet_connection_is_on_socket()) {
		if (getpeername(packet_get_connection_in(),
777
		    (struct sockaddr *)&from, &fromlen) < 0) {
778
			debug("getpeername: %.100s", strerror(errno));
779
			cleanup_exit(255);
780 781 782 783
		}
	}

	record_utmp_only(pid, s->tty, s->pw->pw_name,
784
	    get_remote_name_or_ip(utmp_len, options.use_dns),
785
	    (struct sockaddr *)&from, fromlen);
786 787 788
}
#endif

789 790 791 792
/*
 * This is called to fork and execute a command.  If another command is
 * to be forced, execute that instead.
 */
793
int
794 795
do_exec(Session *s, const char *command)
{
796
	int ret;
797 798
	const char *forced = NULL;
	char session_type[1024], *tty = NULL;
799

800 801 802
	if (options.adm_forced_command) {
		original_command = command;
		command = options.adm_forced_command;
803
		forced = "(config)";
804
	} else if (forced_command) {
805 806
		original_command = command;
		command = forced_command;
807 808 809
		forced = "(key-option)";
	}
	if (forced != NULL) {
810 811 812 813
		if (IS_INTERNAL_SFTP(command)) {
			s->is_subsystem = s->is_subsystem ?
			    SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
		} else if (s->is_subsystem)
814
			s->is_subsystem = SUBSYSTEM_EXT;
815 816 817 818 819 820 821 822 823 824
		snprintf(session_type, sizeof(session_type),
		    "forced-command %s '%.900s'", forced, command);
	} else if (s->is_subsystem) {
		snprintf(session_type, sizeof(session_type),
		    "subsystem '%.900s'", s->subsys);
	} else if (command == NULL) {
		snprintf(session_type, sizeof(session_type), "shell");
	} else {
		/* NB. we don't log unforced commands to preserve privacy */
		snprintf(session_type, sizeof(session_type), "command");
825 826
	}

827 828 829 830 831 832 833 834 835 836 837 838 839 840
	if (s->ttyfd != -1) {
		tty = s->tty;
		if (strncmp(tty, "/dev/", 5) == 0)
			tty += 5;
	}

	verbose("Starting session: %s%s%s for %s from %.200s port %d",
	    session_type,
	    tty == NULL ? "" : " on ",
	    tty == NULL ? "" : tty,
	    s->pw->pw_name,
	    get_remote_ipaddr(),
	    get_remote_port());

841
#ifdef SSH_AUDIT_EVENTS
842 843 844 845 846 847 848 849 850 851
	if (command != NULL)
		PRIVSEP(audit_run_command(command));
	else if (s->ttyfd == -1) {
		char *shell = s->pw->pw_shell;

		if (shell[0] == '\0')	/* empty shell means /bin/sh */
			shell =_PATH_BSHELL;
		PRIVSEP(audit_run_command(shell));
	}
#endif
852
	if (s->ttyfd != -1)
853
		ret = do_exec_pty(s, command);
854
	else
855
		ret = do_exec_no_pty(s, command);
856

857
	original_command = NULL;
858

859 860 861 862 863 864
	/*
	 * Clear loginmsg: 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);
865 866

	return ret;
867
}
868

869 870
/* administrative, login(1)-like work */
void
871
do_login(Session *s, const char *command)
872 873 874 875 876 877 878 879 880 881 882
{
	socklen_t fromlen;
	struct sockaddr_storage from;
	struct passwd * pw = s->pw;
	pid_t pid = getpid();

	/*
	 * Get IP address of client. If the connection is not a socket, let
	 * the address be 0.0.0.0.
	 */
	memset(&from, 0, sizeof(from));
883
	fromlen = sizeof(from);
884 885
	if (packet_connection_is_on_socket()) {
		if (getpeername(packet_get_connection_in(),
886
		    (struct sockaddr *)&from, &fromlen) < 0) {
887
			debug("getpeername: %.100s", strerror(errno));
888
			cleanup_exit(255);
889 890 891 892
		}
	}

	/* Record that there was a login on that tty from the remote host. */
893 894 895
	if (!use_privsep)
		record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
		    get_remote_name_or_ip(utmp_len,
896
		    options.use_dns),
897
		    (struct sockaddr *)&from, fromlen);
898

899 900 901 902 903
#ifdef USE_PAM
	/*
	 * If password change is needed, do it now.
	 * This needs to occur before the ~/.hushlogin check.
	 */
904 905
	if (options.use_pam && !use_privsep && s->authctxt->force_pwchange) {
		display_loginmsg();
906
		do_pam_chauthtok();
907
		s->authctxt->force_pwchange = 0;
908
		/* XXX - signal [net] parent to enable forwardings */
909 910 911
	}
#endif

912
	if (check_quietlogin(s, command))
913 914
		return;

915
	display_loginmsg();
916

917 918 919 920 921 922 923 924 925 926 927 928
	do_motd();
}

/*
 * Display the message of the day.
 */
void
do_motd(void)
{
	FILE *f;
	char buf[256];

929
	if (options.print_motd) {
930 931 932 933
#ifdef HAVE_LOGIN_CAP
		f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
		    "/etc/motd"), "r");
#else
934
		f = fopen("/etc/motd", "r");
935
#endif
936 937 938 939 940 941 942 943
		if (f) {
			while (fgets(buf, sizeof(buf), f))
				fputs(buf, stdout);
			fclose(f);
		}
	}
}

944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968

/*
 * Check for quiet login, either .hushlogin or command given.
 */
int
check_quietlogin(Session *s, const char *command)
{
	char buf[256];
	struct passwd *pw = s->pw;
	struct stat st;

	/* Return 1 if .hushlogin exists or a command given. */
	if (command != NULL)
		return 1;
	snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
#ifdef HAVE_LOGIN_CAP
	if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
		return 1;
#else
	if (stat(buf, &st) >= 0)
		return 1;
#endif
	return 0;
}

969 970
/*
 * Sets the value of the given variable in the environment.  If the variable
971
 * already exists, its value is overridden.
972
 */
973
void
974
child_set_env(char ***envp, u_int *envsizep, const char *name,
975
	const char *value)
976 977
{
	char **env;
978 979
	u_int envsize;
	u_int i, namelen;
980

981 982 983 984 985 986 987 988 989 990
	/*
	 * If we're passed an uninitialized list, allocate a single null
	 * entry before continuing.
	 */
	if (*envp == NULL && *envsizep == 0) {
		*envp = xmalloc(sizeof(char *));
		*envp[0] = NULL;
		*envsizep = 1;
	}

991 992 993 994 995 996 997 998 999 1000 1001 1002
	/*
	 * Find the slot where the value should be stored.  If the variable
	 * already exists, we reuse the slot; otherwise we append a new slot
	 * at the end of the array, expanding if necessary.
	 */
	env = *envp;
	namelen = strlen(name);
	for (i = 0; env[i]; i++)
		if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
			break;
	if (env[i]) {
		/* Reuse the slot. */
1003
		free(env[i]);
1004 1005
	} else {
		/* New variable.  Expand if necessary. */
1006 1007 1008 1009 1010
		envsize = *envsizep;
		if (i >= envsize - 1) {
			if (envsize >= 1000)
				fatal("child_set_env: too many env vars");
			envsize += 50;
1011
			env = (*envp) = xrealloc(env, envsize, sizeof(char *));
1012
			*envsizep = envsize;
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
		}
		/* Need to set the NULL pointer at end of array beyond the new slot. */
		env[i + 1] = NULL;
	}

	/* Allocate space and format the variable in the appropriate slot. */
	env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
	snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
}

/*
 * Reads environment variables from the given file and adds/overrides them
 * into the environment.  If the file does not exist, this does nothing.
 * Otherwise, it must consist of empty lines, comments (line starts with '#')
 * and assignments of the form name=value.  No other forms are allowed.
 */
1029
static void
1030
read_environment_file(char ***env, u_int *envsize,
1031
	const char *filename)
1032 1033 1034 1035
{
	FILE *f;
	char buf[4096];
	char *cp, *value;
1036
	u_int lineno = 0;
1037 1038 1039 1040 1041 1042

	f = fopen(filename, "r");
	if (!f)
		return;

	while (fgets(buf, sizeof(buf), f)) {
1043 1044
		if (++lineno > 1000)
			fatal("Too many lines in environment file %s", filename);
1045 1046 1047 1048
		for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '#' || *cp == '\n')
			continue;
1049 1050 1051

		cp[strcspn(cp, "\n")] = '\0';

1052 1053
		value = strchr(cp, '=');
		if (value == NULL) {
1054 1055
			fprintf(stderr, "Bad line %u in %.100s\n", lineno,
			    filename);
1056 1057
			continue;
		}
1058 1059 1060 1061
		/*
		 * Replace the equals sign by nul, and advance value to
		 * the value string.
		 */
1062 1063 1064 1065 1066 1067 1068
		*value = '\0';
		value++;
		child_set_env(env, envsize, cp, value);
	}
	fclose(f);
}

1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
#ifdef HAVE_ETC_DEFAULT_LOGIN
/*
 * Return named variable from specified environment, or NULL if not present.
 */
static char *
child_get_env(char **env, const char *name)
{
	int i;
	size_t len;

	len = strlen(name);
	for (i=0; env[i] != NULL; i++)
		if (strncmp(name, env[i], len) == 0 && env[i][len] == '=')
			return(env[i] + len + 1);
	return NULL;
}

/*
 * Read /etc/default/login.
 * We pick up the PATH (or SUPATH for root) and UMASK.
 */
static void
read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
{
	char **tmpenv = NULL, *var;
1094
	u_int i, tmpenvsize = 0;
1095
	u_long mask;
1096 1097 1098 1099 1100 1101 1102 1103

	/*
	 * We don't want to copy the whole file to the child's environment,
	 * so we use a temporary environment and copy the variables we're
	 * interested in.
	 */
	read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login");

1104 1105 1106
	if (tmpenv == NULL)
		return;

1107 1108 1109 1110 1111 1112
	if (uid == 0)
		var = child_get_env(tmpenv, "SUPATH");
	else
		var = child_get_env(tmpenv, "PATH");
	if (var != NULL)
		child_set_env(env, envsize, "PATH", var);
1113

1114 1115
	if ((var = child_get_env(tmpenv, "UMASK")) != NULL)
		if (sscanf(var, "%5lo", &mask) == 1)
1116
			umask((mode_t)mask);
1117

1118
	for (i = 0; tmpenv[i] != NULL; i++)
1119 1120
		free(tmpenv[i]);
	free(tmpenv);
1121 1122 1123
}
#endif /* HAVE_ETC_DEFAULT_LOGIN */

Damien Miller's avatar
Damien Miller committed
1124 1125
void
copy_environment(char **source, char ***env, u_int *envsize)
1126
{
1127
	char *var_name, *var_val;
1128 1129
	int i;

1130
	if (source == NULL)
1131
		return;
1132

1133 1134 1135
	for(i = 0; source[i] != NULL; i++) {
		var_name = xstrdup(source[i]);
		if ((var_val = strstr(var_name, "=")) == NULL) {
1136
			free(var_name);
1137 1138
			continue;
		}
1139
		*var_val++ = '\0';
1140

1141 1142
		debug3("Copy environment: %s=%s", var_name, var_val);
		child_set_env(env, envsize, var_name, var_val);
1143

1144
		free(var_name);
1145 1146 1147
	}
}

1148 1149
static char **
do_setup_env(Session *s, const char *shell)
1150 1151
{
	char buf[256];
1152
	u_int i, envsize;
Damien Miller's avatar
Damien Miller committed
1153
	char **env, *laddr;
1154
	struct passwd *pw = s->pw;
1155
#if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
Damien Miller's avatar
Damien Miller committed
1156 1157
	char *path = NULL;
#endif
1158 1159 1160

	/* Initialize the environment. */
	envsize = 100;
1161
	env = xcalloc(envsize, sizeof(char *));
1162 1163
	env[0] = NULL;

1164 1165 1166 1167 1168
#ifdef HAVE_CYGWIN
	/*
	 * The Windows environment contains some setting which are
	 * important for a running system. They must not be dropped.
	 */
1169 1170 1171 1172 1173 1174 1175
	{
		char **p;

		p = fetch_windows_environment();
		copy_environment(p, &env, &envsize);
		free_windows_environment(p);
	}
1176 1177
#endif

1178
#ifdef GSSAPI
1179
	/* Allow any GSSAPI methods that we've used to alter
1180 1181 1182 1183 1184
	 * the childs environment as they see fit
	 */
	ssh_gssapi_do_child(&env, &envsize);
#endif

1185 1186
	if (!options.use_login) {
		/* Set basic environment. */
1187
		for (i = 0; i < s->num_env; i++)
1188
			child_set_env(&env, &envsize, s->env[i].name,
1189 1190
			    s->env[i].val);

1191 1192
		child_set_env(&env, &envsize, "USER", pw->pw_name);
		child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
1193 1194 1195
#ifdef _AIX
		child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
#endif
1196
		child_set_env(&env, &envsize, "HOME", pw->pw_dir);
1197
#ifdef HAVE_LOGIN_CAP
1198 1199 1200 1201
		if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
			child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
		else
			child_set_env(&env, &envsize, "PATH", getenv("PATH"));
1202 1203
#else /* HAVE_LOGIN_CAP */
# ifndef HAVE_CYGWIN
1204 1205 1206 1207 1208 1209
		/*
		 * There's no standard path on Windows. The path contains
		 * important components pointing to the system directories,
		 * needed for loading shared libraries. So the path better
		 * remains intact here.
		 */
1210 1211 1212 1213 1214
#  ifdef HAVE_ETC_DEFAULT_LOGIN
		read_etc_default_login(&env, &envsize, pw->pw_uid);
		path = child_get_env(env, "PATH");
#  endif /* HAVE_ETC_DEFAULT_LOGIN */
		if (path == NULL || *path == '\0') {
1215
			child_set_env(&env, &envsize, "PATH",
1216 1217 1218
			    s->pw->pw_uid == 0 ?
				SUPERUSER_PATH : _PATH_STDPATH);
		}
1219 1220
# endif /* HAVE_CYGWIN */
#endif /* HAVE_LOGIN_CAP */
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232

		snprintf(buf, sizeof buf, "%.200s/%.50s",
			 _PATH_MAILDIR, pw->pw_name);
		child_set_env(&env, &envsize, "MAIL", buf);

		/* Normal systems set SHELL by default. */
		child_set_env(&env, &envsize, "SHELL", shell);
	}
	if (getenv("TZ"))
		child_set_env(&env, &envsize, "TZ", getenv("TZ"));

	/* Set custom environment options from RSA authentication. */
1233 1234 1235
	if (!options.use_login) {
		while (custom_environment) {
			struct envstring *ce = custom_environment;
1236
			char *str = ce->s;
1237

1238
			for (i = 0; str[i] != '=' && str[i]; i++)
1239
				;
1240 1241 1242
			if (str[i] == '=') {
				str[i] = 0;
				child_set_env(&env, &envsize, str, str + i + 1);
1243 1244
			}
			custom_environment = ce->next;
1245 1246
			free(ce->s);
			free(ce);
1247 1248 1249
		}
	}

1250
	/* SSH_CLIENT deprecated */
1251
	snprintf(buf, sizeof buf, "%.50s %d %d",
1252
	    get_remote_ipaddr(), get_remote_port(), get_local_port());
1253 1254
	child_set_env(&env, &envsize, "SSH_CLIENT", buf);

Damien Miller's avatar
Damien Miller committed
1255
	laddr = get_local_ipaddr(packet_get_connection_in());
1256
	snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
Damien Miller's avatar
Damien Miller committed
1257
	    get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
1258
	free(laddr);
1259 1260
	child_set_env(&env, &envsize, "SSH_CONNECTION", buf);

1261 1262 1263 1264 1265 1266
	if (s->ttyfd != -1)
		child_set_env(&env, &envsize, "SSH_TTY", s->tty);
	if (s->term)
		child_set_env(&env, &envsize, "TERM", s->term);
	if (s->display)
		child_set_env(&env, &envsize, "DISPLAY", s->display);
Damien Miller's avatar
Damien Miller committed
1267 1268 1269
	if (original_command)
		child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
		    original_command);
1270

1271 1272 1273 1274 1275
#ifdef _UNICOS
	if (cray_tmpdir[0] != '\0')
		child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);
#endif /* _UNICOS */

1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
	/*
	 * Since we clear KRB5CCNAME at startup, if it's set now then it
	 * must have been set by a native authentication method (eg AIX or
	 * SIA), so copy it to the child.
	 */
	{
		char *cp;

		if ((cp = getenv("KRB5CCNAME")) != NULL)
			child_set_env(&env, &envsize, "KRB5CCNAME", cp);
	}

1288
#ifdef _AIX
1289 1290 1291 1292 1293 1294 1295
	{
		char *cp;

		if ((cp = getenv("AUTHSTATE")) != NULL)
			child_set_env(&env, &envsize, "AUTHSTATE", cp);
		read_environment_file(&env, &envsize, "/etc/environment");
	}
1296
#endif
1297
#ifdef KRB5
1298
	if (s->authctxt->krb5_ccname)
1299
		child_set_env(&env, &envsize, "KRB5CCNAME",
1300
		    s->authctxt->krb5_ccname);
1301
#endif
1302
#ifdef USE_PAM
1303 1304 1305 1306
	/*
	 * Pull in any environment variables that may have
	 * been set by PAM.
	 */
1307
	if (options.use_pam) {
1308
		char **p;
1309

1310 1311 1312
		p = fetch_pam_child_environment();
		copy_environment(p, &env, &envsize);
		free_pam_environment(p);
1313

1314
		p = fetch_pam_environment();
1315 1316 1317
		copy_environment(p, &env, &envsize);
		free_pam_environment(p);
	}
1318 1319
#endif /* USE_PAM */

1320
	if (auth_sock_name != NULL)
1321
		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
1322
		    auth_sock_name);
1323 1324

	/* read $HOME/.ssh/environment. */
1325
	if (options.permit_user_env && !options.use_login) {
1326
		snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
1327
		    strcmp(pw->pw_dir, "/") ? pw->pw_dir : "");
1328 1329 1330 1331 1332 1333 1334 1335
		read_environment_file(&env, &envsize, buf);
	}
	if (debug_flag) {
		/* dump the environment */
		fprintf(stderr, "Environment:\n");
		for (i = 0; env[i]; i++)
			fprintf(stderr, "  %.200s\n", env[i]);
	}
1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
	return env;
}

/*
 * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found
 * first in this order).
 */
static void
do_rc_files(Session *s, const char *shell)
{
	FILE *f = NULL;
	char cmd[1024];
	int do_xauth;
	struct stat st;

	do_xauth =
	    s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;

1354
	/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
1355
	if (!s->is_subsystem && options.adm_forced_command == NULL &&
1356
	    !no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) {