session.c revision 60574
1/*
2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3 *                    All rights reserved
4 */
5/*
6 * SSH2 support by Markus Friedl.
7 * Copyright (c) 2000 Markus Friedl. All rights reserved.
8 */
9
10#include "includes.h"
11RCSID("$OpenBSD: session.c,v 1.12 2000/05/03 18:03:07 markus Exp $");
12
13#include "xmalloc.h"
14#include "ssh.h"
15#include "pty.h"
16#include "packet.h"
17#include "buffer.h"
18#include "cipher.h"
19#include "mpaux.h"
20#include "servconf.h"
21#include "uidswap.h"
22#include "compat.h"
23#include "channels.h"
24#include "nchan.h"
25
26#include "bufaux.h"
27#include "ssh2.h"
28#include "auth.h"
29
30/* types */
31
32#define TTYSZ 64
33typedef struct Session Session;
34struct Session {
35	int	used;
36	int	self;
37	int	extended;
38	struct	passwd *pw;
39	pid_t	pid;
40	/* tty */
41	char	*term;
42	int	ptyfd, ttyfd, ptymaster;
43	int	row, col, xpixel, ypixel;
44	char	tty[TTYSZ];
45	/* X11 */
46	char	*display;
47	int	screen;
48	char	*auth_proto;
49	char	*auth_data;
50	int	single_connection;
51	/* proto 2 */
52	int	chanid;
53};
54
55/* func */
56
57Session *session_new(void);
58void	session_set_fds(Session *s, int fdin, int fdout, int fderr);
59void	session_pty_cleanup(Session *s);
60void	session_proctitle(Session *s);
61void	do_exec_pty(Session *s, const char *command, struct passwd * pw);
62void	do_exec_no_pty(Session *s, const char *command, struct passwd * pw);
63
64void
65do_child(const char *command, struct passwd * pw, const char *term,
66    const char *display, const char *auth_proto,
67    const char *auth_data, const char *ttyname);
68
69/* import */
70extern ServerOptions options;
71extern char *__progname;
72extern int log_stderr;
73extern int debug_flag;
74
75/* Local Xauthority file. */
76static char *xauthfile;
77
78/* data */
79#define MAX_SESSIONS 10
80Session	sessions[MAX_SESSIONS];
81
82/* Flags set in auth-rsa from authorized_keys flags.  These are set in auth-rsa.c. */
83int no_port_forwarding_flag = 0;
84int no_agent_forwarding_flag = 0;
85int no_x11_forwarding_flag = 0;
86int no_pty_flag = 0;
87
88/* RSA authentication "command=" option. */
89char *forced_command = NULL;
90
91/* RSA authentication "environment=" options. */
92struct envstring *custom_environment = NULL;
93
94/*
95 * Remove local Xauthority file.
96 */
97void
98xauthfile_cleanup_proc(void *ignore)
99{
100	debug("xauthfile_cleanup_proc called");
101
102	if (xauthfile != NULL) {
103		char *p;
104		unlink(xauthfile);
105		p = strrchr(xauthfile, '/');
106		if (p != NULL) {
107			*p = '\0';
108			rmdir(xauthfile);
109		}
110		xfree(xauthfile);
111		xauthfile = NULL;
112	}
113}
114
115/*
116 * Function to perform cleanup if we get aborted abnormally (e.g., due to a
117 * dropped connection).
118 */
119void
120pty_cleanup_proc(void *session)
121{
122	Session *s=session;
123	if (s == NULL)
124		fatal("pty_cleanup_proc: no session");
125	debug("pty_cleanup_proc: %s", s->tty);
126
127	if (s->pid != 0) {
128		/* Record that the user has logged out. */
129		record_logout(s->pid, s->tty);
130	}
131
132	/* Release the pseudo-tty. */
133	pty_release(s->tty);
134}
135
136/*
137 * Prepares for an interactive session.  This is called after the user has
138 * been successfully authenticated.  During this message exchange, pseudo
139 * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
140 * are requested, etc.
141 */
142void
143do_authenticated(struct passwd * pw)
144{
145	Session *s;
146	int type;
147	int compression_level = 0, enable_compression_after_reply = 0;
148	int have_pty = 0;
149	char *command;
150	int n_bytes;
151	int plen;
152	unsigned int proto_len, data_len, dlen;
153
154	/*
155	 * Cancel the alarm we set to limit the time taken for
156	 * authentication.
157	 */
158	alarm(0);
159
160	/*
161	 * Inform the channel mechanism that we are the server side and that
162	 * the client may request to connect to any port at all. (The user
163	 * could do it anyway, and we wouldn\'t know what is permitted except
164	 * by the client telling us, so we can equally well trust the client
165	 * not to request anything bogus.)
166	 */
167	if (!no_port_forwarding_flag)
168		channel_permit_all_opens();
169
170	s = session_new();
171	s->pw = pw;
172
173	/*
174	 * We stay in this loop until the client requests to execute a shell
175	 * or a command.
176	 */
177	for (;;) {
178		int success = 0;
179
180		/* Get a packet from the client. */
181		type = packet_read(&plen);
182
183		/* Process the packet. */
184		switch (type) {
185		case SSH_CMSG_REQUEST_COMPRESSION:
186			packet_integrity_check(plen, 4, type);
187			compression_level = packet_get_int();
188			if (compression_level < 1 || compression_level > 9) {
189				packet_send_debug("Received illegal compression level %d.",
190				     compression_level);
191				break;
192			}
193			/* Enable compression after we have responded with SUCCESS. */
194			enable_compression_after_reply = 1;
195			success = 1;
196			break;
197
198		case SSH_CMSG_REQUEST_PTY:
199			if (no_pty_flag) {
200				debug("Allocating a pty not permitted for this authentication.");
201				break;
202			}
203			if (have_pty)
204				packet_disconnect("Protocol error: you already have a pty.");
205
206			debug("Allocating pty.");
207
208			/* Allocate a pty and open it. */
209			if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
210			    sizeof(s->tty))) {
211				error("Failed to allocate pty.");
212				break;
213			}
214			fatal_add_cleanup(pty_cleanup_proc, (void *)s);
215			pty_setowner(pw, s->tty);
216
217			/* Get TERM from the packet.  Note that the value may be of arbitrary length. */
218			s->term = packet_get_string(&dlen);
219			packet_integrity_check(dlen, strlen(s->term), type);
220			/* packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type); */
221			/* Remaining bytes */
222			n_bytes = plen - (4 + dlen + 4 * 4);
223
224			if (strcmp(s->term, "") == 0) {
225				xfree(s->term);
226				s->term = NULL;
227			}
228			/* Get window size from the packet. */
229			s->row = packet_get_int();
230			s->col = packet_get_int();
231			s->xpixel = packet_get_int();
232			s->ypixel = packet_get_int();
233			pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
234
235			/* Get tty modes from the packet. */
236			tty_parse_modes(s->ttyfd, &n_bytes);
237			packet_integrity_check(plen, 4 + dlen + 4 * 4 + n_bytes, type);
238
239			session_proctitle(s);
240
241			/* Indicate that we now have a pty. */
242			success = 1;
243			have_pty = 1;
244			break;
245
246		case SSH_CMSG_X11_REQUEST_FORWARDING:
247			if (!options.x11_forwarding) {
248				packet_send_debug("X11 forwarding disabled in server configuration file.");
249				break;
250			}
251#ifdef XAUTH_PATH
252			if (no_x11_forwarding_flag) {
253				packet_send_debug("X11 forwarding not permitted for this authentication.");
254				break;
255			}
256			debug("Received request for X11 forwarding with auth spoofing.");
257			if (s->display != NULL)
258				packet_disconnect("Protocol error: X11 display already set.");
259
260			s->auth_proto = packet_get_string(&proto_len);
261			s->auth_data = packet_get_string(&data_len);
262			packet_integrity_check(plen, 4 + proto_len + 4 + data_len + 4, type);
263
264			if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER)
265				s->screen = packet_get_int();
266			else
267				s->screen = 0;
268			s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
269
270			if (s->display == NULL)
271				break;
272
273			/* Setup to always have a local .Xauthority. */
274			xauthfile = xmalloc(MAXPATHLEN);
275			strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
276			temporarily_use_uid(pw->pw_uid);
277			if (mkdtemp(xauthfile) == NULL) {
278				restore_uid();
279				error("private X11 dir: mkdtemp %s failed: %s",
280				    xauthfile, strerror(errno));
281				xfree(xauthfile);
282				xauthfile = NULL;
283				/* XXXX remove listening channels */
284				break;
285			}
286			strlcat(xauthfile, "/cookies", MAXPATHLEN);
287			open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
288			restore_uid();
289			fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
290			success = 1;
291			break;
292#else /* XAUTH_PATH */
293			packet_send_debug("No xauth program; cannot forward with spoofing.");
294			break;
295#endif /* XAUTH_PATH */
296
297		case SSH_CMSG_AGENT_REQUEST_FORWARDING:
298			if (no_agent_forwarding_flag || compat13) {
299				debug("Authentication agent forwarding not permitted for this authentication.");
300				break;
301			}
302			debug("Received authentication agent forwarding request.");
303			auth_input_request_forwarding(pw);
304			success = 1;
305			break;
306
307		case SSH_CMSG_PORT_FORWARD_REQUEST:
308			if (no_port_forwarding_flag) {
309				debug("Port forwarding not permitted for this authentication.");
310				break;
311			}
312			debug("Received TCP/IP port forwarding request.");
313			channel_input_port_forward_request(pw->pw_uid == 0, options.gateway_ports);
314			success = 1;
315			break;
316
317		case SSH_CMSG_MAX_PACKET_SIZE:
318			if (packet_set_maxsize(packet_get_int()) > 0)
319				success = 1;
320			break;
321
322		case SSH_CMSG_EXEC_SHELL:
323		case SSH_CMSG_EXEC_CMD:
324			/* Set interactive/non-interactive mode. */
325			packet_set_interactive(have_pty || s->display != NULL,
326			    options.keepalives);
327
328			if (type == SSH_CMSG_EXEC_CMD) {
329				command = packet_get_string(&dlen);
330				debug("Exec command '%.500s'", command);
331				packet_integrity_check(plen, 4 + dlen, type);
332			} else {
333				command = NULL;
334				packet_integrity_check(plen, 0, type);
335			}
336			if (forced_command != NULL) {
337				command = forced_command;
338				debug("Forced command '%.500s'", forced_command);
339			}
340			if (have_pty)
341				do_exec_pty(s, command, pw);
342			else
343				do_exec_no_pty(s, command, pw);
344
345			if (command != NULL)
346				xfree(command);
347			/* Cleanup user's local Xauthority file. */
348			if (xauthfile)
349				xauthfile_cleanup_proc(NULL);
350			return;
351
352		default:
353			/*
354			 * Any unknown messages in this phase are ignored,
355			 * and a failure message is returned.
356			 */
357			log("Unknown packet type received after authentication: %d", type);
358		}
359		packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
360		packet_send();
361		packet_write_wait();
362
363		/* Enable compression now that we have replied if appropriate. */
364		if (enable_compression_after_reply) {
365			enable_compression_after_reply = 0;
366			packet_start_compression(compression_level);
367		}
368	}
369}
370
371/*
372 * This is called to fork and execute a command when we have no tty.  This
373 * will call do_child from the child, and server_loop from the parent after
374 * setting up file descriptors and such.
375 */
376void
377do_exec_no_pty(Session *s, const char *command, struct passwd * pw)
378{
379	int pid;
380
381#ifdef USE_PIPES
382	int pin[2], pout[2], perr[2];
383	/* Allocate pipes for communicating with the program. */
384	if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
385		packet_disconnect("Could not create pipes: %.100s",
386				  strerror(errno));
387#else /* USE_PIPES */
388	int inout[2], err[2];
389	/* Uses socket pairs to communicate with the program. */
390	if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
391	    socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
392		packet_disconnect("Could not create socket pairs: %.100s",
393				  strerror(errno));
394#endif /* USE_PIPES */
395	if (s == NULL)
396		fatal("do_exec_no_pty: no session");
397
398	session_proctitle(s);
399
400	/* Fork the child. */
401	if ((pid = fork()) == 0) {
402		/* Child.  Reinitialize the log since the pid has changed. */
403		log_init(__progname, options.log_level, options.log_facility, log_stderr);
404
405		/*
406		 * Create a new session and process group since the 4.4BSD
407		 * setlogin() affects the entire process group.
408		 */
409		if (setsid() < 0)
410			error("setsid failed: %.100s", strerror(errno));
411
412#ifdef USE_PIPES
413		/*
414		 * Redirect stdin.  We close the parent side of the socket
415		 * pair, and make the child side the standard input.
416		 */
417		close(pin[1]);
418		if (dup2(pin[0], 0) < 0)
419			perror("dup2 stdin");
420		close(pin[0]);
421
422		/* Redirect stdout. */
423		close(pout[0]);
424		if (dup2(pout[1], 1) < 0)
425			perror("dup2 stdout");
426		close(pout[1]);
427
428		/* Redirect stderr. */
429		close(perr[0]);
430		if (dup2(perr[1], 2) < 0)
431			perror("dup2 stderr");
432		close(perr[1]);
433#else /* USE_PIPES */
434		/*
435		 * Redirect stdin, stdout, and stderr.  Stdin and stdout will
436		 * use the same socket, as some programs (particularly rdist)
437		 * seem to depend on it.
438		 */
439		close(inout[1]);
440		close(err[1]);
441		if (dup2(inout[0], 0) < 0)	/* stdin */
442			perror("dup2 stdin");
443		if (dup2(inout[0], 1) < 0)	/* stdout.  Note: same socket as stdin. */
444			perror("dup2 stdout");
445		if (dup2(err[0], 2) < 0)	/* stderr */
446			perror("dup2 stderr");
447#endif /* USE_PIPES */
448
449		/* Do processing for the child (exec command etc). */
450		do_child(command, pw, NULL, s->display, s->auth_proto, s->auth_data, NULL);
451		/* NOTREACHED */
452	}
453	if (pid < 0)
454		packet_disconnect("fork failed: %.100s", strerror(errno));
455	s->pid = pid;
456#ifdef USE_PIPES
457	/* We are the parent.  Close the child sides of the pipes. */
458	close(pin[0]);
459	close(pout[1]);
460	close(perr[1]);
461
462	if (compat20) {
463		session_set_fds(s, pin[1], pout[0], s->extended ? perr[0] : -1);
464	} else {
465		/* Enter the interactive session. */
466		server_loop(pid, pin[1], pout[0], perr[0]);
467		/* server_loop has closed pin[1], pout[1], and perr[1]. */
468	}
469#else /* USE_PIPES */
470	/* We are the parent.  Close the child sides of the socket pairs. */
471	close(inout[0]);
472	close(err[0]);
473
474	/*
475	 * Enter the interactive session.  Note: server_loop must be able to
476	 * handle the case that fdin and fdout are the same.
477	 */
478	if (compat20) {
479		session_set_fds(s, inout[1], inout[1], s->extended ? err[1] : -1);
480	} else {
481		server_loop(pid, inout[1], inout[1], err[1]);
482		/* server_loop has closed inout[1] and err[1]. */
483	}
484#endif /* USE_PIPES */
485}
486
487/*
488 * This is called to fork and execute a command when we have a tty.  This
489 * will call do_child from the child, and server_loop from the parent after
490 * setting up file descriptors, controlling tty, updating wtmp, utmp,
491 * lastlog, and other such operations.
492 */
493void
494do_exec_pty(Session *s, const char *command, struct passwd * pw)
495{
496	FILE *f;
497	char buf[100], *time_string;
498	char line[256];
499	const char *hostname;
500	int fdout, ptyfd, ttyfd, ptymaster;
501	int quiet_login;
502	pid_t pid;
503	socklen_t fromlen;
504	struct sockaddr_storage from;
505	struct stat st;
506	time_t last_login_time;
507
508	if (s == NULL)
509		fatal("do_exec_pty: no session");
510	ptyfd = s->ptyfd;
511	ttyfd = s->ttyfd;
512
513	/* Get remote host name. */
514	hostname = get_canonical_hostname();
515
516	/*
517	 * Get the time when the user last logged in.  Buf will be set to
518	 * contain the hostname the last login was from.
519	 */
520	if (!options.use_login) {
521		last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
522						      buf, sizeof(buf));
523	}
524
525	/* Fork the child. */
526	if ((pid = fork()) == 0) {
527		pid = getpid();
528
529		/* Child.  Reinitialize the log because the pid has
530		   changed. */
531		log_init(__progname, options.log_level, options.log_facility, log_stderr);
532
533		/* Close the master side of the pseudo tty. */
534		close(ptyfd);
535
536		/* Make the pseudo tty our controlling tty. */
537		pty_make_controlling_tty(&ttyfd, s->tty);
538
539		/* Redirect stdin from the pseudo tty. */
540		if (dup2(ttyfd, fileno(stdin)) < 0)
541			error("dup2 stdin failed: %.100s", strerror(errno));
542
543		/* Redirect stdout to the pseudo tty. */
544		if (dup2(ttyfd, fileno(stdout)) < 0)
545			error("dup2 stdin failed: %.100s", strerror(errno));
546
547		/* Redirect stderr to the pseudo tty. */
548		if (dup2(ttyfd, fileno(stderr)) < 0)
549			error("dup2 stdin failed: %.100s", strerror(errno));
550
551		/* Close the extra descriptor for the pseudo tty. */
552		close(ttyfd);
553
554/* XXXX ? move to do_child() ??*/
555		/*
556		 * Get IP address of client.  This is needed because we want
557		 * to record where the user logged in from.  If the
558		 * connection is not a socket, let the ip address be 0.0.0.0.
559		 */
560		memset(&from, 0, sizeof(from));
561		if (packet_connection_is_on_socket()) {
562			fromlen = sizeof(from);
563			if (getpeername(packet_get_connection_in(),
564			     (struct sockaddr *) & from, &fromlen) < 0) {
565				debug("getpeername: %.100s", strerror(errno));
566				fatal_cleanup();
567			}
568		}
569		/* Record that there was a login on that terminal. */
570		record_login(pid, s->tty, pw->pw_name, pw->pw_uid, hostname,
571			     (struct sockaddr *)&from);
572
573		/* Check if .hushlogin exists. */
574		snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
575		quiet_login = stat(line, &st) >= 0;
576
577		/*
578		 * If the user has logged in before, display the time of last
579		 * login. However, don't display anything extra if a command
580		 * has been specified (so that ssh can be used to execute
581		 * commands on a remote machine without users knowing they
582		 * are going to another machine). Login(1) will do this for
583		 * us as well, so check if login(1) is used
584		 */
585		if (command == NULL && last_login_time != 0 && !quiet_login &&
586		    !options.use_login) {
587			/* Convert the date to a string. */
588			time_string = ctime(&last_login_time);
589			/* Remove the trailing newline. */
590			if (strchr(time_string, '\n'))
591				*strchr(time_string, '\n') = 0;
592			/* Display the last login time.  Host if displayed
593			   if known. */
594			if (strcmp(buf, "") == 0)
595				printf("Last login: %s\r\n", time_string);
596			else
597				printf("Last login: %s from %s\r\n", time_string, buf);
598		}
599		/*
600		 * Print /etc/motd unless a command was specified or printing
601		 * it was disabled in server options or login(1) will be
602		 * used.  Note that some machines appear to print it in
603		 * /etc/profile or similar.
604		 */
605		if (command == NULL && options.print_motd && !quiet_login &&
606		    !options.use_login) {
607			/* Print /etc/motd if it exists. */
608			f = fopen("/etc/motd", "r");
609			if (f) {
610				while (fgets(line, sizeof(line), f))
611					fputs(line, stdout);
612				fclose(f);
613			}
614		}
615		/* Do common processing for the child, such as execing the command. */
616		do_child(command, pw, s->term, s->display, s->auth_proto, s->auth_data, s->tty);
617		/* NOTREACHED */
618	}
619	if (pid < 0)
620		packet_disconnect("fork failed: %.100s", strerror(errno));
621	s->pid = pid;
622
623	/* Parent.  Close the slave side of the pseudo tty. */
624	close(ttyfd);
625
626	/*
627	 * Create another descriptor of the pty master side for use as the
628	 * standard input.  We could use the original descriptor, but this
629	 * simplifies code in server_loop.  The descriptor is bidirectional.
630	 */
631	fdout = dup(ptyfd);
632	if (fdout < 0)
633		packet_disconnect("dup #1 failed: %.100s", strerror(errno));
634
635	/* we keep a reference to the pty master */
636	ptymaster = dup(ptyfd);
637	if (ptymaster < 0)
638		packet_disconnect("dup #2 failed: %.100s", strerror(errno));
639	s->ptymaster = ptymaster;
640
641	/* Enter interactive session. */
642	if (compat20) {
643		session_set_fds(s, ptyfd, fdout, -1);
644	} else {
645		server_loop(pid, ptyfd, fdout, -1);
646		/* server_loop _has_ closed ptyfd and fdout. */
647		session_pty_cleanup(s);
648	}
649}
650
651/*
652 * Sets the value of the given variable in the environment.  If the variable
653 * already exists, its value is overriden.
654 */
655void
656child_set_env(char ***envp, unsigned int *envsizep, const char *name,
657	      const char *value)
658{
659	unsigned int i, namelen;
660	char **env;
661
662	/*
663	 * Find the slot where the value should be stored.  If the variable
664	 * already exists, we reuse the slot; otherwise we append a new slot
665	 * at the end of the array, expanding if necessary.
666	 */
667	env = *envp;
668	namelen = strlen(name);
669	for (i = 0; env[i]; i++)
670		if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
671			break;
672	if (env[i]) {
673		/* Reuse the slot. */
674		xfree(env[i]);
675	} else {
676		/* New variable.  Expand if necessary. */
677		if (i >= (*envsizep) - 1) {
678			(*envsizep) += 50;
679			env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
680		}
681		/* Need to set the NULL pointer at end of array beyond the new slot. */
682		env[i + 1] = NULL;
683	}
684
685	/* Allocate space and format the variable in the appropriate slot. */
686	env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
687	snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
688}
689
690/*
691 * Reads environment variables from the given file and adds/overrides them
692 * into the environment.  If the file does not exist, this does nothing.
693 * Otherwise, it must consist of empty lines, comments (line starts with '#')
694 * and assignments of the form name=value.  No other forms are allowed.
695 */
696void
697read_environment_file(char ***env, unsigned int *envsize,
698		      const char *filename)
699{
700	FILE *f;
701	char buf[4096];
702	char *cp, *value;
703
704	f = fopen(filename, "r");
705	if (!f)
706		return;
707
708	while (fgets(buf, sizeof(buf), f)) {
709		for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
710			;
711		if (!*cp || *cp == '#' || *cp == '\n')
712			continue;
713		if (strchr(cp, '\n'))
714			*strchr(cp, '\n') = '\0';
715		value = strchr(cp, '=');
716		if (value == NULL) {
717			fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
718			continue;
719		}
720		/* Replace the equals sign by nul, and advance value to the value string. */
721		*value = '\0';
722		value++;
723		child_set_env(env, envsize, cp, value);
724	}
725	fclose(f);
726}
727
728/*
729 * Performs common processing for the child, such as setting up the
730 * environment, closing extra file descriptors, setting the user and group
731 * ids, and executing the command or shell.
732 */
733void
734do_child(const char *command, struct passwd * pw, const char *term,
735	 const char *display, const char *auth_proto,
736	 const char *auth_data, const char *ttyname)
737{
738	const char *shell, *cp = NULL;
739	char buf[256];
740	FILE *f;
741	unsigned int envsize, i;
742	char **env;
743	extern char **environ;
744	struct stat st;
745	char *argv[10];
746
747	f = fopen("/etc/nologin", "r");
748	if (f) {
749		/* /etc/nologin exists.  Print its contents and exit. */
750		while (fgets(buf, sizeof(buf), f))
751			fputs(buf, stderr);
752		fclose(f);
753		if (pw->pw_uid != 0)
754			exit(254);
755	}
756	/* Set login name in the kernel. */
757	if (setlogin(pw->pw_name) < 0)
758		error("setlogin failed: %s", strerror(errno));
759
760	/* Set uid, gid, and groups. */
761	/* Login(1) does this as well, and it needs uid 0 for the "-h"
762	   switch, so we let login(1) to this for us. */
763	if (!options.use_login) {
764		if (getuid() == 0 || geteuid() == 0) {
765			if (setgid(pw->pw_gid) < 0) {
766				perror("setgid");
767				exit(1);
768			}
769			/* Initialize the group list. */
770			if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
771				perror("initgroups");
772				exit(1);
773			}
774			endgrent();
775
776			/* Permanently switch to the desired uid. */
777			permanently_set_uid(pw->pw_uid);
778		}
779		if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
780			fatal("Failed to set uids to %d.", (int) pw->pw_uid);
781	}
782	/*
783	 * Get the shell from the password data.  An empty shell field is
784	 * legal, and means /bin/sh.
785	 */
786	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
787
788#ifdef AFS
789	/* Try to get AFS tokens for the local cell. */
790	if (k_hasafs()) {
791		char cell[64];
792
793		if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
794			krb_afslog(cell, 0);
795
796		krb_afslog(0, 0);
797	}
798#endif /* AFS */
799
800	/* Initialize the environment. */
801	envsize = 100;
802	env = xmalloc(envsize * sizeof(char *));
803	env[0] = NULL;
804
805	if (!options.use_login) {
806		/* Set basic environment. */
807		child_set_env(&env, &envsize, "USER", pw->pw_name);
808		child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
809		child_set_env(&env, &envsize, "HOME", pw->pw_dir);
810		child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
811
812		snprintf(buf, sizeof buf, "%.200s/%.50s",
813			 _PATH_MAILDIR, pw->pw_name);
814		child_set_env(&env, &envsize, "MAIL", buf);
815
816		/* Normal systems set SHELL by default. */
817		child_set_env(&env, &envsize, "SHELL", shell);
818	}
819	if (getenv("TZ"))
820		child_set_env(&env, &envsize, "TZ", getenv("TZ"));
821
822	/* Set custom environment options from RSA authentication. */
823	while (custom_environment) {
824		struct envstring *ce = custom_environment;
825		char *s = ce->s;
826		int i;
827		for (i = 0; s[i] != '=' && s[i]; i++);
828		if (s[i] == '=') {
829			s[i] = 0;
830			child_set_env(&env, &envsize, s, s + i + 1);
831		}
832		custom_environment = ce->next;
833		xfree(ce->s);
834		xfree(ce);
835	}
836
837	snprintf(buf, sizeof buf, "%.50s %d %d",
838		 get_remote_ipaddr(), get_remote_port(), get_local_port());
839	child_set_env(&env, &envsize, "SSH_CLIENT", buf);
840
841	if (ttyname)
842		child_set_env(&env, &envsize, "SSH_TTY", ttyname);
843	if (term)
844		child_set_env(&env, &envsize, "TERM", term);
845	if (display)
846		child_set_env(&env, &envsize, "DISPLAY", display);
847
848#ifdef KRB4
849	{
850		extern char *ticket;
851
852		if (ticket)
853			child_set_env(&env, &envsize, "KRBTKFILE", ticket);
854	}
855#endif /* KRB4 */
856
857	if (xauthfile)
858		child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
859	if (auth_get_socket_name() != NULL)
860		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
861			      auth_get_socket_name());
862
863	/* read $HOME/.ssh/environment. */
864	if (!options.use_login) {
865		snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir);
866		read_environment_file(&env, &envsize, buf);
867	}
868	if (debug_flag) {
869		/* dump the environment */
870		fprintf(stderr, "Environment:\n");
871		for (i = 0; env[i]; i++)
872			fprintf(stderr, "  %.200s\n", env[i]);
873	}
874	/*
875	 * Close the connection descriptors; note that this is the child, and
876	 * the server will still have the socket open, and it is important
877	 * that we do not shutdown it.  Note that the descriptors cannot be
878	 * closed before building the environment, as we call
879	 * get_remote_ipaddr there.
880	 */
881	if (packet_get_connection_in() == packet_get_connection_out())
882		close(packet_get_connection_in());
883	else {
884		close(packet_get_connection_in());
885		close(packet_get_connection_out());
886	}
887	/*
888	 * Close all descriptors related to channels.  They will still remain
889	 * open in the parent.
890	 */
891	/* XXX better use close-on-exec? -markus */
892	channel_close_all();
893
894	/*
895	 * Close any extra file descriptors.  Note that there may still be
896	 * descriptors left by system functions.  They will be closed later.
897	 */
898	endpwent();
899
900	/*
901	 * Close any extra open file descriptors so that we don\'t have them
902	 * hanging around in clients.  Note that we want to do this after
903	 * initgroups, because at least on Solaris 2.3 it leaves file
904	 * descriptors open.
905	 */
906	for (i = 3; i < 64; i++)
907		close(i);
908
909	/* Change current directory to the user\'s home directory. */
910	if (chdir(pw->pw_dir) < 0)
911		fprintf(stderr, "Could not chdir to home directory %s: %s\n",
912			pw->pw_dir, strerror(errno));
913
914	/*
915	 * Must take new environment into use so that .ssh/rc, /etc/sshrc and
916	 * xauth are run in the proper environment.
917	 */
918	environ = env;
919
920	/*
921	 * Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first
922	 * in this order).
923	 */
924	if (!options.use_login) {
925		if (stat(SSH_USER_RC, &st) >= 0) {
926			if (debug_flag)
927				fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC);
928
929			f = popen("/bin/sh " SSH_USER_RC, "w");
930			if (f) {
931				if (auth_proto != NULL && auth_data != NULL)
932					fprintf(f, "%s %s\n", auth_proto, auth_data);
933				pclose(f);
934			} else
935				fprintf(stderr, "Could not run %s\n", SSH_USER_RC);
936		} else if (stat(SSH_SYSTEM_RC, &st) >= 0) {
937			if (debug_flag)
938				fprintf(stderr, "Running /bin/sh %s\n", SSH_SYSTEM_RC);
939
940			f = popen("/bin/sh " SSH_SYSTEM_RC, "w");
941			if (f) {
942				if (auth_proto != NULL && auth_data != NULL)
943					fprintf(f, "%s %s\n", auth_proto, auth_data);
944				pclose(f);
945			} else
946				fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
947		}
948#ifdef XAUTH_PATH
949		else {
950			/* Add authority data to .Xauthority if appropriate. */
951			if (auth_proto != NULL && auth_data != NULL) {
952				if (debug_flag)
953					fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n",
954						XAUTH_PATH, display, auth_proto, auth_data);
955
956				f = popen(XAUTH_PATH " -q -", "w");
957				if (f) {
958					fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data);
959					pclose(f);
960				} else
961					fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH);
962			}
963		}
964#endif /* XAUTH_PATH */
965
966		/* Get the last component of the shell name. */
967		cp = strrchr(shell, '/');
968		if (cp)
969			cp++;
970		else
971			cp = shell;
972	}
973	/*
974	 * If we have no command, execute the shell.  In this case, the shell
975	 * name to be passed in argv[0] is preceded by '-' to indicate that
976	 * this is a login shell.
977	 */
978	if (!command) {
979		if (!options.use_login) {
980			char buf[256];
981
982			/*
983			 * Check for mail if we have a tty and it was enabled
984			 * in server options.
985			 */
986			if (ttyname && options.check_mail) {
987				char *mailbox;
988				struct stat mailstat;
989				mailbox = getenv("MAIL");
990				if (mailbox != NULL) {
991					if (stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0)
992						printf("No mail.\n");
993					else if (mailstat.st_mtime < mailstat.st_atime)
994						printf("You have mail.\n");
995					else
996						printf("You have new mail.\n");
997				}
998			}
999			/* Start the shell.  Set initial character to '-'. */
1000			buf[0] = '-';
1001			strncpy(buf + 1, cp, sizeof(buf) - 1);
1002			buf[sizeof(buf) - 1] = 0;
1003
1004			/* Execute the shell. */
1005			argv[0] = buf;
1006			argv[1] = NULL;
1007			execve(shell, argv, env);
1008
1009			/* Executing the shell failed. */
1010			perror(shell);
1011			exit(1);
1012
1013		} else {
1014			/* Launch login(1). */
1015
1016			execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(),
1017			      "-p", "-f", "--", pw->pw_name, NULL);
1018
1019			/* Login couldn't be executed, die. */
1020
1021			perror("login");
1022			exit(1);
1023		}
1024	}
1025	/*
1026	 * Execute the command using the user's shell.  This uses the -c
1027	 * option to execute the command.
1028	 */
1029	argv[0] = (char *) cp;
1030	argv[1] = "-c";
1031	argv[2] = (char *) command;
1032	argv[3] = NULL;
1033	execve(shell, argv, env);
1034	perror(shell);
1035	exit(1);
1036}
1037
1038Session *
1039session_new(void)
1040{
1041	int i;
1042	static int did_init = 0;
1043	if (!did_init) {
1044		debug("session_new: init");
1045		for(i = 0; i < MAX_SESSIONS; i++) {
1046			sessions[i].used = 0;
1047			sessions[i].self = i;
1048		}
1049		did_init = 1;
1050	}
1051	for(i = 0; i < MAX_SESSIONS; i++) {
1052		Session *s = &sessions[i];
1053		if (! s->used) {
1054			s->pid = 0;
1055			s->extended = 0;
1056			s->chanid = -1;
1057			s->ptyfd = -1;
1058			s->ttyfd = -1;
1059			s->term = NULL;
1060			s->pw = NULL;
1061			s->display = NULL;
1062			s->screen = 0;
1063			s->auth_data = NULL;
1064			s->auth_proto = NULL;
1065			s->used = 1;
1066			s->pw = NULL;
1067			debug("session_new: session %d", i);
1068			return s;
1069		}
1070	}
1071	return NULL;
1072}
1073
1074void
1075session_dump(void)
1076{
1077	int i;
1078	for(i = 0; i < MAX_SESSIONS; i++) {
1079		Session *s = &sessions[i];
1080		debug("dump: used %d session %d %p channel %d pid %d",
1081		    s->used,
1082		    s->self,
1083		    s,
1084		    s->chanid,
1085		    s->pid);
1086	}
1087}
1088
1089int
1090session_open(int chanid)
1091{
1092	Session *s = session_new();
1093	debug("session_open: channel %d", chanid);
1094	if (s == NULL) {
1095		error("no more sessions");
1096		return 0;
1097	}
1098	s->pw = auth_get_user();
1099	if (s->pw == NULL)
1100		fatal("no user for session %i", s->self);
1101	debug("session_open: session %d: link with channel %d", s->self, chanid);
1102	s->chanid = chanid;
1103	return 1;
1104}
1105
1106Session *
1107session_by_channel(int id)
1108{
1109	int i;
1110	for(i = 0; i < MAX_SESSIONS; i++) {
1111		Session *s = &sessions[i];
1112		if (s->used && s->chanid == id) {
1113			debug("session_by_channel: session %d channel %d", i, id);
1114			return s;
1115		}
1116	}
1117	debug("session_by_channel: unknown channel %d", id);
1118	session_dump();
1119	return NULL;
1120}
1121
1122Session *
1123session_by_pid(pid_t pid)
1124{
1125	int i;
1126	debug("session_by_pid: pid %d", pid);
1127	for(i = 0; i < MAX_SESSIONS; i++) {
1128		Session *s = &sessions[i];
1129		if (s->used && s->pid == pid)
1130			return s;
1131	}
1132	error("session_by_pid: unknown pid %d", pid);
1133	session_dump();
1134	return NULL;
1135}
1136
1137int
1138session_window_change_req(Session *s)
1139{
1140	s->col = packet_get_int();
1141	s->row = packet_get_int();
1142	s->xpixel = packet_get_int();
1143	s->ypixel = packet_get_int();
1144	packet_done();
1145	pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1146	return 1;
1147}
1148
1149int
1150session_pty_req(Session *s)
1151{
1152	unsigned int len;
1153	char *term_modes;	/* encoded terminal modes */
1154
1155	if (s->ttyfd != -1)
1156		return 0;
1157	s->term = packet_get_string(&len);
1158	s->col = packet_get_int();
1159	s->row = packet_get_int();
1160	s->xpixel = packet_get_int();
1161	s->ypixel = packet_get_int();
1162	term_modes = packet_get_string(&len);
1163	packet_done();
1164
1165	if (strcmp(s->term, "") == 0) {
1166		xfree(s->term);
1167		s->term = NULL;
1168	}
1169	/* Allocate a pty and open it. */
1170	if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) {
1171		xfree(s->term);
1172		s->term = NULL;
1173		s->ptyfd = -1;
1174		s->ttyfd = -1;
1175		error("session_pty_req: session %d alloc failed", s->self);
1176		xfree(term_modes);
1177		return 0;
1178	}
1179	debug("session_pty_req: session %d alloc %s", s->self, s->tty);
1180	/*
1181	 * Add a cleanup function to clear the utmp entry and record logout
1182	 * time in case we call fatal() (e.g., the connection gets closed).
1183	 */
1184	fatal_add_cleanup(pty_cleanup_proc, (void *)s);
1185	pty_setowner(s->pw, s->tty);
1186	/* Get window size from the packet. */
1187	pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1188
1189	session_proctitle(s);
1190
1191	/* XXX parse and set terminal modes */
1192	xfree(term_modes);
1193	return 1;
1194}
1195
1196int
1197session_subsystem_req(Session *s)
1198{
1199	unsigned int len;
1200	int success = 0;
1201	char *subsys = packet_get_string(&len);
1202
1203	packet_done();
1204	log("subsystem request for %s", subsys);
1205
1206	xfree(subsys);
1207	return success;
1208}
1209
1210int
1211session_x11_req(Session *s)
1212{
1213	if (!options.x11_forwarding) {
1214		debug("X11 forwarding disabled in server configuration file.");
1215		return 0;
1216	}
1217	if (xauthfile != NULL) {
1218		debug("X11 fwd already started.");
1219		return 0;
1220	}
1221
1222	debug("Received request for X11 forwarding with auth spoofing.");
1223	if (s->display != NULL)
1224		packet_disconnect("Protocol error: X11 display already set.");
1225
1226	s->single_connection = packet_get_char();
1227	s->auth_proto = packet_get_string(NULL);
1228	s->auth_data = packet_get_string(NULL);
1229	s->screen = packet_get_int();
1230	packet_done();
1231
1232	s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
1233	if (s->display == NULL) {
1234		xfree(s->auth_proto);
1235		xfree(s->auth_data);
1236		return 0;
1237	}
1238	xauthfile = xmalloc(MAXPATHLEN);
1239	strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
1240	temporarily_use_uid(s->pw->pw_uid);
1241	if (mkdtemp(xauthfile) == NULL) {
1242		restore_uid();
1243		error("private X11 dir: mkdtemp %s failed: %s",
1244		    xauthfile, strerror(errno));
1245		xfree(xauthfile);
1246		xauthfile = NULL;
1247		xfree(s->auth_proto);
1248		xfree(s->auth_data);
1249		/* XXXX remove listening channels */
1250		return 0;
1251	}
1252	strlcat(xauthfile, "/cookies", MAXPATHLEN);
1253	open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
1254	restore_uid();
1255	fatal_add_cleanup(xauthfile_cleanup_proc, s);
1256	return 1;
1257}
1258
1259void
1260session_input_channel_req(int id, void *arg)
1261{
1262	unsigned int len;
1263	int reply;
1264	int success = 0;
1265	char *rtype;
1266	Session *s;
1267	Channel *c;
1268
1269	rtype = packet_get_string(&len);
1270	reply = packet_get_char();
1271
1272	s = session_by_channel(id);
1273	if (s == NULL)
1274		fatal("session_input_channel_req: channel %d: no session", id);
1275	c = channel_lookup(id);
1276	if (c == NULL)
1277		fatal("session_input_channel_req: channel %d: bad channel", id);
1278
1279	debug("session_input_channel_req: session %d channel %d request %s reply %d",
1280	    s->self, id, rtype, reply);
1281
1282	/*
1283	 * a session is in LARVAL state until a shell
1284	 * or programm is executed
1285	 */
1286	if (c->type == SSH_CHANNEL_LARVAL) {
1287		if (strcmp(rtype, "shell") == 0) {
1288			packet_done();
1289			s->extended = 1;
1290			if (s->ttyfd == -1)
1291				do_exec_no_pty(s, NULL, s->pw);
1292			else
1293				do_exec_pty(s, NULL, s->pw);
1294			success = 1;
1295		} else if (strcmp(rtype, "exec") == 0) {
1296			char *command = packet_get_string(&len);
1297			packet_done();
1298			s->extended = 1;
1299			if (s->ttyfd == -1)
1300				do_exec_no_pty(s, command, s->pw);
1301			else
1302				do_exec_pty(s, command, s->pw);
1303			xfree(command);
1304			success = 1;
1305		} else if (strcmp(rtype, "pty-req") == 0) {
1306			success =  session_pty_req(s);
1307		} else if (strcmp(rtype, "x11-req") == 0) {
1308			success = session_x11_req(s);
1309		} else if (strcmp(rtype, "subsystem") == 0) {
1310			success = session_subsystem_req(s);
1311		}
1312	}
1313	if (strcmp(rtype, "window-change") == 0) {
1314		success = session_window_change_req(s);
1315	}
1316
1317	if (reply) {
1318		packet_start(success ?
1319		    SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1320		packet_put_int(c->remote_id);
1321		packet_send();
1322	}
1323	xfree(rtype);
1324}
1325
1326void
1327session_set_fds(Session *s, int fdin, int fdout, int fderr)
1328{
1329	if (!compat20)
1330		fatal("session_set_fds: called for proto != 2.0");
1331	/*
1332	 * now that have a child and a pipe to the child,
1333	 * we can activate our channel and register the fd's
1334	 */
1335	if (s->chanid == -1)
1336		fatal("no channel for session %d", s->self);
1337	channel_set_fds(s->chanid,
1338	    fdout, fdin, fderr,
1339	    fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ);
1340}
1341
1342void
1343session_pty_cleanup(Session *s)
1344{
1345	if (s == NULL || s->ttyfd == -1)
1346		return;
1347
1348	debug("session_pty_cleanup: session %i release %s", s->self, s->tty);
1349
1350	/* Cancel the cleanup function. */
1351	fatal_remove_cleanup(pty_cleanup_proc, (void *)s);
1352
1353	/* Record that the user has logged out. */
1354	record_logout(s->pid, s->tty);
1355
1356	/* Release the pseudo-tty. */
1357	pty_release(s->tty);
1358
1359	/*
1360	 * Close the server side of the socket pairs.  We must do this after
1361	 * the pty cleanup, so that another process doesn't get this pty
1362	 * while we're still cleaning up.
1363	 */
1364	if (close(s->ptymaster) < 0)
1365		error("close(s->ptymaster): %s", strerror(errno));
1366}
1367
1368void
1369session_exit_message(Session *s, int status)
1370{
1371	Channel *c;
1372	if (s == NULL)
1373		fatal("session_close: no session");
1374	c = channel_lookup(s->chanid);
1375	if (c == NULL)
1376		fatal("session_close: session %d: no channel %d",
1377		    s->self, s->chanid);
1378	debug("session_exit_message: session %d channel %d pid %d",
1379	    s->self, s->chanid, s->pid);
1380
1381	if (WIFEXITED(status)) {
1382		channel_request_start(s->chanid,
1383		    "exit-status", 0);
1384		packet_put_int(WEXITSTATUS(status));
1385		packet_send();
1386	} else if (WIFSIGNALED(status)) {
1387		channel_request_start(s->chanid,
1388		    "exit-signal", 0);
1389		packet_put_int(WTERMSIG(status));
1390		packet_put_char(WCOREDUMP(status));
1391		packet_put_cstring("");
1392		packet_put_cstring("");
1393		packet_send();
1394	} else {
1395		/* Some weird exit cause.  Just exit. */
1396		packet_disconnect("wait returned status %04x.", status);
1397	}
1398
1399	/* disconnect channel */
1400	debug("session_exit_message: release channel %d", s->chanid);
1401	channel_cancel_cleanup(s->chanid);
1402	/*
1403	 * emulate a write failure with 'chan_write_failed', nobody will be
1404	 * interested in data we write.
1405	 * Note that we must not call 'chan_read_failed', since there could
1406	 * be some more data waiting in the pipe.
1407	 */
1408	if (c->ostate != CHAN_OUTPUT_CLOSED)
1409		chan_write_failed(c);
1410	s->chanid = -1;
1411}
1412
1413void
1414session_free(Session *s)
1415{
1416	debug("session_free: session %d pid %d", s->self, s->pid);
1417	if (s->term)
1418		xfree(s->term);
1419	if (s->display)
1420		xfree(s->display);
1421	if (s->auth_data)
1422		xfree(s->auth_data);
1423	if (s->auth_proto)
1424		xfree(s->auth_proto);
1425	s->used = 0;
1426}
1427
1428void
1429session_close(Session *s)
1430{
1431	session_pty_cleanup(s);
1432	session_free(s);
1433	session_proctitle(s);
1434}
1435
1436void
1437session_close_by_pid(pid_t pid, int status)
1438{
1439	Session *s = session_by_pid(pid);
1440	if (s == NULL) {
1441		debug("session_close_by_pid: no session for pid %d", s->pid);
1442		return;
1443	}
1444	if (s->chanid != -1)
1445		session_exit_message(s, status);
1446	session_close(s);
1447}
1448
1449/*
1450 * this is called when a channel dies before
1451 * the session 'child' itself dies
1452 */
1453void
1454session_close_by_channel(int id, void *arg)
1455{
1456	Session *s = session_by_channel(id);
1457	if (s == NULL) {
1458		debug("session_close_by_channel: no session for channel %d", id);
1459		return;
1460	}
1461	/* disconnect channel */
1462	channel_cancel_cleanup(s->chanid);
1463	s->chanid = -1;
1464
1465	debug("session_close_by_channel: channel %d kill %d", id, s->pid);
1466	if (s->pid == 0) {
1467		/* close session immediately */
1468		session_close(s);
1469	} else {
1470		/* notify child, delay session cleanup */
1471		if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0)
1472			error("session_close_by_channel: kill %d: %s",
1473			    s->pid, strerror(errno));
1474	}
1475}
1476
1477char *
1478session_tty_list(void)
1479{
1480	static char buf[1024];
1481	int i;
1482	buf[0] = '\0';
1483	for(i = 0; i < MAX_SESSIONS; i++) {
1484		Session *s = &sessions[i];
1485		if (s->used && s->ttyfd != -1) {
1486			if (buf[0] != '\0')
1487				strlcat(buf, ",", sizeof buf);
1488			strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf);
1489		}
1490	}
1491	if (buf[0] == '\0')
1492		strlcpy(buf, "notty", sizeof buf);
1493	return buf;
1494}
1495
1496void
1497session_proctitle(Session *s)
1498{
1499	if (s->pw == NULL)
1500		error("no user for session %d", s->self);
1501	else
1502		setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
1503}
1504
1505void
1506do_authenticated2(void)
1507{
1508	/*
1509	 * Cancel the alarm we set to limit the time taken for
1510	 * authentication.
1511	 */
1512	alarm(0);
1513	server_loop2();
1514	if (xauthfile)
1515		xauthfile_cleanup_proc(NULL);
1516}
1517