version 1.19, 2016/04/14 16:42:09 |
version 1.19.2.3, 2017/04/26 02:52:15 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
/* $OpenBSD: session.c,v 1.280 2016/02/16 03:37:48 djm Exp $ */ |
/* $OpenBSD: session.c,v 1.286 2016/11/30 03:00:05 djm Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
Line 44 __RCSID("$NetBSD$"); |
|
Line 44 __RCSID("$NetBSD$"); |
|
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <sys/queue.h> |
#include <sys/queue.h> |
|
|
|
#include <ctype.h> |
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <grp.h> |
#include <grp.h> |
Line 60 __RCSID("$NetBSD$"); |
|
Line 61 __RCSID("$NetBSD$"); |
|
|
|
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "ssh.h" |
#include "ssh.h" |
#include "ssh1.h" |
|
#include "ssh2.h" |
#include "ssh2.h" |
#include "sshpty.h" |
#include "sshpty.h" |
#include "packet.h" |
#include "packet.h" |
Line 115 __dead void do_child(Session *, const ch |
|
Line 115 __dead void do_child(Session *, const ch |
|
void do_motd(void); |
void do_motd(void); |
int check_quietlogin(Session *, const char *); |
int check_quietlogin(Session *, const char *); |
|
|
static void do_authenticated1(Authctxt *); |
|
static void do_authenticated2(Authctxt *); |
static void do_authenticated2(Authctxt *); |
|
|
static int session_pty_req(Session *); |
static int session_pty_req(Session *); |
Line 247 do_authenticated(Authctxt *authctxt) |
|
Line 246 do_authenticated(Authctxt *authctxt) |
|
|
|
/* setup the channel layer */ |
/* setup the channel layer */ |
/* XXX - streamlocal? */ |
/* XXX - streamlocal? */ |
if (no_port_forwarding_flag || |
if (no_port_forwarding_flag || options.disable_forwarding || |
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) |
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) |
channel_disable_adm_local_opens(); |
channel_disable_adm_local_opens(); |
else |
else |
Line 255 do_authenticated(Authctxt *authctxt) |
|
Line 254 do_authenticated(Authctxt *authctxt) |
|
|
|
auth_debug_send(); |
auth_debug_send(); |
|
|
if (compat20) |
do_authenticated2(authctxt); |
do_authenticated2(authctxt); |
|
else |
|
do_authenticated1(authctxt); |
|
|
|
do_cleanup(authctxt); |
do_cleanup(authctxt); |
} |
} |
|
|
/* |
/* Check untrusted xauth strings for metacharacters */ |
* Prepares for an interactive session. This is called after the user has |
static int |
* been successfully authenticated. During this message exchange, pseudo |
xauth_valid_string(const char *s) |
* terminals are allocated, X11, TCP/IP, and authentication agent forwardings |
|
* are requested, etc. |
|
*/ |
|
static void |
|
do_authenticated1(Authctxt *authctxt) |
|
{ |
{ |
Session *s; |
size_t i; |
char *command; |
|
int success, type, screen_flag; |
|
int enable_compression_after_reply = 0; |
|
u_int proto_len, data_len, dlen, compression_level = 0; |
|
|
|
s = session_new(); |
|
if (s == NULL) { |
|
error("no more sessions"); |
|
return; |
|
} |
|
s->authctxt = authctxt; |
|
s->pw = authctxt->pw; |
|
|
|
/* |
|
* We stay in this loop until the client requests to execute a shell |
|
* or a command. |
|
*/ |
|
for (;;) { |
|
success = 0; |
|
|
|
/* Get a packet from the client. */ |
|
type = packet_read(); |
|
|
|
/* Process the packet. */ |
|
switch (type) { |
|
case SSH_CMSG_REQUEST_COMPRESSION: |
|
compression_level = packet_get_int(); |
|
packet_check_eom(); |
|
if (compression_level < 1 || compression_level > 9) { |
|
packet_send_debug("Received invalid compression level %d.", |
|
compression_level); |
|
break; |
|
} |
|
if (options.compression == COMP_NONE) { |
|
debug2("compression disabled"); |
|
break; |
|
} |
|
/* Enable compression after we have responded with SUCCESS. */ |
|
enable_compression_after_reply = 1; |
|
success = 1; |
|
break; |
|
|
|
case SSH_CMSG_REQUEST_PTY: |
|
success = session_pty_req(s); |
|
break; |
|
|
|
case SSH_CMSG_X11_REQUEST_FORWARDING: |
|
s->auth_proto = packet_get_string(&proto_len); |
|
s->auth_data = packet_get_string(&data_len); |
|
|
|
screen_flag = packet_get_protocol_flags() & |
|
SSH_PROTOFLAG_SCREEN_NUMBER; |
|
debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag); |
|
|
|
if (packet_remaining() == 4) { |
|
if (!screen_flag) |
|
debug2("Buggy client: " |
|
"X11 screen flag missing"); |
|
s->screen = packet_get_int(); |
|
} else { |
|
s->screen = 0; |
|
} |
|
packet_check_eom(); |
|
success = session_setup_x11fwd(s); |
|
if (!success) { |
|
free(s->auth_proto); |
|
free(s->auth_data); |
|
s->auth_proto = NULL; |
|
s->auth_data = NULL; |
|
} |
|
break; |
|
|
|
case SSH_CMSG_AGENT_REQUEST_FORWARDING: |
|
if (!options.allow_agent_forwarding || |
|
no_agent_forwarding_flag || compat13) { |
|
debug("Authentication agent forwarding not permitted for this authentication."); |
|
break; |
|
} |
|
debug("Received authentication agent forwarding request."); |
|
success = auth_input_request_forwarding(s->pw); |
|
break; |
|
|
|
case SSH_CMSG_PORT_FORWARD_REQUEST: |
for (i = 0; s[i] != '\0'; i++) { |
if (no_port_forwarding_flag) { |
if (!isalnum((u_char)s[i]) && |
debug("Port forwarding not permitted for this authentication."); |
s[i] != '.' && s[i] != ':' && s[i] != '/' && |
break; |
s[i] != '-' && s[i] != '_') |
} |
return 0; |
if (!(options.allow_tcp_forwarding & FORWARD_REMOTE)) { |
|
debug("Port forwarding not permitted."); |
|
break; |
|
} |
|
debug("Received TCP/IP port forwarding request."); |
|
if (channel_input_port_forward_request(s->pw->pw_uid == 0, |
|
&options.fwd_opts) < 0) { |
|
debug("Port forwarding failed."); |
|
break; |
|
} |
|
success = 1; |
|
break; |
|
|
|
case SSH_CMSG_MAX_PACKET_SIZE: |
|
if (packet_set_maxsize(packet_get_int()) > 0) |
|
success = 1; |
|
break; |
|
|
|
#if defined(AFS) || defined(KRB5) |
|
case SSH_CMSG_HAVE_KERBEROS_TGT: |
|
if (!options.kerberos_tgt_passing) { |
|
verbose("Kerberos TGT passing disabled."); |
|
} else { |
|
char *kdata = packet_get_string(&dlen); |
|
packet_check_eom(); |
|
|
|
/* XXX - 0x41, see creds_to_radix version */ |
|
if (kdata[0] != 0x41) { |
|
#ifdef KRB5 |
|
krb5_data tgt; |
|
tgt.data = kdata; |
|
tgt.length = dlen; |
|
|
|
if (auth_krb5_tgt(s->authctxt, &tgt)) |
|
success = 1; |
|
else |
|
verbose("Kerberos v5 TGT refused for %.100s", s->authctxt->user); |
|
#endif /* KRB5 */ |
|
} else { |
|
#ifdef AFS |
|
if (auth_krb4_tgt(s->authctxt, kdata)) |
|
success = 1; |
|
else |
|
verbose("Kerberos v4 TGT refused for %.100s", s->authctxt->user); |
|
#endif /* AFS */ |
|
} |
|
free(kdata); |
|
} |
|
break; |
|
#endif /* AFS || KRB5 */ |
|
|
|
#ifdef AFS |
|
case SSH_CMSG_HAVE_AFS_TOKEN: |
|
if (!options.afs_token_passing || !k_hasafs()) { |
|
verbose("AFS token passing disabled."); |
|
} else { |
|
/* Accept AFS token. */ |
|
char *token = packet_get_string(&dlen); |
|
packet_check_eom(); |
|
|
|
if (auth_afs_token(s->authctxt, token)) |
|
success = 1; |
|
else |
|
verbose("AFS token refused for %.100s", |
|
s->authctxt->user); |
|
free(token); |
|
} |
|
break; |
|
#endif /* AFS */ |
|
|
|
case SSH_CMSG_EXEC_SHELL: |
|
case SSH_CMSG_EXEC_CMD: |
|
if (type == SSH_CMSG_EXEC_CMD) { |
|
command = packet_get_string(&dlen); |
|
debug("Exec command '%.500s'", command); |
|
if (do_exec(s, command) != 0) |
|
packet_disconnect( |
|
"command execution failed"); |
|
free(command); |
|
} else { |
|
if (do_exec(s, NULL) != 0) |
|
packet_disconnect( |
|
"shell execution failed"); |
|
} |
|
packet_check_eom(); |
|
session_close(s); |
|
return; |
|
|
|
default: |
|
/* |
|
* Any unknown messages in this phase are ignored, |
|
* and a failure message is returned. |
|
*/ |
|
logit("Unknown packet type received after authentication: %d", type); |
|
} |
|
packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE); |
|
packet_send(); |
|
packet_write_wait(); |
|
|
|
/* Enable compression now that we have replied if appropriate. */ |
|
if (enable_compression_after_reply) { |
|
enable_compression_after_reply = 0; |
|
packet_start_compression(compression_level); |
|
} |
|
} |
} |
|
return 1; |
} |
} |
|
|
#define USE_PIPES 1 |
#define USE_PIPES 1 |
Line 621 do_exec_no_pty(Session *s, const char *c |
|
Line 427 do_exec_no_pty(Session *s, const char *c |
|
close(pout[1]); |
close(pout[1]); |
close(perr[1]); |
close(perr[1]); |
|
|
if (compat20) { |
session_set_fds(s, pin[1], pout[0], perr[0], |
session_set_fds(s, pin[1], pout[0], perr[0], |
s->is_subsystem, 0); |
s->is_subsystem, 0); |
|
} else { |
|
/* Enter the interactive session. */ |
|
server_loop(pid, pin[1], pout[0], perr[0]); |
|
/* server_loop has closed pin[1], pout[0], and perr[0]. */ |
|
} |
|
#else |
#else |
/* We are the parent. Close the child sides of the socket pairs. */ |
/* We are the parent. Close the child sides of the socket pairs. */ |
close(inout[0]); |
close(inout[0]); |
Line 638 do_exec_no_pty(Session *s, const char *c |
|
Line 438 do_exec_no_pty(Session *s, const char *c |
|
* Enter the interactive session. Note: server_loop must be able to |
* Enter the interactive session. Note: server_loop must be able to |
* handle the case that fdin and fdout are the same. |
* handle the case that fdin and fdout are the same. |
*/ |
*/ |
if (compat20) { |
session_set_fds(s, inout[1], inout[1], err[1], |
session_set_fds(s, inout[1], inout[1], err[1], |
s->is_subsystem, 0); |
s->is_subsystem, 0); |
|
} else { |
|
server_loop(pid, inout[1], inout[1], err[1]); |
|
/* server_loop has closed inout[1] and err[1]. */ |
|
} |
|
#endif |
#endif |
return 0; |
return 0; |
} |
} |
Line 732 do_exec_pty(Session *s, const char *comm |
|
Line 527 do_exec_pty(Session *s, const char *comm |
|
close(ttyfd); |
close(ttyfd); |
|
|
/* record login, etc. similar to login(1) */ |
/* record login, etc. similar to login(1) */ |
if (!(options.use_login && command == NULL)) |
do_login(s, command); |
do_login(s, command); |
|
|
|
/* |
/* |
* Do common processing for the child, such as execing |
* Do common processing for the child, such as execing |
Line 753 do_exec_pty(Session *s, const char *comm |
|
Line 547 do_exec_pty(Session *s, const char *comm |
|
s->ptymaster = ptymaster; |
s->ptymaster = ptymaster; |
packet_set_interactive(1, |
packet_set_interactive(1, |
options.ip_qos_interactive, options.ip_qos_bulk); |
options.ip_qos_interactive, options.ip_qos_bulk); |
if (compat20) { |
session_set_fds(s, ptyfd, fdout, -1, 1, 1); |
session_set_fds(s, ptyfd, fdout, -1, 1, 1); |
|
} else { |
|
server_loop(pid, ptyfd, fdout, -1); |
|
/* server_loop _has_ closed ptyfd and fdout. */ |
|
} |
|
return 0; |
return 0; |
} |
} |
|
|
Line 769 do_exec_pty(Session *s, const char *comm |
|
Line 558 do_exec_pty(Session *s, const char *comm |
|
int |
int |
do_exec(Session *s, const char *command) |
do_exec(Session *s, const char *command) |
{ |
{ |
|
struct ssh *ssh = active_state; /* XXX */ |
int ret; |
int ret; |
const char *forced = NULL, *tty = NULL; |
const char *forced = NULL, *tty = NULL; |
char session_type[1024]; |
char session_type[1024]; |
Line 811 do_exec(Session *s, const char *command) |
|
Line 601 do_exec(Session *s, const char *command) |
|
tty == NULL ? "" : " on ", |
tty == NULL ? "" : " on ", |
tty == NULL ? "" : tty, |
tty == NULL ? "" : tty, |
s->pw->pw_name, |
s->pw->pw_name, |
get_remote_ipaddr(), |
ssh_remote_ipaddr(ssh), |
get_remote_port(), |
ssh_remote_port(ssh), |
s->self); |
s->self); |
|
|
#ifdef GSSAPI |
#ifdef GSSAPI |
Line 844 do_exec(Session *s, const char *command) |
|
Line 634 do_exec(Session *s, const char *command) |
|
void |
void |
do_login(Session *s, const char *command) |
do_login(Session *s, const char *command) |
{ |
{ |
|
struct ssh *ssh = active_state; /* XXX */ |
socklen_t fromlen; |
socklen_t fromlen; |
struct sockaddr_storage from; |
struct sockaddr_storage from; |
struct passwd * pw = s->pw; |
struct passwd * pw = s->pw; |
Line 866 do_login(Session *s, const char *command |
|
Line 657 do_login(Session *s, const char *command |
|
/* Record that there was a login on that tty from the remote host. */ |
/* Record that there was a login on that tty from the remote host. */ |
if (!use_privsep) |
if (!use_privsep) |
record_login(pid, s->tty, pw->pw_name, pw->pw_uid, |
record_login(pid, s->tty, pw->pw_name, pw->pw_uid, |
get_remote_name_or_ip(utmp_len, |
session_get_remote_name_or_ip(ssh, utmp_len, |
options.use_dns), |
options.use_dns), |
(struct sockaddr *)&from, fromlen); |
(struct sockaddr *)&from, fromlen); |
|
|
Line 989 child_set_env(char ***envp, u_int *envsi |
|
Line 780 child_set_env(char ***envp, u_int *envsi |
|
snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); |
snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); |
} |
} |
|
|
#ifdef HAVE_LOGIN_CAP |
|
/* |
|
* Sets any environment variables specified in login.conf. |
|
* Taken from: |
|
* NetBSD: login_cap.c,v 1.11 2001/07/22 13:34:01 wiz Exp |
|
* Modified to use child_set_env instead of setenv. |
|
*/ |
|
static void |
|
lc_setuserenv(char ***env, u_int *envsize, login_cap_t *lcp) |
|
{ |
|
const char *stop = ", \t"; |
|
int i, count; |
|
char *ptr; |
|
char **res; |
|
char *str = login_getcapstr(lcp, "setenv", NULL, NULL); |
|
|
|
if (str == NULL || *str == '\0') |
|
return; |
|
|
|
/* count the sub-strings */ |
|
for (i = 1, ptr = str; *ptr; i++) { |
|
ptr += strcspn(ptr, stop); |
|
if (*ptr) |
|
ptr++; |
|
} |
|
|
|
/* allocate ptr array and string */ |
|
count = i; |
|
res = malloc(count * sizeof(char *) + strlen(str) + 1); |
|
|
|
if (!res) |
|
return; |
|
|
|
ptr = (char *)res + count * sizeof(char *); |
|
strcpy(ptr, str); |
|
|
|
/* split string */ |
|
for (i = 0; *ptr && i < count; i++) { |
|
res[i] = ptr; |
|
ptr += strcspn(ptr, stop); |
|
if (*ptr) |
|
*ptr++ = '\0'; |
|
} |
|
|
|
res[i] = NULL; |
|
|
|
for (i = 0; i < count && res[i]; i++) { |
|
if (*res[i] != '\0') { |
|
if ((ptr = strchr(res[i], '=')) != NULL) |
|
*ptr++ = '\0'; |
|
else |
|
ptr = __UNCONST(""); |
|
child_set_env(env, envsize, res[i], ptr); |
|
} |
|
} |
|
|
|
free(res); |
|
return; |
|
} |
|
#endif |
|
|
|
/* |
/* |
* Reads environment variables from the given file and adds/overrides them |
* Reads environment variables from the given file and adds/overrides them |
* into the environment. If the file does not exist, this does nothing. |
* into the environment. If the file does not exist, this does nothing. |
Line 1125 void copy_environment(char **source, cha |
|
Line 855 void copy_environment(char **source, cha |
|
static char ** |
static char ** |
do_setup_env(Session *s, const char *shell) |
do_setup_env(Session *s, const char *shell) |
{ |
{ |
|
struct ssh *ssh = active_state; /* XXX */ |
char buf[256]; |
char buf[256]; |
u_int i, envsize; |
u_int i, envsize; |
char **env, *laddr; |
char **env, *laddr; |
Line 1142 do_setup_env(Session *s, const char *she |
|
Line 873 do_setup_env(Session *s, const char *she |
|
ssh_gssapi_do_child(&env, &envsize); |
ssh_gssapi_do_child(&env, &envsize); |
#endif |
#endif |
|
|
if (!options.use_login) { |
/* Set basic environment. */ |
#ifdef HAVE_LOGIN_CAP |
for (i = 0; i < s->num_env; i++) |
lc_setuserenv(&env, &envsize, lc); |
child_set_env(&env, &envsize, s->env[i].name, s->env[i].val); |
#endif |
|
/* Set basic environment. */ |
child_set_env(&env, &envsize, "USER", pw->pw_name); |
for (i = 0; i < s->num_env; i++) |
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); |
child_set_env(&env, &envsize, s->env[i].name, |
child_set_env(&env, &envsize, "HOME", pw->pw_dir); |
s->env[i].val); |
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0) |
|
|
child_set_env(&env, &envsize, "USER", pw->pw_name); |
|
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); |
|
child_set_env(&env, &envsize, "HOME", pw->pw_dir); |
|
#ifdef HAVE_LOGIN_CAP |
|
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0) |
|
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); |
|
else |
|
child_set_env(&env, &envsize, "PATH", getenv("PATH")); |
|
#else |
|
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); |
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); |
#endif |
else |
|
child_set_env(&env, &envsize, "PATH", getenv("PATH")); |
|
|
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; |
custom_environment = ce->next; |
free(ce->s); |
free(ce->s); |
free(ce); |
free(ce); |
|
} |
|
} |
} |
|
|
/* SSH_CLIENT deprecated */ |
/* SSH_CLIENT deprecated */ |
snprintf(buf, sizeof buf, "%.50s %d %d", |
snprintf(buf, sizeof buf, "%.50s %d %d", |
get_remote_ipaddr(), get_remote_port(), get_local_port()); |
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), |
|
ssh_local_port(ssh)); |
child_set_env(&env, &envsize, "SSH_CLIENT", buf); |
child_set_env(&env, &envsize, "SSH_CLIENT", buf); |
|
|
laddr = get_local_ipaddr(packet_get_connection_in()); |
laddr = get_local_ipaddr(packet_get_connection_in()); |
snprintf(buf, sizeof buf, "%.50s %d %.50s %d", |
snprintf(buf, sizeof buf, "%.50s %d %.50s %d", |
get_remote_ipaddr(), get_remote_port(), laddr, get_local_port()); |
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), |
|
laddr, ssh_local_port(ssh)); |
free(laddr); |
free(laddr); |
child_set_env(&env, &envsize, "SSH_CONNECTION", buf); |
child_set_env(&env, &envsize, "SSH_CONNECTION", buf); |
|
|
Line 1226 do_setup_env(Session *s, const char *she |
|
Line 947 do_setup_env(Session *s, const char *she |
|
* 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(); |
Line 1244 do_setup_env(Session *s, const char *she |
|
Line 965 do_setup_env(Session *s, const char *she |
|
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", |
pw->pw_dir); |
pw->pw_dir); |
read_environment_file(&env, &envsize, buf); |
read_environment_file(&env, &envsize, buf); |
Line 1513 do_pwchange(Session *s) |
|
Line 1234 do_pwchange(Session *s) |
|
exit(1); |
exit(1); |
} |
} |
|
|
__dead static void |
|
launch_login(struct passwd *pw, const char *hostname) |
|
{ |
|
/* Launch login(1). */ |
|
|
|
execl("/usr/bin/login", "login", "-h", hostname, |
|
"-p", "-f", "--", pw->pw_name, (char *)NULL); |
|
|
|
/* Login couldn't be executed, die. */ |
|
|
|
perror("login"); |
|
exit(1); |
|
} |
|
|
|
static void |
static void |
child_close_fds(void) |
child_close_fds(void) |
{ |
{ |
Line 1577 do_child(Session *s, const char *command |
|
Line 1284 do_child(Session *s, const char *command |
|
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; |
|
|
Line 1591 do_child(Session *s, const char *command |
|
Line 1298 do_child(Session *s, const char *command |
|
do_pwchange(s); |
do_pwchange(s); |
} |
} |
|
|
/* login(1) is only called if we execute the login shell */ |
|
if (options.use_login && command != NULL) |
|
options.use_login = 0; |
|
|
|
/* |
/* |
* 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) { |
|
do_nologin(pw); |
|
do_setusercontext(pw); |
|
/* |
|
* PAM session modules in do_setusercontext may have |
|
* generated messages, so if this in an interactive |
|
* login then display them too. |
|
*/ |
|
if (!check_quietlogin(s, command)) |
|
display_loginmsg(); |
|
} |
|
#ifdef USE_PAM |
#ifdef USE_PAM |
if (options.use_pam && !is_pam_session_open()) { |
if (options.use_pam && !is_pam_session_open()) { |
debug3("PAM session not opened, exiting"); |
debug3("PAM session not opened, exiting"); |
Line 1617 do_child(Session *s, const char *command |
|
Line 1309 do_child(Session *s, const char *command |
|
exit(254); |
exit(254); |
} |
} |
#endif |
#endif |
|
do_nologin(pw); |
|
do_setusercontext(pw); |
|
|
/* |
/* |
* Get the shell from the password data. An empty shell field is |
* Get the shell from the password data. An empty shell field is |
Line 1635 do_child(Session *s, const char *command |
|
Line 1329 do_child(Session *s, const char *command |
|
__UNCONST(shell)); |
__UNCONST(shell)); |
#endif |
#endif |
|
|
/* we have to stash the hostname before we close our socket. */ |
|
if (options.use_login) |
|
hostname = get_remote_name_or_ip(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 |
* that we do not shutdown it. Note that the descriptors cannot be |
* that we do not shutdown it. Note that the descriptors cannot be |
* closed before building the environment, as we call |
* closed before building the environment, as we call |
* get_remote_ipaddr there. |
* ssh_remote_ipaddr there. |
*/ |
*/ |
child_close_fds(); |
child_close_fds(); |
|
|
Line 1695 do_child(Session *s, const char *command |
|
Line 1385 do_child(Session *s, const char *command |
|
|
|
(void)closefrom(STDERR_FILENO + 1); |
(void)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); |
Line 1723 do_child(Session *s, const char *command |
|
Line 1412 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++; |
Line 1971 session_pty_req(Session *s) |
|
Line 1655 session_pty_req(Session *s) |
|
} |
} |
|
|
s->term = packet_get_string(&len); |
s->term = packet_get_string(&len); |
|
s->col = packet_get_int(); |
if (compat20) { |
s->row = packet_get_int(); |
s->col = packet_get_int(); |
|
s->row = packet_get_int(); |
|
} else { |
|
s->row = packet_get_int(); |
|
s->col = packet_get_int(); |
|
} |
|
s->xpixel = packet_get_int(); |
s->xpixel = packet_get_int(); |
s->ypixel = packet_get_int(); |
s->ypixel = packet_get_int(); |
|
|
Line 2000 session_pty_req(Session *s) |
|
Line 1678 session_pty_req(Session *s) |
|
} |
} |
debug("session_pty_req: session %d alloc %s", s->self, s->tty); |
debug("session_pty_req: session %d alloc %s", s->self, s->tty); |
|
|
/* for SSH1 the tty modes length is not given */ |
n_bytes = packet_remaining(); |
if (!compat20) |
|
n_bytes = packet_remaining(); |
|
tty_parse_modes(s->ttyfd, &n_bytes); |
tty_parse_modes(s->ttyfd, &n_bytes); |
|
|
if (!use_privsep) |
if (!use_privsep) |
Line 2072 session_x11_req(Session *s) |
|
Line 1748 session_x11_req(Session *s) |
|
s->screen = packet_get_int(); |
s->screen = packet_get_int(); |
packet_check_eom(); |
packet_check_eom(); |
|
|
success = session_setup_x11fwd(s); |
if (xauth_valid_string(s->auth_proto) && |
|
xauth_valid_string(s->auth_data)) |
|
success = session_setup_x11fwd(s); |
|
else { |
|
success = 0; |
|
error("Invalid X11 forwarding data"); |
|
} |
if (!success) { |
if (!success) { |
free(s->auth_proto); |
free(s->auth_proto); |
free(s->auth_data); |
free(s->auth_data); |
|
|
session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr, |
session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr, |
int is_tty) |
int is_tty) |
{ |
{ |
if (!compat20) |
|
fatal("session_set_fds: called for proto != 2.0"); |
|
/* |
/* |
* now that have a child and a pipe to the child, |
* now that have a child and a pipe to the child, |
* we can activate our channel and register the fd's |
* we can activate our channel and register the fd's |
Line 2394 session_exit_message(Session *s, int sta |
|
Line 2074 session_exit_message(Session *s, int sta |
|
void |
void |
session_close(Session *s) |
session_close(Session *s) |
{ |
{ |
|
struct ssh *ssh = active_state; /* XXX */ |
u_int i; |
u_int i; |
|
|
verbose("Close session: user %s from %.200s port %d id %d", |
verbose("Close session: user %s from %.200s port %d id %d", |
s->pw->pw_name, |
s->pw->pw_name, |
get_remote_ipaddr(), |
ssh_remote_ipaddr(ssh), |
get_remote_port(), |
ssh_remote_port(ssh), |
s->self); |
s->self); |
|
|
if (s->ttyfd != -1) |
if (s->ttyfd != -1) |
Line 2552 session_setup_x11fwd(Session *s) |
|
Line 2233 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; |
Line 2632 do_cleanup(Authctxt *authctxt) |
|
Line 2308 do_cleanup(Authctxt *authctxt) |
|
#endif |
#endif |
|
|
#ifdef GSSAPI |
#ifdef GSSAPI |
if (compat20 && options.gss_cleanup_creds) |
if (options.gss_cleanup_creds) |
ssh_gssapi_cleanup_creds(); |
ssh_gssapi_cleanup_creds(); |
#endif |
#endif |
|
|
Line 2653 do_cleanup(Authctxt *authctxt) |
|
Line 2329 do_cleanup(Authctxt *authctxt) |
|
if (!use_privsep || mm_is_monitor()) |
if (!use_privsep || mm_is_monitor()) |
session_destroy_all(session_pty_cleanup2); |
session_destroy_all(session_pty_cleanup2); |
} |
} |
|
|
|
/* Return a name for the remote host that fits inside utmp_size */ |
|
|
|
const char * |
|
session_get_remote_name_or_ip(struct ssh *ssh, u_int utmp_size, int use_dns) |
|
{ |
|
const char *remote = ""; |
|
|
|
if (utmp_size > 0) |
|
remote = auth_get_canonical_hostname(ssh, use_dns); |
|
if (utmp_size == 0 || strlen(remote) > utmp_size) |
|
remote = ssh_remote_ipaddr(ssh); |
|
return remote; |
|
} |
|
|