11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: session.c,v 1.258 2010/11/25 04:10:09 djm Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *                    All rights reserved
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * As far as I am concerned, the code I have written for this software
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be used freely for any purpose.  Any derived versions of this
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * software must be clearly marked as such, and if the derived work is
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * incompatible with the protocol description in the RFC file, it must be
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called by a name other than "ssh" or "Secure Shell".
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * SSH2 support by Markus Friedl.
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h>
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_STAT_H
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/stat.h>
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/un.h>
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/wait.h>
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <arpa/inet.h>
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <fcntl.h>
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <grp.h>
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PATHS_H
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <paths.h>
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h>
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h>
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h>
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h>
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h"
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh.h"
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh1.h"
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h"
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sshpty.h"
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h"
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "match.h"
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "uidswap.h"
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "compat.h"
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "channels.h"
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "cipher.h"
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh-gss.h"
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "hostfile.h"
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth.h"
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth-options.h"
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "pathnames.h"
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "servconf.h"
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sshlogin.h"
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "serverloop.h"
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "canohost.h"
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "session.h"
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "kex.h"
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "monitor_wrap.h"
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sftp.h"
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(KRB5) && defined(USE_AFS)
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <kafs.h>
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef WITH_SELINUX
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <selinux/selinux.h>
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define IS_INTERNAL_SFTP(c) \
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	(!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	  c[sizeof(INTERNAL_SFTP_NAME) - 1] == ' ' || \
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	  c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t'))
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* func */
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodSession *session_new(void);
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	session_set_fds(Session *, int, int, int, int, int);
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	session_pty_cleanup(Session *);
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	session_proctitle(Session *);
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	session_setup_x11fwd(Session *);
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	do_exec_pty(Session *, const char *);
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	do_exec_no_pty(Session *, const char *);
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	do_exec(Session *, const char *);
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	do_login(Session *, const char *);
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef LOGIN_NEEDS_UTMPX
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void	do_pre_login(Session *s);
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	do_child(Session *, const char *);
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	do_motd(void);
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	check_quietlogin(Session *, const char *);
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void do_authenticated1(Authctxt *);
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void do_authenticated2(Authctxt *);
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int session_pty_req(Session *);
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* import */
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern ServerOptions options;
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern char *__progname;
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int log_stderr;
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int debug_flag;
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern u_int utmp_len;
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int startup_pipe;
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern void destroy_sensitive_data(void);
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern Buffer loginmsg;
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* original command from peer. */
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst char *original_command = NULL;
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* data */
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int sessions_first_unused = -1;
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int sessions_nalloc = 0;
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Session *sessions = NULL;
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SUBSYSTEM_NONE			0
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SUBSYSTEM_EXT			1
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SUBSYSTEM_INT_SFTP		2
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SUBSYSTEM_INT_SFTP_ERROR	3
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LOGIN_CAP
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodlogin_cap_t *lc;
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int is_child = 0;
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Name and directory of socket for authentication agent forwarding. */
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *auth_sock_name = NULL;
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *auth_sock_dir = NULL;
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* removes the agent forwarding socket */
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth_sock_cleanup_proc(struct passwd *pw)
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (auth_sock_name != NULL) {
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		temporarily_use_uid(pw);
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		unlink(auth_sock_name);
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rmdir(auth_sock_dir);
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		auth_sock_name = NULL;
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		restore_uid();
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth_input_request_forwarding(struct passwd * pw)
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *nc;
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int sock = -1;
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_un sunaddr;
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (auth_sock_name != NULL) {
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("authentication forwarding requested twice.");
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Temporarily drop privileged uid for mkdir/bind. */
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	temporarily_use_uid(pw);
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Allocate a buffer for the socket name, and format the name. */
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Create private directory for socket */
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (mkdtemp(auth_sock_dir) == NULL) {
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send_debug("Agent forwarding disabled: "
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "mkdtemp() failed: %.100s", strerror(errno));
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		restore_uid();
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(auth_sock_dir);
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		auth_sock_dir = NULL;
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto authsock_err;
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xasprintf(&auth_sock_name, "%s/agent.%ld",
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    auth_sock_dir, (long) getpid());
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Create the socket. */
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sock = socket(AF_UNIX, SOCK_STREAM, 0);
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sock < 0) {
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("socket: %.100s", strerror(errno));
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		restore_uid();
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto authsock_err;
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Bind it to the name. */
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(&sunaddr, 0, sizeof(sunaddr));
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sunaddr.sun_family = AF_UNIX;
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("bind: %.100s", strerror(errno));
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		restore_uid();
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto authsock_err;
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Restore the privileged uid. */
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	restore_uid();
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Start listening on the socket. */
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("listen: %.100s", strerror(errno));
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto authsock_err;
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Allocate a channel for the authentication agent socket. */
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	nc = channel_new("auth socket",
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    0, "auth socket", 1);
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	nc->path = xstrdup(auth_sock_name);
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood authsock_err:
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (auth_sock_name != NULL)
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(auth_sock_name);
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (auth_sock_dir != NULL) {
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rmdir(auth_sock_dir);
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(auth_sock_dir);
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sock != -1)
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(sock);
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	auth_sock_name = NULL;
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	auth_sock_dir = NULL;
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddisplay_loginmsg(void)
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&loginmsg) > 0) {
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_append(&loginmsg, "\0", 1);
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		printf("%s", (char *)buffer_ptr(&loginmsg));
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_clear(&loginmsg);
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_authenticated(Authctxt *authctxt)
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	setproctitle("%s", authctxt->pw->pw_name);
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* setup the channel layer */
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_permit_all_opens();
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	auth_debug_send();
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20)
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do_authenticated2(authctxt);
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do_authenticated1(authctxt);
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	do_cleanup(authctxt);
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Prepares for an interactive session.  This is called after the user has
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * been successfully authenticated.  During this message exchange, pseudo
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are requested, etc.
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_authenticated1(Authctxt *authctxt)
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Session *s;
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *command;
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int success, type, screen_flag;
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int enable_compression_after_reply = 0;
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int proto_len, data_len, dlen, compression_level = 0;
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s = session_new();
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s == NULL) {
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("no more sessions");
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->authctxt = authctxt;
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->pw = authctxt->pw;
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * We stay in this loop until the client requests to execute a shell
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * or a command.
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (;;) {
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		success = 0;
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Get a packet from the client. */
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		type = packet_read();
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Process the packet. */
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (type) {
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_CMSG_REQUEST_COMPRESSION:
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			compression_level = packet_get_int();
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_check_eom();
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (compression_level < 1 || compression_level > 9) {
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				packet_send_debug("Received invalid compression level %d.",
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    compression_level);
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (options.compression == COMP_NONE) {
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug2("compression disabled");
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Enable compression after we have responded with SUCCESS. */
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			enable_compression_after_reply = 1;
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = 1;
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_CMSG_REQUEST_PTY:
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = session_pty_req(s);
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_CMSG_X11_REQUEST_FORWARDING:
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->auth_proto = packet_get_string(&proto_len);
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->auth_data = packet_get_string(&data_len);
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			screen_flag = packet_get_protocol_flags() &
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    SSH_PROTOFLAG_SCREEN_NUMBER;
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (packet_remaining() == 4) {
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (!screen_flag)
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					debug2("Buggy client: "
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "X11 screen flag missing");
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				s->screen = packet_get_int();
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else {
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				s->screen = 0;
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_check_eom();
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = session_setup_x11fwd(s);
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!success) {
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(s->auth_proto);
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(s->auth_data);
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				s->auth_proto = NULL;
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				s->auth_data = NULL;
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_CMSG_AGENT_REQUEST_FORWARDING:
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!options.allow_agent_forwarding ||
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    no_agent_forwarding_flag || compat13) {
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("Authentication agent forwarding not permitted for this authentication.");
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Received authentication agent forwarding request.");
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = auth_input_request_forwarding(s->pw);
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_CMSG_PORT_FORWARD_REQUEST:
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (no_port_forwarding_flag) {
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("Port forwarding not permitted for this authentication.");
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!options.allow_tcp_forwarding) {
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("Port forwarding not permitted.");
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Received TCP/IP port forwarding request.");
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (channel_input_port_forward_request(s->pw->pw_uid == 0,
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    options.gateway_ports) < 0) {
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("Port forwarding failed.");
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = 1;
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_CMSG_MAX_PACKET_SIZE:
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (packet_set_maxsize(packet_get_int()) > 0)
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				success = 1;
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_CMSG_EXEC_SHELL:
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_CMSG_EXEC_CMD:
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (type == SSH_CMSG_EXEC_CMD) {
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				command = packet_get_string(&dlen);
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("Exec command '%.500s'", command);
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (do_exec(s, command) != 0)
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					packet_disconnect(
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "command execution failed");
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(command);
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else {
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (do_exec(s, NULL) != 0)
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					packet_disconnect(
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "shell execution failed");
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_check_eom();
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			session_close(s);
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Any unknown messages in this phase are ignored,
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * and a failure message is returned.
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			logit("Unknown packet type received after authentication: %d", type);
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_write_wait();
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Enable compression now that we have replied if appropriate. */
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (enable_compression_after_reply) {
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			enable_compression_after_reply = 0;
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_start_compression(compression_level);
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define USE_PIPES
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This is called to fork and execute a command when we have no tty.  This
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * will call do_child from the child, and server_loop from the parent after
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * setting up file descriptors and such.
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_exec_no_pty(Session *s, const char *command)
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pid_t pid;
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PIPES
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int pin[2], pout[2], perr[2];
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s == NULL)
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("do_exec_no_pty: no session");
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Allocate pipes for communicating with the program. */
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pipe(pin) < 0) {
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: pipe in: %.100s", __func__, strerror(errno));
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pipe(pout) < 0) {
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: pipe out: %.100s", __func__, strerror(errno));
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pin[0]);
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pin[1]);
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pipe(perr) < 0) {
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: pipe err: %.100s", __func__,
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strerror(errno));
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pin[0]);
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pin[1]);
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pout[0]);
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pout[1]);
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int inout[2], err[2];
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s == NULL)
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("do_exec_no_pty: no session");
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Uses socket pairs to communicate with the program. */
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: socketpair #1: %.100s", __func__, strerror(errno));
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: socketpair #2: %.100s", __func__,
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strerror(errno));
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(inout[0]);
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(inout[1]);
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_proctitle(s);
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Fork the child. */
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch ((pid = fork())) {
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case -1:
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: fork: %.100s", __func__, strerror(errno));
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PIPES
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pin[0]);
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pin[1]);
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pout[0]);
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pout[1]);
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(perr[0]);
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(perr[1]);
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(inout[0]);
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(inout[1]);
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(err[0]);
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(err[1]);
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 0:
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		is_child = 1;
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Child.  Reinitialize the log since the pid has changed. */
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		log_init(__progname, options.log_level,
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.log_facility, log_stderr);
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Create a new session and process group since the 4.4BSD
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * setlogin() affects the entire process group.
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (setsid() < 0)
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("setsid failed: %.100s", strerror(errno));
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PIPES
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Redirect stdin.  We close the parent side of the socket
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * pair, and make the child side the standard input.
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pin[1]);
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(pin[0], 0) < 0)
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("dup2 stdin");
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pin[0]);
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Redirect stdout. */
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pout[0]);
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(pout[1], 1) < 0)
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("dup2 stdout");
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(pout[1]);
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Redirect stderr. */
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(perr[0]);
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(perr[1], 2) < 0)
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("dup2 stderr");
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(perr[1]);
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Redirect stdin, stdout, and stderr.  Stdin and stdout will
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * use the same socket, as some programs (particularly rdist)
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * seem to depend on it.
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(inout[1]);
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(err[1]);
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(inout[0], 0) < 0)	/* stdin */
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("dup2 stdin");
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(inout[0], 1) < 0)	/* stdout (same as stdin) */
5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("dup2 stdout");
5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(inout[0]);
5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(err[0], 2) < 0)	/* stderr */
5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("dup2 stderr");
5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(err[0]);
5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef _UNICOS
5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cray_init_job(s->pw); /* set up cray jid and tmpdir */
5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Do processing for the child (exec command etc). */
5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do_child(s, command);
5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* NOTREACHED */
5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef _UNICOS
5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(WJSIGNAL, cray_job_termination_handler);
5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* _UNICOS */
5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_CYGWIN
5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->pid = pid;
5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Set interactive/non-interactive mode. */
5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_set_interactive(s->display != NULL,
5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    options.ip_qos_interactive, options.ip_qos_bulk);
5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Clear loginmsg, since it's the child's responsibility to display
5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * it to the user, otherwise multiple sessions may accumulate
5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * multiple copies of the login messages.
5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_clear(&loginmsg);
6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PIPES
6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* We are the parent.  Close the child sides of the pipes. */
6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(pin[0]);
6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(pout[1]);
6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(perr[1]);
6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20) {
6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_set_fds(s, pin[1], pout[0], perr[0],
6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->is_subsystem, 0);
6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Enter the interactive session. */
6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		server_loop(pid, pin[1], pout[0], perr[0]);
6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* server_loop has closed pin[1], pout[0], and perr[0]. */
6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* We are the parent.  Close the child sides of the socket pairs. */
6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(inout[0]);
6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(err[0]);
6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Enter the interactive session.  Note: server_loop must be able to
6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * handle the case that fdin and fdout are the same.
6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20) {
6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_set_fds(s, inout[1], inout[1], err[1],
6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->is_subsystem, 0);
6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		server_loop(pid, inout[1], inout[1], err[1]);
6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* server_loop has closed inout[1] and err[1]. */
6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This is called to fork and execute a command when we have a tty.  This
6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * will call do_child from the child, and server_loop from the parent after
6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * setting up file descriptors, controlling tty, updating wtmp, utmp,
6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * lastlog, and other such operations.
6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_exec_pty(Session *s, const char *command)
6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int fdout, ptyfd, ttyfd, ptymaster;
6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pid_t pid;
6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s == NULL)
6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("do_exec_pty: no session");
6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ptyfd = s->ptyfd;
6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ttyfd = s->ttyfd;
6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Create another descriptor of the pty master side for use as the
6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * standard input.  We could use the original descriptor, but this
6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * simplifies code in server_loop.  The descriptor is bidirectional.
6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Do this before forking (and cleanup in the child) so as to
6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * detect and gracefully fail out-of-fd conditions.
6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((fdout = dup(ptyfd)) < 0) {
6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: dup #1: %s", __func__, strerror(errno));
6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ttyfd);
6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ptyfd);
6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* we keep a reference to the pty master */
6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((ptymaster = dup(ptyfd)) < 0) {
6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: dup #2: %s", __func__, strerror(errno));
6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ttyfd);
6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ptyfd);
6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fdout);
6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Fork the child. */
6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch ((pid = fork())) {
6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case -1:
6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%s: fork: %.100s", __func__, strerror(errno));
6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fdout);
6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ptymaster);
6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ttyfd);
6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ptyfd);
6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 0:
6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		is_child = 1;
6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fdout);
6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ptymaster);
6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Child.  Reinitialize the log because the pid has changed. */
6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		log_init(__progname, options.log_level,
6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.log_facility, log_stderr);
6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Close the master side of the pseudo tty. */
6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ptyfd);
6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Make the pseudo tty our controlling tty. */
6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pty_make_controlling_tty(&ttyfd, s->tty);
6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Redirect stdin/stdout/stderr from the pseudo tty. */
7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(ttyfd, 0) < 0)
7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("dup2 stdin: %s", strerror(errno));
7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(ttyfd, 1) < 0)
7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("dup2 stdout: %s", strerror(errno));
7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(ttyfd, 2) < 0)
7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("dup2 stderr: %s", strerror(errno));
7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Close the extra descriptor for the pseudo tty. */
7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(ttyfd);
7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* record login, etc. similar to login(1) */
7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef HAVE_OSF_SIA
7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!(options.use_login && command == NULL)) {
7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef _UNICOS
7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cray_init_job(s->pw); /* set up cray jid and tmpdir */
7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* _UNICOS */
7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			do_login(s, command);
7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# ifdef LOGIN_NEEDS_UTMPX
7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			do_pre_login(s);
7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# endif
7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Do common processing for the child, such as execing
7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * the command.
7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do_child(s, command);
7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* NOTREACHED */
7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef _UNICOS
7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(WJSIGNAL, cray_job_termination_handler);
7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* _UNICOS */
7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_CYGWIN
7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->pid = pid;
7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Parent.  Close the slave side of the pseudo tty. */
7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(ttyfd);
7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Enter interactive session. */
7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->ptymaster = ptymaster;
7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_set_interactive(1,
7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    options.ip_qos_interactive, options.ip_qos_bulk);
7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20) {
7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_set_fds(s, ptyfd, fdout, -1, 1, 1);
7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		server_loop(pid, ptyfd, fdout, -1);
7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* server_loop _has_ closed ptyfd and fdout. */
7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef LOGIN_NEEDS_UTMPX
7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_pre_login(Session *s)
7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	socklen_t fromlen;
7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_storage from;
7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pid_t pid = getpid();
7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Get IP address of client. If the connection is not a socket, let
7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the address be 0.0.0.0.
7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(&from, 0, sizeof(from));
7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fromlen = sizeof(from);
7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (packet_connection_is_on_socket()) {
7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (getpeername(packet_get_connection_in(),
7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (struct sockaddr *)&from, &fromlen) < 0) {
7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("getpeername: %.100s", strerror(errno));
7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cleanup_exit(255);
7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	record_utmp_only(pid, s->tty, s->pw->pw_name,
7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    get_remote_name_or_ip(utmp_len, options.use_dns),
7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (struct sockaddr *)&from, fromlen);
7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This is called to fork and execute a command.  If another command is
7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * to be forced, execute that instead.
7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_exec(Session *s, const char *command)
7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret;
7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.adm_forced_command) {
7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		original_command = command;
7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		command = options.adm_forced_command;
7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (IS_INTERNAL_SFTP(command)) {
7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->is_subsystem = s->is_subsystem ?
8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (s->is_subsystem)
8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->is_subsystem = SUBSYSTEM_EXT;
8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Forced command (config) '%.900s'", command);
8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (forced_command) {
8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		original_command = command;
8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		command = forced_command;
8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (IS_INTERNAL_SFTP(command)) {
8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->is_subsystem = s->is_subsystem ?
8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (s->is_subsystem)
8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->is_subsystem = SUBSYSTEM_EXT;
8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Forced command (key option) '%.900s'", command);
8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef SSH_AUDIT_EVENTS
8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (command != NULL)
8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		PRIVSEP(audit_run_command(command));
8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else if (s->ttyfd == -1) {
8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char *shell = s->pw->pw_shell;
8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (shell[0] == '\0')	/* empty shell means /bin/sh */
8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			shell =_PATH_BSHELL;
8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		PRIVSEP(audit_run_command(shell));
8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->ttyfd != -1)
8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ret = do_exec_pty(s, command);
8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ret = do_exec_no_pty(s, command);
8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	original_command = NULL;
8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Clear loginmsg: it's the child's responsibility to display
8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * it to the user, otherwise multiple sessions may accumulate
8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * multiple copies of the login messages.
8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_clear(&loginmsg);
8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* administrative, login(1)-like work */
8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_login(Session *s, const char *command)
8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	socklen_t fromlen;
8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_storage from;
8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct passwd * pw = s->pw;
8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pid_t pid = getpid();
8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Get IP address of client. If the connection is not a socket, let
8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the address be 0.0.0.0.
8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(&from, 0, sizeof(from));
8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fromlen = sizeof(from);
8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (packet_connection_is_on_socket()) {
8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (getpeername(packet_get_connection_in(),
8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (struct sockaddr *)&from, &fromlen) < 0) {
8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("getpeername: %.100s", strerror(errno));
8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cleanup_exit(255);
8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Record that there was a login on that tty from the remote host. */
8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!use_privsep)
8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    get_remote_name_or_ip(utmp_len,
8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.use_dns),
8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (struct sockaddr *)&from, fromlen);
8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PAM
8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If password change is needed, do it now.
8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * This needs to occur before the ~/.hushlogin check.
8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.use_pam && !use_privsep && s->authctxt->force_pwchange) {
8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		display_loginmsg();
8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do_pam_chauthtok();
8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->authctxt->force_pwchange = 0;
8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* XXX - signal [net] parent to enable forwardings */
8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (check_quietlogin(s, command))
8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	display_loginmsg();
8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	do_motd();
8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Display the message of the day.
8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_motd(void)
8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	FILE *f;
9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[256];
9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.print_motd) {
9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LOGIN_CAP
9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "/etc/motd"), "r");
9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		f = fopen("/etc/motd", "r");
9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (f) {
9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			while (fgets(buf, sizeof(buf), f))
9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fputs(buf, stdout);
9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fclose(f);
9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Check for quiet login, either .hushlogin or command given.
9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcheck_quietlogin(Session *s, const char *command)
9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[256];
9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct passwd *pw = s->pw;
9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Return 1 if .hushlogin exists or a command given. */
9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (command != NULL)
9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LOGIN_CAP
9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (stat(buf, &st) >= 0)
9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Sets the value of the given variable in the environment.  If the variable
9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * already exists, its value is overridden.
9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
9471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
9481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchild_set_env(char ***envp, u_int *envsizep, const char *name,
9491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *value)
9501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char **env;
9521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int envsize;
9531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, namelen;
9541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
9561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If we're passed an uninitialized list, allocate a single null
9571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * entry before continuing.
9581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
9591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*envp == NULL && *envsizep == 0) {
9601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*envp = xmalloc(sizeof(char *));
9611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*envp[0] = NULL;
9621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*envsizep = 1;
9631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
9661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Find the slot where the value should be stored.  If the variable
9671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * already exists, we reuse the slot; otherwise we append a new slot
9681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * at the end of the array, expanding if necessary.
9691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
9701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	env = *envp;
9711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	namelen = strlen(name);
9721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; env[i]; i++)
9731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
9741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (env[i]) {
9761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Reuse the slot. */
9771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(env[i]);
9781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
9791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* New variable.  Expand if necessary. */
9801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		envsize = *envsizep;
9811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (i >= envsize - 1) {
9821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (envsize >= 1000)
9831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("child_set_env: too many env vars");
9841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			envsize += 50;
9851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			env = (*envp) = xrealloc(env, envsize, sizeof(char *));
9861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*envsizep = envsize;
9871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Need to set the NULL pointer at end of array beyond the new slot. */
9891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		env[i + 1] = NULL;
9901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Allocate space and format the variable in the appropriate slot. */
9931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
9941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
9951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
9981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Reads environment variables from the given file and adds/overrides them
9991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * into the environment.  If the file does not exist, this does nothing.
10001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Otherwise, it must consist of empty lines, comments (line starts with '#')
10011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * and assignments of the form name=value.  No other forms are allowed.
10021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
10031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
10041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodread_environment_file(char ***env, u_int *envsize,
10051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *filename)
10061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	FILE *f;
10081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[4096];
10091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *cp, *value;
10101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int lineno = 0;
10111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	f = fopen(filename, "r");
10131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!f)
10141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
10151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (fgets(buf, sizeof(buf), f)) {
10171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (++lineno > 1000)
10181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("Too many lines in environment file %s", filename);
10191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
10201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			;
10211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!*cp || *cp == '#' || *cp == '\n')
10221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
10231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cp[strcspn(cp, "\n")] = '\0';
10251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		value = strchr(cp, '=');
10271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (value == NULL) {
10281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "Bad line %u in %.100s\n", lineno,
10291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    filename);
10301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
10311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
10321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
10331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Replace the equals sign by nul, and advance value to
10341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * the value string.
10351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
10361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*value = '\0';
10371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		value++;
10381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(env, envsize, cp, value);
10391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
10401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fclose(f);
10411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_ETC_DEFAULT_LOGIN
10441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
10451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Return named variable from specified environment, or NULL if not present.
10461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
10471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
10481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchild_get_env(char **env, const char *name)
10491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
10511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t len;
10521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	len = strlen(name);
10541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i=0; env[i] != NULL; i++)
10551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncmp(name, env[i], len) == 0 && env[i][len] == '=')
10561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return(env[i] + len + 1);
10571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return NULL;
10581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
10611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Read /etc/default/login.
10621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * We pick up the PATH (or SUPATH for root) and UMASK.
10631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
10641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
10651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodread_etc_default_login(char ***env, u_int *envsize, uid_t uid)
10661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char **tmpenv = NULL, *var;
10681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, tmpenvsize = 0;
10691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_long mask;
10701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
10721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * We don't want to copy the whole file to the child's environment,
10731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * so we use a temporary environment and copy the variables we're
10741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * interested in.
10751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
10761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login");
10771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (tmpenv == NULL)
10791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
10801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (uid == 0)
10821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		var = child_get_env(tmpenv, "SUPATH");
10831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
10841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		var = child_get_env(tmpenv, "PATH");
10851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (var != NULL)
10861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(env, envsize, "PATH", var);
10871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((var = child_get_env(tmpenv, "UMASK")) != NULL)
10891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (sscanf(var, "%5lo", &mask) == 1)
10901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			umask((mode_t)mask);
10911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; tmpenv[i] != NULL; i++)
10931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(tmpenv[i]);
10941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(tmpenv);
10951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* HAVE_ETC_DEFAULT_LOGIN */
10971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
10991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcopy_environment(char **source, char ***env, u_int *envsize)
11001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *var_name, *var_val;
11021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
11031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (source == NULL)
11051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
11061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; source[i] != NULL; i++) {
11081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		var_name = xstrdup(source[i]);
11091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((var_val = strstr(var_name, "=")) == NULL) {
11101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(var_name);
11111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
11121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
11131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*var_val++ = '\0';
11141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("Copy environment: %s=%s", var_name, var_val);
11161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(env, envsize, var_name, var_val);
11171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(var_name);
11191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char **
11231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_setup_env(Session *s, const char *shell)
11241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[256];
11261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, envsize;
11271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char **env, *laddr;
11281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct passwd *pw = s->pw;
11291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
11301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *path = NULL;
11311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
11321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Initialize the environment. */
11341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	envsize = 100;
11351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	env = xcalloc(envsize, sizeof(char *));
11361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	env[0] = NULL;
11371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_CYGWIN
11391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
11401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * The Windows environment contains some setting which are
11411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * important for a running system. They must not be dropped.
11421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
11431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{
11441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char **p;
11451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		p = fetch_windows_environment();
11471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		copy_environment(p, &env, &envsize);
11481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		free_windows_environment(p);
11491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
11511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
11531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Allow any GSSAPI methods that we've used to alter
11541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the childs environment as they see fit
11551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
11561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ssh_gssapi_do_child(&env, &envsize);
11571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
11581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.use_login) {
11601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Set basic environment. */
11611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < s->num_env; i++)
11621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			child_set_env(&env, &envsize, s->env[i].name,
11631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    s->env[i].val);
11641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "USER", pw->pw_name);
11661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
11671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef _AIX
11681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
11691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
11701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "HOME", pw->pw_dir);
11711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LOGIN_CAP
11721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
11731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
11741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
11751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			child_set_env(&env, &envsize, "PATH", getenv("PATH"));
11761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else /* HAVE_LOGIN_CAP */
11771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# ifndef HAVE_CYGWIN
11781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
11791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * There's no standard path on Windows. The path contains
11801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * important components pointing to the system directories,
11811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * needed for loading shared libraries. So the path better
11821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * remains intact here.
11831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
11841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#  ifdef HAVE_ETC_DEFAULT_LOGIN
11851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		read_etc_default_login(&env, &envsize, pw->pw_uid);
11861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		path = child_get_env(env, "PATH");
11871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#  endif /* HAVE_ETC_DEFAULT_LOGIN */
11881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (path == NULL || *path == '\0') {
11891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			child_set_env(&env, &envsize, "PATH",
11901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    s->pw->pw_uid == 0 ?
11911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				SUPERUSER_PATH : _PATH_STDPATH);
11921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
11931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# endif /* HAVE_CYGWIN */
11941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* HAVE_LOGIN_CAP */
11951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(buf, sizeof buf, "%.200s/%.50s",
11971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 _PATH_MAILDIR, pw->pw_name);
11981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "MAIL", buf);
11991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Normal systems set SHELL by default. */
12011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "SHELL", shell);
12021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (getenv("TZ"))
12041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "TZ", getenv("TZ"));
12051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Set custom environment options from RSA authentication. */
12071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.use_login) {
12081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		while (custom_environment) {
12091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			struct envstring *ce = custom_environment;
12101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			char *str = ce->s;
12111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			for (i = 0; str[i] != '=' && str[i]; i++)
12131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				;
12141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (str[i] == '=') {
12151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				str[i] = 0;
12161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				child_set_env(&env, &envsize, str, str + i + 1);
12171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
12181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			custom_environment = ce->next;
12191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(ce->s);
12201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(ce);
12211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
12221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* SSH_CLIENT deprecated */
12251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(buf, sizeof buf, "%.50s %d %d",
12261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    get_remote_ipaddr(), get_remote_port(), get_local_port());
12271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	child_set_env(&env, &envsize, "SSH_CLIENT", buf);
12281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	laddr = get_local_ipaddr(packet_get_connection_in());
12301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
12311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
12321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(laddr);
12331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
12341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->ttyfd != -1)
12361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "SSH_TTY", s->tty);
12371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->term)
12381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "TERM", s->term);
12391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->display)
12401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "DISPLAY", s->display);
12411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (original_command)
12421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
12431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    original_command);
12441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef _UNICOS
12461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cray_tmpdir[0] != '\0')
12471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);
12481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* _UNICOS */
12491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
12511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Since we clear KRB5CCNAME at startup, if it's set now then it
12521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * must have been set by a native authentication method (eg AIX or
12531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * SIA), so copy it to the child.
12541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
12551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{
12561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char *cp;
12571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((cp = getenv("KRB5CCNAME")) != NULL)
12591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			child_set_env(&env, &envsize, "KRB5CCNAME", cp);
12601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef _AIX
12631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{
12641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char *cp;
12651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((cp = getenv("AUTHSTATE")) != NULL)
12671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			child_set_env(&env, &envsize, "AUTHSTATE", cp);
12681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		read_environment_file(&env, &envsize, "/etc/environment");
12691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
12711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef KRB5
12721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->authctxt->krb5_ccname)
12731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, "KRB5CCNAME",
12741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->authctxt->krb5_ccname);
12751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
12761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PAM
12771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
12781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Pull in any environment variables that may have
12791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * been set by PAM.
12801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
12811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.use_pam) {
12821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char **p;
12831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		p = fetch_pam_child_environment();
12851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		copy_environment(p, &env, &envsize);
12861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		free_pam_environment(p);
12871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		p = fetch_pam_environment();
12891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		copy_environment(p, &env, &envsize);
12901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		free_pam_environment(p);
12911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_PAM */
12931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (auth_sock_name != NULL)
12951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
12961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    auth_sock_name);
12971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* read $HOME/.ssh/environment. */
12991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.permit_user_env && !options.use_login) {
13001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
13011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strcmp(pw->pw_dir, "/") ? pw->pw_dir : "");
13021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		read_environment_file(&env, &envsize, buf);
13031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (debug_flag) {
13051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* dump the environment */
13061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fprintf(stderr, "Environment:\n");
13071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; env[i]; i++)
13081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "  %.200s\n", env[i]);
13091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return env;
13111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
13141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found
13151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * first in this order).
13161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
13171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
13181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_rc_files(Session *s, const char *shell)
13191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	FILE *f = NULL;
13211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char cmd[1024];
13221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int do_xauth;
13231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
13241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	do_xauth =
13261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;
13271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
13291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!s->is_subsystem && options.adm_forced_command == NULL &&
13301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    !no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) {
13311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
13321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
13331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (debug_flag)
13341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "Running %s\n", cmd);
13351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		f = popen(cmd, "w");
13361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (f) {
13371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (do_xauth)
13381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fprintf(f, "%s %s\n", s->auth_proto,
13391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    s->auth_data);
13401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			pclose(f);
13411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else
13421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "Could not run %s\n",
13431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    _PATH_SSH_USER_RC);
13441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
13451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (debug_flag)
13461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
13471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    _PATH_SSH_SYSTEM_RC);
13481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
13491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (f) {
13501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (do_xauth)
13511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fprintf(f, "%s %s\n", s->auth_proto,
13521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    s->auth_data);
13531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			pclose(f);
13541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else
13551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "Could not run %s\n",
13561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    _PATH_SSH_SYSTEM_RC);
13571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (do_xauth && options.xauth_location != NULL) {
13581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Add authority data to .Xauthority if appropriate. */
13591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (debug_flag) {
13601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr,
13611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "Running %.500s remove %.100s\n",
13621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    options.xauth_location, s->auth_display);
13631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr,
13641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "%.500s add %.100s %.100s %.100s\n",
13651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    options.xauth_location, s->auth_display,
13661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    s->auth_proto, s->auth_data);
13671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
13681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(cmd, sizeof cmd, "%s -q -",
13691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.xauth_location);
13701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		f = popen(cmd, "w");
13711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (f) {
13721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(f, "remove %s\n",
13731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    s->auth_display);
13741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(f, "add %s %s %s\n",
13751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    s->auth_display, s->auth_proto,
13761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    s->auth_data);
13771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			pclose(f);
13781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
13791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "Could not run %s\n",
13801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    cmd);
13811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
13821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
13861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_nologin(struct passwd *pw)
13871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	FILE *f = NULL;
13891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[1024], *nl, *def_nl = _PATH_NOLOGIN;
13901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat sb;
13911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LOGIN_CAP
13931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
13941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
13951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	nl = login_getcapstr(lc, "nologin", def_nl, def_nl);
13961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
13971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pw->pw_uid == 0)
13981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
13991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	nl = def_nl;
14001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
14011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (stat(nl, &sb) == -1) {
14021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (nl != def_nl)
14031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(nl);
14041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
14051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* /etc/nologin exists.  Print its contents if we can and exit. */
14081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	logit("User %.100s not allowed because %s exists", pw->pw_name, nl);
14091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((f = fopen(nl, "r")) != NULL) {
14101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 		while (fgets(buf, sizeof(buf), f))
14111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 			fputs(buf, stderr);
14121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 		fclose(f);
14131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 	}
14141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	exit(254);
14151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
14161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
14181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Chroot into a directory after checking it for safety: all path components
14191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * must be root-owned directories with strict permissions.
14201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
14211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
14221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsafely_chroot(const char *path, uid_t uid)
14231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
14241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *cp;
14251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char component[MAXPATHLEN];
14261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
14271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*path != '/')
14291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("chroot path does not begin at root");
14301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strlen(path) >= sizeof(component))
14311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("chroot path too long");
14321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
14341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Descend the path, checking that each component is a
14351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * root-owned directory with strict permissions.
14361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
14371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (cp = path; cp != NULL;) {
14381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((cp = strchr(cp, '/')) == NULL)
14391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcpy(component, path, sizeof(component));
14401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else {
14411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cp++;
14421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			memcpy(component, path, cp - path);
14431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			component[cp - path] = '\0';
14441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("%s: checking '%s'", __func__, component);
14471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (stat(component, &st) != 0)
14491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: stat(\"%s\"): %s", __func__,
14501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    component, strerror(errno));
14511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (st.st_uid != 0 || (st.st_mode & 022) != 0)
14521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("bad ownership or modes for chroot "
14531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "directory %s\"%s\"",
14541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    cp == NULL ? "" : "component ", component);
14551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!S_ISDIR(st.st_mode))
14561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("chroot path %s\"%s\" is not a directory",
14571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    cp == NULL ? "" : "component ", component);
14581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (chdir(path) == -1)
14621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Unable to chdir to chroot path \"%s\": "
14631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "%s", path, strerror(errno));
14641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (chroot(path) == -1)
14651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("chroot(\"%s\"): %s", path, strerror(errno));
14661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (chdir("/") == -1)
14671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: chdir(/) after chroot: %s",
14681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__, strerror(errno));
14691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	verbose("Changed root directory to \"%s\"", path);
14701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
14711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Set login name, uid, gid, and groups. */
14731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
14741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_setusercontext(struct passwd *pw)
14751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
14761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *chroot_path, *tmp;
14771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	platform_setusercontext(pw);
14791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (platform_privileged_uidswap()) {
14811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LOGIN_CAP
14821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (setusercontext(lc, pw, pw->pw_uid,
14831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
14841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("unable to set user context");
14851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
14861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
14881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (setlogin(pw->pw_name) < 0)
14891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("setlogin failed: %s", strerror(errno));
14901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (setgid(pw->pw_gid) < 0) {
14911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("setgid");
14921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
14931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Initialize the group list. */
14951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
14961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("initgroups");
14971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
14981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14991b6cc98e30329f380546d5f22b1c9c975e3df4f8Mike Lockwood#ifndef ANDROID
15001b6cc98e30329f380546d5f22b1c9c975e3df4f8Mike Lockwood		/* FIXME - Android doesn't have this */
15011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		endgrent();
15021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
15031b6cc98e30329f380546d5f22b1c9c975e3df4f8Mike Lockwood#endif
15041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		platform_setusercontext_post_groups(pw);
15061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (options.chroot_directory != NULL &&
15081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strcasecmp(options.chroot_directory, "none") != 0) {
15091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood                        tmp = tilde_expand_filename(options.chroot_directory,
15101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    pw->pw_uid);
15111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chroot_path = percent_expand(tmp, "h", pw->pw_dir,
15121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "u", pw->pw_name, (char *)NULL);
15131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			safely_chroot(chroot_path, pw->pw_uid);
15141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			free(tmp);
15151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			free(chroot_path);
15161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LOGIN_CAP
15191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) {
15201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("unable to set user context (setuser)");
15211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
15221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
15241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Permanently switch to the desired uid. */
15251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		permanently_set_uid(pw);
15261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
15271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
15301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
15311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
15321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
15341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_pwchange(Session *s)
15351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
15361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fflush(NULL);
15371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "WARNING: Your password has expired.\n");
15381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->ttyfd != -1) {
15391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fprintf(stderr,
15401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "You must change your password now and login again!\n");
15411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef WITH_SELINUX
15421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		setexeccon(NULL);
15431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
15441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef PASSWD_NEEDS_USERNAME
15451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
15461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (char *)NULL);
15471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
15481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL);
15491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
15501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		perror("passwd");
15511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
15521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fprintf(stderr,
15531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Password change required but no TTY available.\n");
15541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	exit(1);
15561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
15571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
15591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodlaunch_login(struct passwd *pw, const char *hostname)
15601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
15611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Launch login(1). */
15621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	execl(LOGIN_PROGRAM, "login", "-h", hostname,
15641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef xxxLOGIN_NEEDS_TERM
15651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (s->term ? s->term : "unknown"),
15661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* LOGIN_NEEDS_TERM */
15671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef LOGIN_NO_ENDOPT
15681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    "-p", "-f", pw->pw_name, (char *)NULL);
15691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
15701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    "-p", "-f", "--", pw->pw_name, (char *)NULL);
15711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
15721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Login couldn't be executed, die. */
15741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	perror("login");
15761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	exit(1);
15771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
15781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
15801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchild_close_fds(void)
15811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
15821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (packet_get_connection_in() == packet_get_connection_out())
15831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(packet_get_connection_in());
15841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else {
15851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(packet_get_connection_in());
15861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(packet_get_connection_out());
15871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
15891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Close all descriptors related to channels.  They will still remain
15901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * open in the parent.
15911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
15921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* XXX better use close-on-exec? -markus */
15931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_close_all();
15941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
15961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Close any extra file descriptors.  Note that there may still be
15971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * descriptors left by system functions.  They will be closed later.
15981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
15991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	endpwent();
16001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
16021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Close any extra open file descriptors so that we don't have them
16031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * hanging around in clients.  Note that we want to do this after
16041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * initgroups, because at least on Solaris 2.3 it leaves file
16051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * descriptors open.
16061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
16071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	closefrom(STDERR_FILENO + 1);
16081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
16091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
16111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Performs common processing for the child, such as setting up the
16121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * environment, closing extra file descriptors, setting the user and group
16131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ids, and executing the command or shell.
16141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
16151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define ARGV_MAX 10
16161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
16171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_child(Session *s, const char *command)
16181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
16191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	extern char **environ;
16201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char **env;
16211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *argv[ARGV_MAX];
16221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *shell, *shell0, *hostname = NULL;
16231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct passwd *pw = s->pw;
16241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int r = 0;
16251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* remove hostkey from the child's memory */
16271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	destroy_sensitive_data();
16281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Force a password change */
16301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->authctxt->force_pwchange) {
16311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do_setusercontext(pw);
16321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		child_close_fds();
16331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do_pwchange(s);
16341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exit(1);
16351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* login(1) is only called if we execute the login shell */
16381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.use_login && command != NULL)
16391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		options.use_login = 0;
16401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef _UNICOS
16421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cray_setup(pw->pw_uid, pw->pw_name, command);
16431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* _UNICOS */
16441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
16461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Login(1) does this as well, and it needs uid 0 for the "-h"
16471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * switch, so we let login(1) to this for us.
16481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
16491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.use_login) {
16501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_OSF_SIA
16511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty);
16521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!check_quietlogin(s, command))
16531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			do_motd();
16541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else /* HAVE_OSF_SIA */
16551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* When PAM is enabled we rely on it to do the nologin check */
16561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!options.use_pam)
16571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			do_nologin(pw);
16581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do_setusercontext(pw);
16591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
16601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * PAM session modules in do_setusercontext may have
16611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * generated messages, so if this in an interactive
16621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * login then display them too.
16631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
16641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!check_quietlogin(s, command))
16651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			display_loginmsg();
16661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* HAVE_OSF_SIA */
16671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PAM
16701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.use_pam && !options.use_login && !is_pam_session_open()) {
16711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("PAM session not opened, exiting");
16721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		display_loginmsg();
16731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exit(254);
16741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
16761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
16781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Get the shell from the password data.  An empty shell field is
16791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * legal, and means /bin/sh.
16801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
16811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
16821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
16841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Make sure $SHELL points to the shell from the password file,
16851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * even if shell is overridden from login.conf
16861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
16871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	env = do_setup_env(s, shell);
16881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LOGIN_CAP
16901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
16911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
16921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* we have to stash the hostname before we close our socket. */
16941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.use_login)
16951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		hostname = get_remote_name_or_ip(utmp_len,
16961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.use_dns);
16971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
16981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Close the connection descriptors; note that this is the child, and
16991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the server will still have the socket open, and it is important
17001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * that we do not shutdown it.  Note that the descriptors cannot be
17011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * closed before building the environment, as we call
17021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * get_remote_ipaddr there.
17031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
17041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	child_close_fds();
17051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
17071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Must take new environment into use so that .ssh/rc,
17081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * /etc/ssh/sshrc and xauth are run in the proper environment.
17091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
17101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	environ = env;
17111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(KRB5) && defined(USE_AFS)
17131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
17141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * At this point, we check to see if AFS is active and if we have
17151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * a valid Kerberos 5 TGT. If so, it seems like a good idea to see
17161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * if we can (and need to) extend the ticket into an AFS token. If
17171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * we don't do this, we run into potential problems if the user's
17181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * home directory is in AFS and it's not world-readable.
17191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
17201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.kerberos_get_afs_token && k_hasafs() &&
17221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (s->authctxt->krb5_ctx != NULL)) {
17231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char cell[64];
17241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Getting AFS token");
17261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k_setpag();
17281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
17301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			krb5_afslog(s->authctxt->krb5_ctx,
17311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    s->authctxt->krb5_fwd_ccache, cell, NULL);
17321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		krb5_afslog_home(s->authctxt->krb5_ctx,
17341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->authctxt->krb5_fwd_ccache, NULL, NULL, pw->pw_dir);
17351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
17371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Change current directory to the user's home directory. */
17391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (chdir(pw->pw_dir) < 0) {
17401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Suppress missing homedir warning for chroot case */
17411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LOGIN_CAP
17421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		r = login_getcapbool(lc, "requirehome", 0);
17431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
17441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (r || options.chroot_directory == NULL ||
17451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strcasecmp(options.chroot_directory, "none") == 0)
17461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "Could not chdir to home "
17471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "directory %s: %s\n", pw->pw_dir,
17481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    strerror(errno));
17491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (r)
17501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
17511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	closefrom(STDERR_FILENO + 1);
17541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.use_login)
17561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do_rc_files(s, shell);
17571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* restore SIGPIPE for child */
17591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGPIPE, SIG_DFL);
17601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) {
17621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		printf("This service allows sftp connections only.\n");
17631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fflush(NULL);
17641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exit(1);
17651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {
17661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		extern int optind, optreset;
17671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		int i;
17681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char *p, *args;
17691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		setproctitle("%s@%s", s->pw->pw_name, INTERNAL_SFTP_NAME);
17711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		args = xstrdup(command ? command : "sftp-server");
17721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " ")))
17731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (i < ARGV_MAX - 1)
17741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				argv[i++] = p;
17751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		argv[i] = NULL;
17761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		optind = optreset = 1;
17771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		__progname = argv[0];
17781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef WITH_SELINUX
17791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ssh_selinux_change_context("sftpd_t");
17801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
17811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exit(sftp_server_main(i, argv, s->pw));
17821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fflush(NULL);
17851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.use_login) {
17871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		launch_login(pw, hostname);
17881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* NEVERREACHED */
17891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Get the last component of the shell name. */
17921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((shell0 = strrchr(shell, '/')) != NULL)
17931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		shell0++;
17941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
17951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		shell0 = shell;
17961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
17981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If we have no command, execute the shell.  In this case, the shell
17991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * name to be passed in argv[0] is preceded by '-' to indicate that
18001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * this is a login shell.
18011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
18021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!command) {
18031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char argv0[256];
18041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Start the shell.  Set initial character to '-'. */
18061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		argv0[0] = '-';
18071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1)
18091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    >= sizeof(argv0) - 1) {
18101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			errno = EINVAL;
18111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror(shell);
18121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
18131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
18141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Execute the shell. */
18161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		argv[0] = argv0;
18171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		argv[1] = NULL;
18181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		execve(shell, argv, env);
18191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Executing the shell failed. */
18211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		perror(shell);
18221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exit(1);
18231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
18251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Execute the command using the user's shell.  This uses the -c
18261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * option to execute the command.
18271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
18281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	argv[0] = (char *) shell0;
18291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	argv[1] = "-c";
18301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	argv[2] = (char *) command;
18311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	argv[3] = NULL;
18321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	execve(shell, argv, env);
18331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	perror(shell);
18341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	exit(1);
18351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
18381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_unused(int id)
18391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: session id %d unused", __func__, id);
18411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (id >= options.max_sessions ||
18421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    id >= sessions_nalloc) {
18431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: insane session id %d (max %d nalloc %d)",
18441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__, id, options.max_sessions, sessions_nalloc);
18451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(&sessions[id], sizeof(*sessions));
18471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions[id].self = id;
18481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions[id].used = 0;
18491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions[id].chanid = -1;
18501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions[id].ptyfd = -1;
18511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions[id].ttyfd = -1;
18521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions[id].ptymaster = -1;
18531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions[id].x11_chanids = NULL;
18541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions[id].next_unused = sessions_first_unused;
18551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions_first_unused = id;
18561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18581305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodSession *
18591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_new(void)
18601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Session *s, *tmp;
18621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sessions_first_unused == -1) {
18641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (sessions_nalloc >= options.max_sessions)
18651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return NULL;
18661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("%s: allocate (allocated %d max %d)",
18671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__, sessions_nalloc, options.max_sessions);
18681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tmp = xrealloc(sessions, sessions_nalloc + 1,
18691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    sizeof(*sessions));
18701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (tmp == NULL) {
18711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: cannot allocate %d sessions",
18721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    __func__, sessions_nalloc + 1);
18731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return NULL;
18741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
18751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sessions = tmp;
18761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_unused(sessions_nalloc++);
18771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sessions_first_unused >= sessions_nalloc ||
18801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    sessions_first_unused < 0) {
18811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: insane first_unused %d max %d nalloc %d",
18821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__, sessions_first_unused, options.max_sessions,
18831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    sessions_nalloc);
18841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s = &sessions[sessions_first_unused];
18871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->used) {
18881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: session %d already used",
18891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__, sessions_first_unused);
18901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sessions_first_unused = s->next_unused;
18921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->used = 1;
18931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->next_unused = -1;
18941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_new: session %d", s->self);
18951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return s;
18971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
19001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_dump(void)
19011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
19031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sessions_nalloc; i++) {
19041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Session *s = &sessions[i];
19051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("dump: used %d next_unused %d session %d %p "
19071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "channel %d pid %ld",
19081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->used,
19091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->next_unused,
19101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->self,
19111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s,
19121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->chanid,
19131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (long)s->pid);
19141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
19181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_open(Authctxt *authctxt, int chanid)
19191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Session *s = session_new();
19211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_open: channel %d", chanid);
19221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s == NULL) {
19231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("no more sessions");
19241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
19251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->authctxt = authctxt;
19271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->pw = authctxt->pw;
19281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->pw == NULL || !authctxt->valid)
19291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("no user for session %d", s->self);
19301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_open: session %d: link with channel %d", s->self, chanid);
19311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->chanid = chanid;
19321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
19331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19351305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodSession *
19361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_by_tty(char *tty)
19371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
19391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sessions_nalloc; i++) {
19401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Session *s = &sessions[i];
19411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
19421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("session_by_tty: session %d tty %s", i, tty);
19431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return s;
19441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
19451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_by_tty: unknown tty %.100s", tty);
19471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_dump();
19481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return NULL;
19491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Session *
19521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_by_channel(int id)
19531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
19551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sessions_nalloc; i++) {
19561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Session *s = &sessions[i];
19571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s->used && s->chanid == id) {
19581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("session_by_channel: session %d channel %d",
19591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    i, id);
19601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return s;
19611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
19621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_by_channel: unknown channel %d", id);
19641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_dump();
19651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return NULL;
19661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Session *
19691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_by_x11_channel(int id)
19701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i, j;
19721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sessions_nalloc; i++) {
19741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Session *s = &sessions[i];
19751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s->x11_chanids == NULL || !s->used)
19771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
19781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (j = 0; s->x11_chanids[j] != -1; j++) {
19791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (s->x11_chanids[j] == id) {
19801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("session_by_x11_channel: session %d "
19811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "channel %d", s->self, id);
19821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return s;
19831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
19841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
19851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_by_x11_channel: unknown channel %d", id);
19871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_dump();
19881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return NULL;
19891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Session *
19921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_by_pid(pid_t pid)
19931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
19951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_by_pid: pid %ld", (long)pid);
19961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sessions_nalloc; i++) {
19971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Session *s = &sessions[i];
19981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s->used && s->pid == pid)
19991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return s;
20001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	error("session_by_pid: unknown pid %ld", (long)pid);
20021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_dump();
20031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return NULL;
20041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
20051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
20071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_window_change_req(Session *s)
20081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
20091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->col = packet_get_int();
20101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->row = packet_get_int();
20111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->xpixel = packet_get_int();
20121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->ypixel = packet_get_int();
20131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
20141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
20151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
20161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
20171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
20191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_pty_req(Session *s)
20201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
20211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len;
20221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int n_bytes;
20231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (no_pty_flag) {
20251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Allocating a pty not permitted for this authentication.");
20261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
20271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->ttyfd != -1) {
20291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_disconnect("Protocol error: you already have a pty.");
20301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
20311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->term = packet_get_string(&len);
20341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20) {
20361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->col = packet_get_int();
20371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->row = packet_get_int();
20381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
20391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->row = packet_get_int();
20401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->col = packet_get_int();
20411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->xpixel = packet_get_int();
20431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->ypixel = packet_get_int();
20441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(s->term, "") == 0) {
20461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->term);
20471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->term = NULL;
20481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Allocate a pty and open it. */
20511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Allocating pty.");
20521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
20531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    sizeof(s->tty)))) {
20541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s->term)
20551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(s->term);
20561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->term = NULL;
20571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->ptyfd = -1;
20581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->ttyfd = -1;
20591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("session_pty_req: session %d alloc failed", s->self);
20601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
20611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_pty_req: session %d alloc %s", s->self, s->tty);
20631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* for SSH1 the tty modes length is not given */
20651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!compat20)
20661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n_bytes = packet_remaining();
20671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	tty_parse_modes(s->ttyfd, &n_bytes);
20681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!use_privsep)
20701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pty_setowner(s->pw, s->tty);
20711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Set window size from the packet. */
20731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
20741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
20761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_proctitle(s);
20771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
20781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
20791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
20811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_subsystem_req(Session *s)
20821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
20831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
20841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len;
20851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int success = 0;
20861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *prog, *cmd, *subsys = packet_get_string(&len);
20871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
20881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
20901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	logit("subsystem request for %.100s by user %s", subsys,
20911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    s->pw->pw_name);
20921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < options.num_subsystems; i++) {
20941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strcmp(subsys, options.subsystem_name[i]) == 0) {
20951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			prog = options.subsystem_command[i];
20961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cmd = options.subsystem_args[i];
20971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) {
20981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				s->is_subsystem = SUBSYSTEM_INT_SFTP;
20991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("subsystem: %s", prog);
21001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else {
21011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (stat(prog, &st) < 0)
21021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					debug("subsystem: cannot stat %s: %s",
21031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    prog, strerror(errno));
21041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				s->is_subsystem = SUBSYSTEM_EXT;
21051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("subsystem: exec() %s", cmd);
21061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
21071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = do_exec(s, cmd) == 0;
21081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
21091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
21101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!success)
21131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("subsystem request for %.100s failed, subsystem not found",
21141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    subsys);
21151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(subsys);
21171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return success;
21181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
21211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_x11_req(Session *s)
21221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int success;
21241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->auth_proto != NULL || s->auth_data != NULL) {
21261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("session_x11_req: session %d: "
21271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "x11 forwarding already active", s->self);
21281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
21291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->single_connection = packet_get_char();
21311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->auth_proto = packet_get_string(NULL);
21321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->auth_data = packet_get_string(NULL);
21331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->screen = packet_get_int();
21341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
21351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	success = session_setup_x11fwd(s);
21371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!success) {
21381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->auth_proto);
21391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->auth_data);
21401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->auth_proto = NULL;
21411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->auth_data = NULL;
21421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return success;
21441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
21471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_shell_req(Session *s)
21481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
21501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return do_exec(s, NULL) == 0;
21511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
21541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_exec_req(Session *s)
21551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len, success;
21571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *command = packet_get_string(&len);
21591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
21601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	success = do_exec(s, command) == 0;
21611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(command);
21621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return success;
21631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
21661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_break_req(Session *s)
21671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_int();	/* ignored */
21701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
21711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->ttyfd == -1 || tcsendbreak(s->ttyfd, 0) < 0)
21731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
21741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
21751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
21781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_env_req(Session *s)
21791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *name, *val;
21811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int name_len, val_len, i;
21821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	name = packet_get_string(&name_len);
21841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	val = packet_get_string(&val_len);
21851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
21861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Don't set too many environment variables */
21881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->num_env > 128) {
21891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("Ignoring env request %s: too many env vars", name);
21901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto fail;
21911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < options.num_accept_env; i++) {
21941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (match_pattern(name, options.accept_env[i])) {
21951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug2("Setting env %d: %s=%s", s->num_env, name, val);
21961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->env = xrealloc(s->env, s->num_env + 1,
21971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    sizeof(*s->env));
21981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->env[s->num_env].name = name;
21991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->env[s->num_env].val = val;
22001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->num_env++;
22011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (1);
22021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
22031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
22041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("Ignoring env request %s: disallowed name", name);
22051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fail:
22071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(name);
22081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(val);
22091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (0);
22101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
22111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
22131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_auth_agent_req(Session *s)
22141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
22151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static int called = 0;
22161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
22171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (no_agent_forwarding_flag || !options.allow_agent_forwarding) {
22181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("session_auth_agent_req: no_agent_forwarding_flag");
22191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
22201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
22211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (called) {
22221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
22231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
22241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		called = 1;
22251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return auth_input_request_forwarding(s->pw);
22261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
22271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
22281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
22301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_input_channel_req(Channel *c, const char *rtype)
22311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
22321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int success = 0;
22331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Session *s;
22341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((s = session_by_channel(c->self)) == NULL) {
22361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("session_input_channel_req: no session %d req %.100s",
22371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, rtype);
22381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
22391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
22401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_input_channel_req: session %d req %s", s->self, rtype);
22411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
22431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * a session is in LARVAL state until a shell, a command
22441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * or a subsystem is executed
22451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
22461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->type == SSH_CHANNEL_LARVAL) {
22471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strcmp(rtype, "shell") == 0) {
22481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = session_shell_req(s);
22491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strcmp(rtype, "exec") == 0) {
22501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = session_exec_req(s);
22511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strcmp(rtype, "pty-req") == 0) {
22521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = session_pty_req(s);
22531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strcmp(rtype, "x11-req") == 0) {
22541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = session_x11_req(s);
22551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
22561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = session_auth_agent_req(s);
22571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strcmp(rtype, "subsystem") == 0) {
22581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = session_subsystem_req(s);
22591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strcmp(rtype, "env") == 0) {
22601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = session_env_req(s);
22611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
22621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
22631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(rtype, "window-change") == 0) {
22641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		success = session_window_change_req(s);
22651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(rtype, "break") == 0) {
22661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		success = session_break_req(s);
22671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
22681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return success;
22701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
22711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
22731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr,
22741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int is_tty)
22751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
22761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!compat20)
22771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("session_set_fds: called for proto != 2.0");
22781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
22791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * now that have a child and a pipe to the child,
22801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * we can activate our channel and register the fd's
22811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
22821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->chanid == -1)
22831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("no channel for session %d", s->self);
22841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_set_fds(s->chanid,
22851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    fdout, fdin, fderr,
22861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
22871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    1, is_tty, CHAN_SES_WINDOW_DEFAULT);
22881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
22891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
22901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
22911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Function to perform pty cleanup. Also called if we get aborted abnormally
22921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (e.g., due to a dropped connection).
22931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
22941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
22951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_pty_cleanup2(Session *s)
22961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
22971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s == NULL) {
22981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("session_pty_cleanup: no session");
22991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
23001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
23011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->ttyfd == -1)
23021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
23031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
23051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Record that the user has logged out. */
23071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->pid != 0)
23081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		record_logout(s->pid, s->tty, s->pw->pw_name);
23091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Release the pseudo-tty. */
23111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (getuid() == 0)
23121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pty_release(s->tty);
23131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
23151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Close the server side of the socket pairs.  We must do this after
23161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the pty cleanup, so that another process doesn't get this pty
23171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * while we're still cleaning up.
23181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
23191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
23201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("close(s->ptymaster/%d): %s",
23211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->ptymaster, strerror(errno));
23221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* unlink pty from session */
23241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->ttyfd = -1;
23251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
23261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
23281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_pty_cleanup(Session *s)
23291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
23301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	PRIVSEP(session_pty_cleanup2(s));
23311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
23321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
23341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsig2name(int sig)
23351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
23361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SSH_SIG(x) if (sig == SIG ## x) return #x
23371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(ABRT);
23381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(ALRM);
23391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(FPE);
23401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(HUP);
23411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(ILL);
23421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(INT);
23431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(KILL);
23441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(PIPE);
23451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(QUIT);
23461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(SEGV);
23471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(TERM);
23481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(USR1);
23491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SSH_SIG(USR2);
23501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#undef	SSH_SIG
23511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return "SIG@openssh.com";
23521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
23531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
23551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_close_x11(int id)
23561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
23571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c;
23581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((c = channel_by_id(id)) == NULL) {
23601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("session_close_x11: x11 channel %d missing", id);
23611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
23621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Detach X11 listener */
23631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("session_close_x11: detach x11 channel %d", id);
23641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_cancel_cleanup(id);
23651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (c->ostate != CHAN_OUTPUT_CLOSED)
23661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_mark_dead(c);
23671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
23681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
23691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
23711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_close_single_x11(int id, void *arg)
23721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
23731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Session *s;
23741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
23751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
23761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("session_close_single_x11: channel %d", id);
23771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_cancel_cleanup(id);
23781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((s = session_by_x11_channel(id)) == NULL)
23791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("session_close_single_x11: no x11 channel %d", id);
23801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; s->x11_chanids[i] != -1; i++) {
23811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("session_close_single_x11: session %d: "
23821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "closing channel %d", s->self, s->x11_chanids[i]);
23831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
23841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * The channel "id" is already closing, but make sure we
23851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * close all of its siblings.
23861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
23871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s->x11_chanids[i] != id)
23881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			session_close_x11(s->x11_chanids[i]);
23891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
23901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(s->x11_chanids);
23911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->x11_chanids = NULL;
23921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->display) {
23931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->display);
23941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->display = NULL;
23951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
23961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->auth_proto) {
23971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->auth_proto);
23981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->auth_proto = NULL;
23991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
24001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->auth_data) {
24011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->auth_data);
24021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->auth_data = NULL;
24031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
24041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->auth_display) {
24051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->auth_display);
24061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->auth_display = NULL;
24071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
24081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
24091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
24101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
24111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_exit_message(Session *s, int status)
24121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
24131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c;
24141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
24151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((c = channel_lookup(s->chanid)) == NULL)
24161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("session_exit_message: session %d: no channel %d",
24171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->self, s->chanid);
24181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_exit_message: session %d channel %d pid %ld",
24191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    s->self, s->chanid, (long)s->pid);
24201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
24211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (WIFEXITED(status)) {
24221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_request_start(s->chanid, "exit-status", 0);
24231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(WEXITSTATUS(status));
24241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
24251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (WIFSIGNALED(status)) {
24261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_request_start(s->chanid, "exit-signal", 0);
24271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_cstring(sig2name(WTERMSIG(status)));
24281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef WCOREDUMP
24291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_char(WCOREDUMP(status)? 1 : 0);
24301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else /* WCOREDUMP */
24311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_char(0);
24321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* WCOREDUMP */
24331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_cstring("");
24341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_cstring("");
24351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
24361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
24371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Some weird exit cause.  Just exit. */
24381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_disconnect("wait returned status %04x.", status);
24391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
24401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
24411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* disconnect channel */
24421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_exit_message: release channel %d", s->chanid);
24431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
24441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
24451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Adjust cleanup callback attachment to send close messages when
24461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the channel gets EOF. The session will be then be closed
24471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * by session_close_by_channel when the childs close their fds.
24481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
24491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_register_cleanup(c->self, session_close_by_channel, 1);
24501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
24511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
24521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * emulate a write failure with 'chan_write_failed', nobody will be
24531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * interested in data we write.
24541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Note that we must not call 'chan_read_failed', since there could
24551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * be some more data waiting in the pipe.
24561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
24571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->ostate != CHAN_OUTPUT_CLOSED)
24581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_write_failed(c);
24591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
24601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
24611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
24621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_close(Session *s)
24631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
24641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
24651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
24661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_close: session %d pid %ld", s->self, (long)s->pid);
24671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->ttyfd != -1)
24681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_pty_cleanup(s);
24691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->term)
24701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->term);
24711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->display)
24721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->display);
24731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->x11_chanids)
24741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->x11_chanids);
24751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->auth_display)
24761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->auth_display);
24771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->auth_data)
24781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->auth_data);
24791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->auth_proto)
24801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->auth_proto);
24811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->env != NULL) {
24821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < s->num_env; i++) {
24831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(s->env[i].name);
24841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(s->env[i].val);
24851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
24861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(s->env);
24871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
24881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_proctitle(s);
24891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_unused(s->self);
24901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
24911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
24921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
24931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_close_by_pid(pid_t pid, int status)
24941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
24951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Session *s = session_by_pid(pid);
24961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s == NULL) {
24971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("session_close_by_pid: no session for pid %ld",
24981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (long)pid);
24991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
25001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
25011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->chanid != -1)
25021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_exit_message(s, status);
25031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->ttyfd != -1)
25041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_pty_cleanup(s);
25051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->pid = 0;
25061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
25071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
25091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * this is called when a channel dies before
25101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the session 'child' itself dies
25111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
25121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
25131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_close_by_channel(int id, void *arg)
25141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
25151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Session *s = session_by_channel(id);
25161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
25171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s == NULL) {
25191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("session_close_by_channel: no session for id %d", id);
25201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
25211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
25221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("session_close_by_channel: channel %d child %ld",
25231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    id, (long)s->pid);
25241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->pid != 0) {
25251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("session_close_by_channel: channel %d: has child", id);
25261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
25271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * delay detach of session, but release pty, since
25281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * the fd's to the child are already closed
25291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
25301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s->ttyfd != -1)
25311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			session_pty_cleanup(s);
25321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
25331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
25341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* detach by removing callback */
25351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_cancel_cleanup(s->chanid);
25361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Close any X11 listeners associated with this session */
25381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->x11_chanids != NULL) {
25391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; s->x11_chanids[i] != -1; i++) {
25401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			session_close_x11(s->x11_chanids[i]);
25411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s->x11_chanids[i] = -1;
25421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
25431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
25441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	s->chanid = -1;
25461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_close(s);
25471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
25481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
25501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_destroy_all(void (*closefunc)(Session *))
25511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
25521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
25531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sessions_nalloc; i++) {
25541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Session *s = &sessions[i];
25551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s->used) {
25561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (closefunc != NULL)
25571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				closefunc(s);
25581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			else
25591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				session_close(s);
25601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
25611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
25621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
25631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
25651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_tty_list(void)
25661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
25671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static char buf[1024];
25681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
25691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *cp;
25701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buf[0] = '\0';
25721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sessions_nalloc; i++) {
25731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Session *s = &sessions[i];
25741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s->used && s->ttyfd != -1) {
25751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (strncmp(s->tty, "/dev/", 5) != 0) {
25771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				cp = strrchr(s->tty, '/');
25781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				cp = (cp == NULL) ? s->tty : cp + 1;
25791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else
25801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				cp = s->tty + 5;
25811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (buf[0] != '\0')
25831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				strlcat(buf, ",", sizeof buf);
25841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcat(buf, cp, sizeof buf);
25851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
25861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
25871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buf[0] == '\0')
25881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		strlcpy(buf, "notty", sizeof buf);
25891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return buf;
25901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
25911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
25921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
25931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_proctitle(Session *s)
25941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
25951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->pw == NULL)
25961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("no user for session %d", s->self);
25971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
25981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
25991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
26001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
26021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsession_setup_x11fwd(Session *s)
26031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
26041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
26051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char display[512], auth_display[512];
26061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char hostname[MAXHOSTNAMELEN];
26071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
26081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (no_x11_forwarding_flag) {
26101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send_debug("X11 forwarding disabled in user configuration file.");
26111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
26121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
26131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.x11_forwarding) {
26141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("X11 forwarding disabled in server configuration file.");
26151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
26161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
26171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.xauth_location ||
26181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (stat(options.xauth_location, &st) == -1)) {
26191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send_debug("No xauth program; cannot forward with spoofing.");
26201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
26211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
26221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.use_login) {
26231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send_debug("X11 forwarding disabled; "
26241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "not compatible with UseLogin=yes.");
26251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
26261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
26271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s->display != NULL) {
26281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("X11 display already set.");
26291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
26301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
26311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (x11_create_display_inet(options.x11_display_offset,
26321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    options.x11_use_localhost, s->single_connection,
26331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &s->display_number, &s->x11_chanids) == -1) {
26341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("x11_create_display_inet failed.");
26351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
26361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
26371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; s->x11_chanids[i] != -1; i++) {
26381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_register_cleanup(s->x11_chanids[i],
26391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    session_close_single_x11, 0);
26401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
26411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Set up a suitable value for the DISPLAY variable. */
26431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (gethostname(hostname, sizeof(hostname)) < 0)
26441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("gethostname: %.100s", strerror(errno));
26451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
26461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * auth_display must be used as the displayname when the
26471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * authorization entry is added with xauth(1).  This will be
26481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * different than the DISPLAY string for localhost displays.
26491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
26501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.x11_use_localhost) {
26511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(display, sizeof display, "localhost:%u.%u",
26521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->display_number, s->screen);
26531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(auth_display, sizeof auth_display, "unix:%u.%u",
26541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->display_number, s->screen);
26551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->display = xstrdup(display);
26561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->auth_display = xstrdup(auth_display);
26571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
26581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef IPADDR_IN_DISPLAY
26591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		struct hostent *he;
26601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		struct in_addr my_addr;
26611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		he = gethostbyname(hostname);
26631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (he == NULL) {
26641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Can't get IP address for X11 DISPLAY.");
26651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_send_debug("Can't get IP address for X11 DISPLAY.");
26661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
26671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
26681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
26691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr),
26701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->display_number, s->screen);
26711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
26721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(display, sizeof display, "%.400s:%u.%u", hostname,
26731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    s->display_number, s->screen);
26741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
26751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->display = xstrdup(display);
26761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s->auth_display = xstrdup(display);
26771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
26781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
26801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
26811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
26831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_authenticated2(Authctxt *authctxt)
26841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
26851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	server_loop2(authctxt);
26861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
26871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
26891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_cleanup(Authctxt *authctxt)
26901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
26911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static int called = 0;
26921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("do_cleanup");
26941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* no cleanup if we're in the child for login shell */
26961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (is_child)
26971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
26981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
26991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* avoid double cleanup */
27001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (called)
27011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
27021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	called = 1;
27031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
27041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
27051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
27061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
27071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PAM
27081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.use_pam) {
27091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_cleanup();
27101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sshpam_thread_cleanup();
27111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
27121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
27131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
27141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!authctxt->authenticated)
27151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
27161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
27171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef KRB5
27181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.kerberos_ticket_cleanup &&
27191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->krb5_ctx)
27201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		krb5_cleanup_proc(authctxt);
27211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
27221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
27231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
27241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20 && options.gss_cleanup_creds)
27251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ssh_gssapi_cleanup_creds();
27261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
27271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
27281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* remove agent socket */
27291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	auth_sock_cleanup_proc(authctxt->pw);
27301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
27311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
27321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Cleanup ptys/utmp only if privsep is disabled,
27331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * or if running in monitor.
27341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
27351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!use_privsep || mm_is_monitor())
27361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_destroy_all(session_pty_cleanup2);
27371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2738