X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/9da5c3c9b3ebe5ae740c25ca6cabe3b8f80d806e..71276795b0a68665fc7aa5e20a3b4433a4cd9d39:/session.c diff --git a/session.c b/session.c index 840a4e9e..4791857c 100644 --- a/session.c +++ b/session.c @@ -8,7 +8,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.5 2000/04/19 09:24:39 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.14 2000/05/25 03:10:18 deraadt Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -34,6 +34,7 @@ typedef struct Session Session; struct Session { int used; int self; + int extended; struct passwd *pw; pid_t pid; /* tty */ @@ -46,6 +47,7 @@ struct Session { int screen; char *auth_proto; char *auth_data; + int single_connection; /* proto 2 */ int chanid; }; @@ -55,6 +57,7 @@ struct Session { Session *session_new(void); void session_set_fds(Session *s, int fdin, int fdout, int fderr); void session_pty_cleanup(Session *s); +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); @@ -65,7 +68,12 @@ do_child(const char *command, struct passwd * pw, const char *term, /* import */ extern ServerOptions options; +#ifdef HAVE___PROGNAME extern char *__progname; +#else /* HAVE___PROGNAME */ +static const char *__progname = "sshd"; +#endif /* HAVE___PROGNAME */ + extern int log_stderr; extern int debug_flag; @@ -75,6 +83,10 @@ static char *xauthfile; /* data */ #define MAX_SESSIONS 10 Session sessions[MAX_SESSIONS]; +#ifdef WITH_AIXAUTHENTICATE +/* AIX's lastlogin message, set in auth1.c */ +char *aixloginmsg; +#endif /* WITH_AIXAUTHENTICATE */ /* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */ int no_port_forwarding_flag = 0; @@ -165,6 +177,7 @@ do_authenticated(struct passwd * pw) channel_permit_all_opens(); s = session_new(); + s->pw = pw; /* * We stay in this loop until the client requests to execute a shell @@ -232,6 +245,8 @@ do_authenticated(struct passwd * pw) tty_parse_modes(s->ttyfd, &n_bytes); packet_integrity_check(plen, 4 + dlen + 4 * 4 + n_bytes, type); + session_proctitle(s); + /* Indicate that we now have a pty. */ success = 1; have_pty = 1; @@ -274,6 +289,7 @@ do_authenticated(struct passwd * pw) xauthfile, strerror(errno)); xfree(xauthfile); xauthfile = NULL; + /* XXXX remove listening channels */ break; } strlcat(xauthfile, "/cookies", MAXPATHLEN); @@ -303,7 +319,7 @@ do_authenticated(struct passwd * pw) break; } debug("Received TCP/IP port forwarding request."); - channel_input_port_forward_request(pw->pw_uid == 0); + channel_input_port_forward_request(pw->pw_uid == 0, options.gateway_ports); success = 1; break; @@ -388,7 +404,7 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) if (s == NULL) fatal("do_exec_no_pty: no session"); - setproctitle("%s@notty", pw->pw_name); + session_proctitle(s); #ifdef USE_PAM do_pam_setcred(); @@ -457,7 +473,7 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) close(perr[1]); if (compat20) { - session_set_fds(s, pin[1], pout[0], perr[0]); + session_set_fds(s, pin[1], pout[0], s->extended ? perr[0] : -1); } else { /* Enter the interactive session. */ server_loop(pid, pin[1], pout[0], perr[0]); @@ -473,7 +489,7 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) * handle the case that fdin and fdout are the same. */ if (compat20) { - session_set_fds(s, inout[1], inout[1], err[1]); + session_set_fds(s, inout[1], inout[1], s->extended ? err[1] : -1); } else { server_loop(pid, inout[1], inout[1], err[1]); /* server_loop has closed inout[1] and err[1]. */ @@ -518,7 +534,6 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, buf, sizeof(buf)); } - setproctitle("%s@%s", pw->pw_name, strrchr(s->tty, '/') + 1); #ifdef USE_PAM do_pam_session(pw->pw_name, s->tty); @@ -554,7 +569,7 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) /* Close the extra descriptor for the pseudo tty. */ close(ttyfd); -///XXXX ? move to do_child() ?? +/* XXXX ? move to do_child() ??*/ /* * Get IP address of client. This is needed because we want * to record where the user logged in from. If the @@ -620,8 +635,18 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) fclose(f); } } +#if defined(WITH_AIXAUTHENTICATE) + /* + * AIX handles the lastlog info differently. Display it here. + */ + if (command == NULL && aixloginmsg && *aixloginmsg && + !quiet_login && !options.use_login) { + printf("%s\n", aixloginmsg); + } +#endif /* Do common processing for the child, such as execing the command. */ - do_child(command, pw, s->term, s->display, s->auth_proto, s->auth_data, s->tty); + do_child(command, pw, s->term, s->display, s->auth_proto, + s->auth_data, s->tty); /* NOTREACHED */ } if (pid < 0) @@ -725,7 +750,10 @@ read_environment_file(char ***env, unsigned int *envsize, fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf); continue; } - /* Replace the equals sign by nul, and advance value to the value string. */ + /* + * Replace the equals sign by nul, and advance value to + * the value string. + */ *value = '\0'; value++; child_set_env(env, envsize, cp, value); @@ -924,7 +952,8 @@ do_child(const char *command, struct passwd * pw, const char *term, /* read $HOME/.ssh/environment. */ if (!options.use_login) { - snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir); + snprintf(buf, sizeof buf, "%.200s/.ssh/environment", + pw->pw_dir); read_environment_file(&env, &envsize, buf); } if (debug_flag) { @@ -1011,16 +1040,29 @@ do_child(const char *command, struct passwd * pw, const char *term, else { /* Add authority data to .Xauthority if appropriate. */ if (auth_proto != NULL && auth_data != NULL) { - if (debug_flag) - fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n", - XAUTH_PATH, display, auth_proto, auth_data); - + char *screen = strchr(display, ':'); + if (debug_flag) { + fprintf(stderr, + "Running %.100s add %.100s %.100s %.100s\n", + XAUTH_PATH, display, auth_proto, auth_data); + if (screen != NULL) + fprintf(stderr, + "Adding %.*s/unix%s %s %s\n", + screen-display, display, + screen, auth_proto, auth_data); + } f = popen(XAUTH_PATH " -q -", "w"); if (f) { - fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data); + fprintf(f, "add %s %s %s\n", display, + auth_proto, auth_data); + if (screen != NULL) + fprintf(f, "add %.*s/unix%s %s %s\n", + screen-display, display, + screen, auth_proto, auth_data); pclose(f); } else - fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH); + fprintf(stderr, "Could not run %s -q -\n", + XAUTH_PATH); } } #endif /* XAUTH_PATH */ @@ -1050,7 +1092,8 @@ do_child(const char *command, struct passwd * pw, const char *term, struct stat mailstat; mailbox = getenv("MAIL"); if (mailbox != NULL) { - if (stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0) + if (stat(mailbox, &mailstat) != 0 || + mailstat.st_size == 0) printf("No mail.\n"); else if (mailstat.st_mtime < mailstat.st_atime) printf("You have mail.\n"); @@ -1114,6 +1157,7 @@ session_new(void) Session *s = &sessions[i]; if (! s->used) { s->pid = 0; + s->extended = 0; s->chanid = -1; s->ptyfd = -1; s->ttyfd = -1; @@ -1124,6 +1168,7 @@ session_new(void) s->auth_data = NULL; s->auth_proto = NULL; s->used = 1; + s->pw = NULL; debug("session_new: session %d", i); return s; } @@ -1155,12 +1200,11 @@ session_open(int chanid) error("no more sessions"); return 0; } - debug("session_open: session %d: link with channel %d", s->self, chanid); - s->chanid = chanid; s->pw = auth_get_user(); if (s->pw == NULL) - fatal("no user for session %i channel %d", - s->self, s->chanid); + fatal("no user for session %i", s->self); + debug("session_open: session %d: link with channel %d", s->self, chanid); + s->chanid = chanid; return 1; } @@ -1247,11 +1291,76 @@ session_pty_req(Session *s) /* Get window size from the packet. */ pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); + session_proctitle(s); + /* XXX parse and set terminal modes */ xfree(term_modes); return 1; } +int +session_subsystem_req(Session *s) +{ + unsigned int len; + int success = 0; + char *subsys = packet_get_string(&len); + + packet_done(); + log("subsystem request for %s", subsys); + + xfree(subsys); + return success; +} + +int +session_x11_req(Session *s) +{ + if (!options.x11_forwarding) { + debug("X11 forwarding disabled in server configuration file."); + return 0; + } + if (xauthfile != NULL) { + debug("X11 fwd already started."); + return 0; + } + + debug("Received request for X11 forwarding with auth spoofing."); + if (s->display != NULL) + packet_disconnect("Protocol error: X11 display already set."); + + s->single_connection = packet_get_char(); + s->auth_proto = packet_get_string(NULL); + s->auth_data = packet_get_string(NULL); + s->screen = packet_get_int(); + packet_done(); + + s->display = x11_create_display_inet(s->screen, options.x11_display_offset); + if (s->display == NULL) { + xfree(s->auth_proto); + xfree(s->auth_data); + return 0; + } + xauthfile = xmalloc(MAXPATHLEN); + strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN); + temporarily_use_uid(s->pw->pw_uid); + if (mkdtemp(xauthfile) == NULL) { + restore_uid(); + error("private X11 dir: mkdtemp %s failed: %s", + xauthfile, strerror(errno)); + xfree(xauthfile); + xauthfile = NULL; + xfree(s->auth_proto); + xfree(s->auth_data); + /* XXXX remove listening channels */ + return 0; + } + strlcat(xauthfile, "/cookies", MAXPATHLEN); + open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); + restore_uid(); + fatal_add_cleanup(xauthfile_cleanup_proc, s); + return 1; +} + void session_input_channel_req(int id, void *arg) { @@ -1281,6 +1390,8 @@ session_input_channel_req(int id, void *arg) */ if (c->type == SSH_CHANNEL_LARVAL) { if (strcmp(rtype, "shell") == 0) { + packet_done(); + s->extended = 1; if (s->ttyfd == -1) do_exec_no_pty(s, NULL, s->pw); else @@ -1289,6 +1400,7 @@ session_input_channel_req(int id, void *arg) } else if (strcmp(rtype, "exec") == 0) { char *command = packet_get_string(&len); packet_done(); + s->extended = 1; if (s->ttyfd == -1) do_exec_no_pty(s, command, s->pw); else @@ -1297,6 +1409,10 @@ session_input_channel_req(int id, void *arg) success = 1; } else if (strcmp(rtype, "pty-req") == 0) { success = session_pty_req(s); + } else if (strcmp(rtype, "x11-req") == 0) { + success = session_x11_req(s); + } else if (strcmp(rtype, "subsystem") == 0) { + success = session_subsystem_req(s); } } if (strcmp(rtype, "window-change") == 0) { @@ -1376,7 +1492,11 @@ session_exit_message(Session *s, int status) channel_request_start(s->chanid, "exit-signal", 0); packet_put_int(WTERMSIG(status)); +#ifdef WCOREDUMP packet_put_char(WCOREDUMP(status)); +#else /* WCOREDUMP */ + packet_put_char(0); +#endif /* WCOREDUMP */ packet_put_cstring(""); packet_put_cstring(""); packet_send(); @@ -1394,7 +1514,8 @@ session_exit_message(Session *s, int status) * Note that we must not call 'chan_read_failed', since there could * be some more data waiting in the pipe. */ - chan_write_failed(c); + if (c->ostate != CHAN_OUTPUT_CLOSED) + chan_write_failed(c); s->chanid = -1; } @@ -1418,6 +1539,7 @@ session_close(Session *s) { session_pty_cleanup(s); session_free(s); + session_proctitle(s); } void @@ -1461,6 +1583,34 @@ session_close_by_channel(int id, void *arg) } } +char * +session_tty_list(void) +{ + static char buf[1024]; + int i; + buf[0] = '\0'; + for(i = 0; i < MAX_SESSIONS; i++) { + Session *s = &sessions[i]; + if (s->used && s->ttyfd != -1) { + if (buf[0] != '\0') + strlcat(buf, ",", sizeof buf); + strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf); + } + } + if (buf[0] == '\0') + strlcpy(buf, "notty", sizeof buf); + return buf; +} + +void +session_proctitle(Session *s) +{ + if (s->pw == NULL) + error("no user for session %d", s->self); + else + setproctitle("%s@%s", s->pw->pw_name, session_tty_list()); +} + void do_authenticated2(void) { @@ -1469,6 +1619,7 @@ do_authenticated2(void) * authentication. */ alarm(0); - log("do_authenticated2"); server_loop2(); + if (xauthfile) + xauthfile_cleanup_proc(NULL); }