summaryrefslogtreecommitdiff
path: root/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'session.c')
-rw-r--r--session.c313
1 files changed, 204 insertions, 109 deletions
diff --git a/session.c b/session.c
index 4497f5c0b..af2e71992 100644
--- a/session.c
+++ b/session.c
@@ -33,7 +33,7 @@
33 */ 33 */
34 34
35#include "includes.h" 35#include "includes.h"
36RCSID("$OpenBSD: session.c,v 1.163 2003/08/31 13:29:05 markus Exp $"); 36RCSID("$OpenBSD: session.c,v 1.172 2004/01/30 09:48:57 markus Exp $");
37 37
38#include "ssh.h" 38#include "ssh.h"
39#include "ssh1.h" 39#include "ssh1.h"
@@ -58,6 +58,10 @@ RCSID("$OpenBSD: session.c,v 1.163 2003/08/31 13:29:05 markus Exp $");
58#include "session.h" 58#include "session.h"
59#include "monitor_wrap.h" 59#include "monitor_wrap.h"
60 60
61#if defined(KRB5) && defined(USE_AFS)
62#include <kafs.h>
63#endif
64
61#ifdef GSSAPI 65#ifdef GSSAPI
62#include "ssh-gss.h" 66#include "ssh-gss.h"
63#endif 67#endif
@@ -66,7 +70,7 @@ RCSID("$OpenBSD: session.c,v 1.163 2003/08/31 13:29:05 markus Exp $");
66 70
67Session *session_new(void); 71Session *session_new(void);
68void session_set_fds(Session *, int, int, int); 72void session_set_fds(Session *, int, int, int);
69void session_pty_cleanup(void *); 73void session_pty_cleanup(Session *);
70void session_proctitle(Session *); 74void session_proctitle(Session *);
71int session_setup_x11fwd(Session *); 75int session_setup_x11fwd(Session *);
72void do_exec_pty(Session *, const char *); 76void do_exec_pty(Session *, const char *);
@@ -106,6 +110,8 @@ Session sessions[MAX_SESSIONS];
106login_cap_t *lc; 110login_cap_t *lc;
107#endif 111#endif
108 112
113static int is_child = 0;
114
109/* Name and directory of socket for authentication agent forwarding. */ 115/* Name and directory of socket for authentication agent forwarding. */
110static char *auth_sock_name = NULL; 116static char *auth_sock_name = NULL;
111static char *auth_sock_dir = NULL; 117static char *auth_sock_dir = NULL;
@@ -113,10 +119,8 @@ static char *auth_sock_dir = NULL;
113/* removes the agent forwarding socket */ 119/* removes the agent forwarding socket */
114 120
115static void 121static void
116auth_sock_cleanup_proc(void *_pw) 122auth_sock_cleanup_proc(struct passwd *pw)
117{ 123{
118 struct passwd *pw = _pw;
119
120 if (auth_sock_name != NULL) { 124 if (auth_sock_name != NULL) {
121 temporarily_use_uid(pw); 125 temporarily_use_uid(pw);
122 unlink(auth_sock_name); 126 unlink(auth_sock_name);
@@ -144,7 +148,7 @@ auth_input_request_forwarding(struct passwd * pw)
144 /* Allocate a buffer for the socket name, and format the name. */ 148 /* Allocate a buffer for the socket name, and format the name. */
145 auth_sock_name = xmalloc(MAXPATHLEN); 149 auth_sock_name = xmalloc(MAXPATHLEN);
146 auth_sock_dir = xmalloc(MAXPATHLEN); 150 auth_sock_dir = xmalloc(MAXPATHLEN);
147 strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN); 151 strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
148 152
149 /* Create private directory for socket */ 153 /* Create private directory for socket */
150 if (mkdtemp(auth_sock_dir) == NULL) { 154 if (mkdtemp(auth_sock_dir) == NULL) {
@@ -160,9 +164,6 @@ auth_input_request_forwarding(struct passwd * pw)
160 snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld", 164 snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
161 auth_sock_dir, (long) getpid()); 165 auth_sock_dir, (long) getpid());
162 166
163 /* delete agent socket on fatal() */
164 fatal_add_cleanup(auth_sock_cleanup_proc, pw);
165
166 /* Create the socket. */ 167 /* Create the socket. */
167 sock = socket(AF_UNIX, SOCK_STREAM, 0); 168 sock = socket(AF_UNIX, SOCK_STREAM, 0);
168 if (sock < 0) 169 if (sock < 0)
@@ -180,7 +181,7 @@ auth_input_request_forwarding(struct passwd * pw)
180 restore_uid(); 181 restore_uid();
181 182
182 /* Start listening on the socket. */ 183 /* Start listening on the socket. */
183 if (listen(sock, 5) < 0) 184 if (listen(sock, SSH_LISTEN_BACKLOG) < 0)
184 packet_disconnect("listen: %.100s", strerror(errno)); 185 packet_disconnect("listen: %.100s", strerror(errno));
185 186
186 /* Allocate a channel for the authentication agent socket. */ 187 /* Allocate a channel for the authentication agent socket. */
@@ -192,6 +193,15 @@ auth_input_request_forwarding(struct passwd * pw)
192 return 1; 193 return 1;
193} 194}
194 195
196static void
197display_loginmsg(void)
198{
199 if (buffer_len(&loginmsg) > 0) {
200 buffer_append(&loginmsg, "\0", 1);
201 printf("%s\n", (char *)buffer_ptr(&loginmsg));
202 buffer_clear(&loginmsg);
203 }
204}
195 205
196void 206void
197do_authenticated(Authctxt *authctxt) 207do_authenticated(Authctxt *authctxt)
@@ -207,7 +217,6 @@ do_authenticated(Authctxt *authctxt)
207 close(startup_pipe); 217 close(startup_pipe);
208 startup_pipe = -1; 218 startup_pipe = -1;
209 } 219 }
210
211 /* setup the channel layer */ 220 /* setup the channel layer */
212 if (!no_port_forwarding_flag && options.allow_tcp_forwarding) 221 if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
213 channel_permit_all_opens(); 222 channel_permit_all_opens();
@@ -217,13 +226,7 @@ do_authenticated(Authctxt *authctxt)
217 else 226 else
218 do_authenticated1(authctxt); 227 do_authenticated1(authctxt);
219 228
220 /* remove agent socket */ 229 do_cleanup(authctxt);
221 if (auth_sock_name != NULL)
222 auth_sock_cleanup_proc(authctxt->pw);
223#ifdef KRB5
224 if (options.kerberos_ticket_cleanup)
225 krb5_cleanup_proc(authctxt);
226#endif
227} 230}
228 231
229/* 232/*
@@ -395,17 +398,13 @@ do_exec_no_pty(Session *s, const char *command)
395 session_proctitle(s); 398 session_proctitle(s);
396 399
397#if defined(USE_PAM) 400#if defined(USE_PAM)
398 if (options.use_pam) { 401 if (options.use_pam && !use_privsep)
399 do_pam_setcred(1); 402 do_pam_setcred(1);
400 if (is_pam_password_change_required())
401 packet_disconnect("Password change required but no "
402 "TTY available");
403 }
404#endif /* USE_PAM */ 403#endif /* USE_PAM */
405 404
406 /* Fork the child. */ 405 /* Fork the child. */
407 if ((pid = fork()) == 0) { 406 if ((pid = fork()) == 0) {
408 fatal_remove_all_cleanups(); 407 is_child = 1;
409 408
410 /* Child. Reinitialize the log since the pid has changed. */ 409 /* Child. Reinitialize the log since the pid has changed. */
411 log_init(__progname, options.log_level, options.log_facility, log_stderr); 410 log_init(__progname, options.log_level, options.log_facility, log_stderr);
@@ -525,13 +524,14 @@ do_exec_pty(Session *s, const char *command)
525#if defined(USE_PAM) 524#if defined(USE_PAM)
526 if (options.use_pam) { 525 if (options.use_pam) {
527 do_pam_set_tty(s->tty); 526 do_pam_set_tty(s->tty);
528 do_pam_setcred(1); 527 if (!use_privsep)
528 do_pam_setcred(1);
529 } 529 }
530#endif 530#endif
531 531
532 /* Fork the child. */ 532 /* Fork the child. */
533 if ((pid = fork()) == 0) { 533 if ((pid = fork()) == 0) {
534 fatal_remove_all_cleanups(); 534 is_child = 1;
535 535
536 /* Child. Reinitialize the log because the pid has changed. */ 536 /* Child. Reinitialize the log because the pid has changed. */
537 log_init(__progname, options.log_level, options.log_facility, log_stderr); 537 log_init(__progname, options.log_level, options.log_facility, log_stderr);
@@ -627,7 +627,7 @@ do_pre_login(Session *s)
627 if (getpeername(packet_get_connection_in(), 627 if (getpeername(packet_get_connection_in(),
628 (struct sockaddr *) & from, &fromlen) < 0) { 628 (struct sockaddr *) & from, &fromlen) < 0) {
629 debug("getpeername: %.100s", strerror(errno)); 629 debug("getpeername: %.100s", strerror(errno));
630 fatal_cleanup(); 630 cleanup_exit(255);
631 } 631 }
632 } 632 }
633 633
@@ -687,7 +687,7 @@ do_login(Session *s, const char *command)
687 if (getpeername(packet_get_connection_in(), 687 if (getpeername(packet_get_connection_in(),
688 (struct sockaddr *) & from, &fromlen) < 0) { 688 (struct sockaddr *) & from, &fromlen) < 0) {
689 debug("getpeername: %.100s", strerror(errno)); 689 debug("getpeername: %.100s", strerror(errno));
690 fatal_cleanup(); 690 cleanup_exit(255);
691 } 691 }
692 } 692 }
693 693
@@ -703,9 +703,10 @@ do_login(Session *s, const char *command)
703 * If password change is needed, do it now. 703 * If password change is needed, do it now.
704 * This needs to occur before the ~/.hushlogin check. 704 * This needs to occur before the ~/.hushlogin check.
705 */ 705 */
706 if (options.use_pam && is_pam_password_change_required()) { 706 if (options.use_pam && !use_privsep && s->authctxt->force_pwchange) {
707 print_pam_messages(); 707 display_loginmsg();
708 do_pam_chauthtok(); 708 do_pam_chauthtok();
709 s->authctxt->force_pwchange = 0;
709 /* XXX - signal [net] parent to enable forwardings */ 710 /* XXX - signal [net] parent to enable forwardings */
710 } 711 }
711#endif 712#endif
@@ -713,17 +714,7 @@ do_login(Session *s, const char *command)
713 if (check_quietlogin(s, command)) 714 if (check_quietlogin(s, command))
714 return; 715 return;
715 716
716#ifdef USE_PAM 717 display_loginmsg();
717 if (options.use_pam && !is_pam_password_change_required())
718 print_pam_messages();
719#endif /* USE_PAM */
720
721 /* display post-login message */
722 if (buffer_len(&loginmsg) > 0) {
723 buffer_append(&loginmsg, "\0", 1);
724 printf("%s\n", (char *)buffer_ptr(&loginmsg));
725 }
726 buffer_free(&loginmsg);
727 718
728#ifndef NO_SSH_LASTLOG 719#ifndef NO_SSH_LASTLOG
729 if (options.print_lastlog && s->last_login_time != 0) { 720 if (options.print_lastlog && s->last_login_time != 0) {
@@ -798,8 +789,9 @@ void
798child_set_env(char ***envp, u_int *envsizep, const char *name, 789child_set_env(char ***envp, u_int *envsizep, const char *name,
799 const char *value) 790 const char *value)
800{ 791{
801 u_int i, namelen;
802 char **env; 792 char **env;
793 u_int envsize;
794 u_int i, namelen;
803 795
804 /* 796 /*
805 * If we're passed an uninitialized list, allocate a single null 797 * If we're passed an uninitialized list, allocate a single null
@@ -826,12 +818,13 @@ child_set_env(char ***envp, u_int *envsizep, const char *name,
826 xfree(env[i]); 818 xfree(env[i]);
827 } else { 819 } else {
828 /* New variable. Expand if necessary. */ 820 /* New variable. Expand if necessary. */
829 if (i >= (*envsizep) - 1) { 821 envsize = *envsizep;
830 if (*envsizep >= 1000) 822 if (i >= envsize - 1) {
831 fatal("child_set_env: too many env vars," 823 if (envsize >= 1000)
832 " skipping: %.100s", name); 824 fatal("child_set_env: too many env vars");
833 (*envsizep) += 50; 825 envsize += 50;
834 env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *)); 826 env = (*envp) = xrealloc(env, envsize * sizeof(char *));
827 *envsizep = envsize;
835 } 828 }
836 /* Need to set the NULL pointer at end of array beyond the new slot. */ 829 /* Need to set the NULL pointer at end of array beyond the new slot. */
837 env[i + 1] = NULL; 830 env[i + 1] = NULL;
@@ -912,9 +905,8 @@ static void
912read_etc_default_login(char ***env, u_int *envsize, uid_t uid) 905read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
913{ 906{
914 char **tmpenv = NULL, *var; 907 char **tmpenv = NULL, *var;
915 u_int i; 908 u_int i, tmpenvsize = 0;
916 size_t tmpenvsize = 0; 909 u_long mask;
917 mode_t mask;
918 910
919 /* 911 /*
920 * We don't want to copy the whole file to the child's environment, 912 * We don't want to copy the whole file to the child's environment,
@@ -923,17 +915,20 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
923 */ 915 */
924 read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login"); 916 read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login");
925 917
918 if (tmpenv == NULL)
919 return;
920
926 if (uid == 0) 921 if (uid == 0)
927 var = child_get_env(tmpenv, "SUPATH"); 922 var = child_get_env(tmpenv, "SUPATH");
928 else 923 else
929 var = child_get_env(tmpenv, "PATH"); 924 var = child_get_env(tmpenv, "PATH");
930 if (var != NULL) 925 if (var != NULL)
931 child_set_env(env, envsize, "PATH", var); 926 child_set_env(env, envsize, "PATH", var);
932 927
933 if ((var = child_get_env(tmpenv, "UMASK")) != NULL) 928 if ((var = child_get_env(tmpenv, "UMASK")) != NULL)
934 if (sscanf(var, "%5lo", &mask) == 1) 929 if (sscanf(var, "%5lo", &mask) == 1)
935 umask(mask); 930 umask((mode_t)mask);
936 931
937 for (i = 0; tmpenv[i] != NULL; i++) 932 for (i = 0; tmpenv[i] != NULL; i++)
938 xfree(tmpenv[i]); 933 xfree(tmpenv[i]);
939 xfree(tmpenv); 934 xfree(tmpenv);
@@ -958,7 +953,7 @@ void copy_environment(char **source, char ***env, u_int *envsize)
958 953
959 debug3("Copy environment: %s=%s", var_name, var_val); 954 debug3("Copy environment: %s=%s", var_name, var_val);
960 child_set_env(env, envsize, var_name, var_val); 955 child_set_env(env, envsize, var_name, var_val);
961 956
962 xfree(var_name); 957 xfree(var_name);
963 } 958 }
964} 959}
@@ -985,7 +980,7 @@ do_setup_env(Session *s, const char *shell)
985#endif 980#endif
986 981
987#ifdef GSSAPI 982#ifdef GSSAPI
988 /* Allow any GSSAPI methods that we've used to alter 983 /* Allow any GSSAPI methods that we've used to alter
989 * the childs environment as they see fit 984 * the childs environment as they see fit
990 */ 985 */
991 ssh_gssapi_do_child(&env, &envsize); 986 ssh_gssapi_do_child(&env, &envsize);
@@ -1017,7 +1012,7 @@ do_setup_env(Session *s, const char *shell)
1017 path = child_get_env(env, "PATH"); 1012 path = child_get_env(env, "PATH");
1018# endif /* HAVE_ETC_DEFAULT_LOGIN */ 1013# endif /* HAVE_ETC_DEFAULT_LOGIN */
1019 if (path == NULL || *path == '\0') { 1014 if (path == NULL || *path == '\0') {
1020 child_set_env(&env, &envsize, "PATH", 1015 child_set_env(&env, &envsize, "PATH",
1021 s->pw->pw_uid == 0 ? 1016 s->pw->pw_uid == 0 ?
1022 SUPERUSER_PATH : _PATH_STDPATH); 1017 SUPERUSER_PATH : _PATH_STDPATH);
1023 } 1018 }
@@ -1100,8 +1095,13 @@ do_setup_env(Session *s, const char *shell)
1100 * been set by PAM. 1095 * been set by PAM.
1101 */ 1096 */
1102 if (options.use_pam) { 1097 if (options.use_pam) {
1103 char **p = fetch_pam_environment(); 1098 char **p;
1099
1100 p = fetch_pam_child_environment();
1101 copy_environment(p, &env, &envsize);
1102 free_pam_environment(p);
1104 1103
1104 p = fetch_pam_environment();
1105 copy_environment(p, &env, &envsize); 1105 copy_environment(p, &env, &envsize);
1106 free_pam_environment(p); 1106 free_pam_environment(p);
1107 } 1107 }
@@ -1174,7 +1174,7 @@ do_rc_files(Session *s, const char *shell)
1174 if (debug_flag) { 1174 if (debug_flag) {
1175 fprintf(stderr, 1175 fprintf(stderr,
1176 "Running %.500s remove %.100s\n", 1176 "Running %.500s remove %.100s\n",
1177 options.xauth_location, s->auth_display); 1177 options.xauth_location, s->auth_display);
1178 fprintf(stderr, 1178 fprintf(stderr,
1179 "%.500s add %.100s %.100s %.100s\n", 1179 "%.500s add %.100s %.100s %.100s\n",
1180 options.xauth_location, s->auth_display, 1180 options.xauth_location, s->auth_display,
@@ -1240,6 +1240,12 @@ do_setusercontext(struct passwd *pw)
1240# ifdef __bsdi__ 1240# ifdef __bsdi__
1241 setpgid(0, 0); 1241 setpgid(0, 0);
1242# endif 1242# endif
1243# ifdef USE_PAM
1244 if (options.use_pam) {
1245 do_pam_session();
1246 do_pam_setcred(0);
1247 }
1248# endif /* USE_PAM */
1243 if (setusercontext(lc, pw, pw->pw_uid, 1249 if (setusercontext(lc, pw, pw->pw_uid,
1244 (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { 1250 (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
1245 perror("unable to set user context"); 1251 perror("unable to set user context");
@@ -1266,7 +1272,7 @@ do_setusercontext(struct passwd *pw)
1266 endgrent(); 1272 endgrent();
1267# ifdef USE_PAM 1273# ifdef USE_PAM
1268 /* 1274 /*
1269 * PAM credentials may take the form of supplementary groups. 1275 * PAM credentials may take the form of supplementary groups.
1270 * These will have been wiped by the above initgroups() call. 1276 * These will have been wiped by the above initgroups() call.
1271 * Reestablish them here. 1277 * Reestablish them here.
1272 */ 1278 */
@@ -1294,6 +1300,22 @@ do_setusercontext(struct passwd *pw)
1294} 1300}
1295 1301
1296static void 1302static void
1303do_pwchange(Session *s)
1304{
1305 fprintf(stderr, "WARNING: Your password has expired.\n");
1306 if (s->ttyfd != -1) {
1307 fprintf(stderr,
1308 "You must change your password now and login again!\n");
1309 execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL);
1310 perror("passwd");
1311 } else {
1312 fprintf(stderr,
1313 "Password change required but no TTY available.\n");
1314 }
1315 exit(1);
1316}
1317
1318static void
1297launch_login(struct passwd *pw, const char *hostname) 1319launch_login(struct passwd *pw, const char *hostname)
1298{ 1320{
1299 /* Launch login(1). */ 1321 /* Launch login(1). */
@@ -1314,6 +1336,40 @@ launch_login(struct passwd *pw, const char *hostname)
1314 exit(1); 1336 exit(1);
1315} 1337}
1316 1338
1339static void
1340child_close_fds(void)
1341{
1342 int i;
1343
1344 if (packet_get_connection_in() == packet_get_connection_out())
1345 close(packet_get_connection_in());
1346 else {
1347 close(packet_get_connection_in());
1348 close(packet_get_connection_out());
1349 }
1350 /*
1351 * Close all descriptors related to channels. They will still remain
1352 * open in the parent.
1353 */
1354 /* XXX better use close-on-exec? -markus */
1355 channel_close_all();
1356
1357 /*
1358 * Close any extra file descriptors. Note that there may still be
1359 * descriptors left by system functions. They will be closed later.
1360 */
1361 endpwent();
1362
1363 /*
1364 * Close any extra open file descriptors so that we don\'t have them
1365 * hanging around in clients. Note that we want to do this after
1366 * initgroups, because at least on Solaris 2.3 it leaves file
1367 * descriptors open.
1368 */
1369 for (i = 3; i < 64; i++)
1370 close(i);
1371}
1372
1317/* 1373/*
1318 * Performs common processing for the child, such as setting up the 1374 * Performs common processing for the child, such as setting up the
1319 * environment, closing extra file descriptors, setting the user and group 1375 * environment, closing extra file descriptors, setting the user and group
@@ -1327,11 +1383,18 @@ do_child(Session *s, const char *command)
1327 char *argv[10]; 1383 char *argv[10];
1328 const char *shell, *shell0, *hostname = NULL; 1384 const char *shell, *shell0, *hostname = NULL;
1329 struct passwd *pw = s->pw; 1385 struct passwd *pw = s->pw;
1330 u_int i;
1331 1386
1332 /* remove hostkey from the child's memory */ 1387 /* remove hostkey from the child's memory */
1333 destroy_sensitive_data(); 1388 destroy_sensitive_data();
1334 1389
1390 /* Force a password change */
1391 if (s->authctxt->force_pwchange) {
1392 do_setusercontext(pw);
1393 child_close_fds();
1394 do_pwchange(s);
1395 exit(1);
1396 }
1397
1335 /* login(1) is only called if we execute the login shell */ 1398 /* login(1) is only called if we execute the login shell */
1336 if (options.use_login && command != NULL) 1399 if (options.use_login && command != NULL)
1337 options.use_login = 0; 1400 options.use_login = 0;
@@ -1382,39 +1445,39 @@ do_child(Session *s, const char *command)
1382 * closed before building the environment, as we call 1445 * closed before building the environment, as we call
1383 * get_remote_ipaddr there. 1446 * get_remote_ipaddr there.
1384 */ 1447 */
1385 if (packet_get_connection_in() == packet_get_connection_out()) 1448 child_close_fds();
1386 close(packet_get_connection_in());
1387 else {
1388 close(packet_get_connection_in());
1389 close(packet_get_connection_out());
1390 }
1391 /*
1392 * Close all descriptors related to channels. They will still remain
1393 * open in the parent.
1394 */
1395 /* XXX better use close-on-exec? -markus */
1396 channel_close_all();
1397 1449
1398 /* 1450 /*
1399 * Close any extra file descriptors. Note that there may still be 1451 * Must take new environment into use so that .ssh/rc,
1400 * descriptors left by system functions. They will be closed later. 1452 * /etc/ssh/sshrc and xauth are run in the proper environment.
1401 */ 1453 */
1402 endpwent(); 1454 environ = env;
1403 1455
1456#if defined(KRB5) && defined(USE_AFS)
1404 /* 1457 /*
1405 * Close any extra open file descriptors so that we don\'t have them 1458 * At this point, we check to see if AFS is active and if we have
1406 * hanging around in clients. Note that we want to do this after 1459 * a valid Kerberos 5 TGT. If so, it seems like a good idea to see
1407 * initgroups, because at least on Solaris 2.3 it leaves file 1460 * if we can (and need to) extend the ticket into an AFS token. If
1408 * descriptors open. 1461 * we don't do this, we run into potential problems if the user's
1462 * home directory is in AFS and it's not world-readable.
1409 */ 1463 */
1410 for (i = 3; i < 64; i++)
1411 close(i);
1412 1464
1413 /* 1465 if (options.kerberos_get_afs_token && k_hasafs() &&
1414 * Must take new environment into use so that .ssh/rc, 1466 (s->authctxt->krb5_ctx != NULL)) {
1415 * /etc/ssh/sshrc and xauth are run in the proper environment. 1467 char cell[64];
1416 */ 1468
1417 environ = env; 1469 debug("Getting AFS token");
1470
1471 k_setpag();
1472
1473 if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
1474 krb5_afslog(s->authctxt->krb5_ctx,
1475 s->authctxt->krb5_fwd_ccache, cell, NULL);
1476
1477 krb5_afslog_home(s->authctxt->krb5_ctx,
1478 s->authctxt->krb5_fwd_ccache, NULL, NULL, pw->pw_dir);
1479 }
1480#endif
1418 1481
1419 /* Change current directory to the user\'s home directory. */ 1482 /* Change current directory to the user\'s home directory. */
1420 if (chdir(pw->pw_dir) < 0) { 1483 if (chdir(pw->pw_dir) < 0) {
@@ -1537,7 +1600,7 @@ session_open(Authctxt *authctxt, int chanid)
1537 } 1600 }
1538 s->authctxt = authctxt; 1601 s->authctxt = authctxt;
1539 s->pw = authctxt->pw; 1602 s->pw = authctxt->pw;
1540 if (s->pw == NULL) 1603 if (s->pw == NULL || !authctxt->valid)
1541 fatal("no user for session %d", s->self); 1604 fatal("no user for session %d", s->self);
1542 debug("session_open: session %d: link with channel %d", s->self, chanid); 1605 debug("session_open: session %d: link with channel %d", s->self, chanid);
1543 s->chanid = chanid; 1606 s->chanid = chanid;
@@ -1659,11 +1722,6 @@ session_pty_req(Session *s)
1659 n_bytes = packet_remaining(); 1722 n_bytes = packet_remaining();
1660 tty_parse_modes(s->ttyfd, &n_bytes); 1723 tty_parse_modes(s->ttyfd, &n_bytes);
1661 1724
1662 /*
1663 * Add a cleanup function to clear the utmp entry and record logout
1664 * time in case we call fatal() (e.g., the connection gets closed).
1665 */
1666 fatal_add_cleanup(session_pty_cleanup, (void *)s);
1667 if (!use_privsep) 1725 if (!use_privsep)
1668 pty_setowner(s->pw, s->tty); 1726 pty_setowner(s->pw, s->tty);
1669 1727
@@ -1845,10 +1903,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
1845 * (e.g., due to a dropped connection). 1903 * (e.g., due to a dropped connection).
1846 */ 1904 */
1847void 1905void
1848session_pty_cleanup2(void *session) 1906session_pty_cleanup2(Session *s)
1849{ 1907{
1850 Session *s = session;
1851
1852 if (s == NULL) { 1908 if (s == NULL) {
1853 error("session_pty_cleanup: no session"); 1909 error("session_pty_cleanup: no session");
1854 return; 1910 return;
@@ -1879,9 +1935,9 @@ session_pty_cleanup2(void *session)
1879} 1935}
1880 1936
1881void 1937void
1882session_pty_cleanup(void *session) 1938session_pty_cleanup(Session *s)
1883{ 1939{
1884 PRIVSEP(session_pty_cleanup2(session)); 1940 PRIVSEP(session_pty_cleanup2(s));
1885} 1941}
1886 1942
1887static char * 1943static char *
@@ -1954,10 +2010,8 @@ void
1954session_close(Session *s) 2010session_close(Session *s)
1955{ 2011{
1956 debug("session_close: session %d pid %ld", s->self, (long)s->pid); 2012 debug("session_close: session %d pid %ld", s->self, (long)s->pid);
1957 if (s->ttyfd != -1) { 2013 if (s->ttyfd != -1)
1958 fatal_remove_cleanup(session_pty_cleanup, (void *)s);
1959 session_pty_cleanup(s); 2014 session_pty_cleanup(s);
1960 }
1961 if (s->term) 2015 if (s->term)
1962 xfree(s->term); 2016 xfree(s->term);
1963 if (s->display) 2017 if (s->display)
@@ -2006,10 +2060,8 @@ session_close_by_channel(int id, void *arg)
2006 * delay detach of session, but release pty, since 2060 * delay detach of session, but release pty, since
2007 * the fd's to the child are already closed 2061 * the fd's to the child are already closed
2008 */ 2062 */
2009 if (s->ttyfd != -1) { 2063 if (s->ttyfd != -1)
2010 fatal_remove_cleanup(session_pty_cleanup, (void *)s);
2011 session_pty_cleanup(s); 2064 session_pty_cleanup(s);
2012 }
2013 return; 2065 return;
2014 } 2066 }
2015 /* detach by removing callback */ 2067 /* detach by removing callback */
@@ -2044,13 +2096,13 @@ session_tty_list(void)
2044 for (i = 0; i < MAX_SESSIONS; i++) { 2096 for (i = 0; i < MAX_SESSIONS; i++) {
2045 Session *s = &sessions[i]; 2097 Session *s = &sessions[i];
2046 if (s->used && s->ttyfd != -1) { 2098 if (s->used && s->ttyfd != -1) {
2047 2099
2048 if (strncmp(s->tty, "/dev/", 5) != 0) { 2100 if (strncmp(s->tty, "/dev/", 5) != 0) {
2049 cp = strrchr(s->tty, '/'); 2101 cp = strrchr(s->tty, '/');
2050 cp = (cp == NULL) ? s->tty : cp + 1; 2102 cp = (cp == NULL) ? s->tty : cp + 1;
2051 } else 2103 } else
2052 cp = s->tty + 5; 2104 cp = s->tty + 5;
2053 2105
2054 if (buf[0] != '\0') 2106 if (buf[0] != '\0')
2055 strlcat(buf, ",", sizeof buf); 2107 strlcat(buf, ",", sizeof buf);
2056 strlcat(buf, cp, sizeof buf); 2108 strlcat(buf, cp, sizeof buf);
@@ -2150,8 +2202,51 @@ static void
2150do_authenticated2(Authctxt *authctxt) 2202do_authenticated2(Authctxt *authctxt)
2151{ 2203{
2152 server_loop2(authctxt); 2204 server_loop2(authctxt);
2153#if defined(GSSAPI) 2205}
2154 if (options.gss_cleanup_creds) 2206
2155 ssh_gssapi_cleanup_creds(NULL); 2207void
2208do_cleanup(Authctxt *authctxt)
2209{
2210 static int called = 0;
2211
2212 debug("do_cleanup");
2213
2214 /* no cleanup if we're in the child for login shell */
2215 if (is_child)
2216 return;
2217
2218 /* avoid double cleanup */
2219 if (called)
2220 return;
2221 called = 1;
2222
2223 if (authctxt == NULL)
2224 return;
2225#ifdef KRB5
2226 if (options.kerberos_ticket_cleanup &&
2227 authctxt->krb5_ctx)
2228 krb5_cleanup_proc(authctxt);
2229#endif
2230
2231#ifdef GSSAPI
2232 if (compat20 && options.gss_cleanup_creds)
2233 ssh_gssapi_cleanup_creds();
2156#endif 2234#endif
2235
2236#ifdef USE_PAM
2237 if (options.use_pam) {
2238 sshpam_cleanup();
2239 sshpam_thread_cleanup();
2240 }
2241#endif
2242
2243 /* remove agent socket */
2244 auth_sock_cleanup_proc(authctxt->pw);
2245
2246 /*
2247 * Cleanup ptys/utmp only if privsep is disabled,
2248 * or if running in monitor.
2249 */
2250 if (!use_privsep || mm_is_monitor())
2251 session_destroy_all(session_pty_cleanup2);
2157} 2252}