aboutsummaryrefslogtreecommitdiff
path: root/crypto/openssh/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/session.c')
-rw-r--r--crypto/openssh/session.c285
1 files changed, 161 insertions, 124 deletions
diff --git a/crypto/openssh/session.c b/crypto/openssh/session.c
index c75fea966933..2898ac5185f0 100644
--- a/crypto/openssh/session.c
+++ b/crypto/openssh/session.c
@@ -33,7 +33,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.154 2003/03/05 22:33:43 markus Exp $");
+RCSID("$OpenBSD: session.c,v 1.164 2003/09/18 08:49:45 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
@@ -58,10 +58,8 @@ RCSID("$OpenBSD: session.c,v 1.154 2003/03/05 22:33:43 markus Exp $");
#include "session.h"
#include "monitor_wrap.h"
-#ifdef HAVE_CYGWIN
-#include <windows.h>
-#include <sys/cygwin.h>
-#define is_winnt (GetVersion() < 0x80000000)
+#ifdef GSSAPI
+#include "ssh-gss.h"
#endif
/* func */
@@ -95,6 +93,7 @@ extern int debug_flag;
extern u_int utmp_len;
extern int startup_pipe;
extern void destroy_sensitive_data(void);
+extern Buffer loginmsg;
/* original command from peer. */
const char *original_command = NULL;
@@ -103,10 +102,6 @@ const char *original_command = NULL;
#define MAX_SESSIONS 10
Session sessions[MAX_SESSIONS];
-#ifdef WITH_AIXAUTHENTICATE
-char *aixloginmsg;
-#endif /* WITH_AIXAUTHENTICATE */
-
#ifdef HAVE_LOGIN_CAP
login_cap_t *lc;
#endif
@@ -192,7 +187,7 @@ auth_input_request_forwarding(struct passwd * pw)
nc = channel_new("auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
- 0, xstrdup("auth socket"), 1);
+ 0, "auth socket", 1);
strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
return 1;
}
@@ -225,10 +220,6 @@ do_authenticated(Authctxt *authctxt)
/* remove agent socket */
if (auth_sock_name != NULL)
auth_sock_cleanup_proc(authctxt->pw);
-#ifdef KRB4
- if (options.kerberos_ticket_cleanup)
- krb4_cleanup_proc(authctxt);
-#endif
#ifdef KRB5
if (options.kerberos_ticket_cleanup)
krb5_cleanup_proc(authctxt);
@@ -341,58 +332,6 @@ do_authenticated1(Authctxt *authctxt)
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 */
- }
- 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_CMD:
if (type == SSH_CMSG_EXEC_CMD) {
@@ -412,7 +351,7 @@ do_authenticated1(Authctxt *authctxt)
* Any unknown messages in this phase are ignored,
* and a failure message is returned.
*/
- log("Unknown packet type received after authentication: %d", type);
+ logit("Unknown packet type received after authentication: %d", type);
}
packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
packet_send();
@@ -456,11 +395,12 @@ do_exec_no_pty(Session *s, const char *command)
session_proctitle(s);
#if defined(USE_PAM)
- do_pam_session(s->pw->pw_name, NULL);
- do_pam_setcred(1);
- if (is_pam_password_change_required())
- packet_disconnect("Password change required but no "
- "TTY available");
+ if (options.use_pam) {
+ do_pam_setcred(1);
+ if (is_pam_password_change_required())
+ packet_disconnect("Password change required but no "
+ "TTY available");
+ }
#endif /* USE_PAM */
/* Fork the child. */
@@ -583,8 +523,10 @@ do_exec_pty(Session *s, const char *command)
ttyfd = s->ttyfd;
#if defined(USE_PAM)
- do_pam_session(s->pw->pw_name, s->tty);
- do_pam_setcred(1);
+ if (options.use_pam) {
+ do_pam_set_tty(s->tty);
+ do_pam_setcred(1);
+ }
#endif
/* Fork the child. */
@@ -690,7 +632,7 @@ do_pre_login(Session *s)
}
record_utmp_only(pid, s->tty, s->pw->pw_name,
- get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
+ get_remote_name_or_ip(utmp_len, options.use_dns),
(struct sockaddr *)&from, fromlen);
}
#endif
@@ -708,6 +650,14 @@ do_exec(Session *s, const char *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)
do_exec_pty(s, command);
else
@@ -745,7 +695,7 @@ do_login(Session *s, const char *command)
if (!use_privsep)
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
get_remote_name_or_ip(utmp_len,
- options.verify_reverse_mapping),
+ options.use_dns),
(struct sockaddr *)&from, fromlen);
#ifdef USE_PAM
@@ -753,9 +703,10 @@ do_login(Session *s, const char *command)
* If password change is needed, do it now.
* This needs to occur before the ~/.hushlogin check.
*/
- if (is_pam_password_change_required()) {
+ if (options.use_pam && is_pam_password_change_required()) {
print_pam_messages();
do_pam_chauthtok();
+ /* XXX - signal [net] parent to enable forwardings */
}
#endif
@@ -763,13 +714,16 @@ do_login(Session *s, const char *command)
return;
#ifdef USE_PAM
- if (!is_pam_password_change_required())
+ if (options.use_pam && !is_pam_password_change_required())
print_pam_messages();
#endif /* USE_PAM */
-#ifdef WITH_AIXAUTHENTICATE
- if (aixloginmsg && *aixloginmsg)
- printf("%s\n", aixloginmsg);
-#endif /* WITH_AIXAUTHENTICATE */
+
+ /* display post-login message */
+ if (buffer_len(&loginmsg) > 0) {
+ buffer_append(&loginmsg, "\0", 1);
+ printf("%s\n", (char *)buffer_ptr(&loginmsg));
+ }
+ buffer_free(&loginmsg);
#ifndef NO_SSH_LASTLOG
if (options.print_lastlog && s->last_login_time != 0) {
@@ -840,12 +794,23 @@ check_quietlogin(Session *s, const char *command)
* Sets the value of the given variable in the environment. If the variable
* already exists, its value is overriden.
*/
-static void
+void
child_set_env(char ***envp, u_int *envsizep, const char *name,
const char *value)
{
- u_int i, namelen;
char **env;
+ u_int envsize;
+ u_int i, namelen;
+
+ /*
+ * If we're passed an uninitialized list, allocate a single null
+ * entry before continuing.
+ */
+ if (*envp == NULL && *envsizep == 0) {
+ *envp = xmalloc(sizeof(char *));
+ *envp[0] = NULL;
+ *envsizep = 1;
+ }
/*
* Find the slot where the value should be stored. If the variable
@@ -862,12 +827,13 @@ child_set_env(char ***envp, u_int *envsizep, const char *name,
xfree(env[i]);
} else {
/* New variable. Expand if necessary. */
- if (i >= (*envsizep) - 1) {
- if (*envsizep >= 1000)
- fatal("child_set_env: too many env vars,"
- " skipping: %.100s", name);
- (*envsizep) += 50;
- env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
+ envsize = *envsizep;
+ if (i >= envsize - 1) {
+ if (envsize >= 1000)
+ fatal("child_set_env: too many env vars");
+ envsize += 50;
+ env = (*envp) = xrealloc(env, envsize * sizeof(char *));
+ *envsizep = envsize;
}
/* Need to set the NULL pointer at end of array beyond the new slot. */
env[i + 1] = NULL;
@@ -923,6 +889,61 @@ read_environment_file(char ***env, u_int *envsize,
fclose(f);
}
+#ifdef HAVE_ETC_DEFAULT_LOGIN
+/*
+ * Return named variable from specified environment, or NULL if not present.
+ */
+static char *
+child_get_env(char **env, const char *name)
+{
+ int i;
+ size_t len;
+
+ len = strlen(name);
+ for (i=0; env[i] != NULL; i++)
+ if (strncmp(name, env[i], len) == 0 && env[i][len] == '=')
+ return(env[i] + len + 1);
+ return NULL;
+}
+
+/*
+ * Read /etc/default/login.
+ * We pick up the PATH (or SUPATH for root) and UMASK.
+ */
+static void
+read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
+{
+ char **tmpenv = NULL, *var;
+ u_int i, tmpenvsize = 0;
+ mode_t mask;
+
+ /*
+ * We don't want to copy the whole file to the child's environment,
+ * so we use a temporary environment and copy the variables we're
+ * interested in.
+ */
+ read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login");
+
+ if (tmpenv == NULL)
+ return;
+
+ if (uid == 0)
+ var = child_get_env(tmpenv, "SUPATH");
+ else
+ var = child_get_env(tmpenv, "PATH");
+ if (var != NULL)
+ child_set_env(env, envsize, "PATH", var);
+
+ if ((var = child_get_env(tmpenv, "UMASK")) != NULL)
+ if (sscanf(var, "%5lo", &mask) == 1)
+ umask(mask);
+
+ for (i = 0; tmpenv[i] != NULL; i++)
+ xfree(tmpenv[i]);
+ xfree(tmpenv);
+}
+#endif /* HAVE_ETC_DEFAULT_LOGIN */
+
void copy_environment(char **source, char ***env, u_int *envsize)
{
char *var_name, *var_val;
@@ -951,7 +972,7 @@ do_setup_env(Session *s, const char *shell)
{
char buf[256];
u_int i, envsize;
- char **env, *laddr;
+ char **env, *laddr, *path = NULL;
struct passwd *pw = s->pw;
/* Initialize the environment. */
@@ -967,6 +988,13 @@ do_setup_env(Session *s, const char *shell)
copy_environment(environ, &env, &envsize);
#endif
+#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) {
/* Set basic environment. */
child_set_env(&env, &envsize, "USER", pw->pw_name);
@@ -988,12 +1016,15 @@ do_setup_env(Session *s, const char *shell)
* needed for loading shared libraries. So the path better
* remains intact here.
*/
-# ifdef SUPERUSER_PATH
- child_set_env(&env, &envsize, "PATH",
- s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH);
-# else
- child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
-# endif /* SUPERUSER_PATH */
+# ifdef HAVE_ETC_DEFAULT_LOGIN
+ read_etc_default_login(&env, &envsize, pw->pw_uid);
+ path = child_get_env(env, "PATH");
+# endif /* HAVE_ETC_DEFAULT_LOGIN */
+ if (path == NULL || *path == '\0') {
+ child_set_env(&env, &envsize, "PATH",
+ s->pw->pw_uid == 0 ?
+ SUPERUSER_PATH : _PATH_STDPATH);
+ }
# endif /* HAVE_CYGWIN */
#endif /* HAVE_LOGIN_CAP */
@@ -1062,11 +1093,6 @@ do_setup_env(Session *s, const char *shell)
read_environment_file(&env, &envsize, "/etc/environment");
}
#endif
-#ifdef KRB4
- if (s->authctxt->krb4_ticket_file)
- child_set_env(&env, &envsize, "KRBTKFILE",
- s->authctxt->krb4_ticket_file);
-#endif
#ifdef KRB5
if (s->authctxt->krb5_ticket_file)
child_set_env(&env, &envsize, "KRB5CCNAME",
@@ -1077,10 +1103,9 @@ do_setup_env(Session *s, const char *shell)
* Pull in any environment variables that may have
* been set by PAM.
*/
- {
- char **p;
+ if (options.use_pam) {
+ char **p = fetch_pam_environment();
- p = fetch_pam_environment();
copy_environment(p, &env, &envsize);
free_pam_environment(p);
}
@@ -1192,7 +1217,7 @@ do_nologin(struct passwd *pw)
#endif
if (f) {
/* /etc/nologin exists. Print its contents and exit. */
- log("User %.100s not allowed because %s exists",
+ logit("User %.100s not allowed because %s exists",
pw->pw_name, _PATH_NOLOGIN);
while (fgets(buf, sizeof(buf), f))
fputs(buf, stderr);
@@ -1212,7 +1237,8 @@ do_setusercontext(struct passwd *pw)
{
#ifdef HAVE_SETPCRED
- setpcred(pw->pw_name);
+ if (setpcred(pw->pw_name, (char **)NULL) == -1)
+ fatal("Failed to set process credentials");
#endif /* HAVE_SETPCRED */
#ifdef HAVE_LOGIN_CAP
# ifdef __bsdi__
@@ -1248,7 +1274,10 @@ do_setusercontext(struct passwd *pw)
* These will have been wiped by the above initgroups() call.
* Reestablish them here.
*/
- do_pam_setcred(0);
+ if (options.use_pam) {
+ do_pam_session();
+ do_pam_setcred(0);
+ }
# endif /* USE_PAM */
# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)
irix_setusercontext(pw);
@@ -1349,7 +1378,7 @@ do_child(Session *s, const char *command)
/* we have to stash the hostname before we close our socket. */
if (options.use_login)
hostname = get_remote_name_or_ip(utmp_len,
- options.verify_reverse_mapping);
+ options.use_dns);
/*
* Close the connection descriptors; note that this is the child, and
* the server will still have the socket open, and it is important
@@ -1391,18 +1420,6 @@ do_child(Session *s, const char *command)
*/
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. */
if (chdir(pw->pw_dir) < 0) {
fprintf(stderr, "Could not chdir to home directory %s: %s\n",
@@ -1672,7 +1689,7 @@ session_subsystem_req(Session *s)
int i;
packet_check_eom();
- log("subsystem request for %.100s", subsys);
+ logit("subsystem request for %.100s", subsys);
for (i = 0; i < options.num_subsystems; i++) {
if (strcmp(subsys, options.subsystem_name[i]) == 0) {
@@ -1691,7 +1708,7 @@ session_subsystem_req(Session *s)
}
if (!success)
- log("subsystem request for %.100s failed, subsystem not found",
+ logit("subsystem request for %.100s failed, subsystem not found",
subsys);
xfree(subsys);
@@ -1739,6 +1756,20 @@ session_exec_req(Session *s)
}
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)
{
static int called = 0;
@@ -1762,7 +1793,7 @@ session_input_channel_req(Channel *c, const char *rtype)
Session *s;
if ((s = session_by_channel(c->self)) == NULL) {
- log("session_input_channel_req: no session %d req %.100s",
+ logit("session_input_channel_req: no session %d req %.100s",
c->self, rtype);
return 0;
}
@@ -1785,6 +1816,8 @@ session_input_channel_req(Channel *c, const char *rtype)
success = session_auth_agent_req(s);
} else if (strcmp(rtype, "subsystem") == 0) {
success = session_subsystem_req(s);
+ } else if (strcmp(rtype, "break") == 0) {
+ success = session_break_req(s);
}
}
if (strcmp(rtype, "window-change") == 0) {
@@ -2121,4 +2154,8 @@ static void
do_authenticated2(Authctxt *authctxt)
{
server_loop2(authctxt);
+#if defined(GSSAPI)
+ if (options.gss_cleanup_creds)
+ ssh_gssapi_cleanup_creds(NULL);
+#endif
}