=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/session.c,v retrieving revision 1.12.2.5 retrieving revision 1.13 diff -u -r1.12.2.5 -r1.13 --- src/usr.bin/ssh/session.c 2001/03/21 18:53:03 1.12.2.5 +++ src/usr.bin/ssh/session.c 2000/05/22 16:51:44 1.13 @@ -1,67 +1,32 @@ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * + */ +/* * SSH2 support by Markus Friedl. - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * Copyright (c) 2000 Markus Friedl. All rights reserved. */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.12.2.5 2001/03/21 18:53:03 jason Exp $"); +RCSID("$OpenBSD: session.c,v 1.13 2000/05/22 16:51:44 markus Exp $"); -#include "ssh.h" -#include "ssh1.h" -#include "ssh2.h" #include "xmalloc.h" -#include "sshpty.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" #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 HAVE_LOGIN_CAP -#include -#endif - /* types */ #define TTYSZ 64 @@ -95,32 +60,37 @@ 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, const char *command); -void do_child(Session *s, const char *command); +void +do_child(const char *command, struct passwd * pw, const char *term, + const char *display, const char *auth_proto, + const char *auth_data, const char *ttyname); + /* import */ extern ServerOptions options; extern char *__progname; extern int log_stderr; extern int debug_flag; -extern u_int utmp_len; -extern int startup_pipe; - /* Local Xauthority file. */ static char *xauthfile; -/* original command from peer. */ -char *original_command = NULL; - /* data */ #define MAX_SESSIONS 10 Session sessions[MAX_SESSIONS]; -#ifdef HAVE_LOGIN_CAP -static login_cap_t *lc; -#endif +/* 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; + /* * Remove local Xauthority file. */ @@ -173,38 +143,33 @@ do_authenticated(struct passwd * pw) { Session *s; - int type, fd; + int type; int compression_level = 0, enable_compression_after_reply = 0; int have_pty = 0; char *command; int n_bytes; int plen; - u_int proto_len, data_len, dlen; - int screen_flag; + unsigned int proto_len, data_len, dlen; /* * Cancel the alarm we set to limit the time taken for * authentication. */ alarm(0); - if (startup_pipe != -1) { - close(startup_pipe); - startup_pipe = -1; - } + /* + * Inform the channel mechanism that we are the server side and that + * the client may request to connect to any port at all. (The user + * could do it anyway, and we wouldn\'t know what is permitted except + * by the client telling us, so we can equally well trust the client + * not to request anything bogus.) + */ + if (!no_port_forwarding_flag) + channel_permit_all_opens(); + s = session_new(); s->pw = pw; - if (!no_port_forwarding_flag && options.allow_tcp_forwarding) - channel_permit_all_opens(); - -#ifdef HAVE_LOGIN_CAP - if ((lc = login_getclass(pw->pw_class)) == NULL) { - error("unable to get login class"); - return; - } -#endif - /* * We stay in this loop until the client requests to execute a shell * or a command. @@ -283,10 +248,7 @@ packet_send_debug("X11 forwarding disabled in server configuration file."); break; } - if (!options.xauth_location) { - packet_send_debug("No xauth program; cannot forward with spoofing."); - break; - } +#ifdef XAUTH_PATH if (no_x11_forwarding_flag) { packet_send_debug("X11 forwarding not permitted for this authentication."); break; @@ -297,23 +259,12 @@ 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); - 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); + if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER) s->screen = packet_get_int(); - } else { - packet_integrity_check(plen, - 4 + proto_len + 4 + data_len, type); + else s->screen = 0; - } s->display = x11_create_display_inet(s->screen, options.x11_display_offset); if (s->display == NULL) @@ -333,13 +284,15 @@ break; } strlcat(xauthfile, "/cookies", MAXPATHLEN); - fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); - if (fd >= 0) - close(fd); + open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); restore_uid(); 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) { @@ -347,7 +300,8 @@ break; } debug("Received authentication agent forwarding request."); - success = auth_input_request_forwarding(pw); + auth_input_request_forwarding(pw); + success = 1; break; case SSH_CMSG_PORT_FORWARD_REQUEST: @@ -355,10 +309,6 @@ 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; @@ -371,6 +321,10 @@ 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); @@ -380,7 +334,6 @@ packet_integrity_check(plen, 0, type); } if (forced_command != NULL) { - original_command = command; command = forced_command; debug("Forced command '%.500s'", forced_command); } @@ -494,14 +447,12 @@ #endif /* USE_PIPES */ /* Do processing for the child (exec command etc). */ - do_child(s, command); + do_child(command, pw, NULL, s->display, s->auth_proto, s->auth_data, NULL); /* NOTREACHED */ } 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]); @@ -542,17 +493,41 @@ void do_exec_pty(Session *s, const char *command, struct passwd * pw) { + FILE *f; + char buf[100], *time_string; + char line[256]; + const char *hostname; int fdout, ptyfd, ttyfd, ptymaster; + int quiet_login; pid_t pid; + socklen_t fromlen; + struct sockaddr_storage from; + struct stat st; + time_t last_login_time; if (s == NULL) fatal("do_exec_pty: no session"); ptyfd = s->ptyfd; ttyfd = s->ttyfd; + /* Get remote host name. */ + hostname = get_canonical_hostname(); + + /* + * Get the time when the user last logged in. Buf will be set to + * contain the hostname the last login was from. + */ + if (!options.use_login) { + last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, + buf, sizeof(buf)); + } + /* Fork the child. */ if ((pid = fork()) == 0) { - /* Child. Reinitialize the log because the pid has changed. */ + pid = getpid(); + + /* Child. Reinitialize the log because the pid has + changed. */ log_init(__progname, options.log_level, options.log_facility, log_stderr); /* Close the master side of the pseudo tty. */ @@ -576,12 +551,69 @@ /* Close the extra descriptor for the pseudo tty. */ close(ttyfd); - /* record login, etc. similar to login(1) */ - if (!(options.use_login && command == NULL)) - do_login(s, command); +/* 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 + * connection is not a socket, let the ip address be 0.0.0.0. + */ + memset(&from, 0, 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)); + fatal_cleanup(); + } + } + /* Record that there was a login on that terminal. */ + record_login(pid, s->tty, pw->pw_name, pw->pw_uid, hostname, + (struct sockaddr *)&from); + /* Check if .hushlogin exists. */ + snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir); + quiet_login = stat(line, &st) >= 0; + + /* + * If the user has logged in before, display the time of last + * login. However, don't display anything extra if a command + * has been specified (so that ssh can be used to execute + * commands on a remote machine without users knowing they + * are going to another machine). Login(1) will do this for + * us as well, so check if login(1) is used + */ + if (command == NULL && last_login_time != 0 && !quiet_login && + !options.use_login) { + /* Convert the date to a string. */ + time_string = ctime(&last_login_time); + /* Remove the trailing newline. */ + if (strchr(time_string, '\n')) + *strchr(time_string, '\n') = 0; + /* Display the last login time. Host if displayed + if known. */ + if (strcmp(buf, "") == 0) + printf("Last login: %s\r\n", time_string); + else + printf("Last login: %s from %s\r\n", time_string, buf); + } + /* + * Print /etc/motd unless a command was specified or printing + * it was disabled in server options or login(1) will be + * used. Note that some machines appear to print it in + * /etc/profile or similar. + */ + if (command == NULL && options.print_motd && !quiet_login && + !options.use_login) { + /* Print /etc/motd if it exists. */ + f = fopen("/etc/motd", "r"); + if (f) { + while (fgets(line, sizeof(line), f)) + fputs(line, stdout); + fclose(f); + } + } /* Do common processing for the child, such as execing the command. */ - do_child(s, command); + do_child(command, pw, s->term, s->display, s->auth_proto, s->auth_data, s->tty); /* NOTREACHED */ } if (pid < 0) @@ -607,7 +639,6 @@ s->ptymaster = ptymaster; /* Enter interactive session. */ - packet_set_interactive(1); if (compat20) { session_set_fds(s, ptyfd, fdout, -1); } else { @@ -617,98 +648,15 @@ } } -const char * -get_remote_name_or_ip(void) -{ - static const char *remote = ""; - if (utmp_len > 0) - remote = get_canonical_hostname(options.reverse_mapping_check); - if (utmp_len == 0 || strlen(remote) > utmp_len) - remote = get_remote_ipaddr(); - return remote; -} - -/* administrative, login(1)-like work */ -void -do_login(Session *s, const char *command) -{ - FILE *f; - char *time_string; - char buf[256]; - char hostname[MAXHOSTNAMELEN]; - socklen_t fromlen; - struct sockaddr_storage from; - struct stat st; - time_t last_login_time; - struct passwd * pw = s->pw; - pid_t pid = getpid(); - - /* - * Get IP address of client. If the connection is not a socket, let - * the address be 0.0.0.0. - */ - memset(&from, 0, 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)); - fatal_cleanup(); - } - } - - /* 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, - hostname, sizeof(hostname)); - - /* Record that there was a login on that tty from the remote host. */ - record_login(pid, s->tty, pw->pw_name, pw->pw_uid, - get_remote_name_or_ip(), (struct sockaddr *)&from); - - /* 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) -#else - if (stat(buf, &st) >= 0) -#endif - return; - if (last_login_time != 0) { - time_string = ctime(&last_login_time); - if (strchr(time_string, '\n')) - *strchr(time_string, '\n') = 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); - } - if (options.print_motd) { -#ifdef HAVE_LOGIN_CAP - f = fopen(login_getcapstr(lc, "welcome", "/etc/motd", - "/etc/motd"), "r"); -#else - f = fopen("/etc/motd", "r"); -#endif - if (f) { - while (fgets(buf, sizeof(buf), f)) - fputs(buf, stdout); - fclose(f); - } - } -} - /* * Sets the value of the given variable in the environment. If the variable * already exists, its value is overriden. */ void -child_set_env(char ***envp, u_int *envsizep, const char *name, +child_set_env(char ***envp, unsigned int *envsizep, const char *name, const char *value) { - u_int i, namelen; + unsigned int i, namelen; char **env; /* @@ -746,7 +694,7 @@ * and assignments of the form name=value. No other forms are allowed. */ void -read_environment_file(char ***env, u_int *envsize, +read_environment_file(char ***env, unsigned int *envsize, const char *filename) { FILE *f; @@ -769,10 +717,7 @@ 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); @@ -786,56 +731,37 @@ * ids, and executing the command or shell. */ void -do_child(Session *s, const char *command) +do_child(const char *command, struct passwd * pw, const char *term, + const char *display, const char *auth_proto, + const char *auth_data, const char *ttyname) { - const char *shell, *hostname = NULL, *cp = NULL; - struct passwd * pw = s->pw; + const char *shell, *cp = NULL; char buf[256]; - char cmd[1024]; - FILE *f = NULL; - u_int envsize, i; + FILE *f; + unsigned int envsize, i; char **env; extern char **environ; struct stat st; char *argv[10]; - int do_xauth = s->auth_proto != NULL && s->auth_data != NULL; - /* login(1) is only called if we execute the login shell */ - if (options.use_login && command != NULL) - options.use_login = 0; - - if (!options.use_login) { -#ifdef HAVE_LOGIN_CAP - if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid) - f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN, - _PATH_NOLOGIN), "r"); -#else - if (pw->pw_uid) - f = fopen(_PATH_NOLOGIN, "r"); -#endif - if (f) { - /* /etc/nologin exists. Print its contents and exit. */ - while (fgets(buf, sizeof(buf), f)) - fputs(buf, stderr); - fclose(f); + f = fopen("/etc/nologin", "r"); + if (f) { + /* /etc/nologin exists. Print its contents and exit. */ + while (fgets(buf, sizeof(buf), f)) + fputs(buf, stderr); + fclose(f); + if (pw->pw_uid != 0) exit(254); - } } - /* Set login name, uid, gid, and groups. */ + /* Set login name in the kernel. */ + if (setlogin(pw->pw_name) < 0) + error("setlogin failed: %s", strerror(errno)); + + /* Set uid, gid, and groups. */ /* 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) { if (getuid() == 0 || geteuid() == 0) { -#ifdef HAVE_LOGIN_CAP - if (setusercontext(lc, pw, pw->pw_uid, - (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { - perror("unable to set user context"); - exit(1); - - } -#else - if (setlogin(pw->pw_name) < 0) - error("setlogin failed: %s", strerror(errno)); if (setgid(pw->pw_gid) < 0) { perror("setgid"); exit(1); @@ -849,19 +775,15 @@ /* Permanently switch to the desired uid. */ permanently_set_uid(pw->pw_uid); -#endif } if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) - fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); + fatal("Failed to set uids to %d.", (int) pw->pw_uid); } /* * Get the shell from the password data. An empty shell field is * legal, and means /bin/sh. */ shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; -#ifdef HAVE_LOGIN_CAP - shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); -#endif #ifdef AFS /* Try to get AFS tokens for the local cell. */ @@ -885,12 +807,7 @@ child_set_env(&env, &envsize, "USER", pw->pw_name); child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); 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")); -#else child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); -#endif snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name); @@ -921,15 +838,12 @@ get_remote_ipaddr(), get_remote_port(), get_local_port()); child_set_env(&env, &envsize, "SSH_CLIENT", buf); - if (s->ttyfd != -1) - child_set_env(&env, &envsize, "SSH_TTY", s->tty); - if (s->term) - child_set_env(&env, &envsize, "TERM", s->term); - if (s->display) - child_set_env(&env, &envsize, "DISPLAY", s->display); - if (original_command) - child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", - original_command); + if (ttyname) + child_set_env(&env, &envsize, "SSH_TTY", ttyname); + if (term) + child_set_env(&env, &envsize, "TERM", term); + if (display) + child_set_env(&env, &envsize, "DISPLAY", display); #ifdef KRB4 { @@ -948,8 +862,7 @@ /* 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) { @@ -958,9 +871,6 @@ for (i = 0; env[i]; i++) fprintf(stderr, " %.200s\n", env[i]); } - /* we have to stash the hostname before we close our socket. */ - if (options.use_login) - hostname = get_remote_name_or_ip(); /* * Close the connection descriptors; note that this is the child, and * the server will still have the socket open, and it is important @@ -997,14 +907,9 @@ close(i); /* Change current directory to the user\'s home directory. */ - if (chdir(pw->pw_dir) < 0) { + if (chdir(pw->pw_dir) < 0) fprintf(stderr, "Could not chdir to home directory %s: %s\n", pw->pw_dir, strerror(errno)); -#ifdef HAVE_LOGIN_CAP - if (login_getcapbool(lc, "requirehome", 0)) - exit(1); -#endif - } /* * Must take new environment into use so that .ssh/rc, /etc/sshrc and @@ -1017,67 +922,54 @@ * in this order). */ if (!options.use_login) { - if (stat(_PATH_SSH_USER_RC, &st) >= 0) { + if (stat(SSH_USER_RC, &st) >= 0) { if (debug_flag) - fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, - _PATH_SSH_USER_RC); - f = popen(_PATH_BSHELL " " _PATH_SSH_USER_RC, "w"); + fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC); + + f = popen("/bin/sh " SSH_USER_RC, "w"); if (f) { - if (do_xauth) - fprintf(f, "%s %s\n", s->auth_proto, - s->auth_data); + 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", - _PATH_SSH_USER_RC); - } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { + fprintf(stderr, "Could not run %s\n", SSH_USER_RC); + } else if (stat(SSH_SYSTEM_RC, &st) >= 0) { if (debug_flag) - fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, - _PATH_SSH_SYSTEM_RC); - f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w"); + fprintf(stderr, "Running /bin/sh %s\n", SSH_SYSTEM_RC); + + f = popen("/bin/sh " SSH_SYSTEM_RC, "w"); if (f) { - if (do_xauth) - fprintf(f, "%s %s\n", s->auth_proto, - s->auth_data); + 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", - _PATH_SSH_SYSTEM_RC); - } else if (do_xauth && options.xauth_location != NULL) { + fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC); + } +#ifdef XAUTH_PATH + else { /* Add authority data to .Xauthority if appropriate. */ - char *screen = strchr(s->display, ':'); - - if (debug_flag) { - fprintf(stderr, - "Running %.100s add " - "%.100s %.100s %.100s\n", - options.xauth_location, s->display, - s->auth_proto, s->auth_data); - if (screen != NULL) - fprintf(stderr, - "Adding %.*s/unix%s %s %s\n", - (int)(screen - s->display), - s->display, screen, - s->auth_proto, s->auth_data); + if (auth_proto != NULL && auth_data != NULL) { + 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); + 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); } - snprintf(cmd, sizeof cmd, "%s -q -", - options.xauth_location); - f = popen(cmd, "w"); - if (f) { - fprintf(f, "add %s %s %s\n", s->display, - s->auth_proto, s->auth_data); - if (screen != NULL) - fprintf(f, "add %.*s/unix%s %s %s\n", - (int)(screen - s->display), - s->display, screen, - s->auth_proto, - s->auth_data); - pclose(f); - } 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) @@ -1098,14 +990,12 @@ * Check for mail if we have a tty and it was enabled * in server options. */ - if (s->ttyfd != -1 && options.check_mail) { + if (ttyname && options.check_mail) { char *mailbox; 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"); @@ -1130,8 +1020,8 @@ } else { /* Launch login(1). */ - execl("/usr/bin/login", "login", "-h", hostname, - "-p", "-f", "--", pw->pw_name, NULL); + execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(), + "-p", "-f", "--", pw->pw_name, NULL); /* Login couldn't be executed, die. */ @@ -1214,7 +1104,7 @@ } s->pw = auth_get_user(); if (s->pw == NULL) - fatal("no user for session %d", s->self); + 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; @@ -1266,11 +1156,9 @@ int session_pty_req(Session *s) { - u_int len; + 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); @@ -1315,25 +1203,13 @@ int session_subsystem_req(Session *s) { - u_int len; + 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; } @@ -1341,11 +1217,6 @@ int session_x11_req(Session *s) { - int fd; - if (no_x11_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; @@ -1386,70 +1257,16 @@ return 0; } strlcat(xauthfile, "/cookies", MAXPATHLEN); - fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); - if (fd >= 0) - close(fd); + 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) -{ - u_int len; - char *command = packet_get_string(&len); - packet_done(); - if (forced_command) { - original_command = 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; -} - -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) { - u_int len; + unsigned int len; int reply; int success = 0; char *rtype; @@ -1475,15 +1292,27 @@ */ if (c->type == SSH_CHANNEL_LARVAL) { if (strcmp(rtype, "shell") == 0) { - success = session_shell_req(s); + packet_done(); + s->extended = 1; + if (s->ttyfd == -1) + do_exec_no_pty(s, NULL, s->pw); + else + do_exec_pty(s, NULL, s->pw); + success = 1; } else if (strcmp(rtype, "exec") == 0) { - success = session_exec_req(s); + char *command = packet_get_string(&len); + packet_done(); + s->extended = 1; + if (s->ttyfd == -1) + do_exec_no_pty(s, command, s->pw); + else + do_exec_pty(s, command, s->pw); + xfree(command); + 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, "auth-agent-req@openssh.com") == 0) { - success = session_auth_agent_req(s); } else if (strcmp(rtype, "subsystem") == 0) { success = session_subsystem_req(s); } @@ -1514,8 +1343,7 @@ fatal("no channel for session %d", s->self); channel_set_fds(s->chanid, fdout, fdin, fderr, - fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, - 1); + fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ); } void @@ -1524,7 +1352,7 @@ if (s == NULL || s->ttyfd == -1) return; - debug("session_pty_cleanup: session %d release %s", s->self, s->tty); + debug("session_pty_cleanup: session %i release %s", s->self, s->tty); /* Cancel the cleanup function. */ fatal_remove_cleanup(pty_cleanup_proc, (void *)s); @@ -1682,25 +1510,13 @@ } void -do_authenticated2(Authctxt *authctxt) +do_authenticated2(void) { /* * Cancel the alarm we set to limit the time taken for * authentication. */ alarm(0); - if (startup_pipe != -1) { - close(startup_pipe); - startup_pipe = -1; - } - if (!no_port_forwarding_flag && options.allow_tcp_forwarding) - channel_permit_all_opens(); -#ifdef HAVE_LOGIN_CAP - if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) { - error("unable to get login class"); - return; - } -#endif server_loop2(); if (xauthfile) xauthfile_cleanup_proc(NULL);