version 1.150.2.2, 2003/09/16 21:20:27 |
version 1.151, 2002/12/04 04:36:47 |
|
|
#include "session.h" |
#include "session.h" |
#include "monitor_wrap.h" |
#include "monitor_wrap.h" |
|
|
#ifdef GSSAPI |
|
#include "ssh-gss.h" |
|
#endif |
|
|
|
/* func */ |
/* func */ |
|
|
Session *session_new(void); |
Session *session_new(void); |
|
|
nc = channel_new("auth socket", |
nc = channel_new("auth socket", |
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, |
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, |
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, |
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, |
0, "auth socket", 1); |
0, xstrdup("auth socket"), 1); |
strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); |
strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); |
return 1; |
return 1; |
} |
} |
|
|
void |
void |
do_authenticated(Authctxt *authctxt) |
do_authenticated(Authctxt *authctxt) |
{ |
{ |
setproctitle("%s", authctxt->pw->pw_name); |
|
|
|
/* |
/* |
* Cancel the alarm we set to limit the time taken for |
* Cancel the alarm we set to limit the time taken for |
* authentication. |
* authentication. |
|
|
/* remove agent socket */ |
/* remove agent socket */ |
if (auth_sock_name != NULL) |
if (auth_sock_name != NULL) |
auth_sock_cleanup_proc(authctxt->pw); |
auth_sock_cleanup_proc(authctxt->pw); |
|
#ifdef KRB4 |
|
if (options.kerberos_ticket_cleanup) |
|
krb4_cleanup_proc(authctxt); |
|
#endif |
#ifdef KRB5 |
#ifdef KRB5 |
if (options.kerberos_ticket_cleanup) |
if (options.kerberos_ticket_cleanup) |
krb5_cleanup_proc(authctxt); |
krb5_cleanup_proc(authctxt); |
|
|
success = 1; |
success = 1; |
break; |
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 */ |
|
} |
|
xfree(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); |
|
xfree(token); |
|
} |
|
break; |
|
#endif /* AFS */ |
|
|
case SSH_CMSG_EXEC_SHELL: |
case SSH_CMSG_EXEC_SHELL: |
case SSH_CMSG_EXEC_CMD: |
case SSH_CMSG_EXEC_CMD: |
if (type == SSH_CMSG_EXEC_CMD) { |
if (type == SSH_CMSG_EXEC_CMD) { |
|
|
* Any unknown messages in this phase are ignored, |
* Any unknown messages in this phase are ignored, |
* and a failure message is returned. |
* and a failure message is returned. |
*/ |
*/ |
logit("Unknown packet type received after authentication: %d", type); |
log("Unknown packet type received after authentication: %d", type); |
} |
} |
packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE); |
packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE); |
packet_send(); |
packet_send(); |
|
|
debug("Forced command '%.900s'", command); |
debug("Forced command '%.900s'", command); |
} |
} |
|
|
#ifdef GSSAPI |
|
if (options.gss_authentication) { |
|
temporarily_use_uid(s->pw); |
|
ssh_gssapi_storecreds(); |
|
restore_uid(); |
|
} |
|
#endif |
|
|
|
if (s->ttyfd != -1) |
if (s->ttyfd != -1) |
do_exec_pty(s, command); |
do_exec_pty(s, command); |
else |
else |
|
|
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, |
get_remote_name_or_ip(utmp_len, |
options.use_dns), |
options.verify_reverse_mapping), |
(struct sockaddr *)&from, fromlen); |
(struct sockaddr *)&from, fromlen); |
|
|
if (check_quietlogin(s, command)) |
if (check_quietlogin(s, command)) |
|
|
* Sets the value of the given variable in the environment. If the variable |
* Sets the value of the given variable in the environment. If the variable |
* already exists, its value is overriden. |
* already exists, its value is overriden. |
*/ |
*/ |
void |
static void |
child_set_env(char ***envp, u_int *envsizep, const char *name, |
child_set_env(char ***envp, u_int *envsizep, const char *name, |
const char *value) |
const char *value) |
{ |
{ |
|
|
{ |
{ |
char buf[256]; |
char buf[256]; |
u_int i, envsize; |
u_int i, envsize; |
char **env, *laddr; |
char **env; |
struct passwd *pw = s->pw; |
struct passwd *pw = s->pw; |
|
|
/* Initialize the environment. */ |
/* Initialize the environment. */ |
|
|
env = xmalloc(envsize * sizeof(char *)); |
env = xmalloc(envsize * sizeof(char *)); |
env[0] = NULL; |
env[0] = NULL; |
|
|
#ifdef GSSAPI |
|
/* Allow any GSSAPI methods that we've used to alter |
|
* the childs environment as they see fit |
|
*/ |
|
ssh_gssapi_do_child(&env, &envsize); |
|
#endif |
|
|
|
if (!options.use_login) { |
if (!options.use_login) { |
/* Set basic environment. */ |
/* Set basic environment. */ |
child_set_env(&env, &envsize, "USER", pw->pw_name); |
child_set_env(&env, &envsize, "USER", pw->pw_name); |
|
|
get_remote_ipaddr(), get_remote_port(), get_local_port()); |
get_remote_ipaddr(), get_remote_port(), get_local_port()); |
child_set_env(&env, &envsize, "SSH_CLIENT", buf); |
child_set_env(&env, &envsize, "SSH_CLIENT", buf); |
|
|
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()); |
get_remote_ipaddr(), get_remote_port(), |
xfree(laddr); |
get_local_ipaddr(packet_get_connection_in()), get_local_port()); |
child_set_env(&env, &envsize, "SSH_CONNECTION", buf); |
child_set_env(&env, &envsize, "SSH_CONNECTION", buf); |
|
|
if (s->ttyfd != -1) |
if (s->ttyfd != -1) |
|
|
if (original_command) |
if (original_command) |
child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", |
child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", |
original_command); |
original_command); |
|
#ifdef KRB4 |
|
if (s->authctxt->krb4_ticket_file) |
|
child_set_env(&env, &envsize, "KRBTKFILE", |
|
s->authctxt->krb4_ticket_file); |
|
#endif |
#ifdef KRB5 |
#ifdef KRB5 |
if (s->authctxt->krb5_ticket_file) |
if (s->authctxt->krb5_ticket_file) |
child_set_env(&env, &envsize, "KRB5CCNAME", |
child_set_env(&env, &envsize, "KRB5CCNAME", |
|
|
#endif |
#endif |
if (f) { |
if (f) { |
/* /etc/nologin exists. Print its contents and exit. */ |
/* /etc/nologin exists. Print its contents and exit. */ |
logit("User %.100s not allowed because %s exists", |
log("User %.100s not allowed because %s exists", |
pw->pw_name, _PATH_NOLOGIN); |
pw->pw_name, _PATH_NOLOGIN); |
while (fgets(buf, sizeof(buf), f)) |
while (fgets(buf, sizeof(buf), f)) |
fputs(buf, stderr); |
fputs(buf, stderr); |
|
|
* legal, and means /bin/sh. |
* legal, and means /bin/sh. |
*/ |
*/ |
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; |
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; |
|
|
/* |
|
* Make sure $SHELL points to the shell from the password file, |
|
* even if shell is overridden from login.conf |
|
*/ |
|
env = do_setup_env(s, shell); |
|
|
|
#ifdef HAVE_LOGIN_CAP |
#ifdef HAVE_LOGIN_CAP |
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); |
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); |
#endif |
#endif |
|
|
|
env = do_setup_env(s, shell); |
|
|
/* we have to stash the hostname before we close our socket. */ |
/* we have to stash the hostname before we close our socket. */ |
if (options.use_login) |
if (options.use_login) |
hostname = get_remote_name_or_ip(utmp_len, |
hostname = get_remote_name_or_ip(utmp_len, |
options.use_dns); |
options.verify_reverse_mapping); |
/* |
/* |
* 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 |
|
|
*/ |
*/ |
environ = env; |
environ = env; |
|
|
|
#ifdef AFS |
|
/* Try to get AFS tokens for the local cell. */ |
|
if (k_hasafs()) { |
|
char cell[64]; |
|
|
|
if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0) |
|
krb_afslog(cell, 0); |
|
|
|
krb_afslog(0, 0); |
|
} |
|
#endif /* AFS */ |
|
|
/* Change current directory to the user\'s home directory. */ |
/* Change current directory to the user\'s home directory. */ |
if (chdir(pw->pw_dir) < 0) { |
if (chdir(pw->pw_dir) < 0) { |
fprintf(stderr, "Could not chdir to home directory %s: %s\n", |
fprintf(stderr, "Could not chdir to home directory %s: %s\n", |
|
|
int i; |
int i; |
|
|
packet_check_eom(); |
packet_check_eom(); |
logit("subsystem request for %.100s", subsys); |
log("subsystem request for %.100s", subsys); |
|
|
for (i = 0; i < options.num_subsystems; i++) { |
for (i = 0; i < options.num_subsystems; i++) { |
if (strcmp(subsys, options.subsystem_name[i]) == 0) { |
if (strcmp(subsys, options.subsystem_name[i]) == 0) { |
|
|
} |
} |
|
|
if (!success) |
if (!success) |
logit("subsystem request for %.100s failed, subsystem not found", |
log("subsystem request for %.100s failed, subsystem not found", |
subsys); |
subsys); |
|
|
xfree(subsys); |
xfree(subsys); |
|
|
} |
} |
|
|
static int |
static int |
session_break_req(Session *s) |
|
{ |
|
u_int break_length; |
|
|
|
break_length = packet_get_int(); /* ignored */ |
|
packet_check_eom(); |
|
|
|
if (s->ttyfd == -1 || |
|
tcsendbreak(s->ttyfd, 0) < 0) |
|
return 0; |
|
return 1; |
|
} |
|
|
|
static int |
|
session_auth_agent_req(Session *s) |
session_auth_agent_req(Session *s) |
{ |
{ |
static int called = 0; |
static int called = 0; |
|
|
Session *s; |
Session *s; |
|
|
if ((s = session_by_channel(c->self)) == NULL) { |
if ((s = session_by_channel(c->self)) == NULL) { |
logit("session_input_channel_req: no session %d req %.100s", |
log("session_input_channel_req: no session %d req %.100s", |
c->self, rtype); |
c->self, rtype); |
return 0; |
return 0; |
} |
} |
|
|
success = session_auth_agent_req(s); |
success = session_auth_agent_req(s); |
} else if (strcmp(rtype, "subsystem") == 0) { |
} else if (strcmp(rtype, "subsystem") == 0) { |
success = session_subsystem_req(s); |
success = session_subsystem_req(s); |
} else if (strcmp(rtype, "break") == 0) { |
|
success = session_break_req(s); |
|
} |
} |
} |
} |
if (strcmp(rtype, "window-change") == 0) { |
if (strcmp(rtype, "window-change") == 0) { |
|
|
do_authenticated2(Authctxt *authctxt) |
do_authenticated2(Authctxt *authctxt) |
{ |
{ |
server_loop2(authctxt); |
server_loop2(authctxt); |
#if defined(GSSAPI) |
|
if (options.gss_cleanup_creds) |
|
ssh_gssapi_cleanup_creds(NULL); |
|
#endif |
|
} |
} |