X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/ad55cd035c604a3aa5f76a1f52b9f1a153b44790..47af6577fd425738a4ecdfa368f5df7b5084298b:/session.c diff --git a/session.c b/session.c index 296dfade..20975cb6 100644 --- a/session.c +++ b/session.c @@ -33,14 +33,13 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.37 2000/09/07 20:27:53 deraadt Exp $"); +RCSID("$OpenBSD: session.c,v 1.49 2001/01/18 17:00:00 markus Exp $"); #include "xmalloc.h" #include "ssh.h" #include "pty.h" #include "packet.h" #include "buffer.h" -#include "cipher.h" #include "mpaux.h" #include "servconf.h" #include "uidswap.h" @@ -56,6 +55,12 @@ RCSID("$OpenBSD: session.c,v 1.37 2000/09/07 20:27:53 deraadt Exp $"); #ifdef WITH_IRIX_PROJECT #include #endif /* WITH_IRIX_PROJECT */ +#ifdef WITH_IRIX_JOBS +#include +#endif +#ifdef WITH_IRIX_AUDIT +#include +#endif /* WITH_IRIX_AUDIT */ #if defined(HAVE_USERSEC_H) #include @@ -120,7 +125,7 @@ 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); -void do_login(Session *s); +void do_login(Session *s, const char *command); void do_child(const char *command, struct passwd * pw, const char *term, @@ -129,15 +134,10 @@ 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; -extern unsigned int utmp_len; +extern u_int utmp_len; extern int startup_pipe; @@ -150,6 +150,7 @@ char *original_command = NULL; /* data */ #define MAX_SESSIONS 10 Session sessions[MAX_SESSIONS]; + #ifdef WITH_AIXAUTHENTICATE /* AIX's lastlogin message, set in auth1.c */ char *aixloginmsg; @@ -217,7 +218,7 @@ 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; /* * Cancel the alarm we set to limit the time taken for @@ -236,13 +237,13 @@ do_authenticated(struct passwd * pw) * by the client telling us, so we can equally well trust the client * not to request anything bogus.) */ - if (!no_port_forwarding_flag) + if (!no_port_forwarding_flag && options.allow_tcp_forwarding) channel_permit_all_opens(); s = session_new(); s->pw = pw; -#ifdef HAVE_LOGIN_CAP +#if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD) if ((lc = login_getclass(pw->pw_class)) == NULL) { error("unable to get login class"); return; @@ -388,6 +389,10 @@ do_authenticated(struct passwd * pw) debug("Port forwarding not permitted for this authentication."); break; } + if (!options.allow_tcp_forwarding) { + debug("Port forwarding not permitted."); + break; + } debug("Received TCP/IP port forwarding request."); channel_input_port_forward_request(pw->pw_uid == 0, options.gateway_ports); success = 1; @@ -400,10 +405,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); @@ -486,6 +487,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. @@ -541,6 +544,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]); @@ -599,6 +604,8 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) /* 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); @@ -621,8 +628,8 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) close(ttyfd); /* record login, etc. similar to login(1) */ - if (command == NULL && !options.use_login) - do_login(s); + if (!(options.use_login && command == NULL)) + do_login(s, command); /* Do common processing for the child, such as execing the command. */ do_child(command, pw, s->term, s->display, s->auth_proto, @@ -656,6 +663,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 { @@ -678,7 +686,7 @@ get_remote_name_or_ip(void) /* administrative, login(1)-like work */ void -do_login(Session *s) +do_login(Session *s, const char *command) { FILE *f; char *time_string; @@ -705,10 +713,6 @@ do_login(Session *s) } } - /* Get the time and hostname when the user last logged in. */ - last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, - hostname, sizeof(hostname)); - /* Get the time and hostname when the user last logged in. */ hostname[0] = '\0'; last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, @@ -718,7 +722,20 @@ do_login(Session *s) record_login(pid, s->tty, pw->pw_name, pw->pw_uid, get_remote_name_or_ip(), (struct sockaddr *)&from); - /* Done if .hushlogin exists. */ +#ifdef USE_PAM + /* + * If password change is needed, do it now. + * This needs to occur before the ~/.hushlogin check. + */ + if (pam_password_change_required()) { + print_pam_messages(); + do_pam_chauthtok(); + } +#endif + + /* Done if .hushlogin exists or a command given. */ + if (command != NULL) + return; snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir); #ifdef HAVE_LOGIN_CAP if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0) @@ -728,9 +745,8 @@ do_login(Session *s) return; #ifdef USE_PAM - print_pam_messages(); - /* If password change is needed, do it now. */ - do_pam_chauthtok(); + if (!pam_password_change_required()) + print_pam_messages(); #endif /* USE_PAM */ #ifdef WITH_AIXAUTHENTICATE if (aixloginmsg && *aixloginmsg) @@ -741,7 +757,7 @@ do_login(Session *s) time_string = ctime(&last_login_time); if (strchr(time_string, '\n')) *strchr(time_string, '\n') = 0; - if (strcmp(buf, "") == 0) + if (strcmp(hostname, "") == 0) printf("Last login: %s\r\n", time_string); else printf("Last login: %s from %s\r\n", time_string, hostname); @@ -766,10 +782,10 @@ do_login(Session *s) * 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; /* @@ -807,7 +823,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; @@ -865,7 +881,7 @@ void do_pam_environment(char ***env, int *envsize) strncpy(var_name, pam_env[i], equals - pam_env[i]); strcpy(var_val, equals + 1); - debug("PAM environment: %s=%s", var_name, var_val); + debug3("PAM environment: %s=%s", var_name, var_val); child_set_env(env, envsize, var_name, var_val); } @@ -873,6 +889,32 @@ void do_pam_environment(char ***env, int *envsize) } #endif /* USE_PAM */ + +#ifdef HAVE_CYGWIN +void copy_environment(char ***env, int *envsize) +{ + char *equals, var_name[512], var_val[512]; + int i; + + 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)); + + strncpy(var_name, environ[i], equals - environ[i]); + strcpy(var_val, equals + 1); + + debug3("Copy environment: %s=%s", var_name, var_val); + + child_set_env(env, envsize, var_name, var_val); + } + } +} +#endif + #if defined(HAVE_GETUSERATTR) /* * AIX-specific login initialisation @@ -966,7 +1008,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; @@ -974,6 +1016,14 @@ do_child(const char *command, struct passwd * pw, const char *term, #ifdef WITH_IRIX_PROJECT prid_t projid; #endif /* WITH_IRIX_PROJECT */ +#ifdef WITH_IRIX_JOBS + jid_t jid = 0; +#else +#ifdef WITH_IRIX_ARRAY + int jid = 0; +#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) @@ -1046,11 +1096,20 @@ do_child(const char *command, struct passwd * pw, const char *term, exit(1); } endgrent(); +# ifdef WITH_IRIX_JOBS + jid = jlimit_startjob(pw->pw_name, pw->pw_uid, "interactive"); + if (jid == -1) { + fatal("Failed to create job container: %.100s", + strerror(errno)); + } +# endif /* WITH_IRIX_JOBS */ # ifdef WITH_IRIX_ARRAY /* initialize array session */ - if (newarraysess() != 0) - fatal("Failed to set up new array session: %.100s", - strerror(errno)); + if (jid == 0) { + if (newarraysess() != 0) + fatal("Failed to set up new array session: %.100s", + strerror(errno)); + } # endif /* WITH_IRIX_ARRAY */ # ifdef WITH_IRIX_PROJECT /* initialize irix project info */ @@ -1062,6 +1121,14 @@ do_child(const char *command, struct passwd * pw, const char *term, fatal("Failed to initialize project %d for %s: %.100s", (int)projid, pw->pw_name, strerror(errno)); # endif /* WITH_IRIX_PROJECT */ +#ifdef WITH_IRIX_AUDIT + if (sysconf(_SC_AUDIT)) { + debug("Setting sat id to %d", (int) pw->pw_uid); + if (satsetid(pw->pw_uid)) + debug("error setting satid: %.100s", strerror(errno)); + } +#endif /* WITH_IRIX_AUDIT */ + /* Permanently switch to the desired uid. */ permanently_set_uid(pw->pw_uid); # endif /* HAVE_LOGIN_CAP */ @@ -1105,15 +1172,7 @@ do_child(const char *command, struct passwd * pw, const char *term, * The Windows environment contains some setting which are * important for a running system. They must not be dropped. */ - { - char **ep; - for (ep = environ; *ep; ++ep) { - char *esp = strchr(*ep, '='); - *esp = '\0'; - child_set_env(&env, &envsize, *ep, esp + 1); - *esp = '='; - } - } + copy_environment(&env, &envsize); #endif if (!options.use_login) { @@ -1124,8 +1183,8 @@ do_child(const char *command, struct passwd * pw, const char *term, #ifdef HAVE_LOGIN_CAP (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH); child_set_env(&env, &envsize, "PATH", getenv("PATH")); -#else -#ifndef HAVE_CYGWIN +#else /* HAVE_LOGIN_CAP */ +# ifndef HAVE_CYGWIN /* * There's no standard path on Windows. The path contains * important components pointing to the system directories, @@ -1133,8 +1192,8 @@ do_child(const char *command, struct passwd * pw, const char *term, * remains intact here. */ child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); -#endif -#endif +# endif /* HAVE_CYGWIN */ +#endif /* HAVE_LOGIN_CAP */ snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name); @@ -1176,15 +1235,11 @@ do_child(const char *command, struct passwd * pw, const char *term, original_command); #ifdef _AIX - { - char *authstate,*krb5cc; - - if ((authstate = getenv("AUTHSTATE")) != NULL) - child_set_env(&env,&envsize,"AUTHSTATE",authstate); - - if ((krb5cc = getenv("KRB5CCNAME")) != NULL) - child_set_env(&env,&envsize,"KRB5CCNAME",krb5cc); - } + if ((cp = getenv("AUTHSTATE")) != NULL) + child_set_env(&env, &envsize, "AUTHSTATE", cp); + if ((cp = getenv("KRB5CCNAME")) != NULL) + child_set_env(&env, &envsize, "KRB5CCNAME", cp); + read_environment_file(&env, &envsize, "/etc/environment"); #endif #ifdef KRB4 @@ -1201,8 +1256,6 @@ do_child(const char *command, struct passwd * pw, const char *term, do_pam_environment(&env, &envsize); #endif /* USE_PAM */ - read_environment_file(&env,&envsize,"/etc/environment"); - if (xauthfile) child_set_env(&env, &envsize, "XAUTHORITY", xauthfile); if (auth_get_socket_name() != NULL) @@ -1282,7 +1335,7 @@ do_child(const char *command, struct passwd * pw, const char *term, if (!options.use_login) { if (stat(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, SSH_USER_RC); f = popen(_PATH_BSHELL " " SSH_USER_RC, "w"); if (f) { @@ -1293,7 +1346,7 @@ do_child(const char *command, struct passwd * pw, const char *term, fprintf(stderr, "Could not run %s\n", SSH_USER_RC); } else if (stat(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, SSH_SYSTEM_RC); f = popen(_PATH_BSHELL " " SSH_SYSTEM_RC, "w"); if (f) { @@ -1311,7 +1364,7 @@ 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 +#ifndef HAVE_CYGWIN /* Unix sockets are not supported */ if (screen != NULL) fprintf(stderr, "Adding %.*s/unix%s %s %s\n", @@ -1325,7 +1378,7 @@ 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 +#ifndef HAVE_CYGWIN /* Unix sockets are not supported */ if (screen != NULL) fprintf(f, "add %.*s/unix%s %s %s\n", (int)(screen-display), display, @@ -1525,7 +1578,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) @@ -1574,7 +1627,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; @@ -1670,7 +1723,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) { @@ -1688,10 +1741,27 @@ session_exec_req(Session *s) return 1; } +int +session_auth_agent_req(Session *s) +{ + static int called = 0; + packet_done(); + if (no_agent_forwarding_flag) { + debug("session_auth_agent_req: no_agent_forwarding_flag"); + return 0; + } + if (called) { + return 0; + } else { + called = 1; + return auth_input_request_forwarding(s->pw); + } +} + void session_input_channel_req(int id, void *arg) { - unsigned int len; + u_int len; int reply; int success = 0; char *rtype; @@ -1724,6 +1794,8 @@ session_input_channel_req(int id, void *arg) success = session_pty_req(s); } else if (strcmp(rtype, "x11-req") == 0) { success = session_x11_req(s); + } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { + success = session_auth_agent_req(s); } else if (strcmp(rtype, "subsystem") == 0) { success = session_subsystem_req(s); } @@ -1754,7 +1826,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr) fatal("no channel for session %d", s->self); channel_set_fds(s->chanid, fdout, fdin, fderr, - fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ); + fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, + 1); } void @@ -1927,11 +2000,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 @@ -1942,9 +2012,8 @@ do_authenticated2(void) close(startup_pipe); startup_pipe = -1; } -#ifdef HAVE_LOGIN_CAP - pw = auth_get_user(); - if ((lc = login_getclass(pw->pw_class)) == NULL) { +#if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD) + if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) { error("unable to get login class"); return; }