session.c revision 77925
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
31590Srgrimes *                    All rights reserved
41590Srgrimes *
51590Srgrimes * As far as I am concerned, the code I have written for this software
61590Srgrimes * can be used freely for any purpose.  Any derived versions of this
71590Srgrimes * software must be clearly marked as such, and if the derived work is
81590Srgrimes * incompatible with the protocol description in the RFC file, it must be
91590Srgrimes * called by a name other than "ssh" or "Secure Shell".
101590Srgrimes *
111590Srgrimes * SSH2 support by Markus Friedl.
121590Srgrimes * Copyright (c) 2000 Markus Friedl.  All rights reserved.
131590Srgrimes *
141590Srgrimes * Redistribution and use in source and binary forms, with or without
151590Srgrimes * modification, are permitted provided that the following conditions
161590Srgrimes * are met:
171590Srgrimes * 1. Redistributions of source code must retain the above copyright
181590Srgrimes *    notice, this list of conditions and the following disclaimer.
191590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
201590Srgrimes *    notice, this list of conditions and the following disclaimer in the
211590Srgrimes *    documentation and/or other materials provided with the distribution.
221590Srgrimes *
231590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
241590Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
251590Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
261590Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
271590Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
281590Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
291590Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
301590Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
311590Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
321590Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
331590Srgrimes */
341590Srgrimes
351590Srgrimes#include "includes.h"
361590SrgrimesRCSID("$OpenBSD: session.c,v 1.80 2001/06/04 21:59:43 markus Exp $");
371590SrgrimesRCSID("$FreeBSD: head/crypto/openssh/session.c 77925 2001-06-08 22:22:09Z green $");
381590Srgrimes
391590Srgrimes#include "ssh.h"
401590Srgrimes#include "ssh1.h"
411590Srgrimes#include "ssh2.h"
421590Srgrimes#include "xmalloc.h"
431590Srgrimes#include "sshpty.h"
441590Srgrimes#include "packet.h"
451590Srgrimes#include "buffer.h"
4611914Sphk#include "mpaux.h"
471590Srgrimes#include "uidswap.h"
481590Srgrimes#include "compat.h"
491590Srgrimes#include "channels.h"
501590Srgrimes#include "nchan.h"
511590Srgrimes#include "bufaux.h"
521590Srgrimes#include "auth.h"
531590Srgrimes#include "auth-options.h"
541590Srgrimes#include "pathnames.h"
551590Srgrimes#include "log.h"
561590Srgrimes#include "servconf.h"
571590Srgrimes#include "sshlogin.h"
581590Srgrimes#include "serverloop.h"
591590Srgrimes#include "canohost.h"
601590Srgrimes#include "session.h"
611590Srgrimes
621590Srgrimes#ifdef __FreeBSD__
631590Srgrimes#define _PATH_CHPASS "/usr/bin/passwd"
641590Srgrimes#endif /* __FreeBSD__ */
651590Srgrimes
661590Srgrimes#ifdef HAVE_LOGIN_CAP
671590Srgrimes#include <login_cap.h>
681590Srgrimes#endif
691590Srgrimes
701590Srgrimes#ifdef KRB5
711590Srgrimesextern krb5_context ssh_context;
721590Srgrimes#endif
731590Srgrimes
741590Srgrimes/* types */
751590Srgrimes
761590Srgrimes#define TTYSZ 64
771590Srgrimestypedef struct Session Session;
781590Srgrimesstruct Session {
791590Srgrimes	int	used;
801590Srgrimes	int	self;
811590Srgrimes	struct	passwd *pw;
821590Srgrimes	pid_t	pid;
831590Srgrimes	/* tty */
841590Srgrimes	char	*term;
851590Srgrimes	int	ptyfd, ttyfd, ptymaster;
861590Srgrimes	int	row, col, xpixel, ypixel;
871590Srgrimes	char	tty[TTYSZ];
881590Srgrimes	/* X11 */
891590Srgrimes	char	*display;
901590Srgrimes	int	screen;
911590Srgrimes	char	*auth_proto;
921590Srgrimes	char	*auth_data;
931590Srgrimes	int	single_connection;
941590Srgrimes	/* proto 2 */
951590Srgrimes	int	chanid;
961590Srgrimes	int	is_subsystem;
971590Srgrimes};
981590Srgrimes
991590Srgrimes/* func */
1001590Srgrimes
1011590SrgrimesSession *session_new(void);
1021590Srgrimesvoid	session_set_fds(Session *s, int fdin, int fdout, int fderr);
1031590Srgrimesvoid	session_pty_cleanup(Session *s);
1041590Srgrimesvoid	session_proctitle(Session *s);
1051590Srgrimesvoid	do_exec_pty(Session *s, const char *command);
1061590Srgrimesvoid	do_exec_no_pty(Session *s, const char *command);
1071590Srgrimesvoid	do_login(Session *s, const char *command);
1081590Srgrimesvoid	do_child(Session *s, const char *command);
1091590Srgrimesvoid	do_motd(void);
1101590Srgrimesint	check_quietlogin(Session *s, const char *command);
1111590Srgrimesvoid	xauthfile_cleanup_proc(void *pw);
1121590Srgrimes
1131590Srgrimesvoid	do_authenticated1(Authctxt *authctxt);
1141590Srgrimesvoid	do_authenticated2(Authctxt *authctxt);
1151590Srgrimes
1161590Srgrimes/* import */
1171590Srgrimesextern ServerOptions options;
1181590Srgrimesextern char *__progname;
1191590Srgrimesextern int log_stderr;
1201590Srgrimesextern int debug_flag;
1211590Srgrimesextern u_int utmp_len;
1221590Srgrimesextern int startup_pipe;
1231590Srgrimesextern void destroy_sensitive_data(void);
1241590Srgrimes
1251590Srgrimes/* Local Xauthority file. */
1261590Srgrimesstatic char *xauthfile;
1271590Srgrimes
12836789Simp/* original command from peer. */
1291590Srgrimeschar *original_command = NULL;
1301590Srgrimes
1311590Srgrimes/* data */
1321590Srgrimes#define MAX_SESSIONS 10
1331590SrgrimesSession	sessions[MAX_SESSIONS];
1341590Srgrimes
1351590Srgrimes#ifdef HAVE_LOGIN_CAP
1361590Srgrimesstatic login_cap_t *lc;
1371590Srgrimes#endif
1381590Srgrimes
1391590Srgrimesvoid
1401590Srgrimesdo_authenticated(Authctxt *authctxt)
1411590Srgrimes{
1421590Srgrimes	/*
1431590Srgrimes	 * Cancel the alarm we set to limit the time taken for
1441590Srgrimes	 * authentication.
1451590Srgrimes	 */
1461590Srgrimes	alarm(0);
1471590Srgrimes	if (startup_pipe != -1) {
1481590Srgrimes		close(startup_pipe);
1491590Srgrimes		startup_pipe = -1;
1501590Srgrimes	}
1511590Srgrimes#ifdef HAVE_LOGIN_CAP
1521590Srgrimes	if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) {
1531590Srgrimes		error("unable to get login class");
1541590Srgrimes		return;
1551590Srgrimes	}
1561590Srgrimes#ifdef BSD_AUTH
1571590Srgrimes	if (auth_approval(NULL, lc, authctxt->pw->pw_name, "ssh") <= 0) {
1581590Srgrimes		packet_disconnect("Approval failure for %s",
1591590Srgrimes		    authctxt->pw->pw_name);
1601590Srgrimes	}
1611590Srgrimes#endif
1621590Srgrimes#endif
1631590Srgrimes	/* setup the channel layer */
1641590Srgrimes	if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
1651590Srgrimes		channel_permit_all_opens();
1661590Srgrimes
1671590Srgrimes	if (compat20)
1681590Srgrimes		do_authenticated2(authctxt);
1691590Srgrimes	else
1701590Srgrimes		do_authenticated1(authctxt);
1711590Srgrimes
1721590Srgrimes	/* remote user's local Xauthority file and agent socket */
1731590Srgrimes	if (xauthfile)
1741590Srgrimes		xauthfile_cleanup_proc(authctxt->pw);
1751590Srgrimes	if (auth_get_socket_name())
1761590Srgrimes		auth_sock_cleanup_proc(authctxt->pw);
1771590Srgrimes}
1781590Srgrimes
1791590Srgrimes/*
1801590Srgrimes * Remove local Xauthority file.
1811590Srgrimes */
1821590Srgrimesvoid
1831590Srgrimesxauthfile_cleanup_proc(void *_pw)
1841590Srgrimes{
1851590Srgrimes	struct passwd *pw = _pw;
1861590Srgrimes	char *p;
1871590Srgrimes
1881590Srgrimes	debug("xauthfile_cleanup_proc called");
1891590Srgrimes	if (xauthfile != NULL) {
1901590Srgrimes		temporarily_use_uid(pw);
1911590Srgrimes		unlink(xauthfile);
1921590Srgrimes		p = strrchr(xauthfile, '/');
1931590Srgrimes		if (p != NULL) {
1941590Srgrimes			*p = '\0';
1951590Srgrimes			rmdir(xauthfile);
1961590Srgrimes		}
1971590Srgrimes		xfree(xauthfile);
1981590Srgrimes		xauthfile = NULL;
1991590Srgrimes		restore_uid();
2001590Srgrimes	}
2011590Srgrimes}
2021590Srgrimes
2031590Srgrimes/*
2041590Srgrimes * Function to perform cleanup if we get aborted abnormally (e.g., due to a
2051590Srgrimes * dropped connection).
2061590Srgrimes */
2071590Srgrimesvoid
2081590Srgrimespty_cleanup_proc(void *session)
2091590Srgrimes{
2101590Srgrimes	Session *s=session;
2111590Srgrimes	if (s == NULL)
2128874Srgrimes		fatal("pty_cleanup_proc: no session");
2131590Srgrimes	debug("pty_cleanup_proc: %s", s->tty);
2141590Srgrimes
2151590Srgrimes	if (s->pid != 0) {
2161590Srgrimes		/* Record that the user has logged out. */
2171590Srgrimes		record_logout(s->pid, s->tty);
2181590Srgrimes	}
2191590Srgrimes
2201590Srgrimes	/* Release the pseudo-tty. */
2211590Srgrimes	pty_release(s->tty);
2221590Srgrimes}
2231590Srgrimes
2241590Srgrimes/*
2251590Srgrimes * Prepares for an interactive session.  This is called after the user has
2261590Srgrimes * been successfully authenticated.  During this message exchange, pseudo
2271590Srgrimes * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
2281590Srgrimes * are requested, etc.
2291590Srgrimes */
2301590Srgrimesvoid
2311590Srgrimesdo_authenticated1(Authctxt *authctxt)
2321590Srgrimes{
2331590Srgrimes	Session *s;
2341590Srgrimes	char *command;
2351590Srgrimes	int success, type, fd, n_bytes, plen, screen_flag, have_pty = 0;
2361590Srgrimes	int compression_level = 0, enable_compression_after_reply = 0;
2371590Srgrimes	u_int proto_len, data_len, dlen;
2381590Srgrimes	struct stat st;
2391590Srgrimes
2401590Srgrimes	s = session_new();
2411590Srgrimes	s->pw = authctxt->pw;
2421590Srgrimes
2431590Srgrimes	/*
2441590Srgrimes	 * We stay in this loop until the client requests to execute a shell
2451590Srgrimes	 * or a command.
246	 */
247	for (;;) {
248		success = 0;
249
250		/* Get a packet from the client. */
251		type = packet_read(&plen);
252
253		/* Process the packet. */
254		switch (type) {
255		case SSH_CMSG_REQUEST_COMPRESSION:
256			packet_integrity_check(plen, 4, type);
257			compression_level = packet_get_int();
258			if (compression_level < 1 || compression_level > 9) {
259				packet_send_debug("Received illegal compression level %d.",
260				     compression_level);
261				break;
262			}
263			/* Enable compression after we have responded with SUCCESS. */
264			enable_compression_after_reply = 1;
265			success = 1;
266			break;
267
268		case SSH_CMSG_REQUEST_PTY:
269			if (no_pty_flag) {
270				debug("Allocating a pty not permitted for this authentication.");
271				break;
272			}
273			if (have_pty)
274				packet_disconnect("Protocol error: you already have a pty.");
275
276			debug("Allocating pty.");
277
278			/* Allocate a pty and open it. */
279			if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
280			    sizeof(s->tty))) {
281				error("Failed to allocate pty.");
282				break;
283			}
284			fatal_add_cleanup(pty_cleanup_proc, (void *)s);
285			pty_setowner(s->pw, s->tty);
286
287			/* Get TERM from the packet.  Note that the value may be of arbitrary length. */
288			s->term = packet_get_string(&dlen);
289			packet_integrity_check(dlen, strlen(s->term), type);
290			/* packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type); */
291			/* Remaining bytes */
292			n_bytes = plen - (4 + dlen + 4 * 4);
293
294			if (strcmp(s->term, "") == 0) {
295				xfree(s->term);
296				s->term = NULL;
297			}
298			/* Get window size from the packet. */
299			s->row = packet_get_int();
300			s->col = packet_get_int();
301			s->xpixel = packet_get_int();
302			s->ypixel = packet_get_int();
303			pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
304
305			/* Get tty modes from the packet. */
306			tty_parse_modes(s->ttyfd, &n_bytes);
307			packet_integrity_check(plen, 4 + dlen + 4 * 4 + n_bytes, type);
308
309			session_proctitle(s);
310
311			/* Indicate that we now have a pty. */
312			success = 1;
313			have_pty = 1;
314			break;
315
316		case SSH_CMSG_X11_REQUEST_FORWARDING:
317			if (!options.x11_forwarding) {
318				packet_send_debug("X11 forwarding disabled in server configuration file.");
319				break;
320			}
321			if (!options.xauth_location ||
322			    (stat(options.xauth_location, &st) == -1)) {
323				packet_send_debug("No xauth program; cannot forward with spoofing.");
324				break;
325			}
326			if (no_x11_forwarding_flag) {
327				packet_send_debug("X11 forwarding not permitted for this authentication.");
328				break;
329			}
330			debug("Received request for X11 forwarding with auth spoofing.");
331			if (s->display != NULL)
332				packet_disconnect("Protocol error: X11 display already set.");
333
334			s->auth_proto = packet_get_string(&proto_len);
335			s->auth_data = packet_get_string(&data_len);
336
337			screen_flag = packet_get_protocol_flags() &
338			    SSH_PROTOFLAG_SCREEN_NUMBER;
339			debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);
340
341			if (packet_remaining() == 4) {
342				if (!screen_flag)
343					debug2("Buggy client: "
344					    "X11 screen flag missing");
345				packet_integrity_check(plen,
346				    4 + proto_len + 4 + data_len + 4, type);
347				s->screen = packet_get_int();
348			} else {
349				packet_integrity_check(plen,
350				    4 + proto_len + 4 + data_len, type);
351				s->screen = 0;
352			}
353			s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
354
355			if (s->display == NULL)
356				break;
357
358			/* Setup to always have a local .Xauthority. */
359			xauthfile = xmalloc(MAXPATHLEN);
360			strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
361			temporarily_use_uid(s->pw);
362			if (mkdtemp(xauthfile) == NULL) {
363				restore_uid();
364				error("private X11 dir: mkdtemp %s failed: %s",
365				    xauthfile, strerror(errno));
366				xfree(xauthfile);
367				xauthfile = NULL;
368				/* XXXX remove listening channels */
369				break;
370			}
371			strlcat(xauthfile, "/cookies", MAXPATHLEN);
372			fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
373			if (fd >= 0)
374				close(fd);
375			restore_uid();
376			fatal_add_cleanup(xauthfile_cleanup_proc, s->pw);
377			success = 1;
378			break;
379
380		case SSH_CMSG_AGENT_REQUEST_FORWARDING:
381			if (no_agent_forwarding_flag || compat13) {
382				debug("Authentication agent forwarding not permitted for this authentication.");
383				break;
384			}
385			debug("Received authentication agent forwarding request.");
386			success = auth_input_request_forwarding(s->pw);
387			break;
388
389		case SSH_CMSG_PORT_FORWARD_REQUEST:
390			if (no_port_forwarding_flag) {
391				debug("Port forwarding not permitted for this authentication.");
392				break;
393			}
394			if (!options.allow_tcp_forwarding) {
395				debug("Port forwarding not permitted.");
396				break;
397			}
398			debug("Received TCP/IP port forwarding request.");
399			channel_input_port_forward_request(s->pw->pw_uid == 0, options.gateway_ports);
400			success = 1;
401			break;
402
403		case SSH_CMSG_MAX_PACKET_SIZE:
404			if (packet_set_maxsize(packet_get_int()) > 0)
405				success = 1;
406			break;
407
408		case SSH_CMSG_EXEC_SHELL:
409		case SSH_CMSG_EXEC_CMD:
410			if (type == SSH_CMSG_EXEC_CMD) {
411				command = packet_get_string(&dlen);
412				debug("Exec command '%.500s'", command);
413				packet_integrity_check(plen, 4 + dlen, type);
414			} else {
415				command = NULL;
416				packet_integrity_check(plen, 0, type);
417			}
418			if (forced_command != NULL) {
419				original_command = command;
420				command = forced_command;
421				debug("Forced command '%.500s'", forced_command);
422			}
423			if (have_pty)
424				do_exec_pty(s, command);
425			else
426				do_exec_no_pty(s, command);
427
428			if (command != NULL)
429				xfree(command);
430			return;
431
432		default:
433			/*
434			 * Any unknown messages in this phase are ignored,
435			 * and a failure message is returned.
436			 */
437			log("Unknown packet type received after authentication: %d", type);
438		}
439		packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
440		packet_send();
441		packet_write_wait();
442
443		/* Enable compression now that we have replied if appropriate. */
444		if (enable_compression_after_reply) {
445			enable_compression_after_reply = 0;
446			packet_start_compression(compression_level);
447		}
448	}
449}
450
451/*
452 * This is called to fork and execute a command when we have no tty.  This
453 * will call do_child from the child, and server_loop from the parent after
454 * setting up file descriptors and such.
455 */
456void
457do_exec_no_pty(Session *s, const char *command)
458{
459	int pid;
460
461#ifdef USE_PIPES
462	int pin[2], pout[2], perr[2];
463	/* Allocate pipes for communicating with the program. */
464	if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
465		packet_disconnect("Could not create pipes: %.100s",
466				  strerror(errno));
467#else /* USE_PIPES */
468	int inout[2], err[2];
469	/* Uses socket pairs to communicate with the program. */
470	if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
471	    socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
472		packet_disconnect("Could not create socket pairs: %.100s",
473				  strerror(errno));
474#endif /* USE_PIPES */
475	if (s == NULL)
476		fatal("do_exec_no_pty: no session");
477
478	session_proctitle(s);
479
480#ifdef USE_PAM
481	do_pam_setcred();
482#endif /* USE_PAM */
483
484	/* Fork the child. */
485	if ((pid = fork()) == 0) {
486		/* Child.  Reinitialize the log since the pid has changed. */
487		log_init(__progname, options.log_level, options.log_facility, log_stderr);
488
489		/*
490		 * Create a new session and process group since the 4.4BSD
491		 * setlogin() affects the entire process group.
492		 */
493		if (setsid() < 0)
494			error("setsid failed: %.100s", strerror(errno));
495
496#ifdef USE_PIPES
497		/*
498		 * Redirect stdin.  We close the parent side of the socket
499		 * pair, and make the child side the standard input.
500		 */
501		close(pin[1]);
502		if (dup2(pin[0], 0) < 0)
503			perror("dup2 stdin");
504		close(pin[0]);
505
506		/* Redirect stdout. */
507		close(pout[0]);
508		if (dup2(pout[1], 1) < 0)
509			perror("dup2 stdout");
510		close(pout[1]);
511
512		/* Redirect stderr. */
513		close(perr[0]);
514		if (dup2(perr[1], 2) < 0)
515			perror("dup2 stderr");
516		close(perr[1]);
517#else /* USE_PIPES */
518		/*
519		 * Redirect stdin, stdout, and stderr.  Stdin and stdout will
520		 * use the same socket, as some programs (particularly rdist)
521		 * seem to depend on it.
522		 */
523		close(inout[1]);
524		close(err[1]);
525		if (dup2(inout[0], 0) < 0)	/* stdin */
526			perror("dup2 stdin");
527		if (dup2(inout[0], 1) < 0)	/* stdout.  Note: same socket as stdin. */
528			perror("dup2 stdout");
529		if (dup2(err[0], 2) < 0)	/* stderr */
530			perror("dup2 stderr");
531#endif /* USE_PIPES */
532
533		/* Do processing for the child (exec command etc). */
534		do_child(s, command);
535		/* NOTREACHED */
536	}
537	if (pid < 0)
538		packet_disconnect("fork failed: %.100s", strerror(errno));
539	s->pid = pid;
540	/* Set interactive/non-interactive mode. */
541	packet_set_interactive(s->display != NULL);
542#ifdef USE_PIPES
543	/* We are the parent.  Close the child sides of the pipes. */
544	close(pin[0]);
545	close(pout[1]);
546	close(perr[1]);
547
548	if (compat20) {
549		session_set_fds(s, pin[1], pout[0], s->is_subsystem ? -1 : perr[0]);
550	} else {
551		/* Enter the interactive session. */
552		server_loop(pid, pin[1], pout[0], perr[0]);
553		/* server_loop has closed pin[1], pout[0], and perr[0]. */
554	}
555#else /* USE_PIPES */
556	/* We are the parent.  Close the child sides of the socket pairs. */
557	close(inout[0]);
558	close(err[0]);
559
560	/*
561	 * Enter the interactive session.  Note: server_loop must be able to
562	 * handle the case that fdin and fdout are the same.
563	 */
564	if (compat20) {
565		session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]);
566	} else {
567		server_loop(pid, inout[1], inout[1], err[1]);
568		/* server_loop has closed inout[1] and err[1]. */
569	}
570#endif /* USE_PIPES */
571}
572
573/*
574 * This is called to fork and execute a command when we have a tty.  This
575 * will call do_child from the child, and server_loop from the parent after
576 * setting up file descriptors, controlling tty, updating wtmp, utmp,
577 * lastlog, and other such operations.
578 */
579void
580do_exec_pty(Session *s, const char *command)
581{
582	int fdout, ptyfd, ttyfd, ptymaster;
583	pid_t pid;
584
585	if (s == NULL)
586		fatal("do_exec_pty: no session");
587	ptyfd = s->ptyfd;
588	ttyfd = s->ttyfd;
589
590#ifdef USE_PAM
591	do_pam_session(s->pw->pw_name, s->tty);
592	do_pam_setcred();
593#endif /* USE_PAM */
594
595	/* Fork the child. */
596	if ((pid = fork()) == 0) {
597		/* Child.  Reinitialize the log because the pid has changed. */
598		log_init(__progname, options.log_level, options.log_facility, log_stderr);
599
600		/* Close the master side of the pseudo tty. */
601		close(ptyfd);
602
603		/* Make the pseudo tty our controlling tty. */
604		pty_make_controlling_tty(&ttyfd, s->tty);
605
606		/* Redirect stdin from the pseudo tty. */
607		if (dup2(ttyfd, fileno(stdin)) < 0)
608			error("dup2 stdin failed: %.100s", strerror(errno));
609
610		/* Redirect stdout to the pseudo tty. */
611		if (dup2(ttyfd, fileno(stdout)) < 0)
612			error("dup2 stdin failed: %.100s", strerror(errno));
613
614		/* Redirect stderr to the pseudo tty. */
615		if (dup2(ttyfd, fileno(stderr)) < 0)
616			error("dup2 stdin failed: %.100s", strerror(errno));
617
618		/* Close the extra descriptor for the pseudo tty. */
619		close(ttyfd);
620
621		/* record login, etc. similar to login(1) */
622		if (!(options.use_login && command == NULL))
623			do_login(s, command);
624
625		/* Do common processing for the child, such as execing the command. */
626		do_child(s, command);
627		/* NOTREACHED */
628	}
629	if (pid < 0)
630		packet_disconnect("fork failed: %.100s", strerror(errno));
631	s->pid = pid;
632
633	/* Parent.  Close the slave side of the pseudo tty. */
634	close(ttyfd);
635
636	/*
637	 * Create another descriptor of the pty master side for use as the
638	 * standard input.  We could use the original descriptor, but this
639	 * simplifies code in server_loop.  The descriptor is bidirectional.
640	 */
641	fdout = dup(ptyfd);
642	if (fdout < 0)
643		packet_disconnect("dup #1 failed: %.100s", strerror(errno));
644
645	/* we keep a reference to the pty master */
646	ptymaster = dup(ptyfd);
647	if (ptymaster < 0)
648		packet_disconnect("dup #2 failed: %.100s", strerror(errno));
649	s->ptymaster = ptymaster;
650
651	/* Enter interactive session. */
652	packet_set_interactive(1);
653	if (compat20) {
654		session_set_fds(s, ptyfd, fdout, -1);
655	} else {
656		server_loop(pid, ptyfd, fdout, -1);
657		/* server_loop _has_ closed ptyfd and fdout. */
658		session_pty_cleanup(s);
659	}
660}
661
662/* administrative, login(1)-like work */
663void
664do_login(Session *s, const char *command)
665{
666	FILE *f;
667	char *time_string, *newcommand;
668	char buf[256];
669	char hostname[MAXHOSTNAMELEN];
670	socklen_t fromlen;
671	struct sockaddr_storage from;
672	time_t last_login_time;
673	struct passwd * pw = s->pw;
674	pid_t pid = getpid();
675#ifdef HAVE_LOGIN_CAP
676	char *fname;
677#endif /* HAVE_LOGIN_CAP */
678#ifdef __FreeBSD__
679#define DEFAULT_WARN  (2L * 7L * 86400L)  /* Two weeks */
680	struct timeval tv;
681	time_t warntime = DEFAULT_WARN;
682#endif /* __FreeBSD__ */
683
684	/*
685	 * Get IP address of client. If the connection is not a socket, let
686	 * the address be 0.0.0.0.
687	 */
688	memset(&from, 0, sizeof(from));
689	if (packet_connection_is_on_socket()) {
690		fromlen = sizeof(from);
691		if (getpeername(packet_get_connection_in(),
692		     (struct sockaddr *) & from, &fromlen) < 0) {
693			debug("getpeername: %.100s", strerror(errno));
694			fatal_cleanup();
695		}
696	}
697
698	/* Get the time and hostname when the user last logged in. */
699	if (options.print_lastlog) {
700		hostname[0] = '\0';
701		last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
702		    hostname, sizeof(hostname));
703	}
704
705	/* Record that there was a login on that tty from the remote host. */
706	record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
707	    get_remote_name_or_ip(utmp_len, options.reverse_mapping_check),
708	    (struct sockaddr *)&from);
709
710#ifdef USE_PAM
711	/*
712	 * If password change is needed, do it now.
713	 * This needs to occur before the ~/.hushlogin check.
714	 */
715	if (pam_password_change_required()) {
716		print_pam_messages();
717		do_pam_chauthtok();
718	}
719#endif
720
721#ifdef USE_PAM
722	if (!check_quietlogin(s, command) && !pam_password_change_required())
723		print_pam_messages();
724#endif /* USE_PAM */
725
726#ifdef __FreeBSD__
727	if (pw->pw_change || pw->pw_expire)
728		(void)gettimeofday(&tv, NULL);
729#ifdef HAVE_LOGIN_CAP
730	warntime = login_getcaptime(lc, "warnpassword",
731				    DEFAULT_WARN, DEFAULT_WARN);
732#endif /* HAVE_LOGIN_CAP */
733	/*
734	 * If the password change time is set and has passed, give the
735	 * user a password expiry notice and chance to change it.
736	 */
737	if (pw->pw_change != 0) {
738		if (tv.tv_sec >= pw->pw_change) {
739			(void)printf(
740			    "Sorry -- your password has expired.\n");
741			log("%s Password expired - forcing change",
742			    pw->pw_name);
743			if (newcommand != NULL)
744				xfree(newcommand);
745			newcommand = xstrdup(_PATH_CHPASS);
746		} else if (pw->pw_change - tv.tv_sec < warntime &&
747			   !check_quietlogin(s, command))
748			(void)printf(
749			    "Warning: your password expires on %s",
750			     ctime(&pw->pw_change));
751	}
752#ifdef HAVE_LOGIN_CAP
753	warntime = login_getcaptime(lc, "warnexpire",
754				    DEFAULT_WARN, DEFAULT_WARN);
755#endif /* HAVE_LOGIN_CAP */
756#ifndef USE_PAM
757	if (pw->pw_expire) {
758		if (tv.tv_sec >= pw->pw_expire) {
759			(void)printf(
760			    "Sorry -- your account has expired.\n");
761			log(
762	   "LOGIN %.200s REFUSED (EXPIRED) FROM %.200s ON TTY %.200s",
763				pw->pw_name, get_remote_name_or_ip(utmp_len,
764				options.reverse_mapping_check), s->tty);
765			exit(254);
766		} else if (pw->pw_expire - tv.tv_sec < warntime &&
767			   !check_quietlogin(s, command))
768			(void)printf(
769			    "Warning: your account expires on %s",
770			     ctime(&pw->pw_expire));
771	}
772#endif /* !USE_PAM */
773#endif /* __FreeBSD__ */
774
775#ifdef HAVE_LOGIN_CAP
776	if (!auth_ttyok(lc, s->tty)) {
777		(void)printf("Permission denied.\n");
778		log(
779	       "LOGIN %.200s REFUSED (TTY) FROM %.200s ON TTY %.200s",
780		    pw->pw_name, get_remote_name_or_ip(utmp_len,
781			options.reverse_mapping_check), s->tty);
782		exit(254);
783	}
784#endif /* HAVE_LOGIN_CAP */
785
786	/*
787	 * If the user has logged in before, display the time of last
788	 * login. However, don't display anything extra if a command
789	 * has been specified (so that ssh can be used to execute
790	 * commands on a remote machine without users knowing they
791	 * are going to another machine). Login(1) will do this for
792	 * us as well, so check if login(1) is used
793	 */
794	if (command == NULL && options.print_lastlog &&
795	    last_login_time != 0 && !check_quietlogin(s, command) &&
796	    !options.use_login) {
797		time_string = ctime(&last_login_time);
798		/* Remove the trailing newline. */
799		if (strchr(time_string, '\n'))
800			*strchr(time_string, '\n') = 0;
801		if (strcmp(hostname, "") == 0)
802			printf("Last login: %s\r\n", time_string);
803		else
804			printf("Last login: %s from %s\r\n", time_string, hostname);
805	}
806
807#ifdef HAVE_LOGIN_CAP
808	if (command == NULL && !check_quietlogin(s, command) &&
809	    !options.use_login) {
810		fname = login_getcapstr(lc, "copyright", NULL, NULL);
811		if (fname != NULL && (f = fopen(fname, "r")) != NULL) {
812			while (fgets(buf, sizeof(buf), f) != NULL)
813				fputs(buf, stdout);
814				fclose(f);
815		} else
816			(void)printf("%s\n\t%s %s\n",
817		"Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
818		"The Regents of the University of California. ",
819		"All rights reserved.");
820	}
821#endif /* HAVE_LOGIN_CAP */
822
823	/*
824	 * Print /etc/motd unless a command was specified or printing
825	 * it was disabled in server options or login(1) will be
826	 * used.  Note that some machines appear to print it in
827	 * /etc/profile or similar.
828	 */
829	if (command == NULL && !check_quietlogin(s, command) && !options.use_login)
830		do_motd();
831}
832
833/*
834 * Display the message of the day.
835 */
836void
837do_motd(void)
838{
839	FILE *f;
840	char buf[256];
841
842	if (options.print_motd) {
843#ifdef HAVE_LOGIN_CAP
844		f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
845		    "/etc/motd"), "r");
846#else /* !HAVE_LOGIN_CAP */
847		f = fopen("/etc/motd", "r");
848#endif /* HAVE_LOGIN_CAP */
849		if (f) {
850			while (fgets(buf, sizeof(buf), f))
851				fputs(buf, stdout);
852			fclose(f);
853		}
854	}
855}
856
857/*
858 * Check for quiet login, either .hushlogin or command given.
859 */
860int
861check_quietlogin(Session *s, const char *command)
862{
863	char buf[256];
864	struct passwd * pw = s->pw;
865	struct stat st;
866
867	/* Return 1 if .hushlogin exists or a command given. */
868	if (command != NULL)
869		return 1;
870	snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
871#ifdef HAVE_LOGIN_CAP
872	if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
873		return 1;
874#else
875	if (stat(buf, &st) >= 0)
876		return 1;
877#endif
878	return 0;
879}
880
881/*
882 * Sets the value of the given variable in the environment.  If the variable
883 * already exists, its value is overriden.
884 */
885void
886child_set_env(char ***envp, u_int *envsizep, const char *name,
887	      const char *value)
888{
889	u_int i, namelen;
890	char **env;
891
892	/*
893	 * Find the slot where the value should be stored.  If the variable
894	 * already exists, we reuse the slot; otherwise we append a new slot
895	 * at the end of the array, expanding if necessary.
896	 */
897	env = *envp;
898	namelen = strlen(name);
899	for (i = 0; env[i]; i++)
900		if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
901			break;
902	if (env[i]) {
903		/* Reuse the slot. */
904		xfree(env[i]);
905	} else {
906		/* New variable.  Expand if necessary. */
907		if (i >= (*envsizep) - 1) {
908			(*envsizep) += 50;
909			env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
910		}
911		/* Need to set the NULL pointer at end of array beyond the new slot. */
912		env[i + 1] = NULL;
913	}
914
915	/* Allocate space and format the variable in the appropriate slot. */
916	env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
917	snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
918}
919
920/*
921 * Reads environment variables from the given file and adds/overrides them
922 * into the environment.  If the file does not exist, this does nothing.
923 * Otherwise, it must consist of empty lines, comments (line starts with '#')
924 * and assignments of the form name=value.  No other forms are allowed.
925 */
926void
927read_environment_file(char ***env, u_int *envsize,
928		      const char *filename)
929{
930	FILE *f;
931	char buf[4096];
932	char *cp, *value;
933
934	f = fopen(filename, "r");
935	if (!f)
936		return;
937
938	while (fgets(buf, sizeof(buf), f)) {
939		for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
940			;
941		if (!*cp || *cp == '#' || *cp == '\n')
942			continue;
943		if (strchr(cp, '\n'))
944			*strchr(cp, '\n') = '\0';
945		value = strchr(cp, '=');
946		if (value == NULL) {
947			fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
948			continue;
949		}
950		/*
951		 * Replace the equals sign by nul, and advance value to
952		 * the value string.
953		 */
954		*value = '\0';
955		value++;
956		child_set_env(env, envsize, cp, value);
957	}
958	fclose(f);
959}
960
961#ifdef USE_PAM
962/*
963 * Sets any environment variables which have been specified by PAM
964 */
965void do_pam_environment(char ***env, int *envsize)
966{
967	char *equals, var_name[512], var_val[512];
968	char **pam_env;
969	int i;
970
971	if ((pam_env = fetch_pam_environment()) == NULL)
972		return;
973
974	for(i = 0; pam_env[i] != NULL; i++) {
975		if ((equals = strstr(pam_env[i], "=")) == NULL)
976			continue;
977
978		if (strlen(pam_env[i]) < (sizeof(var_name) - 1)) {
979			memset(var_name, '\0', sizeof(var_name));
980			memset(var_val, '\0', sizeof(var_val));
981
982			strncpy(var_name, pam_env[i], equals - pam_env[i]);
983			strcpy(var_val, equals + 1);
984
985			child_set_env(env, envsize, var_name, var_val);
986		}
987	}
988}
989#endif /* USE_PAM */
990
991
992/*
993 * Performs common processing for the child, such as setting up the
994 * environment, closing extra file descriptors, setting the user and group
995 * ids, and executing the command or shell.
996 */
997void
998do_child(Session *s, const char *command)
999{
1000	const char *shell, *hostname = NULL, *cp = NULL;
1001	struct passwd * pw = s->pw;
1002	char buf[256];
1003	char cmd[1024];
1004	FILE *f = NULL;
1005	u_int envsize, i;
1006	char **env;
1007	extern char **environ;
1008	struct stat st;
1009	char *argv[10];
1010	int do_xauth = s->auth_proto != NULL && s->auth_data != NULL;
1011
1012	/* remove hostkey from the child's memory */
1013	destroy_sensitive_data();
1014
1015	/* login(1) is only called if we execute the login shell */
1016	if (options.use_login && command != NULL)
1017		options.use_login = 0;
1018
1019#ifndef USE_PAM
1020	if (!options.use_login) {
1021#ifdef HAVE_LOGIN_CAP
1022	if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
1023		f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
1024		    _PATH_NOLOGIN), "r");
1025#else
1026		if (pw->pw_uid)
1027			f = fopen(_PATH_NOLOGIN, "r");
1028#endif
1029		if (f) {
1030			/* /etc/nologin exists.  Print its contents and exit. */
1031			while (fgets(buf, sizeof(buf), f))
1032				fputs(buf, stderr);
1033			fclose(f);
1034			exit(254);
1035		}
1036	}
1037#endif /* !USE_PAM */
1038	/* Set login name, uid, gid, and groups. */
1039	/* Login(1) does this as well, and it needs uid 0 for the "-h"
1040	   switch, so we let login(1) to this for us. */
1041	if (!options.use_login) {
1042#ifdef HAVE_LOGIN_CAP
1043		char **tmpenv;
1044
1045		/* Initialize temp environment */
1046		envsize = 64;
1047		env = xmalloc(envsize * sizeof(char *));
1048		env[0] = NULL;
1049
1050		child_set_env(&env, &envsize, "PATH",
1051			      (pw->pw_uid == 0) ?
1052			      _PATH_STDPATH : _PATH_DEFPATH);
1053
1054		snprintf(buf, sizeof buf, "%.200s/%.50s",
1055			 _PATH_MAILDIR, pw->pw_name);
1056		child_set_env(&env, &envsize, "MAIL", buf);
1057
1058		if (getenv("TZ"))
1059			child_set_env(&env, &envsize, "TZ", getenv("TZ"));
1060
1061		/* Save parent environment */
1062		tmpenv = environ;
1063		environ = env;
1064
1065		if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETALL) < 0)
1066			fatal("setusercontext failed: %s", strerror(errno));
1067
1068		/* Restore parent environment */
1069		env = environ;
1070		environ = tmpenv;
1071
1072		for (envsize = 0; env[envsize] != NULL; ++envsize)
1073			;
1074		envsize = (envsize < 100) ? 100 : envsize + 16;
1075		env = xrealloc(env, envsize * sizeof(char *));
1076
1077#endif /* !HAVE_LOGIN_CAP */
1078		if (getuid() == 0 || geteuid() == 0) {
1079#ifdef HAVE_LOGIN_CAP
1080			if (setusercontext(lc, pw, pw->pw_uid,
1081			    (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
1082				perror("unable to set user context");
1083				exit(1);
1084			}
1085#else
1086			if (setlogin(pw->pw_name) < 0)
1087				error("setlogin failed: %s", strerror(errno));
1088			if (setgid(pw->pw_gid) < 0) {
1089				perror("setgid");
1090				exit(1);
1091			}
1092			/* Initialize the group list. */
1093			if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
1094				perror("initgroups");
1095				exit(1);
1096			}
1097			endgrent();
1098
1099			/* Permanently switch to the desired uid. */
1100			permanently_set_uid(pw);
1101#endif /* HAVE_LOGIN_CAP */
1102		}
1103		if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
1104			fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
1105	}
1106	/*
1107	 * Get the shell from the password data.  An empty shell field is
1108	 * legal, and means /bin/sh.
1109	 */
1110	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
1111#ifdef HAVE_LOGIN_CAP
1112	shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
1113#endif
1114
1115#ifdef AFS
1116	/* Try to get AFS tokens for the local cell. */
1117	if (k_hasafs()) {
1118		char cell[64];
1119
1120		if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
1121			krb_afslog(cell, 0);
1122
1123		krb_afslog(0, 0);
1124	}
1125#endif /* AFS */
1126
1127	/* Initialize the environment. */
1128	if (env == NULL) {
1129		envsize = 100;
1130		env = xmalloc(envsize * sizeof(char *));
1131		env[0] = NULL;
1132	}
1133
1134	if (!options.use_login) {
1135		/* Set basic environment. */
1136		child_set_env(&env, &envsize, "USER", pw->pw_name);
1137		child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
1138		child_set_env(&env, &envsize, "HOME", pw->pw_dir);
1139#ifdef HAVE_LOGIN_CAP
1140		(void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH);
1141		child_set_env(&env, &envsize, "PATH", getenv("PATH"));
1142#else
1143		child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
1144#endif
1145
1146		snprintf(buf, sizeof buf, "%.200s/%.50s",
1147			 _PATH_MAILDIR, pw->pw_name);
1148		child_set_env(&env, &envsize, "MAIL", buf);
1149
1150		/* Normal systems set SHELL by default. */
1151		child_set_env(&env, &envsize, "SHELL", shell);
1152	}
1153	if (getenv("TZ"))
1154		child_set_env(&env, &envsize, "TZ", getenv("TZ"));
1155
1156	/* Set custom environment options from RSA authentication. */
1157	while (custom_environment) {
1158		struct envstring *ce = custom_environment;
1159		char *s = ce->s;
1160		int i;
1161		for (i = 0; s[i] != '=' && s[i]; i++);
1162		if (s[i] == '=') {
1163			s[i] = 0;
1164			child_set_env(&env, &envsize, s, s + i + 1);
1165		}
1166		custom_environment = ce->next;
1167		xfree(ce->s);
1168		xfree(ce);
1169	}
1170
1171	snprintf(buf, sizeof buf, "%.50s %d %d",
1172		 get_remote_ipaddr(), get_remote_port(), get_local_port());
1173	child_set_env(&env, &envsize, "SSH_CLIENT", buf);
1174
1175	if (s->ttyfd != -1)
1176		child_set_env(&env, &envsize, "SSH_TTY", s->tty);
1177	if (s->term)
1178		child_set_env(&env, &envsize, "TERM", s->term);
1179	if (s->display)
1180		child_set_env(&env, &envsize, "DISPLAY", s->display);
1181	if (original_command)
1182		child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
1183		    original_command);
1184
1185#ifdef KRB4
1186	{
1187		extern char *ticket;
1188
1189		if (ticket)
1190			child_set_env(&env, &envsize, "KRBTKFILE", ticket);
1191	}
1192#endif /* KRB4 */
1193#ifdef KRB5
1194{
1195	  extern krb5_ccache mem_ccache;
1196
1197	   if (mem_ccache) {
1198	     krb5_error_code problem;
1199	      krb5_ccache ccache;
1200#ifdef AFS
1201	      if (k_hasafs())
1202		krb5_afslog(ssh_context, mem_ccache, NULL, NULL);
1203#endif /* AFS */
1204
1205	      problem = krb5_cc_default(ssh_context, &ccache);
1206	      if (problem) {}
1207	      else {
1208		problem = krb5_cc_copy_cache(ssh_context, mem_ccache, ccache);
1209		 if (problem) {}
1210	      }
1211
1212	      krb5_cc_close(ssh_context, ccache);
1213	   }
1214
1215	   krb5_cleanup_proc(NULL);
1216	}
1217#endif /* KRB5 */
1218
1219#ifdef USE_PAM
1220	/* Pull in any environment variables that may have been set by PAM. */
1221	do_pam_environment(&env, &envsize);
1222#endif /* USE_PAM */
1223
1224	if (xauthfile)
1225		child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
1226	if (auth_get_socket_name() != NULL)
1227		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
1228			      auth_get_socket_name());
1229
1230	/* read $HOME/.ssh/environment. */
1231	if (!options.use_login) {
1232		snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
1233		    pw->pw_dir);
1234		read_environment_file(&env, &envsize, buf);
1235	}
1236	if (debug_flag) {
1237		/* dump the environment */
1238		fprintf(stderr, "Environment:\n");
1239		for (i = 0; env[i]; i++)
1240			fprintf(stderr, "  %.200s\n", env[i]);
1241	}
1242	/* we have to stash the hostname before we close our socket. */
1243	if (options.use_login)
1244		hostname = get_remote_name_or_ip(utmp_len,
1245		    options.reverse_mapping_check);
1246	/*
1247	 * Close the connection descriptors; note that this is the child, and
1248	 * the server will still have the socket open, and it is important
1249	 * that we do not shutdown it.  Note that the descriptors cannot be
1250	 * closed before building the environment, as we call
1251	 * get_remote_ipaddr there.
1252	 */
1253	if (packet_get_connection_in() == packet_get_connection_out())
1254		close(packet_get_connection_in());
1255	else {
1256		close(packet_get_connection_in());
1257		close(packet_get_connection_out());
1258	}
1259	/*
1260	 * Close all descriptors related to channels.  They will still remain
1261	 * open in the parent.
1262	 */
1263	/* XXX better use close-on-exec? -markus */
1264	channel_close_all();
1265
1266	/*
1267	 * Close any extra file descriptors.  Note that there may still be
1268	 * descriptors left by system functions.  They will be closed later.
1269	 */
1270	endpwent();
1271
1272	/*
1273	 * Restore any signal handlers set by sshd previously that should
1274	 * be restored to their initial state.
1275	 */
1276	signal(SIGPIPE, SIG_DFL);
1277
1278	/* Change current directory to the user\'s home directory. */
1279	if (
1280#ifdef __FreeBSD__
1281		!*pw->pw_dir ||
1282#endif /* __FreeBSD__ */
1283		chdir(pw->pw_dir) < 0
1284	   ) {
1285#ifdef HAVE_LOGIN_CAP
1286		if (login_getcapbool(lc, "requirehome", 0)) {
1287			(void)printf("Home directory not available\n");
1288			log("LOGIN %.200s REFUSED (HOMEDIR) ON TTY %.200s",
1289				pw->pw_name, ttyname);
1290			exit(254);
1291		}
1292#endif /* HAVE_LOGIN_CAP */
1293#ifdef __FreeBSD__
1294		if (chdir("/") < 0) {
1295			(void)printf("Cannot find root directory\n");
1296			log("LOGIN %.200s REFUSED (ROOTDIR) ON TTY %.200s",
1297				pw->pw_name, ttyname);
1298			exit(254);
1299		}
1300		if (!check_quietlogin(s, command) || *pw->pw_dir)
1301			(void)printf(
1302		       "No home directory.\nLogging in with home = \"/\".\n");
1303
1304#else /* !__FreeBSD__ */
1305
1306		fprintf(stderr, "Could not chdir to home directory %s: %s\n",
1307			pw->pw_dir, strerror(errno));
1308#endif /* __FreeBSD__ */
1309	}
1310
1311	/*
1312	 * Close any extra open file descriptors so that we don\'t have them
1313	 * hanging around in clients.  Note that we want to do this after
1314	 * initgroups, because at least on Solaris 2.3 it leaves file
1315	 * descriptors open.
1316	 */
1317	for (i = 3; i < getdtablesize(); i++)
1318		close(i);
1319
1320	/*
1321	 * Must take new environment into use so that .ssh/rc, /etc/sshrc and
1322	 * xauth are run in the proper environment.
1323	 */
1324	environ = env;
1325
1326	/*
1327	 * Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first
1328	 * in this order).
1329	 */
1330	if (!options.use_login) {
1331		/* ignore _PATH_SSH_USER_RC for subsystems */
1332		if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) {
1333			snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
1334			    shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
1335			if (debug_flag)
1336				fprintf(stderr, "Running %s\n", cmd);
1337			f = popen(cmd, "w");
1338			if (f) {
1339				if (do_xauth)
1340					fprintf(f, "%s %s\n", s->auth_proto,
1341					    s->auth_data);
1342				pclose(f);
1343			} else
1344				fprintf(stderr, "Could not run %s\n",
1345				    _PATH_SSH_USER_RC);
1346		} else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
1347			if (debug_flag)
1348				fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
1349				    _PATH_SSH_SYSTEM_RC);
1350			f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
1351			if (f) {
1352				if (do_xauth)
1353					fprintf(f, "%s %s\n", s->auth_proto,
1354					    s->auth_data);
1355				pclose(f);
1356			} else
1357				fprintf(stderr, "Could not run %s\n",
1358				    _PATH_SSH_SYSTEM_RC);
1359		} else if (do_xauth && options.xauth_location != NULL) {
1360			/* Add authority data to .Xauthority if appropriate. */
1361			char *screen = strchr(s->display, ':');
1362
1363			if (debug_flag) {
1364				fprintf(stderr,
1365				    "Running %.100s add "
1366				    "%.100s %.100s %.100s\n",
1367				    options.xauth_location, s->display,
1368				    s->auth_proto, s->auth_data);
1369				if (screen != NULL)
1370					fprintf(stderr,
1371					    "Adding %.*s/unix%s %s %s\n",
1372					    (int)(screen - s->display),
1373					    s->display, screen,
1374					    s->auth_proto, s->auth_data);
1375			}
1376			snprintf(cmd, sizeof cmd, "%s -q -",
1377			    options.xauth_location);
1378			f = popen(cmd, "w");
1379			if (f) {
1380				fprintf(f, "add %s %s %s\n", s->display,
1381				    s->auth_proto, s->auth_data);
1382				if (screen != NULL)
1383					fprintf(f, "add %.*s/unix%s %s %s\n",
1384					    (int)(screen - s->display),
1385					    s->display, screen,
1386					    s->auth_proto,
1387					    s->auth_data);
1388				pclose(f);
1389			} else {
1390				fprintf(stderr, "Could not run %s\n",
1391				    cmd);
1392			}
1393		}
1394		/* Get the last component of the shell name. */
1395		cp = strrchr(shell, '/');
1396		if (cp)
1397			cp++;
1398		else
1399			cp = shell;
1400	}
1401
1402	/* restore SIGPIPE for child */
1403	signal(SIGPIPE,  SIG_DFL);
1404
1405	/*
1406	 * If we have no command, execute the shell.  In this case, the shell
1407	 * name to be passed in argv[0] is preceded by '-' to indicate that
1408	 * this is a login shell.
1409	 */
1410	if (!command) {
1411		if (!options.use_login) {
1412			char buf[256];
1413
1414			/*
1415			 * Check for mail if we have a tty and it was enabled
1416			 * in server options.
1417			 */
1418			if (s->ttyfd != -1 && options.check_mail) {
1419				char *mailbox;
1420				struct stat mailstat;
1421
1422				mailbox = getenv("MAIL");
1423				if (mailbox != NULL) {
1424					if (stat(mailbox, &mailstat) != 0 ||
1425					    mailstat.st_size == 0)
1426#ifdef __FreeBSD__
1427						;
1428#else /* !__FreeBSD__ */
1429						printf("No mail.\n");
1430#endif /* __FreeBSD__ */
1431					else if (mailstat.st_mtime < mailstat.st_atime)
1432						printf("You have mail.\n");
1433					else
1434						printf("You have new mail.\n");
1435				}
1436			}
1437			/* Start the shell.  Set initial character to '-'. */
1438			buf[0] = '-';
1439			strncpy(buf + 1, cp, sizeof(buf) - 1);
1440			buf[sizeof(buf) - 1] = 0;
1441
1442			/* Execute the shell. */
1443			argv[0] = buf;
1444			argv[1] = NULL;
1445			execve(shell, argv, env);
1446
1447			/* Executing the shell failed. */
1448			perror(shell);
1449			exit(1);
1450
1451		} else {
1452			/* Launch login(1). */
1453
1454			execl("/usr/bin/login", "login", "-h", hostname,
1455			     "-p", "-f", "--", pw->pw_name, NULL);
1456
1457			/* Login couldn't be executed, die. */
1458
1459			perror("login");
1460			exit(1);
1461		}
1462	}
1463	/*
1464	 * Execute the command using the user's shell.  This uses the -c
1465	 * option to execute the command.
1466	 */
1467	argv[0] = (char *) cp;
1468	argv[1] = "-c";
1469	argv[2] = (char *) command;
1470	argv[3] = NULL;
1471	execve(shell, argv, env);
1472	perror(shell);
1473	exit(1);
1474}
1475
1476Session *
1477session_new(void)
1478{
1479	int i;
1480	static int did_init = 0;
1481	if (!did_init) {
1482		debug("session_new: init");
1483		for(i = 0; i < MAX_SESSIONS; i++) {
1484			sessions[i].used = 0;
1485			sessions[i].self = i;
1486		}
1487		did_init = 1;
1488	}
1489	for(i = 0; i < MAX_SESSIONS; i++) {
1490		Session *s = &sessions[i];
1491		if (! s->used) {
1492			memset(s, 0, sizeof(*s));
1493			s->chanid = -1;
1494			s->ptyfd = -1;
1495			s->ttyfd = -1;
1496			s->used = 1;
1497			debug("session_new: session %d", i);
1498			return s;
1499		}
1500	}
1501	return NULL;
1502}
1503
1504void
1505session_dump(void)
1506{
1507	int i;
1508	for(i = 0; i < MAX_SESSIONS; i++) {
1509		Session *s = &sessions[i];
1510		debug("dump: used %d session %d %p channel %d pid %d",
1511		    s->used,
1512		    s->self,
1513		    s,
1514		    s->chanid,
1515		    s->pid);
1516	}
1517}
1518
1519int
1520session_open(int chanid)
1521{
1522	Session *s = session_new();
1523	debug("session_open: channel %d", chanid);
1524	if (s == NULL) {
1525		error("no more sessions");
1526		return 0;
1527	}
1528	s->pw = auth_get_user();
1529	if (s->pw == NULL)
1530		fatal("no user for session %d", s->self);
1531	debug("session_open: session %d: link with channel %d", s->self, chanid);
1532	s->chanid = chanid;
1533	return 1;
1534}
1535
1536Session *
1537session_by_channel(int id)
1538{
1539	int i;
1540	for(i = 0; i < MAX_SESSIONS; i++) {
1541		Session *s = &sessions[i];
1542		if (s->used && s->chanid == id) {
1543			debug("session_by_channel: session %d channel %d", i, id);
1544			return s;
1545		}
1546	}
1547	debug("session_by_channel: unknown channel %d", id);
1548	session_dump();
1549	return NULL;
1550}
1551
1552Session *
1553session_by_pid(pid_t pid)
1554{
1555	int i;
1556	debug("session_by_pid: pid %d", pid);
1557	for(i = 0; i < MAX_SESSIONS; i++) {
1558		Session *s = &sessions[i];
1559		if (s->used && s->pid == pid)
1560			return s;
1561	}
1562	error("session_by_pid: unknown pid %d", pid);
1563	session_dump();
1564	return NULL;
1565}
1566
1567int
1568session_window_change_req(Session *s)
1569{
1570	s->col = packet_get_int();
1571	s->row = packet_get_int();
1572	s->xpixel = packet_get_int();
1573	s->ypixel = packet_get_int();
1574	packet_done();
1575	pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1576	return 1;
1577}
1578
1579int
1580session_pty_req(Session *s)
1581{
1582	u_int len;
1583	int n_bytes;
1584
1585	if (no_pty_flag)
1586		return 0;
1587	if (s->ttyfd != -1)
1588		return 0;
1589	s->term = packet_get_string(&len);
1590	s->col = packet_get_int();
1591	s->row = packet_get_int();
1592	s->xpixel = packet_get_int();
1593	s->ypixel = packet_get_int();
1594
1595	if (strcmp(s->term, "") == 0) {
1596		xfree(s->term);
1597		s->term = NULL;
1598	}
1599	/* Allocate a pty and open it. */
1600	if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) {
1601		xfree(s->term);
1602		s->term = NULL;
1603		s->ptyfd = -1;
1604		s->ttyfd = -1;
1605		error("session_pty_req: session %d alloc failed", s->self);
1606		return 0;
1607	}
1608	debug("session_pty_req: session %d alloc %s", s->self, s->tty);
1609	/*
1610	 * Add a cleanup function to clear the utmp entry and record logout
1611	 * time in case we call fatal() (e.g., the connection gets closed).
1612	 */
1613	fatal_add_cleanup(pty_cleanup_proc, (void *)s);
1614	pty_setowner(s->pw, s->tty);
1615	/* Get window size from the packet. */
1616	pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1617
1618	/* Get tty modes from the packet. */
1619	tty_parse_modes(s->ttyfd, &n_bytes);
1620	packet_done();
1621
1622	session_proctitle(s);
1623
1624	return 1;
1625}
1626
1627int
1628session_subsystem_req(Session *s)
1629{
1630	u_int len;
1631	int success = 0;
1632	char *subsys = packet_get_string(&len);
1633	int i;
1634
1635	packet_done();
1636	log("subsystem request for %s", subsys);
1637
1638	for (i = 0; i < options.num_subsystems; i++) {
1639		if(strcmp(subsys, options.subsystem_name[i]) == 0) {
1640			debug("subsystem: exec() %s", options.subsystem_command[i]);
1641			s->is_subsystem = 1;
1642			do_exec_no_pty(s, options.subsystem_command[i]);
1643			success = 1;
1644		}
1645	}
1646
1647	if (!success)
1648		log("subsystem request for %s failed, subsystem not found", subsys);
1649
1650	xfree(subsys);
1651	return success;
1652}
1653
1654int
1655session_x11_req(Session *s)
1656{
1657	int fd;
1658	struct stat st;
1659	if (no_x11_forwarding_flag) {
1660		debug("X11 forwarding disabled in user configuration file.");
1661		return 0;
1662	}
1663	if (!options.x11_forwarding) {
1664		debug("X11 forwarding disabled in server configuration file.");
1665		return 0;
1666	}
1667	if (!options.xauth_location ||
1668	    (stat(options.xauth_location, &st) == -1)) {
1669		packet_send_debug("No xauth program; cannot forward with spoofing.");
1670		return 0;
1671	}
1672	if (xauthfile != NULL) {
1673		debug("X11 fwd already started.");
1674		return 0;
1675	}
1676
1677	debug("Received request for X11 forwarding with auth spoofing.");
1678	if (s->display != NULL)
1679		packet_disconnect("Protocol error: X11 display already set.");
1680
1681	s->single_connection = packet_get_char();
1682	s->auth_proto = packet_get_string(NULL);
1683	s->auth_data = packet_get_string(NULL);
1684	s->screen = packet_get_int();
1685	packet_done();
1686
1687	s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
1688	if (s->display == NULL) {
1689		xfree(s->auth_proto);
1690		xfree(s->auth_data);
1691		return 0;
1692	}
1693	xauthfile = xmalloc(MAXPATHLEN);
1694	strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
1695	temporarily_use_uid(s->pw);
1696	if (mkdtemp(xauthfile) == NULL) {
1697		restore_uid();
1698		error("private X11 dir: mkdtemp %s failed: %s",
1699		    xauthfile, strerror(errno));
1700		xfree(xauthfile);
1701		xauthfile = NULL;
1702		xfree(s->auth_proto);
1703		xfree(s->auth_data);
1704		/* XXXX remove listening channels */
1705		return 0;
1706	}
1707	strlcat(xauthfile, "/cookies", MAXPATHLEN);
1708	fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
1709	if (fd >= 0)
1710		close(fd);
1711	restore_uid();
1712	fatal_add_cleanup(xauthfile_cleanup_proc, s->pw);
1713	return 1;
1714}
1715
1716int
1717session_shell_req(Session *s)
1718{
1719	/* if forced_command == NULL, the shell is execed */
1720	char *shell = forced_command;
1721	packet_done();
1722	if (s->ttyfd == -1)
1723		do_exec_no_pty(s, shell);
1724	else
1725		do_exec_pty(s, shell);
1726	return 1;
1727}
1728
1729int
1730session_exec_req(Session *s)
1731{
1732	u_int len;
1733	char *command = packet_get_string(&len);
1734	packet_done();
1735	if (forced_command) {
1736		original_command = command;
1737		command = forced_command;
1738		debug("Forced command '%.500s'", forced_command);
1739	}
1740	if (s->ttyfd == -1)
1741		do_exec_no_pty(s, command);
1742	else
1743		do_exec_pty(s, command);
1744	if (forced_command == NULL)
1745		xfree(command);
1746	return 1;
1747}
1748
1749int
1750session_auth_agent_req(Session *s)
1751{
1752	static int called = 0;
1753	packet_done();
1754	if (no_agent_forwarding_flag) {
1755		debug("session_auth_agent_req: no_agent_forwarding_flag");
1756		return 0;
1757	}
1758	if (called) {
1759		return 0;
1760	} else {
1761		called = 1;
1762		return auth_input_request_forwarding(s->pw);
1763	}
1764}
1765
1766void
1767session_input_channel_req(int id, void *arg)
1768{
1769	u_int len;
1770	int reply;
1771	int success = 0;
1772	char *rtype;
1773	Session *s;
1774	Channel *c;
1775
1776	rtype = packet_get_string(&len);
1777	reply = packet_get_char();
1778
1779	s = session_by_channel(id);
1780	if (s == NULL)
1781		fatal("session_input_channel_req: channel %d: no session", id);
1782	c = channel_lookup(id);
1783	if (c == NULL)
1784		fatal("session_input_channel_req: channel %d: bad channel", id);
1785
1786	debug("session_input_channel_req: session %d channel %d request %s reply %d",
1787	    s->self, id, rtype, reply);
1788
1789	/*
1790	 * a session is in LARVAL state until a shell, a command
1791	 * or a subsystem is executed
1792	 */
1793	if (c->type == SSH_CHANNEL_LARVAL) {
1794		if (strcmp(rtype, "shell") == 0) {
1795			success = session_shell_req(s);
1796		} else if (strcmp(rtype, "exec") == 0) {
1797			success = session_exec_req(s);
1798		} else if (strcmp(rtype, "pty-req") == 0) {
1799			success =  session_pty_req(s);
1800		} else if (strcmp(rtype, "x11-req") == 0) {
1801			success = session_x11_req(s);
1802		} else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
1803			success = session_auth_agent_req(s);
1804		} else if (strcmp(rtype, "subsystem") == 0) {
1805			success = session_subsystem_req(s);
1806		}
1807	}
1808	if (strcmp(rtype, "window-change") == 0) {
1809		success = session_window_change_req(s);
1810	}
1811
1812	if (reply) {
1813		packet_start(success ?
1814		    SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1815		packet_put_int(c->remote_id);
1816		packet_send();
1817	}
1818	xfree(rtype);
1819}
1820
1821void
1822session_set_fds(Session *s, int fdin, int fdout, int fderr)
1823{
1824	if (!compat20)
1825		fatal("session_set_fds: called for proto != 2.0");
1826	/*
1827	 * now that have a child and a pipe to the child,
1828	 * we can activate our channel and register the fd's
1829	 */
1830	if (s->chanid == -1)
1831		fatal("no channel for session %d", s->self);
1832	channel_set_fds(s->chanid,
1833	    fdout, fdin, fderr,
1834	    fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
1835	    1);
1836}
1837
1838void
1839session_pty_cleanup(Session *s)
1840{
1841	if (s == NULL || s->ttyfd == -1)
1842		return;
1843
1844	debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
1845
1846	/* Cancel the cleanup function. */
1847	fatal_remove_cleanup(pty_cleanup_proc, (void *)s);
1848
1849	/* Record that the user has logged out. */
1850	record_logout(s->pid, s->tty);
1851
1852	/* Release the pseudo-tty. */
1853	pty_release(s->tty);
1854
1855	/*
1856	 * Close the server side of the socket pairs.  We must do this after
1857	 * the pty cleanup, so that another process doesn't get this pty
1858	 * while we're still cleaning up.
1859	 */
1860	if (close(s->ptymaster) < 0)
1861		error("close(s->ptymaster): %s", strerror(errno));
1862}
1863
1864void
1865session_exit_message(Session *s, int status)
1866{
1867	Channel *c;
1868	if (s == NULL)
1869		fatal("session_close: no session");
1870	c = channel_lookup(s->chanid);
1871	if (c == NULL)
1872		fatal("session_close: session %d: no channel %d",
1873		    s->self, s->chanid);
1874	debug("session_exit_message: session %d channel %d pid %d",
1875	    s->self, s->chanid, s->pid);
1876
1877	if (WIFEXITED(status)) {
1878		channel_request_start(s->chanid,
1879		    "exit-status", 0);
1880		packet_put_int(WEXITSTATUS(status));
1881		packet_send();
1882	} else if (WIFSIGNALED(status)) {
1883		channel_request_start(s->chanid,
1884		    "exit-signal", 0);
1885		packet_put_int(WTERMSIG(status));
1886		packet_put_char(WCOREDUMP(status));
1887		packet_put_cstring("");
1888		packet_put_cstring("");
1889		packet_send();
1890	} else {
1891		/* Some weird exit cause.  Just exit. */
1892		packet_disconnect("wait returned status %04x.", status);
1893	}
1894
1895	/* disconnect channel */
1896	debug("session_exit_message: release channel %d", s->chanid);
1897	channel_cancel_cleanup(s->chanid);
1898	/*
1899	 * emulate a write failure with 'chan_write_failed', nobody will be
1900	 * interested in data we write.
1901	 * Note that we must not call 'chan_read_failed', since there could
1902	 * be some more data waiting in the pipe.
1903	 */
1904	if (c->ostate != CHAN_OUTPUT_CLOSED)
1905		chan_write_failed(c);
1906	s->chanid = -1;
1907}
1908
1909void
1910session_free(Session *s)
1911{
1912	debug("session_free: session %d pid %d", s->self, s->pid);
1913	if (s->term)
1914		xfree(s->term);
1915	if (s->display)
1916		xfree(s->display);
1917	if (s->auth_data)
1918		xfree(s->auth_data);
1919	if (s->auth_proto)
1920		xfree(s->auth_proto);
1921	s->used = 0;
1922}
1923
1924void
1925session_close(Session *s)
1926{
1927	session_pty_cleanup(s);
1928	session_free(s);
1929	session_proctitle(s);
1930}
1931
1932void
1933session_close_by_pid(pid_t pid, int status)
1934{
1935	Session *s = session_by_pid(pid);
1936	if (s == NULL) {
1937		debug("session_close_by_pid: no session for pid %d", s->pid);
1938		return;
1939	}
1940	if (s->chanid != -1)
1941		session_exit_message(s, status);
1942	session_close(s);
1943}
1944
1945/*
1946 * this is called when a channel dies before
1947 * the session 'child' itself dies
1948 */
1949void
1950session_close_by_channel(int id, void *arg)
1951{
1952	Session *s = session_by_channel(id);
1953	if (s == NULL) {
1954		debug("session_close_by_channel: no session for channel %d", id);
1955		return;
1956	}
1957	/* disconnect channel */
1958	channel_cancel_cleanup(s->chanid);
1959	s->chanid = -1;
1960
1961	debug("session_close_by_channel: channel %d kill %d", id, s->pid);
1962	if (s->pid == 0) {
1963		/* close session immediately */
1964		session_close(s);
1965	} else {
1966		/* notify child, delay session cleanup */
1967		if (s->pid <= 1)
1968			fatal("session_close_by_channel: Unsafe s->pid = %d", s->pid);
1969		if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0)
1970			error("session_close_by_channel: kill %d: %s",
1971			    s->pid, strerror(errno));
1972	}
1973}
1974
1975char *
1976session_tty_list(void)
1977{
1978	static char buf[1024];
1979	int i;
1980	buf[0] = '\0';
1981	for(i = 0; i < MAX_SESSIONS; i++) {
1982		Session *s = &sessions[i];
1983		if (s->used && s->ttyfd != -1) {
1984			if (buf[0] != '\0')
1985				strlcat(buf, ",", sizeof buf);
1986			strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf);
1987		}
1988	}
1989	if (buf[0] == '\0')
1990		strlcpy(buf, "notty", sizeof buf);
1991	return buf;
1992}
1993
1994void
1995session_proctitle(Session *s)
1996{
1997	if (s->pw == NULL)
1998		error("no user for session %d", s->self);
1999	else
2000		setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
2001}
2002
2003void
2004do_authenticated2(Authctxt *authctxt)
2005{
2006
2007	server_loop2();
2008}
2009