xref: /openssh-portable/session.c (revision 31d8d231)
1*31d8d231Sdjm@openbsd.org /* $OpenBSD: session.c,v 1.328 2021/04/03 06:18:41 djm Exp $ */
2b38eff8eSDamien Miller /*
3b38eff8eSDamien Miller  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4b38eff8eSDamien Miller  *                    All rights reserved
5e4340be5SDamien Miller  *
6e4340be5SDamien Miller  * As far as I am concerned, the code I have written for this software
7e4340be5SDamien Miller  * can be used freely for any purpose.  Any derived versions of this
8e4340be5SDamien Miller  * software must be clearly marked as such, and if the derived work is
9e4340be5SDamien Miller  * incompatible with the protocol description in the RFC file, it must be
10e4340be5SDamien Miller  * called by a name other than "ssh" or "Secure Shell".
11e4340be5SDamien Miller  *
12efb4afe0SDamien Miller  * SSH2 support by Markus Friedl.
1344697233SBen Lindstrom  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
14e4340be5SDamien Miller  *
15e4340be5SDamien Miller  * Redistribution and use in source and binary forms, with or without
16e4340be5SDamien Miller  * modification, are permitted provided that the following conditions
17e4340be5SDamien Miller  * are met:
18e4340be5SDamien Miller  * 1. Redistributions of source code must retain the above copyright
19e4340be5SDamien Miller  *    notice, this list of conditions and the following disclaimer.
20e4340be5SDamien Miller  * 2. Redistributions in binary form must reproduce the above copyright
21e4340be5SDamien Miller  *    notice, this list of conditions and the following disclaimer in the
22e4340be5SDamien Miller  *    documentation and/or other materials provided with the distribution.
23e4340be5SDamien Miller  *
24e4340be5SDamien Miller  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25e4340be5SDamien Miller  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26e4340be5SDamien Miller  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27e4340be5SDamien Miller  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28e4340be5SDamien Miller  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29e4340be5SDamien Miller  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30e4340be5SDamien Miller  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31e4340be5SDamien Miller  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32e4340be5SDamien Miller  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33e4340be5SDamien Miller  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34efb4afe0SDamien Miller  */
35b38eff8eSDamien Miller 
36b38eff8eSDamien Miller #include "includes.h"
379cf6d077SDamien Miller 
389cf6d077SDamien Miller #include <sys/types.h>
398dbffe79SDamien Miller #include <sys/param.h>
40f17883e6SDamien Miller #ifdef HAVE_SYS_STAT_H
41f17883e6SDamien Miller # include <sys/stat.h>
42f17883e6SDamien Miller #endif
43e3b60b52SDamien Miller #include <sys/socket.h>
44574c41fdSDamien Miller #include <sys/un.h>
458dbffe79SDamien Miller #include <sys/wait.h>
4603e2003aSDamien Miller 
471cdde6f5SDamien Miller #include <arpa/inet.h>
481cdde6f5SDamien Miller 
494b4bfb01Sdjm@openbsd.org #include <ctype.h>
5039972493SDarren Tucker #include <errno.h>
5122a29880SDamien Miller #include <fcntl.h>
52427a1d57SDamien Miller #include <grp.h>
53e5c0d52cSDamien Miller #include <netdb.h>
546645e7a7SDamien Miller #ifdef HAVE_PATHS_H
5503e2003aSDamien Miller #include <paths.h>
566645e7a7SDamien Miller #endif
579f2abc47SDamien Miller #include <pwd.h>
586ff3caddSDamien Miller #include <signal.h>
59a7a73ee3SDamien Miller #include <stdio.h>
60e7a1e5cfSDamien Miller #include <stdlib.h>
61e3476ed0SDamien Miller #include <string.h>
6272687c8eSderaadt@openbsd.org #include <stdarg.h>
631cdde6f5SDamien Miller #include <unistd.h>
642ae4f337Sderaadt@openbsd.org #include <limits.h>
65b38eff8eSDamien Miller 
66b84886baSDamien Miller #include "openbsd-compat/sys-queue.h"
67d7834353SDamien Miller #include "xmalloc.h"
68b38eff8eSDamien Miller #include "ssh.h"
69226cfa03SBen Lindstrom #include "ssh2.h"
70d95c09ccSBen Lindstrom #include "sshpty.h"
71b38eff8eSDamien Miller #include "packet.h"
722808d18cSmarkus@openbsd.org #include "sshbuf.h"
732808d18cSmarkus@openbsd.org #include "ssherr.h"
7446bc0754SDarren Tucker #include "match.h"
75b38eff8eSDamien Miller #include "uidswap.h"
76b38eff8eSDamien Miller #include "compat.h"
77c763767fSBen Lindstrom #include "channels.h"
785467fbcbSmarkus@openbsd.org #include "sshkey.h"
79d7834353SDamien Miller #include "cipher.h"
80d7834353SDamien Miller #ifdef GSSAPI
81d7834353SDamien Miller #include "ssh-gss.h"
82d7834353SDamien Miller #endif
83d7834353SDamien Miller #include "hostfile.h"
84efb4afe0SDamien Miller #include "auth.h"
85f6d9e221SDamien Miller #include "auth-options.h"
8685b45e09SDamien Miller #include "authfd.h"
87226cfa03SBen Lindstrom #include "pathnames.h"
88226cfa03SBen Lindstrom #include "log.h"
897acefbbcSDamien Miller #include "misc.h"
90226cfa03SBen Lindstrom #include "servconf.h"
91d95c09ccSBen Lindstrom #include "sshlogin.h"
92226cfa03SBen Lindstrom #include "serverloop.h"
93226cfa03SBen Lindstrom #include "canohost.h"
9431ca54aaSBen Lindstrom #include "session.h"
959786e6e2SDamien Miller #include "kex.h"
967a2073c5SBen Lindstrom #include "monitor_wrap.h"
97dfc24258SDamien Miller #include "sftp.h"
988f574959Sdjm@openbsd.org #include "atomicio.h"
99efb4afe0SDamien Miller 
1003c78c5edSDarren Tucker #if defined(KRB5) && defined(USE_AFS)
1018f341f8bSDamien Miller #include <kafs.h>
1028f341f8bSDamien Miller #endif
1038f341f8bSDamien Miller 
10414684a1fSDamien Miller #ifdef WITH_SELINUX
10514684a1fSDamien Miller #include <selinux/selinux.h>
10614684a1fSDamien Miller #endif
10714684a1fSDamien Miller 
108ad793d59SDamien Miller #define IS_INTERNAL_SFTP(c) \
109ad793d59SDamien Miller 	(!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
110ad793d59SDamien Miller 	 (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
111ad793d59SDamien Miller 	  c[sizeof(INTERNAL_SFTP_NAME) - 1] == ' ' || \
112ad793d59SDamien Miller 	  c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t'))
113ad793d59SDamien Miller 
114b38eff8eSDamien Miller /* func */
115b38eff8eSDamien Miller 
116b38eff8eSDamien Miller Session *session_new(void);
117dbee4119Sdjm@openbsd.org void	session_set_fds(struct ssh *, Session *, int, int, int, int, int);
1183e33cecfSDarren Tucker void	session_pty_cleanup(Session *);
119bba81213SBen Lindstrom void	session_proctitle(Session *);
120dbee4119Sdjm@openbsd.org int	session_setup_x11fwd(struct ssh *, Session *);
121dbee4119Sdjm@openbsd.org int	do_exec_pty(struct ssh *, Session *, const char *);
122dbee4119Sdjm@openbsd.org int	do_exec_no_pty(struct ssh *, Session *, const char *);
123dbee4119Sdjm@openbsd.org int	do_exec(struct ssh *, Session *, const char *);
124dbee4119Sdjm@openbsd.org void	do_login(struct ssh *, Session *, const char *);
125dbee4119Sdjm@openbsd.org void	do_child(struct ssh *, Session *, const char *);
126cf205e8fSDamien Miller void	do_motd(void);
1278f63caa1SKevin Steves int	check_quietlogin(Session *, const char *);
128b38eff8eSDamien Miller 
129dbee4119Sdjm@openbsd.org static void do_authenticated2(struct ssh *, Authctxt *);
130bba81213SBen Lindstrom 
131dbee4119Sdjm@openbsd.org static int session_pty_req(struct ssh *, Session *);
132b31783d5SBen Lindstrom 
133b38eff8eSDamien Miller /* import */
134b38eff8eSDamien Miller extern ServerOptions options;
135b38eff8eSDamien Miller extern char *__progname;
136b38eff8eSDamien Miller extern int debug_flag;
13746c16220SBen Lindstrom extern u_int utmp_len;
13837023965SDamien Miller extern int startup_pipe;
139005dd22cSBen Lindstrom extern void destroy_sensitive_data(void);
1402808d18cSmarkus@openbsd.org extern struct sshbuf *loginmsg;
1417c856857Sdjm@openbsd.org extern struct sshauthopt *auth_opts;
142f47d72ddSdjm@openbsd.org extern char *tun_fwd_ifnames; /* serverloop.c */
14337023965SDamien Miller 
1447b28dc5eSDamien Miller /* original command from peer. */
1450a7ca6c7SBen Lindstrom const char *original_command = NULL;
1467b28dc5eSDamien Miller 
147b38eff8eSDamien Miller /* data */
1487207f64aSDamien Miller static int sessions_first_unused = -1;
1497207f64aSDamien Miller static int sessions_nalloc = 0;
1507207f64aSDamien Miller static Session *sessions = NULL;
15115e7d4b6SDamien Miller 
152dfc24258SDamien Miller #define SUBSYSTEM_NONE			0
153dfc24258SDamien Miller #define SUBSYSTEM_EXT			1
154dfc24258SDamien Miller #define SUBSYSTEM_INT_SFTP		2
155d6b06a9fSDarren Tucker #define SUBSYSTEM_INT_SFTP_ERROR	3
156dfc24258SDamien Miller 
157ad833b3eSDamien Miller #ifdef HAVE_LOGIN_CAP
158b481e132SBen Lindstrom login_cap_t *lc;
159ad833b3eSDamien Miller #endif
160ad833b3eSDamien Miller 
1613e33cecfSDarren Tucker static int is_child = 0;
16244fc7cd7Sdjm@openbsd.org static int in_chroot = 0;
1633e33cecfSDarren Tucker 
1648f574959Sdjm@openbsd.org /* File containing userauth info, if ExposeAuthInfo set */
1658f574959Sdjm@openbsd.org static char *auth_info_file = NULL;
1668f574959Sdjm@openbsd.org 
1678bb6f36cSBen Lindstrom /* Name and directory of socket for authentication agent forwarding. */
1688bb6f36cSBen Lindstrom static char *auth_sock_name = NULL;
1698bb6f36cSBen Lindstrom static char *auth_sock_dir = NULL;
1708bb6f36cSBen Lindstrom 
1718bb6f36cSBen Lindstrom /* removes the agent forwarding socket */
1728bb6f36cSBen Lindstrom 
1738bb6f36cSBen Lindstrom static void
auth_sock_cleanup_proc(struct passwd * pw)1743e33cecfSDarren Tucker auth_sock_cleanup_proc(struct passwd *pw)
1758bb6f36cSBen Lindstrom {
1768bb6f36cSBen Lindstrom 	if (auth_sock_name != NULL) {
1778bb6f36cSBen Lindstrom 		temporarily_use_uid(pw);
1788bb6f36cSBen Lindstrom 		unlink(auth_sock_name);
1798bb6f36cSBen Lindstrom 		rmdir(auth_sock_dir);
1808bb6f36cSBen Lindstrom 		auth_sock_name = NULL;
1818bb6f36cSBen Lindstrom 		restore_uid();
1828bb6f36cSBen Lindstrom 	}
1838bb6f36cSBen Lindstrom }
1848bb6f36cSBen Lindstrom 
1858bb6f36cSBen Lindstrom static int
auth_input_request_forwarding(struct ssh * ssh,struct passwd * pw)186dbee4119Sdjm@openbsd.org auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw)
1878bb6f36cSBen Lindstrom {
1888bb6f36cSBen Lindstrom 	Channel *nc;
1897207f64aSDamien Miller 	int sock = -1;
1908bb6f36cSBen Lindstrom 
1918bb6f36cSBen Lindstrom 	if (auth_sock_name != NULL) {
1928bb6f36cSBen Lindstrom 		error("authentication forwarding requested twice.");
1938bb6f36cSBen Lindstrom 		return 0;
1948bb6f36cSBen Lindstrom 	}
1958bb6f36cSBen Lindstrom 
1968bb6f36cSBen Lindstrom 	/* Temporarily drop privileged uid for mkdir/bind. */
1978bb6f36cSBen Lindstrom 	temporarily_use_uid(pw);
1988bb6f36cSBen Lindstrom 
1998bb6f36cSBen Lindstrom 	/* Allocate a buffer for the socket name, and format the name. */
2007207f64aSDamien Miller 	auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
2018bb6f36cSBen Lindstrom 
2028bb6f36cSBen Lindstrom 	/* Create private directory for socket */
2038bb6f36cSBen Lindstrom 	if (mkdtemp(auth_sock_dir) == NULL) {
204a5e2ad88Sdjm@openbsd.org 		ssh_packet_send_debug(ssh, "Agent forwarding disabled: "
2058bb6f36cSBen Lindstrom 		    "mkdtemp() failed: %.100s", strerror(errno));
2068bb6f36cSBen Lindstrom 		restore_uid();
207a627d42eSDarren Tucker 		free(auth_sock_dir);
2088bb6f36cSBen Lindstrom 		auth_sock_dir = NULL;
2097207f64aSDamien Miller 		goto authsock_err;
2108bb6f36cSBen Lindstrom 	}
2117207f64aSDamien Miller 
2127207f64aSDamien Miller 	xasprintf(&auth_sock_name, "%s/agent.%ld",
213ce0f6342SBen Lindstrom 	    auth_sock_dir, (long) getpid());
2148bb6f36cSBen Lindstrom 
2157acefbbcSDamien Miller 	/* Start a Unix listener on auth_sock_name. */
2167acefbbcSDamien Miller 	sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0);
2178bb6f36cSBen Lindstrom 
2188bb6f36cSBen Lindstrom 	/* Restore the privileged uid. */
2198bb6f36cSBen Lindstrom 	restore_uid();
2208bb6f36cSBen Lindstrom 
2217acefbbcSDamien Miller 	/* Check for socket/bind/listen failure. */
2227acefbbcSDamien Miller 	if (sock < 0)
2237207f64aSDamien Miller 		goto authsock_err;
2248bb6f36cSBen Lindstrom 
2258bb6f36cSBen Lindstrom 	/* Allocate a channel for the authentication agent socket. */
226dbee4119Sdjm@openbsd.org 	nc = channel_new(ssh, "auth socket",
2278bb6f36cSBen Lindstrom 	    SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
2288bb6f36cSBen Lindstrom 	    CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
229b1ca8bb1SDamien Miller 	    0, "auth socket", 1);
230a1c1b6c8SDamien Miller 	nc->path = xstrdup(auth_sock_name);
2318bb6f36cSBen Lindstrom 	return 1;
2327207f64aSDamien Miller 
2337207f64aSDamien Miller  authsock_err:
234a627d42eSDarren Tucker 	free(auth_sock_name);
2357207f64aSDamien Miller 	if (auth_sock_dir != NULL) {
236625b6263Sdjm@openbsd.org 		temporarily_use_uid(pw);
2377207f64aSDamien Miller 		rmdir(auth_sock_dir);
238625b6263Sdjm@openbsd.org 		restore_uid();
239a627d42eSDarren Tucker 		free(auth_sock_dir);
2407207f64aSDamien Miller 	}
2417207f64aSDamien Miller 	if (sock != -1)
2427207f64aSDamien Miller 		close(sock);
2437207f64aSDamien Miller 	auth_sock_name = NULL;
2447207f64aSDamien Miller 	auth_sock_dir = NULL;
2457207f64aSDamien Miller 	return 0;
2468bb6f36cSBen Lindstrom }
2478bb6f36cSBen Lindstrom 
2481921ed9fSDarren Tucker static void
display_loginmsg(void)2491921ed9fSDarren Tucker display_loginmsg(void)
2501921ed9fSDarren Tucker {
2512808d18cSmarkus@openbsd.org 	int r;
2522808d18cSmarkus@openbsd.org 
2532808d18cSmarkus@openbsd.org 	if (sshbuf_len(loginmsg) == 0)
2542808d18cSmarkus@openbsd.org 		return;
2552808d18cSmarkus@openbsd.org 	if ((r = sshbuf_put_u8(loginmsg, 0)) != 0)
256816036f1Sdjm@openbsd.org 		fatal_fr(r, "sshbuf_put_u8");
2572808d18cSmarkus@openbsd.org 	printf("%s", (char *)sshbuf_ptr(loginmsg));
2582808d18cSmarkus@openbsd.org 	sshbuf_reset(loginmsg);
2591921ed9fSDarren Tucker }
2608bb6f36cSBen Lindstrom 
2618f574959Sdjm@openbsd.org static void
prepare_auth_info_file(struct passwd * pw,struct sshbuf * info)2628f574959Sdjm@openbsd.org prepare_auth_info_file(struct passwd *pw, struct sshbuf *info)
2638f574959Sdjm@openbsd.org {
2648f574959Sdjm@openbsd.org 	int fd = -1, success = 0;
2658f574959Sdjm@openbsd.org 
2668f574959Sdjm@openbsd.org 	if (!options.expose_userauth_info || info == NULL)
2678f574959Sdjm@openbsd.org 		return;
2688f574959Sdjm@openbsd.org 
2698f574959Sdjm@openbsd.org 	temporarily_use_uid(pw);
2708f574959Sdjm@openbsd.org 	auth_info_file = xstrdup("/tmp/sshauth.XXXXXXXXXXXXXXX");
2718f574959Sdjm@openbsd.org 	if ((fd = mkstemp(auth_info_file)) == -1) {
272816036f1Sdjm@openbsd.org 		error_f("mkstemp: %s", strerror(errno));
2738f574959Sdjm@openbsd.org 		goto out;
2748f574959Sdjm@openbsd.org 	}
2758f574959Sdjm@openbsd.org 	if (atomicio(vwrite, fd, sshbuf_mutable_ptr(info),
2768f574959Sdjm@openbsd.org 	    sshbuf_len(info)) != sshbuf_len(info)) {
277816036f1Sdjm@openbsd.org 		error_f("write: %s", strerror(errno));
2788f574959Sdjm@openbsd.org 		goto out;
2798f574959Sdjm@openbsd.org 	}
2808f574959Sdjm@openbsd.org 	if (close(fd) != 0) {
281816036f1Sdjm@openbsd.org 		error_f("close: %s", strerror(errno));
2828f574959Sdjm@openbsd.org 		goto out;
2838f574959Sdjm@openbsd.org 	}
2848f574959Sdjm@openbsd.org 	success = 1;
2858f574959Sdjm@openbsd.org  out:
2868f574959Sdjm@openbsd.org 	if (!success) {
2878f574959Sdjm@openbsd.org 		if (fd != -1)
2888f574959Sdjm@openbsd.org 			close(fd);
2898f574959Sdjm@openbsd.org 		free(auth_info_file);
2908f574959Sdjm@openbsd.org 		auth_info_file = NULL;
2918f574959Sdjm@openbsd.org 	}
2928f574959Sdjm@openbsd.org 	restore_uid();
2938f574959Sdjm@openbsd.org }
2948f574959Sdjm@openbsd.org 
2957c856857Sdjm@openbsd.org static void
set_fwdpermit_from_authopts(struct ssh * ssh,const struct sshauthopt * opts)29693c06ab6Sdjm@openbsd.org set_fwdpermit_from_authopts(struct ssh *ssh, const struct sshauthopt *opts)
2977c856857Sdjm@openbsd.org {
2987c856857Sdjm@openbsd.org 	char *tmp, *cp, *host;
2997c856857Sdjm@openbsd.org 	int port;
3007c856857Sdjm@openbsd.org 	size_t i;
3017c856857Sdjm@openbsd.org 
30293c06ab6Sdjm@openbsd.org 	if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) {
303115063a6Sdjm@openbsd.org 		channel_clear_permission(ssh, FORWARD_USER, FORWARD_LOCAL);
3047c856857Sdjm@openbsd.org 		for (i = 0; i < auth_opts->npermitopen; i++) {
3057c856857Sdjm@openbsd.org 			tmp = cp = xstrdup(auth_opts->permitopen[i]);
3067c856857Sdjm@openbsd.org 			/* This shouldn't fail as it has already been checked */
3077c856857Sdjm@openbsd.org 			if ((host = hpdelim(&cp)) == NULL)
308816036f1Sdjm@openbsd.org 				fatal_f("internal error: hpdelim");
3097c856857Sdjm@openbsd.org 			host = cleanhostname(host);
3107c856857Sdjm@openbsd.org 			if (cp == NULL || (port = permitopen_port(cp)) < 0)
311816036f1Sdjm@openbsd.org 				fatal_f("internal error: permitopen port");
31293c06ab6Sdjm@openbsd.org 			channel_add_permission(ssh,
31393c06ab6Sdjm@openbsd.org 			    FORWARD_USER, FORWARD_LOCAL, host, port);
3147c856857Sdjm@openbsd.org 			free(tmp);
3157c856857Sdjm@openbsd.org 		}
3167c856857Sdjm@openbsd.org 	}
31793c06ab6Sdjm@openbsd.org 	if ((options.allow_tcp_forwarding & FORWARD_REMOTE) != 0) {
31893c06ab6Sdjm@openbsd.org 		channel_clear_permission(ssh, FORWARD_USER, FORWARD_REMOTE);
31993c06ab6Sdjm@openbsd.org 		for (i = 0; i < auth_opts->npermitlisten; i++) {
32093c06ab6Sdjm@openbsd.org 			tmp = cp = xstrdup(auth_opts->permitlisten[i]);
32193c06ab6Sdjm@openbsd.org 			/* This shouldn't fail as it has already been checked */
32293c06ab6Sdjm@openbsd.org 			if ((host = hpdelim(&cp)) == NULL)
323816036f1Sdjm@openbsd.org 				fatal_f("internal error: hpdelim");
32493c06ab6Sdjm@openbsd.org 			host = cleanhostname(host);
32593c06ab6Sdjm@openbsd.org 			if (cp == NULL || (port = permitopen_port(cp)) < 0)
326816036f1Sdjm@openbsd.org 				fatal_f("internal error: permitlisten port");
32793c06ab6Sdjm@openbsd.org 			channel_add_permission(ssh,
32893c06ab6Sdjm@openbsd.org 			    FORWARD_USER, FORWARD_REMOTE, host, port);
32993c06ab6Sdjm@openbsd.org 			free(tmp);
33093c06ab6Sdjm@openbsd.org 		}
33193c06ab6Sdjm@openbsd.org 	}
33293c06ab6Sdjm@openbsd.org }
3337c856857Sdjm@openbsd.org 
334b31783d5SBen Lindstrom void
do_authenticated(struct ssh * ssh,Authctxt * authctxt)335dbee4119Sdjm@openbsd.org do_authenticated(struct ssh *ssh, Authctxt *authctxt)
336b31783d5SBen Lindstrom {
33797f39ae8SDamien Miller 	setproctitle("%s", authctxt->pw->pw_name);
33897f39ae8SDamien Miller 
3397c856857Sdjm@openbsd.org 	auth_log_authopts("active", auth_opts, 0);
3407c856857Sdjm@openbsd.org 
341b31783d5SBen Lindstrom 	/* setup the channel layer */
3427acefbbcSDamien Miller 	/* XXX - streamlocal? */
34393c06ab6Sdjm@openbsd.org 	set_fwdpermit_from_authopts(ssh, auth_opts);
344b31783d5SBen Lindstrom 
345115063a6Sdjm@openbsd.org 	if (!auth_opts->permit_port_forwarding_flag ||
346115063a6Sdjm@openbsd.org 	    options.disable_forwarding) {
347115063a6Sdjm@openbsd.org 		channel_disable_admin(ssh, FORWARD_LOCAL);
348115063a6Sdjm@openbsd.org 		channel_disable_admin(ssh, FORWARD_REMOTE);
349115063a6Sdjm@openbsd.org 	} else {
350115063a6Sdjm@openbsd.org 		if ((options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
351115063a6Sdjm@openbsd.org 			channel_disable_admin(ssh, FORWARD_LOCAL);
352115063a6Sdjm@openbsd.org 		else
353115063a6Sdjm@openbsd.org 			channel_permit_all(ssh, FORWARD_LOCAL);
354115063a6Sdjm@openbsd.org 		if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0)
355115063a6Sdjm@openbsd.org 			channel_disable_admin(ssh, FORWARD_REMOTE);
356115063a6Sdjm@openbsd.org 		else
357115063a6Sdjm@openbsd.org 			channel_permit_all(ssh, FORWARD_REMOTE);
358115063a6Sdjm@openbsd.org 	}
3593a00a921Sdjm@openbsd.org 	auth_debug_send(ssh);
360cd70e1b8SDarren Tucker 
3618f574959Sdjm@openbsd.org 	prepare_auth_info_file(authctxt->pw, authctxt->session_info);
3628f574959Sdjm@openbsd.org 
363dbee4119Sdjm@openbsd.org 	do_authenticated2(ssh, authctxt);
3648f574959Sdjm@openbsd.org 
365dbee4119Sdjm@openbsd.org 	do_cleanup(ssh, authctxt);
366b31783d5SBen Lindstrom }
367b31783d5SBen Lindstrom 
3684b4bfb01Sdjm@openbsd.org /* Check untrusted xauth strings for metacharacters */
3694b4bfb01Sdjm@openbsd.org static int
xauth_valid_string(const char * s)3704b4bfb01Sdjm@openbsd.org xauth_valid_string(const char *s)
3714b4bfb01Sdjm@openbsd.org {
3724b4bfb01Sdjm@openbsd.org 	size_t i;
3734b4bfb01Sdjm@openbsd.org 
3744b4bfb01Sdjm@openbsd.org 	for (i = 0; s[i] != '\0'; i++) {
3754b4bfb01Sdjm@openbsd.org 		if (!isalnum((u_char)s[i]) &&
3764b4bfb01Sdjm@openbsd.org 		    s[i] != '.' && s[i] != ':' && s[i] != '/' &&
3774b4bfb01Sdjm@openbsd.org 		    s[i] != '-' && s[i] != '_')
3784b4bfb01Sdjm@openbsd.org 			return 0;
3794b4bfb01Sdjm@openbsd.org 	}
3804b4bfb01Sdjm@openbsd.org 	return 1;
3814b4bfb01Sdjm@openbsd.org }
3824b4bfb01Sdjm@openbsd.org 
383293ee3c9SDarren Tucker #define USE_PIPES 1
384b38eff8eSDamien Miller /*
385b38eff8eSDamien Miller  * This is called to fork and execute a command when we have no tty.  This
386b38eff8eSDamien Miller  * will call do_child from the child, and server_loop from the parent after
387b38eff8eSDamien Miller  * setting up file descriptors and such.
388b38eff8eSDamien Miller  */
3897207f64aSDamien Miller int
do_exec_no_pty(struct ssh * ssh,Session * s,const char * command)390dbee4119Sdjm@openbsd.org do_exec_no_pty(struct ssh *ssh, Session *s, const char *command)
391b38eff8eSDamien Miller {
392ce0f6342SBen Lindstrom 	pid_t pid;
393b38eff8eSDamien Miller #ifdef USE_PIPES
394b38eff8eSDamien Miller 	int pin[2], pout[2], perr[2];
3957207f64aSDamien Miller 
39622a29880SDamien Miller 	if (s == NULL)
39722a29880SDamien Miller 		fatal("do_exec_no_pty: no session");
39822a29880SDamien Miller 
399b38eff8eSDamien Miller 	/* Allocate pipes for communicating with the program. */
4004d28fa78Sderaadt@openbsd.org 	if (pipe(pin) == -1) {
401816036f1Sdjm@openbsd.org 		error_f("pipe in: %.100s", strerror(errno));
4027207f64aSDamien Miller 		return -1;
4037207f64aSDamien Miller 	}
4044d28fa78Sderaadt@openbsd.org 	if (pipe(pout) == -1) {
405816036f1Sdjm@openbsd.org 		error_f("pipe out: %.100s", strerror(errno));
4067207f64aSDamien Miller 		close(pin[0]);
4077207f64aSDamien Miller 		close(pin[1]);
4087207f64aSDamien Miller 		return -1;
4097207f64aSDamien Miller 	}
4104d28fa78Sderaadt@openbsd.org 	if (pipe(perr) == -1) {
411816036f1Sdjm@openbsd.org 		error_f("pipe err: %.100s", strerror(errno));
41222a29880SDamien Miller 		close(pin[0]);
41322a29880SDamien Miller 		close(pin[1]);
41422a29880SDamien Miller 		close(pout[0]);
41522a29880SDamien Miller 		close(pout[1]);
41622a29880SDamien Miller 		return -1;
41722a29880SDamien Miller 	}
4187207f64aSDamien Miller #else
419b38eff8eSDamien Miller 	int inout[2], err[2];
4207207f64aSDamien Miller 
42122a29880SDamien Miller 	if (s == NULL)
42222a29880SDamien Miller 		fatal("do_exec_no_pty: no session");
42322a29880SDamien Miller 
424b38eff8eSDamien Miller 	/* Uses socket pairs to communicate with the program. */
4254d28fa78Sderaadt@openbsd.org 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) {
426816036f1Sdjm@openbsd.org 		error_f("socketpair #1: %.100s", strerror(errno));
4277207f64aSDamien Miller 		return -1;
4287207f64aSDamien Miller 	}
4294d28fa78Sderaadt@openbsd.org 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) == -1) {
430816036f1Sdjm@openbsd.org 		error_f("socketpair #2: %.100s", strerror(errno));
43122a29880SDamien Miller 		close(inout[0]);
43222a29880SDamien Miller 		close(inout[1]);
43322a29880SDamien Miller 		return -1;
43422a29880SDamien Miller 	}
4357207f64aSDamien Miller #endif
4367207f64aSDamien Miller 
437e247cc40SDamien Miller 	session_proctitle(s);
438b38eff8eSDamien Miller 
439b38eff8eSDamien Miller 	/* Fork the child. */
4407207f64aSDamien Miller 	switch ((pid = fork())) {
4417207f64aSDamien Miller 	case -1:
442816036f1Sdjm@openbsd.org 		error_f("fork: %.100s", strerror(errno));
4437207f64aSDamien Miller #ifdef USE_PIPES
4447207f64aSDamien Miller 		close(pin[0]);
4457207f64aSDamien Miller 		close(pin[1]);
4467207f64aSDamien Miller 		close(pout[0]);
4477207f64aSDamien Miller 		close(pout[1]);
4487207f64aSDamien Miller 		close(perr[0]);
4497207f64aSDamien Miller 		close(perr[1]);
4507207f64aSDamien Miller #else
4517207f64aSDamien Miller 		close(inout[0]);
4527207f64aSDamien Miller 		close(inout[1]);
4537207f64aSDamien Miller 		close(err[0]);
4547207f64aSDamien Miller 		close(err[1]);
4557207f64aSDamien Miller #endif
4567207f64aSDamien Miller 		return -1;
4577207f64aSDamien Miller 	case 0:
4583e33cecfSDarren Tucker 		is_child = 1;
459264ee307SBen Lindstrom 
460b38eff8eSDamien Miller 		/*
461b38eff8eSDamien Miller 		 * Create a new session and process group since the 4.4BSD
462b38eff8eSDamien Miller 		 * setlogin() affects the entire process group.
463b38eff8eSDamien Miller 		 */
4644d28fa78Sderaadt@openbsd.org 		if (setsid() == -1)
465b38eff8eSDamien Miller 			error("setsid failed: %.100s", strerror(errno));
466b38eff8eSDamien Miller 
467b38eff8eSDamien Miller #ifdef USE_PIPES
468b38eff8eSDamien Miller 		/*
469b38eff8eSDamien Miller 		 * Redirect stdin.  We close the parent side of the socket
470b38eff8eSDamien Miller 		 * pair, and make the child side the standard input.
471b38eff8eSDamien Miller 		 */
472b38eff8eSDamien Miller 		close(pin[1]);
4734d28fa78Sderaadt@openbsd.org 		if (dup2(pin[0], 0) == -1)
474b38eff8eSDamien Miller 			perror("dup2 stdin");
475b38eff8eSDamien Miller 		close(pin[0]);
476b38eff8eSDamien Miller 
477b38eff8eSDamien Miller 		/* Redirect stdout. */
478b38eff8eSDamien Miller 		close(pout[0]);
4794d28fa78Sderaadt@openbsd.org 		if (dup2(pout[1], 1) == -1)
480b38eff8eSDamien Miller 			perror("dup2 stdout");
481b38eff8eSDamien Miller 		close(pout[1]);
482b38eff8eSDamien Miller 
483b38eff8eSDamien Miller 		/* Redirect stderr. */
484b38eff8eSDamien Miller 		close(perr[0]);
4854d28fa78Sderaadt@openbsd.org 		if (dup2(perr[1], 2) == -1)
486b38eff8eSDamien Miller 			perror("dup2 stderr");
487b38eff8eSDamien Miller 		close(perr[1]);
4887207f64aSDamien Miller #else
489