upstream commit

remove UseLogin option and support for having /bin/login
manage login sessions; ok deraadt markus dtucker

Upstream-ID: bea7213fbf158efab7e602d9d844fba4837d2712
This commit is contained in:
djm@openbsd.org 2016-08-19 03:18:06 +00:00 committed by Damien Miller
parent ffe6549c2f
commit 83b581862a
7 changed files with 71 additions and 157 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.162 2016/08/13 17:47:41 markus Exp $ */ /* $OpenBSD: monitor.c,v 1.163 2016/08/19 03:18:06 djm Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org> * Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -1395,9 +1395,6 @@ mm_record_login(Session *s, struct passwd *pw)
socklen_t fromlen; socklen_t fromlen;
struct sockaddr_storage from; struct sockaddr_storage from;
if (options.use_login)
return;
/* /*
* Get IP address of client. If the connection is not a socket, let * Get IP address of client. If the connection is not a socket, let
* the address be 0.0.0.0. * the address be 0.0.0.0.

View File

@ -1,5 +1,5 @@
/* $OpenBSD: servconf.c,v 1.293 2016/08/15 12:27:56 naddy Exp $ */ /* $OpenBSD: servconf.c,v 1.294 2016/08/19 03:18:06 djm Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -120,7 +120,6 @@ initialize_server_options(ServerOptions *options)
options->challenge_response_authentication = -1; options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1; options->permit_empty_passwd = -1;
options->permit_user_env = -1; options->permit_user_env = -1;
options->use_login = -1;
options->compression = -1; options->compression = -1;
options->rekey_limit = -1; options->rekey_limit = -1;
options->rekey_interval = -1; options->rekey_interval = -1;
@ -281,8 +280,6 @@ fill_default_server_options(ServerOptions *options)
options->permit_empty_passwd = 0; options->permit_empty_passwd = 0;
if (options->permit_user_env == -1) if (options->permit_user_env == -1)
options->permit_user_env = 0; options->permit_user_env = 0;
if (options->use_login == -1)
options->use_login = 0;
if (options->compression == -1) if (options->compression == -1)
options->compression = COMP_DELAYED; options->compression = COMP_DELAYED;
if (options->rekey_limit == -1) if (options->rekey_limit == -1)
@ -397,7 +394,7 @@ typedef enum {
sPrintMotd, sPrintLastLog, sIgnoreRhosts, sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes, sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
@ -508,7 +505,7 @@ static struct {
{ "strictmodes", sStrictModes, SSHCFG_GLOBAL }, { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
{ "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
{ "uselogin", sUseLogin, SSHCFG_GLOBAL }, { "uselogin", sDeprecated, SSHCFG_GLOBAL },
{ "compression", sCompression, SSHCFG_GLOBAL }, { "compression", sCompression, SSHCFG_GLOBAL },
{ "rekeylimit", sRekeyLimit, SSHCFG_ALL }, { "rekeylimit", sRekeyLimit, SSHCFG_ALL },
{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
@ -1283,10 +1280,6 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->permit_user_env; intptr = &options->permit_user_env;
goto parse_flag; goto parse_flag;
case sUseLogin:
intptr = &options->use_login;
goto parse_flag;
case sCompression: case sCompression:
intptr = &options->compression; intptr = &options->compression;
multistate_ptr = multistate_compression; multistate_ptr = multistate_compression;
@ -2261,7 +2254,6 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
dump_cfg_fmtint(sUseLogin, o->use_login);
dump_cfg_fmtint(sCompression, o->compression); dump_cfg_fmtint(sCompression, o->compression);
dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
dump_cfg_fmtint(sUseDNS, o->use_dns); dump_cfg_fmtint(sUseDNS, o->use_dns);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.121 2016/08/15 12:27:56 naddy Exp $ */ /* $OpenBSD: servconf.h,v 1.122 2016/08/19 03:18:06 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -121,7 +121,6 @@ typedef struct {
int permit_empty_passwd; /* If false, do not permit empty int permit_empty_passwd; /* If false, do not permit empty
* passwords. */ * passwords. */
int permit_user_env; /* If true, read ~/.ssh/environment */ int permit_user_env; /* If true, read ~/.ssh/environment */
int use_login; /* If true, login(1) is used */
int compression; /* If true, compression is allowed */ int compression; /* If true, compression is allowed */
int allow_tcp_forwarding; /* One of FORWARD_* */ int allow_tcp_forwarding; /* One of FORWARD_* */
int allow_streamlocal_forwarding; /* One of FORWARD_* */ int allow_streamlocal_forwarding; /* One of FORWARD_* */

169
session.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.283 2016/08/13 17:47:41 markus Exp $ */ /* $OpenBSD: session.c,v 1.284 2016/08/19 03:18:06 djm Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -544,7 +544,7 @@ do_exec_pty(Session *s, const char *command)
/* record login, etc. similar to login(1) */ /* record login, etc. similar to login(1) */
#ifndef HAVE_OSF_SIA #ifndef HAVE_OSF_SIA
if (!(options.use_login && command == NULL)) { if (command != NULL) {
#ifdef _UNICOS #ifdef _UNICOS
cray_init_job(s->pw); /* set up cray jid and tmpdir */ cray_init_job(s->pw); /* set up cray jid and tmpdir */
#endif /* _UNICOS */ #endif /* _UNICOS */
@ -1019,69 +1019,63 @@ do_setup_env(Session *s, const char *shell)
ssh_gssapi_do_child(&env, &envsize); ssh_gssapi_do_child(&env, &envsize);
#endif #endif
if (!options.use_login) { /* Set basic environment. */
/* Set basic environment. */ for (i = 0; i < s->num_env; i++)
for (i = 0; i < s->num_env; i++) child_set_env(&env, &envsize, s->env[i].name, s->env[i].val);
child_set_env(&env, &envsize, s->env[i].name,
s->env[i].val);
child_set_env(&env, &envsize, "USER", pw->pw_name); child_set_env(&env, &envsize, "USER", pw->pw_name);
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
#ifdef _AIX #ifdef _AIX
child_set_env(&env, &envsize, "LOGIN", pw->pw_name); child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
#endif #endif
child_set_env(&env, &envsize, "HOME", pw->pw_dir); child_set_env(&env, &envsize, "HOME", pw->pw_dir);
#ifdef HAVE_LOGIN_CAP #ifdef HAVE_LOGIN_CAP
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0) if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
else else
child_set_env(&env, &envsize, "PATH", getenv("PATH")); child_set_env(&env, &envsize, "PATH", getenv("PATH"));
#else /* HAVE_LOGIN_CAP */ #else /* HAVE_LOGIN_CAP */
# ifndef HAVE_CYGWIN # ifndef HAVE_CYGWIN
/* /*
* There's no standard path on Windows. The path contains * There's no standard path on Windows. The path contains
* important components pointing to the system directories, * important components pointing to the system directories,
* needed for loading shared libraries. So the path better * needed for loading shared libraries. So the path better
* remains intact here. * remains intact here.
*/ */
# ifdef HAVE_ETC_DEFAULT_LOGIN # ifdef HAVE_ETC_DEFAULT_LOGIN
read_etc_default_login(&env, &envsize, pw->pw_uid); read_etc_default_login(&env, &envsize, pw->pw_uid);
path = child_get_env(env, "PATH"); path = child_get_env(env, "PATH");
# endif /* HAVE_ETC_DEFAULT_LOGIN */ # endif /* HAVE_ETC_DEFAULT_LOGIN */
if (path == NULL || *path == '\0') { if (path == NULL || *path == '\0') {
child_set_env(&env, &envsize, "PATH", child_set_env(&env, &envsize, "PATH",
s->pw->pw_uid == 0 ? s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH);
SUPERUSER_PATH : _PATH_STDPATH); }
}
# endif /* HAVE_CYGWIN */ # endif /* HAVE_CYGWIN */
#endif /* HAVE_LOGIN_CAP */ #endif /* HAVE_LOGIN_CAP */
snprintf(buf, sizeof buf, "%.200s/%.50s", snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name);
_PATH_MAILDIR, pw->pw_name); child_set_env(&env, &envsize, "MAIL", buf);
child_set_env(&env, &envsize, "MAIL", buf);
/* Normal systems set SHELL by default. */
child_set_env(&env, &envsize, "SHELL", shell);
/* Normal systems set SHELL by default. */
child_set_env(&env, &envsize, "SHELL", shell);
}
if (getenv("TZ")) if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ")); child_set_env(&env, &envsize, "TZ", getenv("TZ"));
/* Set custom environment options from RSA authentication. */ /* Set custom environment options from RSA authentication. */
if (!options.use_login) { while (custom_environment) {
while (custom_environment) { struct envstring *ce = custom_environment;
struct envstring *ce = custom_environment; char *str = ce->s;
char *str = ce->s;
for (i = 0; str[i] != '=' && str[i]; i++) for (i = 0; str[i] != '=' && str[i]; i++)
; ;
if (str[i] == '=') { if (str[i] == '=') {
str[i] = 0; str[i] = 0;
child_set_env(&env, &envsize, str, str + i + 1); child_set_env(&env, &envsize, str, str + i + 1);
}
custom_environment = ce->next;
free(ce->s);
free(ce);
} }
custom_environment = ce->next;
free(ce->s);
free(ce);
} }
/* SSH_CLIENT deprecated */ /* SSH_CLIENT deprecated */
@ -1143,7 +1137,7 @@ do_setup_env(Session *s, const char *shell)
* Pull in any environment variables that may have * Pull in any environment variables that may have
* been set by PAM. * been set by PAM.
*/ */
if (options.use_pam && !options.use_login) { if (options.use_pam) {
char **p; char **p;
p = fetch_pam_child_environment(); p = fetch_pam_child_environment();
@ -1161,7 +1155,7 @@ do_setup_env(Session *s, const char *shell)
auth_sock_name); auth_sock_name);
/* read $HOME/.ssh/environment. */ /* read $HOME/.ssh/environment. */
if (options.permit_user_env && !options.use_login) { if (options.permit_user_env) {
snprintf(buf, sizeof buf, "%.200s/.ssh/environment", snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
strcmp(pw->pw_dir, "/") ? pw->pw_dir : ""); strcmp(pw->pw_dir, "/") ? pw->pw_dir : "");
read_environment_file(&env, &envsize, buf); read_environment_file(&env, &envsize, buf);
@ -1442,27 +1436,6 @@ do_pwchange(Session *s)
exit(1); exit(1);
} }
static void
launch_login(struct passwd *pw, const char *hostname)
{
/* Launch login(1). */
execl(LOGIN_PROGRAM, "login", "-h", hostname,
#ifdef xxxLOGIN_NEEDS_TERM
(s->term ? s->term : "unknown"),
#endif /* LOGIN_NEEDS_TERM */
#ifdef LOGIN_NO_ENDOPT
"-p", "-f", pw->pw_name, (char *)NULL);
#else
"-p", "-f", "--", pw->pw_name, (char *)NULL);
#endif
/* Login couldn't be executed, die. */
perror("login");
exit(1);
}
static void static void
child_close_fds(void) child_close_fds(void)
{ {
@ -1510,11 +1483,10 @@ child_close_fds(void)
void void
do_child(Session *s, const char *command) do_child(Session *s, const char *command)
{ {
struct ssh *ssh = active_state; /* XXX */
extern char **environ; extern char **environ;
char **env; char **env;
char *argv[ARGV_MAX]; char *argv[ARGV_MAX];
const char *shell, *shell0, *hostname = NULL; const char *shell, *shell0;
struct passwd *pw = s->pw; struct passwd *pw = s->pw;
int r = 0; int r = 0;
@ -1529,10 +1501,6 @@ do_child(Session *s, const char *command)
exit(1); exit(1);
} }
/* login(1) is only called if we execute the login shell */
if (options.use_login && command != NULL)
options.use_login = 0;
#ifdef _UNICOS #ifdef _UNICOS
cray_setup(pw->pw_uid, pw->pw_name, command); cray_setup(pw->pw_uid, pw->pw_name, command);
#endif /* _UNICOS */ #endif /* _UNICOS */
@ -1541,28 +1509,26 @@ do_child(Session *s, const char *command)
* Login(1) does this as well, and it needs uid 0 for the "-h" * Login(1) does this as well, and it needs uid 0 for the "-h"
* switch, so we let login(1) to this for us. * switch, so we let login(1) to this for us.
*/ */
if (!options.use_login) {
#ifdef HAVE_OSF_SIA #ifdef HAVE_OSF_SIA
session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty); session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty);
if (!check_quietlogin(s, command)) if (!check_quietlogin(s, command))
do_motd(); do_motd();
#else /* HAVE_OSF_SIA */ #else /* HAVE_OSF_SIA */
/* When PAM is enabled we rely on it to do the nologin check */ /* When PAM is enabled we rely on it to do the nologin check */
if (!options.use_pam) if (!options.use_pam)
do_nologin(pw); do_nologin(pw);
do_setusercontext(pw); do_setusercontext(pw);
/* /*
* PAM session modules in do_setusercontext may have * PAM session modules in do_setusercontext may have
* generated messages, so if this in an interactive * generated messages, so if this in an interactive
* login then display them too. * login then display them too.
*/ */
if (!check_quietlogin(s, command)) if (!check_quietlogin(s, command))
display_loginmsg(); display_loginmsg();
#endif /* HAVE_OSF_SIA */ #endif /* HAVE_OSF_SIA */
}
#ifdef USE_PAM #ifdef USE_PAM
if (options.use_pam && !options.use_login && !is_pam_session_open()) { if (options.use_pam && !is_pam_session_open()) {
debug3("PAM session not opened, exiting"); debug3("PAM session not opened, exiting");
display_loginmsg(); display_loginmsg();
exit(254); exit(254);
@ -1585,10 +1551,6 @@ do_child(Session *s, const char *command)
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
#endif #endif
/* we have to stash the hostname before we close our socket. */
if (options.use_login)
hostname = session_get_remote_name_or_ip(ssh, utmp_len,
options.use_dns);
/* /*
* Close the connection descriptors; note that this is the child, and * Close the connection descriptors; note that this is the child, and
* the server will still have the socket open, and it is important * the server will still have the socket open, and it is important
@ -1647,8 +1609,7 @@ do_child(Session *s, const char *command)
closefrom(STDERR_FILENO + 1); closefrom(STDERR_FILENO + 1);
if (!options.use_login) do_rc_files(s, shell);
do_rc_files(s, shell);
/* restore SIGPIPE for child */ /* restore SIGPIPE for child */
signal(SIGPIPE, SIG_DFL); signal(SIGPIPE, SIG_DFL);
@ -1678,11 +1639,6 @@ do_child(Session *s, const char *command)
fflush(NULL); fflush(NULL);
if (options.use_login) {
launch_login(pw, hostname);
/* NEVERREACHED */
}
/* Get the last component of the shell name. */ /* Get the last component of the shell name. */
if ((shell0 = strrchr(shell, '/')) != NULL) if ((shell0 = strrchr(shell, '/')) != NULL)
shell0++; shell0++;
@ -2502,11 +2458,6 @@ session_setup_x11fwd(Session *s)
packet_send_debug("No xauth program; cannot forward with spoofing."); packet_send_debug("No xauth program; cannot forward with spoofing.");
return 0; return 0;
} }
if (options.use_login) {
packet_send_debug("X11 forwarding disabled; "
"not compatible with UseLogin=yes.");
return 0;
}
if (s->display != NULL) { if (s->display != NULL) {
debug("X11 display already set."); debug("X11 display already set.");
return 0; return 0;

7
sshd.8
View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: sshd.8,v 1.285 2016/08/15 12:32:04 naddy Exp $ .\" $OpenBSD: sshd.8,v 1.286 2016/08/19 03:18:06 djm Exp $
.Dd $Mdocdate: August 15 2016 $ .Dd $Mdocdate: August 19 2016 $
.Dt SSHD 8 .Dt SSHD 8
.Os .Os
.Sh NAME .Sh NAME
@ -504,9 +504,6 @@ Environment processing is disabled by default and is
controlled via the controlled via the
.Cm PermitUserEnvironment .Cm PermitUserEnvironment
option. option.
This option is automatically disabled if
.Cm UseLogin
is enabled.
.It Cm from="pattern-list" .It Cm from="pattern-list"
Specifies that in addition to public key authentication, either the canonical Specifies that in addition to public key authentication, either the canonical
name of the remote host or its IP address must be present in the name of the remote host or its IP address must be present in the

4
sshd.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.473 2016/08/15 12:27:56 naddy Exp $ */ /* $OpenBSD: sshd.c,v 1.474 2016/08/19 03:18:07 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -629,7 +629,7 @@ privsep_postauth(Authctxt *authctxt)
#ifdef DISABLE_FD_PASSING #ifdef DISABLE_FD_PASSING
if (1) { if (1) {
#else #else
if (authctxt->pw->pw_uid == 0 || options.use_login) { if (authctxt->pw->pw_uid == 0) {
#endif #endif
/* File descriptor passing is broken or root login */ /* File descriptor passing is broken or root login */
use_privsep = 0; use_privsep = 0;

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: sshd_config.5,v 1.229 2016/08/15 12:32:04 naddy Exp $ .\" $OpenBSD: sshd_config.5,v 1.230 2016/08/19 03:18:07 djm Exp $
.Dd $Mdocdate: August 15 2016 $ .Dd $Mdocdate: August 19 2016 $
.Dt SSHD_CONFIG 5 .Dt SSHD_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -1489,25 +1489,6 @@ and
.Cm Match .Cm Match
.Cm Host .Cm Host
directives. directives.
.It Cm UseLogin
Specifies whether
.Xr login 1
is used for interactive login sessions.
The default is
.Dq no .
Note that
.Xr login 1
is never used for remote command execution.
Note also, that if this is enabled,
.Cm X11Forwarding
will be disabled because
.Xr login 1
does not know how to handle
.Xr xauth 1
cookies.
If
.Cm UsePrivilegeSeparation
is specified, it will be disabled after authentication.
.It Cm UsePAM .It Cm UsePAM
Enables the Pluggable Authentication Module interface. Enables the Pluggable Authentication Module interface.
If set to If set to
@ -1596,9 +1577,6 @@ setting.
.Pp .Pp
Note that disabling X11 forwarding does not prevent users from Note that disabling X11 forwarding does not prevent users from
forwarding X11 traffic, as users can always install their own forwarders. forwarding X11 traffic, as users can always install their own forwarders.
X11 forwarding is automatically disabled if
.Cm UseLogin
is enabled.
.It Cm X11UseLocalhost .It Cm X11UseLocalhost
Specifies whether Specifies whether
.Xr sshd 8 .Xr sshd 8