*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.170 2003/12/23 16:12:10 jakob Exp $");
+RCSID("$OpenBSD: session.c,v 1.164 2003/09/18 08:49:45 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
Session *session_new(void);
void session_set_fds(Session *, int, int, int);
-void session_pty_cleanup(Session *);
+void session_pty_cleanup(void *);
void session_proctitle(Session *);
int session_setup_x11fwd(Session *);
void do_exec_pty(Session *, const char *);
login_cap_t *lc;
#endif
-static int is_child = 0;
-
/* Name and directory of socket for authentication agent forwarding. */
static char *auth_sock_name = NULL;
static char *auth_sock_dir = NULL;
/* removes the agent forwarding socket */
static void
-auth_sock_cleanup_proc(struct passwd *pw)
+auth_sock_cleanup_proc(void *_pw)
{
+ struct passwd *pw = _pw;
+
if (auth_sock_name != NULL) {
temporarily_use_uid(pw);
unlink(auth_sock_name);
/* Allocate a buffer for the socket name, and format the name. */
auth_sock_name = xmalloc(MAXPATHLEN);
auth_sock_dir = xmalloc(MAXPATHLEN);
- strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
+ strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
/* Create private directory for socket */
if (mkdtemp(auth_sock_dir) == NULL) {
snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
auth_sock_dir, (long) getpid());
+ /* delete agent socket on fatal() */
+ fatal_add_cleanup(auth_sock_cleanup_proc, pw);
+
/* Create the socket. */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
restore_uid();
/* Start listening on the socket. */
- if (listen(sock, SSH_LISTEN_BACKLOG) < 0)
+ if (listen(sock, 5) < 0)
packet_disconnect("listen: %.100s", strerror(errno));
/* Allocate a channel for the authentication agent socket. */
close(startup_pipe);
startup_pipe = -1;
}
+
/* setup the channel layer */
if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
channel_permit_all_opens();
else
do_authenticated1(authctxt);
- do_cleanup(authctxt);
+ /* remove agent socket */
+ if (auth_sock_name != NULL)
+ auth_sock_cleanup_proc(authctxt->pw);
+#ifdef KRB5
+ if (options.kerberos_ticket_cleanup)
+ krb5_cleanup_proc(authctxt);
+#endif
}
/*
/* Fork the child. */
if ((pid = fork()) == 0) {
- is_child = 1;
+ fatal_remove_all_cleanups();
/* Child. Reinitialize the log since the pid has changed. */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
/* Fork the child. */
if ((pid = fork()) == 0) {
- is_child = 1;
+ fatal_remove_all_cleanups();
/* Child. Reinitialize the log because the pid has changed. */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
if (getpeername(packet_get_connection_in(),
(struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername: %.100s", strerror(errno));
- cleanup_exit(255);
+ fatal_cleanup();
}
}
if (getpeername(packet_get_connection_in(),
(struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername: %.100s", strerror(errno));
- cleanup_exit(255);
+ fatal_cleanup();
}
}
{
char **tmpenv = NULL, *var;
u_int i, tmpenvsize = 0;
- u_long mask;
+ mode_t mask;
/*
* We don't want to copy the whole file to the child's environment,
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((mode_t)mask);
-
+ umask(mask);
+
for (i = 0; tmpenv[i] != NULL; i++)
xfree(tmpenv[i]);
xfree(tmpenv);
debug3("Copy environment: %s=%s", var_name, var_val);
child_set_env(env, envsize, var_name, var_val);
-
+
xfree(var_name);
}
}
#endif
#ifdef GSSAPI
- /* Allow any GSSAPI methods that we've used to alter
+ /* Allow any GSSAPI methods that we've used to alter
* the childs environment as they see fit
*/
ssh_gssapi_do_child(&env, &envsize);
path = child_get_env(env, "PATH");
# endif /* HAVE_ETC_DEFAULT_LOGIN */
if (path == NULL || *path == '\0') {
- child_set_env(&env, &envsize, "PATH",
+ child_set_env(&env, &envsize, "PATH",
s->pw->pw_uid == 0 ?
SUPERUSER_PATH : _PATH_STDPATH);
}
* been set by PAM.
*/
if (options.use_pam) {
- char **p;
+ char **p = fetch_pam_environment();
- p = fetch_pam_child_environment();
- copy_environment(p, &env, &envsize);
- free_pam_environment(p);
-
- p = fetch_pam_environment();
copy_environment(p, &env, &envsize);
free_pam_environment(p);
}
if (debug_flag) {
fprintf(stderr,
"Running %.500s remove %.100s\n",
- options.xauth_location, s->auth_display);
+ options.xauth_location, s->auth_display);
fprintf(stderr,
"%.500s add %.100s %.100s %.100s\n",
options.xauth_location, s->auth_display,
endgrent();
# ifdef USE_PAM
/*
- * PAM credentials may take the form of supplementary groups.
+ * PAM credentials may take the form of supplementary groups.
* These will have been wiped by the above initgroups() call.
* Reestablish them here.
*/
*/
environ = env;
-#ifdef KRB5
- /*
- * At this point, we check to see if AFS is active and if we have
- * a valid Kerberos 5 TGT. If so, it seems like a good idea to see
- * if we can (and need to) extend the ticket into an AFS token. If
- * we don't do this, we run into potential problems if the user's
- * home directory is in AFS and it's not world-readable.
- */
-
- if (options.kerberos_get_afs_token && k_hasafs() &&
- (s->authctxt->krb5_ctx != NULL)) {
- char cell[64];
-
- debug("Getting AFS token");
-
- k_setpag();
-
- if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
- krb5_afslog(s->authctxt->krb5_ctx,
- s->authctxt->krb5_fwd_ccache, cell, NULL);
-
- krb5_afslog_home(s->authctxt->krb5_ctx,
- s->authctxt->krb5_fwd_ccache, NULL, NULL, pw->pw_dir);
- }
-#endif
-
/* 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",
}
s->authctxt = authctxt;
s->pw = authctxt->pw;
- if (s->pw == NULL || !authctxt->valid)
+ if (s->pw == NULL)
fatal("no user for session %d", s->self);
debug("session_open: session %d: link with channel %d", s->self, chanid);
s->chanid = chanid;
n_bytes = packet_remaining();
tty_parse_modes(s->ttyfd, &n_bytes);
+ /*
+ * Add a cleanup function to clear the utmp entry and record logout
+ * time in case we call fatal() (e.g., the connection gets closed).
+ */
+ fatal_add_cleanup(session_pty_cleanup, (void *)s);
if (!use_privsep)
pty_setowner(s->pw, s->tty);
* (e.g., due to a dropped connection).
*/
void
-session_pty_cleanup2(Session *s)
+session_pty_cleanup2(void *session)
{
+ Session *s = session;
+
if (s == NULL) {
error("session_pty_cleanup: no session");
return;
}
void
-session_pty_cleanup(Session *s)
+session_pty_cleanup(void *session)
{
- PRIVSEP(session_pty_cleanup2(s));
+ PRIVSEP(session_pty_cleanup2(session));
}
static char *
session_close(Session *s)
{
debug("session_close: session %d pid %ld", s->self, (long)s->pid);
- if (s->ttyfd != -1)
+ if (s->ttyfd != -1) {
+ fatal_remove_cleanup(session_pty_cleanup, (void *)s);
session_pty_cleanup(s);
+ }
if (s->term)
xfree(s->term);
if (s->display)
* delay detach of session, but release pty, since
* the fd's to the child are already closed
*/
- if (s->ttyfd != -1)
+ if (s->ttyfd != -1) {
+ fatal_remove_cleanup(session_pty_cleanup, (void *)s);
session_pty_cleanup(s);
+ }
return;
}
/* detach by removing callback */
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used && s->ttyfd != -1) {
-
+
if (strncmp(s->tty, "/dev/", 5) != 0) {
cp = strrchr(s->tty, '/');
cp = (cp == NULL) ? s->tty : cp + 1;
} else
cp = s->tty + 5;
-
+
if (buf[0] != '\0')
strlcat(buf, ",", sizeof buf);
strlcat(buf, cp, sizeof buf);
do_authenticated2(Authctxt *authctxt)
{
server_loop2(authctxt);
-}
-
-void
-do_cleanup(Authctxt *authctxt)
-{
- static int called = 0;
-
- debug("do_cleanup");
-
- /* no cleanup if we're in the child for login shell */
- if (is_child)
- return;
-
- /* avoid double cleanup */
- if (called)
- return;
- called = 1;
-
- if (authctxt == NULL)
- return;
-#ifdef KRB5
- if (options.kerberos_ticket_cleanup &&
- authctxt->krb5_ctx)
- krb5_cleanup_proc(authctxt);
-#endif
-
-#ifdef GSSAPI
- if (compat20 && options.gss_cleanup_creds)
- ssh_gssapi_cleanup_creds();
+#if defined(GSSAPI)
+ if (options.gss_cleanup_creds)
+ ssh_gssapi_cleanup_creds(NULL);
#endif
-
-#ifdef USE_PAM
- if (options.use_pam) {
- sshpam_cleanup();
- sshpam_thread_cleanup();
- }
-#endif
-
- /* remove agent socket */
- auth_sock_cleanup_proc(authctxt->pw);
-
- /*
- * Cleanup ptys/utmp only if privsep is disabled,
- * or if running in monitor.
- */
- if (!use_privsep || mm_is_monitor())
- session_destroy_all(session_pty_cleanup2);
}