X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/d343d900d99497266aa41c838d8a7ad050b43392..3b1a83dffbbf9a551e854922844daa2089e670c5:/session.c diff --git a/session.c b/session.c index 826307ef..2fa0700f 100644 --- a/session.c +++ b/session.c @@ -33,31 +33,37 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.44 2000/11/14 23:44:19 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.57 2001/02/23 15:37:45 markus Exp $"); -#include "xmalloc.h" #include "ssh.h" -#include "pty.h" +#include "ssh1.h" +#include "ssh2.h" +#include "xmalloc.h" +#include "sshpty.h" #include "packet.h" #include "buffer.h" #include "mpaux.h" -#include "servconf.h" #include "uidswap.h" #include "compat.h" #include "channels.h" #include "nchan.h" - #include "bufaux.h" -#include "ssh2.h" #include "auth.h" #include "auth-options.h" +#include "pathnames.h" +#include "log.h" +#include "servconf.h" +#include "sshlogin.h" +#include "serverloop.h" +#include "canohost.h" +#include "session.h" #ifdef WITH_IRIX_PROJECT #include #endif /* WITH_IRIX_PROJECT */ #ifdef WITH_IRIX_JOBS #include -#endif +#endif #ifdef WITH_IRIX_AUDIT #include #endif /* WITH_IRIX_AUDIT */ @@ -66,11 +72,6 @@ RCSID("$OpenBSD: session.c,v 1.44 2000/11/14 23:44:19 markus Exp $"); #include #endif -#ifdef HAVE_OSF_SIA -# include -# include -#endif - #ifdef HAVE_CYGWIN #include #include @@ -88,10 +89,6 @@ RCSID("$OpenBSD: session.c,v 1.44 2000/11/14 23:44:19 markus Exp $"); # define S_UNOFILE_HARD S_UNOFILE "_hard" #endif -#ifdef HAVE_LOGIN_CAP -#include -#endif - /* types */ #define TTYSZ 64 @@ -137,7 +134,7 @@ extern ServerOptions options; extern char *__progname; extern int log_stderr; extern int debug_flag; -extern unsigned int utmp_len; +extern u_int utmp_len; extern int startup_pipe; @@ -145,7 +142,7 @@ extern int startup_pipe; static char *xauthfile; /* original command from peer. */ -char *original_command = NULL; +char *original_command = NULL; /* data */ #define MAX_SESSIONS 10 @@ -218,7 +215,8 @@ do_authenticated(struct passwd * pw) char *command; int n_bytes; int plen; - unsigned int proto_len, data_len, dlen; + u_int proto_len, data_len, dlen; + int screen_flag; /* * Cancel the alarm we set to limit the time taken for @@ -342,12 +340,23 @@ do_authenticated(struct passwd * pw) s->auth_proto = packet_get_string(&proto_len); s->auth_data = packet_get_string(&data_len); - packet_integrity_check(plen, 4 + proto_len + 4 + data_len + 4, type); - if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER) + screen_flag = packet_get_protocol_flags() & + SSH_PROTOFLAG_SCREEN_NUMBER; + debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag); + + if (packet_remaining() == 4) { + if (!screen_flag) + debug2("Buggy client: " + "X11 screen flag missing"); + packet_integrity_check(plen, + 4 + proto_len + 4 + data_len + 4, type); s->screen = packet_get_int(); - else + } else { + packet_integrity_check(plen, + 4 + proto_len + 4 + data_len, type); s->screen = 0; + } s->display = x11_create_display_inet(s->screen, options.x11_display_offset); if (s->display == NULL) @@ -405,10 +414,6 @@ do_authenticated(struct passwd * pw) case SSH_CMSG_EXEC_SHELL: case SSH_CMSG_EXEC_CMD: - /* Set interactive/non-interactive mode. */ - packet_set_interactive(have_pty || s->display != NULL, - options.keepalives); - if (type == SSH_CMSG_EXEC_CMD) { command = packet_get_string(&dlen); debug("Exec command '%.500s'", command); @@ -480,12 +485,10 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) if (s == NULL) fatal("do_exec_no_pty: no session"); - signal(SIGPIPE, SIG_DFL); - session_proctitle(s); -#ifdef USE_PAM - do_pam_setcred(); +#if defined(USE_PAM) + do_pam_setcred(); #endif /* USE_PAM */ /* Fork the child. */ @@ -493,6 +496,8 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) /* Child. Reinitialize the log since the pid has changed. */ log_init(__progname, options.log_level, options.log_facility, log_stderr); + signal(SIGPIPE, SIG_DFL); + /* * Create a new session and process group since the 4.4BSD * setlogin() affects the entire process group. @@ -548,6 +553,8 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) if (pid < 0) packet_disconnect("fork failed: %.100s", strerror(errno)); s->pid = pid; + /* Set interactive/non-interactive mode. */ + packet_set_interactive(s->display != NULL); #ifdef USE_PIPES /* We are the parent. Close the child sides of the pipes. */ close(pin[0]); @@ -596,16 +603,18 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) ptyfd = s->ptyfd; ttyfd = s->ttyfd; -#ifdef USE_PAM - do_pam_session(pw->pw_name, s->tty); - do_pam_setcred(); -#endif /* USE_PAM */ +#if defined(USE_PAM) + do_pam_session(pw->pw_name, s->tty); + do_pam_setcred(); +#endif /* Fork the child. */ if ((pid = fork()) == 0) { /* Child. Reinitialize the log because the pid has changed. */ log_init(__progname, options.log_level, options.log_facility, log_stderr); + signal(SIGPIPE, SIG_DFL); + /* Close the master side of the pseudo tty. */ close(ptyfd); @@ -663,6 +672,7 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) s->ptymaster = ptymaster; /* Enter interactive session. */ + packet_set_interactive(1); if (compat20) { session_set_fds(s, ptyfd, fdout, -1); } else { @@ -677,7 +687,7 @@ get_remote_name_or_ip(void) { static const char *remote = ""; if (utmp_len > 0) - remote = get_canonical_hostname(); + remote = get_canonical_hostname(options.reverse_mapping_check); if (utmp_len == 0 || strlen(remote) > utmp_len) remote = get_remote_ipaddr(); return remote; @@ -726,7 +736,7 @@ do_login(Session *s, const char *command) * If password change is needed, do it now. * This needs to occur before the ~/.hushlogin check. */ - if (pam_password_change_required()) { + if (is_pam_password_change_required()) { print_pam_messages(); do_pam_chauthtok(); } @@ -744,7 +754,7 @@ do_login(Session *s, const char *command) return; #ifdef USE_PAM - if (!pam_password_change_required()) + if (!is_pam_password_change_required()) print_pam_messages(); #endif /* USE_PAM */ #ifdef WITH_AIXAUTHENTICATE @@ -781,10 +791,10 @@ do_login(Session *s, const char *command) * already exists, its value is overriden. */ void -child_set_env(char ***envp, unsigned int *envsizep, const char *name, +child_set_env(char ***envp, u_int *envsizep, const char *name, const char *value) { - unsigned int i, namelen; + u_int i, namelen; char **env; /* @@ -822,7 +832,7 @@ child_set_env(char ***envp, unsigned int *envsizep, const char *name, * and assignments of the form name=value. No other forms are allowed. */ void -read_environment_file(char ***env, unsigned int *envsize, +read_environment_file(char ***env, u_int *envsize, const char *filename) { FILE *f; @@ -868,11 +878,11 @@ void do_pam_environment(char ***env, int *envsize) if ((pam_env = fetch_pam_environment()) == NULL) return; - + for(i = 0; pam_env[i] != NULL; i++) { if ((equals = strstr(pam_env[i], "=")) == NULL) continue; - + if (strlen(pam_env[i]) < (sizeof(var_name) - 1)) { memset(var_name, '\0', sizeof(var_name)); memset(var_val, '\0', sizeof(var_val)); @@ -888,7 +898,6 @@ void do_pam_environment(char ***env, int *envsize) } #endif /* USE_PAM */ - #ifdef HAVE_CYGWIN void copy_environment(char ***env, int *envsize) { @@ -898,7 +907,7 @@ void copy_environment(char ***env, int *envsize) for(i = 0; environ[i] != NULL; i++) { if ((equals = strstr(environ[i], "=")) == NULL) continue; - + if (strlen(environ[i]) < (sizeof(var_name) - 1)) { memset(var_name, '\0', sizeof(var_name)); memset(var_val, '\0', sizeof(var_val)); @@ -1007,7 +1016,7 @@ do_child(const char *command, struct passwd * pw, const char *term, char buf[256]; char cmd[1024]; FILE *f = NULL; - unsigned int envsize, i; + u_int envsize, i; char **env; extern char **environ; struct stat st; @@ -1023,7 +1032,6 @@ do_child(const char *command, struct passwd * pw, const char *term, #endif /* WITH_IRIX_ARRAY */ #endif /* WITH_IRIX_JOBS */ - /* login(1) is only called if we execute the login shell */ if (options.use_login && command != NULL) options.use_login = 0; @@ -1053,20 +1061,7 @@ do_child(const char *command, struct passwd * pw, const char *term, switch, so we let login(1) to this for us. */ if (!options.use_login) { #ifdef HAVE_OSF_SIA - extern char **saved_argv; - extern int saved_argc; - char *host = get_canonical_hostname (); - - if (sia_become_user(NULL, saved_argc, saved_argv, host, - pw->pw_name, ttyname, 0, NULL, NULL, SIA_BEU_SETLUID) != - SIASUCCESS) { - perror("sia_become_user"); - exit(1); - } - if (setreuid(geteuid(), geteuid()) < 0) { - perror("setreuid"); - exit(1); - } + session_setup_sia(pw->pw_name, ttyname); #else /* HAVE_OSF_SIA */ #ifdef HAVE_CYGWIN if (is_winnt) { @@ -1082,7 +1077,20 @@ do_child(const char *command, struct passwd * pw, const char *term, perror("unable to set user context"); exit(1); } +#ifdef BSD_AUTH + if (auth_approval(NULL, lc, pw->pw_name, "ssh") <= 0) { + error("approval failure for %s", pw->pw_name); + fprintf(stderr, "Approval failure"); + exit(1); + } +#endif # else /* HAVE_LOGIN_CAP */ +#if defined(HAVE_GETLUID) && defined(HAVE_SETLUID) + /* Sets login uid for accounting */ + if (getluid() == -1 && setluid(pw->pw_uid) == -1) + error("setluid: %s", strerror(errno)); +#endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */ + if (setlogin(pw->pw_name) < 0) error("setlogin failed: %s", strerror(errno)); if (setgid(pw->pw_gid) < 0) { @@ -1100,7 +1108,7 @@ do_child(const char *command, struct passwd * pw, const char *term, if (jid == -1) { fatal("Failed to create job container: %.100s", strerror(errno)); - } + } # endif /* WITH_IRIX_JOBS */ # ifdef WITH_IRIX_ARRAY /* initialize array session */ @@ -1332,28 +1340,28 @@ do_child(const char *command, struct passwd * pw, const char *term, * in this order). */ if (!options.use_login) { - if (stat(SSH_USER_RC, &st) >= 0) { + if (stat(_PATH_SSH_USER_RC, &st) >= 0) { if (debug_flag) - fprintf(stderr, "Running "_PATH_BSHELL" %s\n", SSH_USER_RC); + fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, _PATH_SSH_USER_RC); - f = popen(_PATH_BSHELL " " SSH_USER_RC, "w"); + f = popen(_PATH_BSHELL " " _PATH_SSH_USER_RC, "w"); if (f) { if (auth_proto != NULL && auth_data != NULL) fprintf(f, "%s %s\n", auth_proto, auth_data); pclose(f); } else - fprintf(stderr, "Could not run %s\n", SSH_USER_RC); - } else if (stat(SSH_SYSTEM_RC, &st) >= 0) { + fprintf(stderr, "Could not run %s\n", _PATH_SSH_USER_RC); + } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { if (debug_flag) - fprintf(stderr, "Running "_PATH_BSHELL" %s\n", SSH_SYSTEM_RC); + fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, _PATH_SSH_SYSTEM_RC); - f = popen(_PATH_BSHELL " " SSH_SYSTEM_RC, "w"); + f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w"); if (f) { if (auth_proto != NULL && auth_data != NULL) fprintf(f, "%s %s\n", auth_proto, auth_data); pclose(f); } else - fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC); + fprintf(stderr, "Could not run %s\n", _PATH_SSH_SYSTEM_RC); } else if (options.xauth_location != NULL) { /* Add authority data to .Xauthority if appropriate. */ if (auth_proto != NULL && auth_data != NULL) { @@ -1363,13 +1371,13 @@ do_child(const char *command, struct passwd * pw, const char *term, "Running %.100s add %.100s %.100s %.100s\n", options.xauth_location, display, auth_proto, auth_data); -#ifndef HAVE_CYGWIN /* Unix sockets are not supported */ +#ifndef NO_X11_UNIX_SOCKETS if (screen != NULL) fprintf(stderr, "Adding %.*s/unix%s %s %s\n", (int)(screen-display), display, screen, auth_proto, auth_data); -#endif +#endif /* NO_X11_UNIX_SOCKETS */ } snprintf(cmd, sizeof cmd, "%s -q -", options.xauth_location); @@ -1377,12 +1385,12 @@ do_child(const char *command, struct passwd * pw, const char *term, if (f) { fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data); -#ifndef HAVE_CYGWIN /* Unix sockets are not supported */ - if (screen != NULL) +#ifndef NO_X11_UNIX_SOCKETS + if (screen != NULL) fprintf(f, "add %.*s/unix%s %s %s\n", (int)(screen-display), display, screen, auth_proto, auth_data); -#endif +#endif /* NO_X11_UNIX_SOCKETS */ pclose(f); } else { fprintf(stderr, "Could not run %s\n", @@ -1525,7 +1533,7 @@ session_open(int chanid) } s->pw = auth_get_user(); if (s->pw == NULL) - fatal("no user for session %i", s->self); + fatal("no user for session %d", s->self); debug("session_open: session %d: link with channel %d", s->self, chanid); s->chanid = chanid; return 1; @@ -1577,7 +1585,7 @@ session_window_change_req(Session *s) int session_pty_req(Session *s) { - unsigned int len; + u_int len; char *term_modes; /* encoded terminal modes */ if (no_pty_flag) @@ -1626,7 +1634,7 @@ session_pty_req(Session *s) int session_subsystem_req(Session *s) { - unsigned int len; + u_int len; int success = 0; char *subsys = packet_get_string(&len); int i; @@ -1722,7 +1730,7 @@ session_shell_req(Session *s) int session_exec_req(Session *s) { - unsigned int len; + u_int len; char *command = packet_get_string(&len); packet_done(); if (forced_command) { @@ -1760,7 +1768,7 @@ session_auth_agent_req(Session *s) void session_input_channel_req(int id, void *arg) { - unsigned int len; + u_int len; int reply; int success = 0; char *rtype; @@ -1835,7 +1843,7 @@ session_pty_cleanup(Session *s) if (s == NULL || s->ttyfd == -1) return; - debug("session_pty_cleanup: session %i release %s", s->self, s->tty); + debug("session_pty_cleanup: session %d release %s", s->self, s->tty); /* Cancel the cleanup function. */ fatal_remove_cleanup(pty_cleanup_proc, (void *)s); @@ -1898,13 +1906,9 @@ session_exit_message(Session *s, int status) * interested in data we write. * Note that we must not call 'chan_read_failed', since there could * be some more data waiting in the pipe. - * djm - This is no longer true as we have allowed one pass through - * the select loop before killing the connection */ if (c->ostate != CHAN_OUTPUT_CLOSED) chan_write_failed(c); - if (c->istate != CHAN_INPUT_CLOSED) - chan_read_failed(c); s->chanid = -1; } @@ -1966,8 +1970,6 @@ session_close_by_channel(int id, void *arg) session_close(s); } else { /* notify child, delay session cleanup */ - if (s->pid <= 1) - fatal("session_close_by_channel: Unsafe s->pid = %d", s->pid); if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0) error("session_close_by_channel: kill %d: %s", s->pid, strerror(errno)); @@ -2003,12 +2005,8 @@ session_proctitle(Session *s) } void -do_authenticated2(void) +do_authenticated2(Authctxt *authctxt) { -#ifdef HAVE_LOGIN_CAP - struct passwd *pw; -#endif - /* * Cancel the alarm we set to limit the time taken for * authentication. @@ -2019,8 +2017,7 @@ do_authenticated2(void) startup_pipe = -1; } #if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD) - pw = auth_get_user(); - if ((lc = login_getclass(pw->pw_class)) == NULL) { + if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) { error("unable to get login class"); return; }