X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/85cc9118048e24adf529137cd433ccf068944fbc..bbe88b6d930d2f3cef8d1c896edaa60fd146e84f:/session.c diff --git a/session.c b/session.c index 8c6cdada..9e1dd914 100644 --- a/session.c +++ b/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.135 2002/05/16 22:09:59 stevesk Exp $"); +RCSID("$OpenBSD: session.c,v 1.154 2003/03/05 22:33:43 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -111,9 +111,98 @@ char *aixloginmsg; login_cap_t *lc; #endif +/* 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(void *_pw) +{ + struct passwd *pw = _pw; + + if (auth_sock_name != NULL) { + temporarily_use_uid(pw); + unlink(auth_sock_name); + rmdir(auth_sock_dir); + auth_sock_name = NULL; + restore_uid(); + } +} + +static int +auth_input_request_forwarding(struct passwd * pw) +{ + Channel *nc; + int sock; + struct sockaddr_un sunaddr; + + if (auth_sock_name != NULL) { + error("authentication forwarding requested twice."); + return 0; + } + + /* Temporarily drop privileged uid for mkdir/bind. */ + temporarily_use_uid(pw); + + /* 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-XXXXXXXX", MAXPATHLEN); + + /* Create private directory for socket */ + if (mkdtemp(auth_sock_dir) == NULL) { + packet_send_debug("Agent forwarding disabled: " + "mkdtemp() failed: %.100s", strerror(errno)); + restore_uid(); + xfree(auth_sock_name); + xfree(auth_sock_dir); + auth_sock_name = NULL; + auth_sock_dir = NULL; + return 0; + } + 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) + packet_disconnect("socket: %.100s", strerror(errno)); + + /* Bind it to the name. */ + memset(&sunaddr, 0, sizeof(sunaddr)); + sunaddr.sun_family = AF_UNIX; + strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); + + if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) + packet_disconnect("bind: %.100s", strerror(errno)); + + /* Restore the privileged uid. */ + restore_uid(); + + /* Start listening on the socket. */ + if (listen(sock, 5) < 0) + packet_disconnect("listen: %.100s", strerror(errno)); + + /* Allocate a channel for the authentication agent socket. */ + 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); + strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); + return 1; +} + + void do_authenticated(Authctxt *authctxt) { + setproctitle("%s", authctxt->pw->pw_name); + /* * Cancel the alarm we set to limit the time taken for * authentication. @@ -123,13 +212,6 @@ do_authenticated(Authctxt *authctxt) close(startup_pipe); startup_pipe = -1; } -#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.verify_reverse_mapping), - "ssh", &aixloginmsg) < 0) - aixloginmsg = NULL; -#endif /* WITH_AIXAUTHENTICATE */ /* setup the channel layer */ if (!no_port_forwarding_flag && options.allow_tcp_forwarding) @@ -141,7 +223,7 @@ do_authenticated(Authctxt *authctxt) do_authenticated1(authctxt); /* remove agent socket */ - if (auth_get_socket_name()) + if (auth_sock_name != NULL) auth_sock_cleanup_proc(authctxt->pw); #ifdef KRB4 if (options.kerberos_ticket_cleanup) @@ -165,8 +247,8 @@ do_authenticated1(Authctxt *authctxt) Session *s; char *command; int success, type, screen_flag; - int compression_level = 0, enable_compression_after_reply = 0; - u_int proto_len, data_len, dlen; + int enable_compression_after_reply = 0; + u_int proto_len, data_len, dlen, compression_level = 0; s = session_new(); s->authctxt = authctxt; @@ -192,6 +274,10 @@ do_authenticated1(Authctxt *authctxt) compression_level); break; } + if (!options.compression) { + debug2("compression disabled"); + break; + } /* Enable compression after we have responded with SUCCESS. */ enable_compression_after_reply = 1; success = 1; @@ -326,7 +412,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(); @@ -348,7 +434,7 @@ do_authenticated1(Authctxt *authctxt) void do_exec_no_pty(Session *s, const char *command) { - int pid; + pid_t pid; #ifdef USE_PIPES int pin[2], pout[2], perr[2]; @@ -379,6 +465,8 @@ do_exec_no_pty(Session *s, const char *command) /* Fork the child. */ if ((pid = fork()) == 0) { + fatal_remove_all_cleanups(); + /* Child. Reinitialize the log since the pid has changed. */ log_init(__progname, options.log_level, options.log_facility, log_stderr); @@ -426,10 +514,17 @@ do_exec_no_pty(Session *s, const char *command) perror("dup2 stderr"); #endif /* USE_PIPES */ +#ifdef _UNICOS + cray_init_job(s->pw); /* set up cray jid and tmpdir */ +#endif + /* Do processing for the child (exec command etc). */ do_child(s, command); /* NOTREACHED */ } +#ifdef _UNICOS + signal(WJSIGNAL, cray_job_termination_handler); +#endif /* _UNICOS */ #ifdef HAVE_CYGWIN if (is_winnt) cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); @@ -494,6 +589,7 @@ do_exec_pty(Session *s, const char *command) /* Fork the child. */ if ((pid = fork()) == 0) { + fatal_remove_all_cleanups(); /* Child. Reinitialize the log because the pid has changed. */ log_init(__progname, options.log_level, options.log_facility, log_stderr); @@ -516,8 +612,12 @@ do_exec_pty(Session *s, const char *command) /* record login, etc. similar to login(1) */ #ifndef HAVE_OSF_SIA - if (!(options.use_login && command == NULL)) + if (!(options.use_login && command == NULL)) { +#ifdef _UNICOS + cray_init_job(s->pw); /* set up cray jid and tmpdir */ +#endif /* _UNICOS */ do_login(s, command); + } # ifdef LOGIN_NEEDS_UTMPX else do_pre_login(s); @@ -528,6 +628,9 @@ do_exec_pty(Session *s, const char *command) do_child(s, command); /* NOTREACHED */ } +#ifdef _UNICOS + signal(WJSIGNAL, cray_job_termination_handler); +#endif /* _UNICOS */ #ifdef HAVE_CYGWIN if (is_winnt) cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); @@ -577,8 +680,8 @@ do_pre_login(Session *s) * the address be 0.0.0.0. */ memset(&from, 0, sizeof(from)); + fromlen = sizeof(from); if (packet_connection_is_on_socket()) { - fromlen = sizeof(from); if (getpeername(packet_get_connection_in(), (struct sockaddr *) & from, &fromlen) < 0) { debug("getpeername: %.100s", strerror(errno)); @@ -588,7 +691,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), - (struct sockaddr *)&from); + (struct sockaddr *)&from, fromlen); } #endif @@ -629,8 +732,8 @@ do_login(Session *s, const char *command) * the address be 0.0.0.0. */ memset(&from, 0, sizeof(from)); + fromlen = sizeof(from); if (packet_connection_is_on_socket()) { - fromlen = sizeof(from); if (getpeername(packet_get_connection_in(), (struct sockaddr *) & from, &fromlen) < 0) { debug("getpeername: %.100s", strerror(errno)); @@ -643,7 +746,7 @@ do_login(Session *s, const char *command) record_login(pid, s->tty, pw->pw_name, pw->pw_uid, get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), - (struct sockaddr *)&from); + (struct sockaddr *)&from, fromlen); #ifdef USE_PAM /* @@ -668,6 +771,7 @@ do_login(Session *s, const char *command) printf("%s\n", aixloginmsg); #endif /* WITH_AIXAUTHENTICATE */ +#ifndef NO_SSH_LASTLOG if (options.print_lastlog && s->last_login_time != 0) { time_string = ctime(&s->last_login_time); if (strchr(time_string, '\n')) @@ -678,6 +782,7 @@ do_login(Session *s, const char *command) printf("Last login: %s from %s\r\n", time_string, s->hostname); } +#endif /* NO_SSH_LASTLOG */ do_motd(); } @@ -758,6 +863,9 @@ child_set_env(char ***envp, u_int *envsizep, const char *name, } 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 *)); } @@ -783,12 +891,15 @@ read_environment_file(char ***env, u_int *envsize, FILE *f; char buf[4096]; char *cp, *value; + u_int lineno = 0; f = fopen(filename, "r"); if (!f) return; while (fgets(buf, sizeof(buf), f)) { + if (++lineno > 1000) + fatal("Too many lines in environment file %s", filename); for (cp = buf; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '#' || *cp == '\n') @@ -797,7 +908,8 @@ read_environment_file(char ***env, u_int *envsize, *strchr(cp, '\n') = '\0'; value = strchr(cp, '='); if (value == NULL) { - fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf); + fprintf(stderr, "Bad line %u in %.100s\n", lineno, + filename); continue; } /* @@ -839,7 +951,7 @@ do_setup_env(Session *s, const char *shell) { char buf[256]; u_int i, envsize; - char **env; + char **env, *laddr; struct passwd *pw = s->pw; /* Initialize the environment. */ @@ -859,10 +971,15 @@ do_setup_env(Session *s, const char *shell) /* Set basic environment. */ child_set_env(&env, &envsize, "USER", pw->pw_name); child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); +#ifdef _AIX + child_set_env(&env, &envsize, "LOGIN", pw->pw_name); +#endif child_set_env(&env, &envsize, "HOME", pw->pw_dir); #ifdef HAVE_LOGIN_CAP - (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH); - child_set_env(&env, &envsize, "PATH", getenv("PATH")); + if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0) + child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); + else + child_set_env(&env, &envsize, "PATH", getenv("PATH")); #else /* HAVE_LOGIN_CAP */ # ifndef HAVE_CYGWIN /* @@ -894,13 +1011,13 @@ do_setup_env(Session *s, const char *shell) if (!options.use_login) { while (custom_environment) { struct envstring *ce = custom_environment; - char *s = ce->s; + char *str = ce->s; - for (i = 0; s[i] != '=' && s[i]; i++) + for (i = 0; str[i] != '=' && str[i]; i++) ; - if (s[i] == '=') { - s[i] = 0; - child_set_env(&env, &envsize, s, s + i + 1); + if (str[i] == '=') { + str[i] = 0; + child_set_env(&env, &envsize, str, str + i + 1); } custom_environment = ce->next; xfree(ce->s); @@ -908,10 +1025,17 @@ do_setup_env(Session *s, const char *shell) } } + /* SSH_CLIENT deprecated */ snprintf(buf, sizeof buf, "%.50s %d %d", get_remote_ipaddr(), get_remote_port(), get_local_port()); child_set_env(&env, &envsize, "SSH_CLIENT", buf); + laddr = get_local_ipaddr(packet_get_connection_in()); + snprintf(buf, sizeof buf, "%.50s %d %.50s %d", + get_remote_ipaddr(), get_remote_port(), laddr, get_local_port()); + xfree(laddr); + child_set_env(&env, &envsize, "SSH_CONNECTION", buf); + if (s->ttyfd != -1) child_set_env(&env, &envsize, "SSH_TTY", s->tty); if (s->term) @@ -922,6 +1046,11 @@ do_setup_env(Session *s, const char *shell) child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", original_command); +#ifdef _UNICOS + if (cray_tmpdir[0] != '\0') + child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir); +#endif /* _UNICOS */ + #ifdef _AIX { char *cp; @@ -944,18 +1073,27 @@ do_setup_env(Session *s, const char *shell) s->authctxt->krb5_ticket_file); #endif #ifdef USE_PAM - /* Pull in any environment variables that may have been set by PAM. */ - copy_environment(fetch_pam_environment(), &env, &envsize); + /* + * Pull in any environment variables that may have + * been set by PAM. + */ + { + char **p; + + p = fetch_pam_environment(); + copy_environment(p, &env, &envsize); + free_pam_environment(p); + } #endif /* USE_PAM */ - if (auth_get_socket_name() != NULL) + if (auth_sock_name != NULL) child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, - auth_get_socket_name()); + auth_sock_name); /* read $HOME/.ssh/environment. */ - if (!options.use_login) { + if (options.permit_user_env && !options.use_login) { snprintf(buf, sizeof buf, "%.200s/.ssh/environment", - pw->pw_dir); + strcmp(pw->pw_dir, "/") ? pw->pw_dir : ""); read_environment_file(&env, &envsize, buf); } if (debug_flag) { @@ -1014,8 +1152,10 @@ do_rc_files(Session *s, const char *shell) /* Add authority data to .Xauthority if appropriate. */ if (debug_flag) { fprintf(stderr, - "Running %.500s add " - "%.100s %.100s %.100s\n", + "Running %.500s remove %.100s\n", + options.xauth_location, s->auth_display); + fprintf(stderr, + "%.500s add %.100s %.100s %.100s\n", options.xauth_location, s->auth_display, s->auth_proto, s->auth_data); } @@ -1023,6 +1163,8 @@ do_rc_files(Session *s, const char *shell) options.xauth_location); f = popen(cmd, "w"); if (f) { + fprintf(f, "remove %s\n", + s->auth_display); fprintf(f, "add %s %s %s\n", s->auth_display, s->auth_proto, s->auth_data); @@ -1050,9 +1192,12 @@ do_nologin(struct passwd *pw) #endif if (f) { /* /etc/nologin exists. Print its contents and exit. */ + logit("User %.100s not allowed because %s exists", + pw->pw_name, _PATH_NOLOGIN); while (fgets(buf, sizeof(buf), f)) fputs(buf, stderr); fclose(f); + fflush(NULL); exit(254); } } @@ -1061,15 +1206,18 @@ do_nologin(struct passwd *pw) void do_setusercontext(struct passwd *pw) { -#ifdef HAVE_CYGWIN - if (is_winnt) { -#else /* HAVE_CYGWIN */ - if (getuid() == 0 || geteuid() == 0) { +#ifndef HAVE_CYGWIN + if (getuid() == 0 || geteuid() == 0) #endif /* HAVE_CYGWIN */ -#ifdef HAVE_GETUSERATTR - set_limits_from_userattr(pw->pw_name); -#endif /* HAVE_GETUSERATTR */ + { + +#ifdef HAVE_SETPCRED + setpcred(pw->pw_name); +#endif /* HAVE_SETPCRED */ #ifdef HAVE_LOGIN_CAP +# ifdef __bsdi__ + setpgid(0, 0); +# endif if (setusercontext(lc, pw, pw->pw_uid, (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { perror("unable to set user context"); @@ -1105,10 +1253,17 @@ do_setusercontext(struct passwd *pw) # if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) irix_setusercontext(pw); # endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ +# ifdef _AIX + aix_usrinfo(pw); +# endif /* _AIX */ /* Permanently switch to the desired uid. */ permanently_set_uid(pw); #endif } + +#ifdef HAVE_CYGWIN + if (is_winnt) +#endif if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); } @@ -1120,7 +1275,7 @@ launch_login(struct passwd *pw, const char *hostname) execl(LOGIN_PROGRAM, "login", "-h", hostname, #ifdef xxxLOGIN_NEEDS_TERM - (s->term ? s->term : "unknown"), + (s->term ? s->term : "unknown"), #endif /* LOGIN_NEEDS_TERM */ #ifdef LOGIN_NO_ENDOPT "-p", "-f", pw->pw_name, (char *)NULL); @@ -1156,20 +1311,21 @@ do_child(Session *s, const char *command) if (options.use_login && command != NULL) options.use_login = 0; +#ifdef _UNICOS + cray_setup(pw->pw_uid, pw->pw_name, command); +#endif /* _UNICOS */ + /* * Login(1) does this as well, and it needs uid 0 for the "-h" * switch, so we let login(1) to this for us. */ if (!options.use_login) { #ifdef HAVE_OSF_SIA - session_setup_sia(pw->pw_name, s->ttyfd == -1 ? NULL : s->tty); + session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty); if (!check_quietlogin(s, command)) do_motd(); #else /* HAVE_OSF_SIA */ do_nologin(pw); -# ifdef _AIX - aix_usrinfo(pw, s->tty, s->ttyfd); -# endif /* _AIX */ do_setusercontext(pw); #endif /* HAVE_OSF_SIA */ } @@ -1179,12 +1335,17 @@ do_child(Session *s, const char *command) * legal, and means /bin/sh. */ shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; + + /* + * Make sure $SHELL points to the shell from the password file, + * even if shell is overridden from login.conf + */ + env = do_setup_env(s, shell); + #ifdef HAVE_LOGIN_CAP shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); #endif - env = do_setup_env(s, shell); - /* we have to stash the hostname before we close our socket. */ if (options.use_login) hostname = get_remote_name_or_ip(utmp_len, @@ -1343,12 +1504,12 @@ session_dump(void) int i; for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; - debug("dump: used %d session %d %p channel %d pid %d", + debug("dump: used %d session %d %p channel %d pid %ld", s->used, s->self, s, s->chanid, - s->pid); + (long)s->pid); } } @@ -1406,13 +1567,13 @@ static Session * session_by_pid(pid_t pid) { int i; - debug("session_by_pid: pid %d", pid); + debug("session_by_pid: pid %ld", (long)pid); for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used && s->pid == pid) return s; } - error("session_by_pid: unknown pid %d", pid); + error("session_by_pid: unknown pid %ld", (long)pid); session_dump(); return NULL; } @@ -1511,7 +1672,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) { @@ -1530,7 +1691,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); @@ -1601,7 +1762,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; } @@ -1694,6 +1855,27 @@ session_pty_cleanup(void *session) PRIVSEP(session_pty_cleanup2(session)); } +static char * +sig2name(int sig) +{ +#define SSH_SIG(x) if (sig == SIG ## x) return #x + SSH_SIG(ABRT); + SSH_SIG(ALRM); + SSH_SIG(FPE); + SSH_SIG(HUP); + SSH_SIG(ILL); + SSH_SIG(INT); + SSH_SIG(KILL); + SSH_SIG(PIPE); + SSH_SIG(QUIT); + SSH_SIG(SEGV); + SSH_SIG(TERM); + SSH_SIG(USR1); + SSH_SIG(USR2); +#undef SSH_SIG + return "SIG@openssh.com"; +} + static void session_exit_message(Session *s, int status) { @@ -1702,8 +1884,8 @@ session_exit_message(Session *s, int status) if ((c = channel_lookup(s->chanid)) == NULL) fatal("session_exit_message: session %d: no channel %d", s->self, s->chanid); - debug("session_exit_message: session %d channel %d pid %d", - s->self, s->chanid, s->pid); + debug("session_exit_message: session %d channel %d pid %ld", + s->self, s->chanid, (long)s->pid); if (WIFEXITED(status)) { channel_request_start(s->chanid, "exit-status", 0); @@ -1711,7 +1893,7 @@ session_exit_message(Session *s, int status) packet_send(); } else if (WIFSIGNALED(status)) { channel_request_start(s->chanid, "exit-signal", 0); - packet_put_int(WTERMSIG(status)); + packet_put_cstring(sig2name(WTERMSIG(status))); #ifdef WCOREDUMP packet_put_char(WCOREDUMP(status)); #else /* WCOREDUMP */ @@ -1742,7 +1924,7 @@ session_exit_message(Session *s, int status) void session_close(Session *s) { - debug("session_close: session %d pid %d", s->self, s->pid); + debug("session_close: session %d pid %ld", s->self, (long)s->pid); if (s->ttyfd != -1) { fatal_remove_cleanup(session_pty_cleanup, (void *)s); session_pty_cleanup(s); @@ -1766,7 +1948,8 @@ session_close_by_pid(pid_t pid, int status) { Session *s = session_by_pid(pid); if (s == NULL) { - debug("session_close_by_pid: no session for pid %d", pid); + debug("session_close_by_pid: no session for pid %ld", + (long)pid); return; } if (s->chanid != -1) @@ -1786,7 +1969,8 @@ session_close_by_channel(int id, void *arg) debug("session_close_by_channel: no session for id %d", id); return; } - debug("session_close_by_channel: channel %d child %d", id, s->pid); + debug("session_close_by_channel: channel %d child %ld", + id, (long)s->pid); if (s->pid != 0) { debug("session_close_by_channel: channel %d: has child", id); /* @@ -1825,13 +2009,22 @@ session_tty_list(void) { static char buf[1024]; int i; + char *cp; + buf[0] = '\0'; 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, strrchr(s->tty, '/') + 1, sizeof buf); + strlcat(buf, cp, sizeof buf); } } if (buf[0] == '\0') @@ -1877,9 +2070,9 @@ session_setup_x11fwd(Session *s) debug("X11 display already set."); return 0; } - s->display_number = x11_create_display_inet(options.x11_display_offset, - options.x11_use_localhost, s->single_connection); - if (s->display_number == -1) { + if (x11_create_display_inet(options.x11_display_offset, + options.x11_use_localhost, s->single_connection, + &s->display_number) == -1) { debug("x11_create_display_inet failed."); return 0; } @@ -1893,9 +2086,9 @@ session_setup_x11fwd(Session *s) * different than the DISPLAY string for localhost displays. */ if (options.x11_use_localhost) { - snprintf(display, sizeof display, "localhost:%d.%d", + snprintf(display, sizeof display, "localhost:%u.%u", s->display_number, s->screen); - snprintf(auth_display, sizeof auth_display, "unix:%d.%d", + snprintf(auth_display, sizeof auth_display, "unix:%u.%u", s->display_number, s->screen); s->display = xstrdup(display); s->auth_display = xstrdup(auth_display); @@ -1911,10 +2104,10 @@ session_setup_x11fwd(Session *s) 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), + snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr), s->display_number, s->screen); #else - snprintf(display, sizeof display, "%.400s:%d.%d", hostname, + snprintf(display, sizeof display, "%.400s:%u.%u", hostname, s->display_number, s->screen); #endif s->display = xstrdup(display);