X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/a306f2dd74b7488671decc385f82830c98f4a0d3..38c295d646559d5e684af97dbdfe3378871a9081:/session.c diff --git a/session.c b/session.c index d5c53f11..64e240b7 100644 --- a/session.c +++ b/session.c @@ -8,7 +8,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.6 2000/04/27 15:23:02 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.20 2000/06/18 04:42:54 markus Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -26,6 +26,7 @@ RCSID("$OpenBSD: session.c,v 1.6 2000/04/27 15:23:02 markus Exp $"); #include "bufaux.h" #include "ssh2.h" #include "auth.h" +#include "auth-options.h" /* types */ @@ -34,6 +35,7 @@ typedef struct Session Session; struct Session { int used; int self; + int extended; struct passwd *pw; pid_t pid; /* tty */ @@ -46,6 +48,7 @@ struct Session { int screen; char *auth_proto; char *auth_data; + int single_connection; /* proto 2 */ int chanid; }; @@ -55,6 +58,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); @@ -68,7 +72,7 @@ extern ServerOptions options; #ifdef HAVE___PROGNAME extern char *__progname; #else /* HAVE___PROGNAME */ -const char *__progname = "sshd"; +static const char *__progname = "sshd"; #endif /* HAVE___PROGNAME */ extern int log_stderr; @@ -80,18 +84,10 @@ static char *xauthfile; /* data */ #define MAX_SESSIONS 10 Session sessions[MAX_SESSIONS]; - -/* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */ -int no_port_forwarding_flag = 0; -int no_agent_forwarding_flag = 0; -int no_x11_forwarding_flag = 0; -int no_pty_flag = 0; - -/* RSA authentication "command=" option. */ -char *forced_command = NULL; - -/* RSA authentication "environment=" options. */ -struct envstring *custom_environment = NULL; +#ifdef WITH_AIXAUTHENTICATE +/* AIX's lastlogin message, set in auth1.c */ +char *aixloginmsg; +#endif /* WITH_AIXAUTHENTICATE */ /* * Remove local Xauthority file. @@ -170,6 +166,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 @@ -237,6 +234,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; @@ -247,7 +246,10 @@ do_authenticated(struct passwd * pw) packet_send_debug("X11 forwarding disabled in server configuration file."); break; } -#ifdef XAUTH_PATH + if (!options.xauth_location) { + packet_send_debug("No xauth program; cannot forward with spoofing."); + break; + } if (no_x11_forwarding_flag) { packet_send_debug("X11 forwarding not permitted for this authentication."); break; @@ -279,6 +281,7 @@ do_authenticated(struct passwd * pw) xauthfile, strerror(errno)); xfree(xauthfile); xauthfile = NULL; + /* XXXX remove listening channels */ break; } strlcat(xauthfile, "/cookies", MAXPATHLEN); @@ -287,10 +290,6 @@ do_authenticated(struct passwd * pw) fatal_add_cleanup(xauthfile_cleanup_proc, NULL); success = 1; break; -#else /* XAUTH_PATH */ - packet_send_debug("No xauth program; cannot forward with spoofing."); - break; -#endif /* XAUTH_PATH */ case SSH_CMSG_AGENT_REQUEST_FORWARDING: if (no_agent_forwarding_flag || compat13) { @@ -298,8 +297,7 @@ do_authenticated(struct passwd * pw) break; } debug("Received authentication agent forwarding request."); - auth_input_request_forwarding(pw); - success = 1; + success = auth_input_request_forwarding(pw); break; case SSH_CMSG_PORT_FORWARD_REQUEST: @@ -308,7 +306,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; @@ -393,7 +391,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(); @@ -462,7 +460,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]); @@ -478,7 +476,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]. */ @@ -523,7 +521,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); @@ -559,7 +556,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 @@ -625,8 +622,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) @@ -730,7 +737,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); @@ -782,6 +792,7 @@ do_child(const char *command, struct passwd * pw, const char *term, { const char *shell, *cp = NULL; char buf[256]; + char cmd[1024]; FILE *f; unsigned int envsize, i; char **env; @@ -789,6 +800,10 @@ do_child(const char *command, struct passwd * pw, const char *term, struct stat st; char *argv[10]; + /* login(1) is only called if we execute the login shell */ + if (options.use_login && command != NULL) + options.use_login = 0; + #ifndef USE_PAM /* pam_nologin handles this */ f = fopen("/etc/nologin", "r"); if (f) { @@ -929,7 +944,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,25 +1027,38 @@ do_child(const char *command, struct passwd * pw, const char *term, pclose(f); } else fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC); - } -#ifdef XAUTH_PATH - else { + } else if (options.xauth_location != NULL) { /* 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); - - f = popen(XAUTH_PATH " -q -", "w"); + char *screen = strchr(display, ':'); + if (debug_flag) { + fprintf(stderr, + "Running %.100s add %.100s %.100s %.100s\n", + options.xauth_location, 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); + } + snprintf(cmd, sizeof cmd, "%s -q -", + options.xauth_location); + f = popen(cmd, "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); + } else { + fprintf(stderr, "Could not run %s\n", + cmd); + } } } -#endif /* XAUTH_PATH */ - /* Get the last component of the shell name. */ cp = strrchr(shell, '/'); if (cp) @@ -1055,7 +1084,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"); @@ -1119,6 +1149,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; @@ -1129,6 +1160,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; } @@ -1160,12 +1192,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; } @@ -1218,6 +1249,8 @@ session_pty_req(Session *s) unsigned int len; char *term_modes; /* encoded terminal modes */ + if (no_pty_flag) + return 0; if (s->ttyfd != -1) return 0; s->term = packet_get_string(&len); @@ -1252,11 +1285,127 @@ 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); + int i; + + packet_done(); + log("subsystem request for %s", subsys); + + for (i = 0; i < options.num_subsystems; i++) { + if(strcmp(subsys, options.subsystem_name[i]) == 0) { + debug("subsystem: exec() %s", options.subsystem_command[i]); + do_exec_no_pty(s, options.subsystem_command[i], s->pw); + success = 1; + } + } + + if (!success) + log("subsystem request for %s failed, subsystem not found", subsys); + + xfree(subsys); + return success; +} + +int +session_x11_req(Session *s) +{ + if (!no_port_forwarding_flag) { + debug("X11 forwarding disabled in user configuration file."); + return 0; + } + 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; +} + +int +session_shell_req(Session *s) +{ + /* if forced_command == NULL, the shell is execed */ + char *shell = forced_command; + packet_done(); + s->extended = 1; + if (s->ttyfd == -1) + do_exec_no_pty(s, shell, s->pw); + else + do_exec_pty(s, shell, s->pw); + return 1; +} + +int +session_exec_req(Session *s) +{ + unsigned int len; + char *command = packet_get_string(&len); + packet_done(); + if (forced_command) { + xfree(command); + command = forced_command; + debug("Forced command '%.500s'", forced_command); + } + s->extended = 1; + if (s->ttyfd == -1) + do_exec_no_pty(s, command, s->pw); + else + do_exec_pty(s, command, s->pw); + if (forced_command == NULL) + xfree(command); + return 1; +} + void session_input_channel_req(int id, void *arg) { @@ -1286,22 +1435,15 @@ session_input_channel_req(int id, void *arg) */ if (c->type == SSH_CHANNEL_LARVAL) { if (strcmp(rtype, "shell") == 0) { - if (s->ttyfd == -1) - do_exec_no_pty(s, NULL, s->pw); - else - do_exec_pty(s, NULL, s->pw); - success = 1; + success = session_shell_req(s); } else if (strcmp(rtype, "exec") == 0) { - char *command = packet_get_string(&len); - packet_done(); - if (s->ttyfd == -1) - do_exec_no_pty(s, command, s->pw); - else - do_exec_pty(s, command, s->pw); - xfree(command); - success = 1; + success = session_exec_req(s); } 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) { @@ -1381,7 +1523,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(); @@ -1399,7 +1545,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; } @@ -1423,6 +1570,7 @@ session_close(Session *s) { session_pty_cleanup(s); session_free(s); + session_proctitle(s); } void @@ -1466,6 +1614,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) { @@ -1475,4 +1651,6 @@ do_authenticated2(void) */ alarm(0); server_loop2(); + if (xauthfile) + xauthfile_cleanup_proc(NULL); }