X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/d5f24f9484edc9f09cbcdbefe62da0b3bd0cde6a..46df736f763231f048df88bfbacff7a2282d81a5:/session.c diff --git a/session.c b/session.c index 0d6ebdae..cc3fb044 100644 --- a/session.c +++ b/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.106 2001/10/09 21:59:41 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.111 2001/12/06 18:09:23 stevesk Exp $"); #include "ssh.h" #include "ssh1.h" @@ -108,8 +108,10 @@ struct Session { int row, col, xpixel, ypixel; char tty[TTYSZ]; /* X11 */ + int display_number; char *display; int screen; + char *auth_display[2]; char *auth_proto; char *auth_data; int single_connection; @@ -159,7 +161,6 @@ const char *original_command = NULL; Session sessions[MAX_SESSIONS]; #ifdef WITH_AIXAUTHENTICATE -/* AIX's lastlogin message, set in auth1.c */ char *aixloginmsg; #endif /* WITH_AIXAUTHENTICATE */ @@ -191,6 +192,14 @@ do_authenticated(Authctxt *authctxt) } #endif #endif +#ifdef WITH_AIXAUTHENTICATE + /* We don't have a pty yet, so just label the line as "ssh" */ + if (loginsuccess(authctxt->user, + get_canonical_hostname(options.reverse_mapping_check), + "ssh", &aixloginmsg) < 0) + aixloginmsg = NULL; +#endif /* WITH_AIXAUTHENTICATE */ + /* setup the channel layer */ if (!no_port_forwarding_flag && options.allow_tcp_forwarding) channel_permit_all_opens(); @@ -432,6 +441,9 @@ do_exec_no_pty(Session *s, const char *command) #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"); #endif /* USE_PAM */ /* Fork the child. */ @@ -1237,18 +1249,21 @@ do_child(Session *s, const char *command) child_set_env(&env, &envsize, "TZ", getenv("TZ")); /* Set custom environment options from RSA authentication. */ - while (custom_environment) { - struct envstring *ce = custom_environment; - char *s = ce->s; - int i; - for (i = 0; s[i] != '=' && s[i]; i++); - if (s[i] == '=') { - s[i] = 0; - child_set_env(&env, &envsize, s, s + i + 1); + if (!options.use_login) { + while (custom_environment) { + struct envstring *ce = custom_environment; + char *s = ce->s; + int i; + for (i = 0; s[i] != '=' && s[i]; i++) + ; + if (s[i] == '=') { + s[i] = 0; + child_set_env(&env, &envsize, s, s + i + 1); + } + custom_environment = ce->next; + xfree(ce->s); + xfree(ce); } - custom_environment = ce->next; - xfree(ce->s); - xfree(ce); } snprintf(buf, sizeof buf, "%.50s %d %d", @@ -1405,32 +1420,28 @@ do_child(Session *s, const char *command) _PATH_SSH_SYSTEM_RC); } else if (do_xauth && options.xauth_location != NULL) { /* Add authority data to .Xauthority if appropriate. */ - char *screen = strchr(s->display, ':'); - if (debug_flag) { fprintf(stderr, "Running %.100s add " "%.100s %.100s %.100s\n", - options.xauth_location, s->display, + options.xauth_location, s->auth_display[0], s->auth_proto, s->auth_data); - if (screen != NULL) + if (s->auth_display[1]) fprintf(stderr, - "Adding %.*s/unix%s %s %s\n", - (int)(screen - s->display), - s->display, screen, + "add %.100s %.100s %.100s\n", + s->auth_display[1], s->auth_proto, s->auth_data); } snprintf(cmd, sizeof cmd, "%s -q -", options.xauth_location); f = popen(cmd, "w"); if (f) { - fprintf(f, "add %s %s %s\n", s->display, - s->auth_proto, s->auth_data); - if (screen != NULL) - fprintf(f, "add %.*s/unix%s %s %s\n", - (int)(screen - s->display), - s->display, screen, - s->auth_proto, + fprintf(f, "add %s %s %s\n", + s->auth_display[0], s->auth_proto, + s->auth_data); + if (s->auth_display[1]) + fprintf(f, "add %s %s %s\n", + s->auth_display[1], s->auth_proto, s->auth_data); pclose(f); } else { @@ -1460,8 +1471,7 @@ do_child(Session *s, const char *command) /* Start the shell. Set initial character to '-'. */ buf[0] = '-'; - strncpy(buf + 1, cp, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = 0; + strlcpy(buf + 1, cp, sizeof(buf) - 1); /* Execute the shell. */ argv[0] = buf; @@ -1865,6 +1875,9 @@ session_pty_cleanup(void *session) */ if (close(s->ptymaster) < 0) error("close(s->ptymaster): %s", strerror(errno)); + + /* unlink pty from session */ + s->ttyfd = -1; } static void @@ -1928,6 +1941,10 @@ session_close(Session *s) xfree(s->term); if (s->display) xfree(s->display); + if (s->auth_display[0]) + xfree(s->auth_display[0]); + if (s->auth_display[1]) + xfree(s->auth_display[1]); if (s->auth_data) xfree(s->auth_data); if (s->auth_proto) @@ -1958,36 +1975,36 @@ session_close_by_channel(int id, void *arg) { Session *s = session_by_channel(id); if (s == NULL) { - debug("session_close_by_channel: no session for channel %d", id); + debug("session_close_by_channel: no session for id %d", id); return; } - /* disconnect channel */ - channel_cancel_cleanup(s->chanid); - s->chanid = -1; - - debug("session_close_by_channel: channel %d kill %d", id, s->pid); + debug("session_close_by_channel: channel %d child %d", id, s->pid); if (s->pid != 0) { - /* notify child */ - if (kill(s->pid, SIGHUP) < 0) - error("session_close_by_channel: kill %d: %s", - s->pid, strerror(errno)); + debug("session_close_by_channel: channel %d: has child", id); + /* + * delay detach of session, but release pty, since + * the fd's to the child are already closed + */ + if (s->ttyfd != -1) { + fatal_remove_cleanup(session_pty_cleanup, (void *)s); + session_pty_cleanup(s); + } + return; } + /* detach by removing callback */ + channel_cancel_cleanup(s->chanid); + s->chanid = -1; session_close(s); } void -session_close_all(void) +session_destroy_all(void) { int i; for(i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; - if (s->used) { - if (s->chanid != -1) { - channel_cancel_cleanup(s->chanid); - s->chanid = -1; - } + if (s->used) session_close(s); - } } } @@ -2023,6 +2040,8 @@ int session_setup_x11fwd(Session *s) { struct stat st; + char display[512], auth_display[512]; + char hostname[MAXHOSTNAMELEN]; if (no_x11_forwarding_flag) { packet_send_debug("X11 forwarding disabled in user configuration file."); @@ -2046,11 +2065,68 @@ session_setup_x11fwd(Session *s) debug("X11 display already set."); return 0; } - s->display = x11_create_display_inet(s->screen, options.x11_display_offset); - if (s->display == NULL) { + s->display_number = x11_create_display_inet(options.x11_display_offset, + options.gateway_ports); + if (s->display_number == -1) { debug("x11_create_display_inet failed."); return 0; } + + /* Set up a suitable value for the DISPLAY variable. */ + if (gethostname(hostname, sizeof(hostname)) < 0) + fatal("gethostname: %.100s", strerror(errno)); + /* + * auth_display must be used as the displayname when the + * authorization entry is added with xauth(1). This will be + * different than the DISPLAY string for localhost displays. + */ + s->auth_display[1] = NULL; + if (!options.gateway_ports) { + struct utsname uts; + + snprintf(display, sizeof display, "localhost:%d.%d", + s->display_number, s->screen); + snprintf(auth_display, sizeof auth_display, "%.400s/unix:%d.%d", + hostname, s->display_number, s->screen); + s->display = xstrdup(display); + s->auth_display[0] = xstrdup(auth_display); + /* + * Xlib may use gethostbyname() or uname() hostname to + * look up authorization data for FamilyLocal; see: + * xc/lib/xtrans/Xtrans.c:TRANS(GetHostname) + * We just add authorization entries with both + * hostname and nodename if they are different. + */ + if (uname(&uts) == -1) + fatal("uname: %.100s", strerror(errno)); + if (strcmp(hostname, uts.nodename) != 0) { + snprintf(auth_display, sizeof auth_display, + "%.400s/unix:%d.%d", uts.nodename, + s->display_number, s->screen); + s->auth_display[1] = xstrdup(auth_display); + } + } else { +#ifdef IPADDR_IN_DISPLAY + struct hostent *he; + struct in_addr my_addr; + + he = gethostbyname(hostname); + if (he == NULL) { + error("Can't get IP address for X11 DISPLAY."); + packet_send_debug("Can't get IP address for X11 DISPLAY."); + return 0; + } + memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr)); + snprintf(display, sizeof display, "%.50s:%d.%d", inet_ntoa(my_addr), + s->display_number, s->screen); +#else + snprintf(display, sizeof display, "%.400s:%d.%d", hostname, + s->display_number, s->screen); +#endif + s->display = xstrdup(display); + s->auth_display[0] = xstrdup(display); + } + return 1; }