*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.37 2000/09/07 20:27:53 deraadt Exp $");
+RCSID("$OpenBSD: session.c,v 1.42 2000/10/27 07:32:18 markus Exp $");
#include "xmalloc.h"
#include "ssh.h"
#include "pty.h"
#include "packet.h"
#include "buffer.h"
-#include "cipher.h"
#include "mpaux.h"
#include "servconf.h"
#include "uidswap.h"
void session_proctitle(Session *s);
void do_exec_pty(Session *s, const char *command, struct passwd * pw);
void do_exec_no_pty(Session *s, const char *command, struct passwd * pw);
-void do_login(Session *s);
+void do_login(Session *s, const char *command);
void
do_child(const char *command, struct passwd * pw, const char *term,
/* data */
#define MAX_SESSIONS 10
Session sessions[MAX_SESSIONS];
-static int num_used_sessions;
#ifdef WITH_AIXAUTHENTICATE
/* AIX's lastlogin message, set in auth1.c */
* by the client telling us, so we can equally well trust the client
* not to request anything bogus.)
*/
- if (!no_port_forwarding_flag)
+ if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
channel_permit_all_opens();
s = session_new();
s->pw = pw;
-#ifdef HAVE_LOGIN_CAP
+#if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD)
if ((lc = login_getclass(pw->pw_class)) == NULL) {
error("unable to get login class");
return;
debug("Port forwarding not permitted for this authentication.");
break;
}
+ if (!options.allow_tcp_forwarding) {
+ debug("Port forwarding not permitted.");
+ break;
+ }
debug("Received TCP/IP port forwarding request.");
channel_input_port_forward_request(pw->pw_uid == 0, options.gateway_ports);
success = 1;
if (s == NULL)
fatal("do_exec_no_pty: no session");
+ signal(SIGPIPE, SIG_DFL);
+
session_proctitle(s);
#ifdef USE_PAM
close(ttyfd);
/* record login, etc. similar to login(1) */
- if (command == NULL && !options.use_login)
- do_login(s);
+ if (!(options.use_login && command == NULL))
+ do_login(s, command);
/* Do common processing for the child, such as execing the command. */
do_child(command, pw, s->term, s->display, s->auth_proto,
/* administrative, login(1)-like work */
void
-do_login(Session *s)
+do_login(Session *s, const char *command)
{
FILE *f;
char *time_string;
}
}
- /* Get the time and hostname when the user last logged in. */
- last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
- hostname, sizeof(hostname));
-
/* Get the time and hostname when the user last logged in. */
hostname[0] = '\0';
last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
get_remote_name_or_ip(), (struct sockaddr *)&from);
- /* Done if .hushlogin exists. */
+#ifdef USE_PAM
+ /*
+ * If password change is needed, do it now.
+ * This needs to occur before the ~/.hushlogin check.
+ */
+ if (pam_password_change_required()) {
+ print_pam_messages();
+ do_pam_chauthtok();
+ }
+#endif
+
+ /* Done if .hushlogin exists or a command given. */
+ if (command != NULL)
+ return;
snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
#ifdef HAVE_LOGIN_CAP
if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
return;
#ifdef USE_PAM
- print_pam_messages();
- /* If password change is needed, do it now. */
- do_pam_chauthtok();
+ if (!pam_password_change_required())
+ print_pam_messages();
#endif /* USE_PAM */
#ifdef WITH_AIXAUTHENTICATE
if (aixloginmsg && *aixloginmsg)
time_string = ctime(&last_login_time);
if (strchr(time_string, '\n'))
*strchr(time_string, '\n') = 0;
- if (strcmp(buf, "") == 0)
+ if (strcmp(hostname, "") == 0)
printf("Last login: %s\r\n", time_string);
else
printf("Last login: %s from %s\r\n", time_string, hostname);
strncpy(var_name, pam_env[i], equals - pam_env[i]);
strcpy(var_val, equals + 1);
- debug("PAM environment: %s=%s", var_name, var_val);
+ debug3("PAM environment: %s=%s", var_name, var_val);
child_set_env(env, envsize, var_name, var_val);
}
}
#endif /* USE_PAM */
+
+#ifdef HAVE_CYGWIN
+void copy_environment(char ***env, int *envsize)
+{
+ char *equals, var_name[512], var_val[512];
+ int i;
+
+ for(i = 0; environ[i] != NULL; i++) {
+ if ((equals = strstr(environ[i], "=")) == NULL)
+ continue;
+
+ if (strlen(environ[i]) < (sizeof(var_name) - 1)) {
+ memset(var_name, '\0', sizeof(var_name));
+ memset(var_val, '\0', sizeof(var_val));
+
+ strncpy(var_name, environ[i], equals - environ[i]);
+ strcpy(var_val, equals + 1);
+
+ debug3("Copy environment: %s=%s", var_name, var_val);
+
+ child_set_env(env, envsize, var_name, var_val);
+ }
+ }
+}
+#endif
+
#if defined(HAVE_GETUSERATTR)
/*
* AIX-specific login initialisation
* The Windows environment contains some setting which are
* important for a running system. They must not be dropped.
*/
- {
- char **ep;
- for (ep = environ; *ep; ++ep) {
- char *esp = strchr(*ep, '=');
- *esp = '\0';
- child_set_env(&env, &envsize, *ep, esp + 1);
- *esp = '=';
- }
- }
+ copy_environment(&env, &envsize);
#endif
if (!options.use_login) {
#ifdef HAVE_LOGIN_CAP
(void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH);
child_set_env(&env, &envsize, "PATH", getenv("PATH"));
-#else
-#ifndef HAVE_CYGWIN
+#else /* HAVE_LOGIN_CAP */
+# ifndef HAVE_CYGWIN
/*
* There's no standard path on Windows. The path contains
* important components pointing to the system directories,
* remains intact here.
*/
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
-#endif
-#endif
+# endif /* HAVE_CYGWIN */
+#endif /* HAVE_LOGIN_CAP */
snprintf(buf, sizeof buf, "%.200s/%.50s",
_PATH_MAILDIR, pw->pw_name);
original_command);
#ifdef _AIX
- {
- char *authstate,*krb5cc;
-
- if ((authstate = getenv("AUTHSTATE")) != NULL)
- child_set_env(&env,&envsize,"AUTHSTATE",authstate);
-
- if ((krb5cc = getenv("KRB5CCNAME")) != NULL)
- child_set_env(&env,&envsize,"KRB5CCNAME",krb5cc);
- }
+ if ((cp = getenv("AUTHSTATE")) != NULL)
+ child_set_env(&env, &envsize, "AUTHSTATE", cp);
+ if ((cp = getenv("KRB5CCNAME")) != NULL)
+ child_set_env(&env, &envsize, "KRB5CCNAME", cp);
+ read_environment_file(&env, &envsize, "/etc/environment");
#endif
#ifdef KRB4
do_pam_environment(&env, &envsize);
#endif /* USE_PAM */
- read_environment_file(&env,&envsize,"/etc/environment");
-
if (xauthfile)
child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
if (auth_get_socket_name() != NULL)
"Running %.100s add %.100s %.100s %.100s\n",
options.xauth_location, display,
auth_proto, auth_data);
-#ifndef HAVE_CYGWIN
+#ifndef HAVE_CYGWIN /* Unix sockets are not supported */
if (screen != NULL)
fprintf(stderr,
"Adding %.*s/unix%s %s %s\n",
if (f) {
fprintf(f, "add %s %s %s\n", display,
auth_proto, auth_data);
-#ifndef HAVE_CYGWIN
+#ifndef HAVE_CYGWIN /* Unix sockets are not supported */
if (screen != NULL)
fprintf(f, "add %.*s/unix%s %s %s\n",
(int)(screen-display), display,
sessions[i].used = 0;
sessions[i].self = i;
}
- num_used_sessions = 0;
did_init = 1;
}
for(i = 0; i < MAX_SESSIONS; i++) {
s->auth_proto = NULL;
s->used = 1;
s->pw = NULL;
- num_used_sessions++;
- debug("session_new: session %d (%d used)", i, num_used_sessions);
+ debug("session_new: session %d", i);
return s;
}
}
fatal("no channel for session %d", s->self);
channel_set_fds(s->chanid,
fdout, fdin, fderr,
- fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ);
+ fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
+ 1);
}
void
* interested in data we write.
* Note that we must not call 'chan_read_failed', since there could
* be some more data waiting in the pipe.
+ * djm - This is no longer true as we have allowed one pass through
+ * the select loop before killing the connection
*/
if (c->ostate != CHAN_OUTPUT_CLOSED)
chan_write_failed(c);
+ if (c->istate != CHAN_INPUT_CLOSED)
+ chan_read_failed(c);
s->chanid = -1;
}
session_pty_cleanup(s);
session_free(s);
session_proctitle(s);
- num_used_sessions--;
}
void
}
}
-int used_sessions(void)
-{
- return(num_used_sessions);
-}
-
char *
session_tty_list(void)
{
close(startup_pipe);
startup_pipe = -1;
}
-#ifdef HAVE_LOGIN_CAP
+#if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD)
pw = auth_get_user();
if ((lc = login_getclass(pw->pw_class)) == NULL) {
error("unable to get login class");