[BACK]Return to session.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/session.c between version 1.12.2.5 and 1.13

version 1.12.2.5, 2001/03/21 18:53:03 version 1.13, 2000/05/22 16:51:44
Line 1 
Line 1 
 /*  /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland   * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved   *                    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.   * SSH2 support by Markus Friedl.
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.   * 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.  
  */   */
   
 #include "includes.h"  #include "includes.h"
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
 #include "ssh.h"  
 #include "ssh1.h"  
 #include "ssh2.h"  
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "sshpty.h"  #include "ssh.h"
   #include "pty.h"
 #include "packet.h"  #include "packet.h"
 #include "buffer.h"  #include "buffer.h"
   #include "cipher.h"
 #include "mpaux.h"  #include "mpaux.h"
   #include "servconf.h"
 #include "uidswap.h"  #include "uidswap.h"
 #include "compat.h"  #include "compat.h"
 #include "channels.h"  #include "channels.h"
 #include "nchan.h"  #include "nchan.h"
   
 #include "bufaux.h"  #include "bufaux.h"
   #include "ssh2.h"
 #include "auth.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 <login_cap.h>  
 #endif  
   
 /* types */  /* types */
   
 #define TTYSZ 64  #define TTYSZ 64
Line 95 
Line 60 
 void    session_proctitle(Session *s);  void    session_proctitle(Session *s);
 void    do_exec_pty(Session *s, const char *command, struct passwd * pw);  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_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 */  /* import */
 extern ServerOptions options;  extern ServerOptions options;
 extern char *__progname;  extern char *__progname;
 extern int log_stderr;  extern int log_stderr;
 extern int debug_flag;  extern int debug_flag;
 extern u_int utmp_len;  
   
 extern int startup_pipe;  
   
 /* Local Xauthority file. */  /* Local Xauthority file. */
 static char *xauthfile;  static char *xauthfile;
   
 /* original command from peer. */  
 char *original_command = NULL;  
   
 /* data */  /* data */
 #define MAX_SESSIONS 10  #define MAX_SESSIONS 10
 Session sessions[MAX_SESSIONS];  Session sessions[MAX_SESSIONS];
   
 #ifdef HAVE_LOGIN_CAP  /* Flags set in auth-rsa from authorized_keys flags.  These are set in auth-rsa.c. */
 static login_cap_t *lc;  int no_port_forwarding_flag = 0;
 #endif  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.   * Remove local Xauthority file.
  */   */
Line 173 
Line 143 
 do_authenticated(struct passwd * pw)  do_authenticated(struct passwd * pw)
 {  {
         Session *s;          Session *s;
         int type, fd;          int type;
         int compression_level = 0, enable_compression_after_reply = 0;          int compression_level = 0, enable_compression_after_reply = 0;
         int have_pty = 0;          int have_pty = 0;
         char *command;          char *command;
         int n_bytes;          int n_bytes;
         int plen;          int plen;
         u_int proto_len, data_len, dlen;          unsigned int proto_len, data_len, dlen;
         int screen_flag;  
   
         /*          /*
          * Cancel the alarm we set to limit the time taken for           * Cancel the alarm we set to limit the time taken for
          * authentication.           * authentication.
          */           */
         alarm(0);          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 = session_new();
         s->pw = pw;          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           * We stay in this loop until the client requests to execute a shell
          * or a command.           * or a command.
Line 283 
Line 248 
                                 packet_send_debug("X11 forwarding disabled in server configuration file.");                                  packet_send_debug("X11 forwarding disabled in server configuration file.");
                                 break;                                  break;
                         }                          }
                         if (!options.xauth_location) {  #ifdef XAUTH_PATH
                                 packet_send_debug("No xauth program; cannot forward with spoofing.");  
                                 break;  
                         }  
                         if (no_x11_forwarding_flag) {                          if (no_x11_forwarding_flag) {
                                 packet_send_debug("X11 forwarding not permitted for this authentication.");                                  packet_send_debug("X11 forwarding not permitted for this authentication.");
                                 break;                                  break;
Line 297 
Line 259 
   
                         s->auth_proto = packet_get_string(&proto_len);                          s->auth_proto = packet_get_string(&proto_len);
                         s->auth_data = packet_get_string(&data_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() &                          if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER)
                             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();                                  s->screen = packet_get_int();
                         } else {                          else
                                 packet_integrity_check(plen,  
                                     4 + proto_len + 4 + data_len, type);  
                                 s->screen = 0;                                  s->screen = 0;
                         }  
                         s->display = x11_create_display_inet(s->screen, options.x11_display_offset);                          s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
   
                         if (s->display == NULL)                          if (s->display == NULL)
Line 333 
Line 284 
                                 break;                                  break;
                         }                          }
                         strlcat(xauthfile, "/cookies", MAXPATHLEN);                          strlcat(xauthfile, "/cookies", MAXPATHLEN);
                         fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);                          open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
                         if (fd >= 0)  
                                 close(fd);  
                         restore_uid();                          restore_uid();
                         fatal_add_cleanup(xauthfile_cleanup_proc, NULL);                          fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
                         success = 1;                          success = 1;
                         break;                          break;
   #else /* XAUTH_PATH */
                           packet_send_debug("No xauth program; cannot forward with spoofing.");
                           break;
   #endif /* XAUTH_PATH */
   
                 case SSH_CMSG_AGENT_REQUEST_FORWARDING:                  case SSH_CMSG_AGENT_REQUEST_FORWARDING:
                         if (no_agent_forwarding_flag || compat13) {                          if (no_agent_forwarding_flag || compat13) {
Line 347 
Line 300 
                                 break;                                  break;
                         }                          }
                         debug("Received authentication agent forwarding request.");                          debug("Received authentication agent forwarding request.");
                         success = auth_input_request_forwarding(pw);                          auth_input_request_forwarding(pw);
                           success = 1;
                         break;                          break;
   
                 case SSH_CMSG_PORT_FORWARD_REQUEST:                  case SSH_CMSG_PORT_FORWARD_REQUEST:
Line 355 
Line 309 
                                 debug("Port forwarding not permitted for this authentication.");                                  debug("Port forwarding not permitted for this authentication.");
                                 break;                                  break;
                         }                          }
                         if (!options.allow_tcp_forwarding) {  
                                 debug("Port forwarding not permitted.");  
                                 break;  
                         }  
                         debug("Received TCP/IP port forwarding request.");                          debug("Received TCP/IP port forwarding request.");
                         channel_input_port_forward_request(pw->pw_uid == 0, options.gateway_ports);                          channel_input_port_forward_request(pw->pw_uid == 0, options.gateway_ports);
                         success = 1;                          success = 1;
Line 371 
Line 321 
   
                 case SSH_CMSG_EXEC_SHELL:                  case SSH_CMSG_EXEC_SHELL:
                 case SSH_CMSG_EXEC_CMD:                  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) {                          if (type == SSH_CMSG_EXEC_CMD) {
                                 command = packet_get_string(&dlen);                                  command = packet_get_string(&dlen);
                                 debug("Exec command '%.500s'", command);                                  debug("Exec command '%.500s'", command);
Line 380 
Line 334 
                                 packet_integrity_check(plen, 0, type);                                  packet_integrity_check(plen, 0, type);
                         }                          }
                         if (forced_command != NULL) {                          if (forced_command != NULL) {
                                 original_command = command;  
                                 command = forced_command;                                  command = forced_command;
                                 debug("Forced command '%.500s'", forced_command);                                  debug("Forced command '%.500s'", forced_command);
                         }                          }
Line 494 
Line 447 
 #endif /* USE_PIPES */  #endif /* USE_PIPES */
   
                 /* Do processing for the child (exec command etc). */                  /* 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 */                  /* NOTREACHED */
         }          }
         if (pid < 0)          if (pid < 0)
                 packet_disconnect("fork failed: %.100s", strerror(errno));                  packet_disconnect("fork failed: %.100s", strerror(errno));
         s->pid = pid;          s->pid = pid;
         /* Set interactive/non-interactive mode. */  
         packet_set_interactive(s->display != NULL);  
 #ifdef USE_PIPES  #ifdef USE_PIPES
         /* We are the parent.  Close the child sides of the pipes. */          /* We are the parent.  Close the child sides of the pipes. */
         close(pin[0]);          close(pin[0]);
Line 542 
Line 493 
 void  void
 do_exec_pty(Session *s, const char *command, struct passwd * pw)  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 fdout, ptyfd, ttyfd, ptymaster;
           int quiet_login;
         pid_t pid;          pid_t pid;
           socklen_t fromlen;
           struct sockaddr_storage from;
           struct stat st;
           time_t last_login_time;
   
         if (s == NULL)          if (s == NULL)
                 fatal("do_exec_pty: no session");                  fatal("do_exec_pty: no session");
         ptyfd = s->ptyfd;          ptyfd = s->ptyfd;
         ttyfd = s->ttyfd;          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. */          /* Fork the child. */
         if ((pid = fork()) == 0) {          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);                  log_init(__progname, options.log_level, options.log_facility, log_stderr);
   
                 /* Close the master side of the pseudo tty. */                  /* Close the master side of the pseudo tty. */
Line 576 
Line 551 
                 /* Close the extra descriptor for the pseudo tty. */                  /* Close the extra descriptor for the pseudo tty. */
                 close(ttyfd);                  close(ttyfd);
   
                 /* record login, etc. similar to login(1) */  /* XXXX ? move to do_child() ??*/
                 if (!(options.use_login && command == NULL))                  /*
                         do_login(s, command);                   * 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 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 */                  /* NOTREACHED */
         }          }
         if (pid < 0)          if (pid < 0)
Line 607 
Line 639 
         s->ptymaster = ptymaster;          s->ptymaster = ptymaster;
   
         /* Enter interactive session. */          /* Enter interactive session. */
         packet_set_interactive(1);  
         if (compat20) {          if (compat20) {
                 session_set_fds(s, ptyfd, fdout, -1);                  session_set_fds(s, ptyfd, fdout, -1);
         } else {          } else {
Line 617 
Line 648 
         }          }
 }  }
   
 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   * Sets the value of the given variable in the environment.  If the variable
  * already exists, its value is overriden.   * already exists, its value is overriden.
  */   */
 void  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)                const char *value)
 {  {
         u_int i, namelen;          unsigned int i, namelen;
         char **env;          char **env;
   
         /*          /*
Line 746 
Line 694 
  * and assignments of the form name=value.  No other forms are allowed.   * and assignments of the form name=value.  No other forms are allowed.
  */   */
 void  void
 read_environment_file(char ***env, u_int *envsize,  read_environment_file(char ***env, unsigned int *envsize,
                       const char *filename)                        const char *filename)
 {  {
         FILE *f;          FILE *f;
Line 769 
Line 717 
                         fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);                          fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
                         continue;                          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 = '\0';
                 value++;                  value++;
                 child_set_env(env, envsize, cp, value);                  child_set_env(env, envsize, cp, value);
Line 786 
Line 731 
  * ids, and executing the command or shell.   * ids, and executing the command or shell.
  */   */
 void  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;          const char *shell, *cp = NULL;
         struct passwd * pw = s->pw;  
         char buf[256];          char buf[256];
         char cmd[1024];          FILE *f;
         FILE *f = NULL;          unsigned int envsize, i;
         u_int envsize, i;  
         char **env;          char **env;
         extern char **environ;          extern char **environ;
         struct stat st;          struct stat st;
         char *argv[10];          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 */          f = fopen("/etc/nologin", "r");
         if (options.use_login && command != NULL)          if (f) {
                 options.use_login = 0;                  /* /etc/nologin exists.  Print its contents and exit. */
                   while (fgets(buf, sizeof(buf), f))
         if (!options.use_login) {                          fputs(buf, stderr);
 #ifdef HAVE_LOGIN_CAP                  fclose(f);
                 if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)                  if (pw->pw_uid != 0)
                         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);  
                         exit(254);                          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"          /* Login(1) does this as well, and it needs uid 0 for the "-h"
            switch, so we let login(1) to this for us. */             switch, so we let login(1) to this for us. */
         if (!options.use_login) {          if (!options.use_login) {
                 if (getuid() == 0 || geteuid() == 0) {                  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) {                          if (setgid(pw->pw_gid) < 0) {
                                 perror("setgid");                                  perror("setgid");
                                 exit(1);                                  exit(1);
Line 849 
Line 775 
   
                         /* Permanently switch to the desired uid. */                          /* Permanently switch to the desired uid. */
                         permanently_set_uid(pw->pw_uid);                          permanently_set_uid(pw->pw_uid);
 #endif  
                 }                  }
                 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)                  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           * Get the shell from the password data.  An empty shell field is
          * legal, and means /bin/sh.           * legal, and means /bin/sh.
          */           */
         shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;          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  #ifdef AFS
         /* Try to get AFS tokens for the local cell. */          /* Try to get AFS tokens for the local cell. */
Line 885 
Line 807 
                 child_set_env(&env, &envsize, "USER", pw->pw_name);                  child_set_env(&env, &envsize, "USER", pw->pw_name);
                 child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);                  child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
                 child_set_env(&env, &envsize, "HOME", pw->pw_dir);                  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);                  child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
 #endif  
   
                 snprintf(buf, sizeof buf, "%.200s/%.50s",                  snprintf(buf, sizeof buf, "%.200s/%.50s",
                          _PATH_MAILDIR, pw->pw_name);                           _PATH_MAILDIR, pw->pw_name);
Line 921 
Line 838 
                  get_remote_ipaddr(), get_remote_port(), get_local_port());                   get_remote_ipaddr(), get_remote_port(), get_local_port());
         child_set_env(&env, &envsize, "SSH_CLIENT", buf);          child_set_env(&env, &envsize, "SSH_CLIENT", buf);
   
         if (s->ttyfd != -1)          if (ttyname)
                 child_set_env(&env, &envsize, "SSH_TTY", s->tty);                  child_set_env(&env, &envsize, "SSH_TTY", ttyname);
         if (s->term)          if (term)
                 child_set_env(&env, &envsize, "TERM", s->term);                  child_set_env(&env, &envsize, "TERM", term);
         if (s->display)          if (display)
                 child_set_env(&env, &envsize, "DISPLAY", s->display);                  child_set_env(&env, &envsize, "DISPLAY", display);
         if (original_command)  
                 child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",  
                     original_command);  
   
 #ifdef KRB4  #ifdef KRB4
         {          {
Line 948 
Line 862 
   
         /* read $HOME/.ssh/environment. */          /* read $HOME/.ssh/environment. */
         if (!options.use_login) {          if (!options.use_login) {
                 snprintf(buf, sizeof buf, "%.200s/.ssh/environment",                  snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir);
                     pw->pw_dir);  
                 read_environment_file(&env, &envsize, buf);                  read_environment_file(&env, &envsize, buf);
         }          }
         if (debug_flag) {          if (debug_flag) {
Line 958 
Line 871 
                 for (i = 0; env[i]; i++)                  for (i = 0; env[i]; i++)
                         fprintf(stderr, "  %.200s\n", env[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           * Close the connection descriptors; note that this is the child, and
          * the server will still have the socket open, and it is important           * the server will still have the socket open, and it is important
Line 997 
Line 907 
                 close(i);                  close(i);
   
         /* Change current directory to the user\'s home directory. */          /* 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",                  fprintf(stderr, "Could not chdir to home directory %s: %s\n",
                         pw->pw_dir, strerror(errno));                          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           * Must take new environment into use so that .ssh/rc, /etc/sshrc and
Line 1017 
Line 922 
          * in this order).           * in this order).
          */           */
         if (!options.use_login) {          if (!options.use_login) {
                 if (stat(_PATH_SSH_USER_RC, &st) >= 0) {                  if (stat(SSH_USER_RC, &st) >= 0) {
                         if (debug_flag)                          if (debug_flag)
                                 fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,                                  fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC);
                                     _PATH_SSH_USER_RC);  
                         f = popen(_PATH_BSHELL " " _PATH_SSH_USER_RC, "w");                          f = popen("/bin/sh " SSH_USER_RC, "w");
                         if (f) {                          if (f) {
                                 if (do_xauth)                                  if (auth_proto != NULL && auth_data != NULL)
                                         fprintf(f, "%s %s\n", s->auth_proto,                                          fprintf(f, "%s %s\n", auth_proto, auth_data);
                                             s->auth_data);  
                                 pclose(f);                                  pclose(f);
                         } else                          } else
                                 fprintf(stderr, "Could not run %s\n",                                  fprintf(stderr, "Could not run %s\n", SSH_USER_RC);
                                     _PATH_SSH_USER_RC);                  } else if (stat(SSH_SYSTEM_RC, &st) >= 0) {
                 } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {  
                         if (debug_flag)                          if (debug_flag)
                                 fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,                                  fprintf(stderr, "Running /bin/sh %s\n", SSH_SYSTEM_RC);
                                     _PATH_SSH_SYSTEM_RC);  
                         f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");                          f = popen("/bin/sh " SSH_SYSTEM_RC, "w");
                         if (f) {                          if (f) {
                                 if (do_xauth)                                  if (auth_proto != NULL && auth_data != NULL)
                                         fprintf(f, "%s %s\n", s->auth_proto,                                          fprintf(f, "%s %s\n", auth_proto, auth_data);
                                             s->auth_data);  
                                 pclose(f);                                  pclose(f);
                         } else                          } else
                                 fprintf(stderr, "Could not run %s\n",                                  fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
                                     _PATH_SSH_SYSTEM_RC);                  }
                 } else if (do_xauth && options.xauth_location != NULL) {  #ifdef XAUTH_PATH
                   else {
                         /* Add authority data to .Xauthority if appropriate. */                          /* Add authority data to .Xauthority if appropriate. */
                         char *screen = strchr(s->display, ':');                          if (auth_proto != NULL && auth_data != NULL) {
                                   char *screen = strchr(display, ':');
                         if (debug_flag) {                                  if (debug_flag) {
                                 fprintf(stderr,                                          fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n",
                                     "Running %.100s add "                                              XAUTH_PATH, display, auth_proto, auth_data);
                                     "%.100s %.100s %.100s\n",                                          if (screen != NULL)
                                     options.xauth_location, s->display,                                                  fprintf(stderr, "Adding %.*s/unix%s %s %s\n",
                                     s->auth_proto, s->auth_data);                                                      screen-display, display, screen, auth_proto, auth_data);
                                 if (screen != NULL)                                  }
                                         fprintf(stderr,                                  f = popen(XAUTH_PATH " -q -", "w");
                                             "Adding %.*s/unix%s %s %s\n",                                  if (f) {
                                             (int)(screen - s->display),                                          fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data);
                                             s->display, screen,                                          if (screen != NULL)
                                             s->auth_proto, s->auth_data);                                                  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. */                  /* Get the last component of the shell name. */
                 cp = strrchr(shell, '/');                  cp = strrchr(shell, '/');
                 if (cp)                  if (cp)
Line 1098 
Line 990 
                          * Check for mail if we have a tty and it was enabled                           * Check for mail if we have a tty and it was enabled
                          * in server options.                           * in server options.
                          */                           */
                         if (s->ttyfd != -1 && options.check_mail) {                          if (ttyname && options.check_mail) {
                                 char *mailbox;                                  char *mailbox;
                                 struct stat mailstat;                                  struct stat mailstat;
   
                                 mailbox = getenv("MAIL");                                  mailbox = getenv("MAIL");
                                 if (mailbox != NULL) {                                  if (mailbox != NULL) {
                                         if (stat(mailbox, &mailstat) != 0 ||                                          if (stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0)
                                             mailstat.st_size == 0)  
                                                 printf("No mail.\n");                                                  printf("No mail.\n");
                                         else if (mailstat.st_mtime < mailstat.st_atime)                                          else if (mailstat.st_mtime < mailstat.st_atime)
                                                 printf("You have mail.\n");                                                  printf("You have mail.\n");
Line 1130 
Line 1020 
                 } else {                  } else {
                         /* Launch login(1). */                          /* Launch login(1). */
   
                         execl("/usr/bin/login", "login", "-h", hostname,                          execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(),
                              "-p", "-f", "--", pw->pw_name, NULL);                                "-p", "-f", "--", pw->pw_name, NULL);
   
                         /* Login couldn't be executed, die. */                          /* Login couldn't be executed, die. */
   
Line 1214 
Line 1104 
         }          }
         s->pw = auth_get_user();          s->pw = auth_get_user();
         if (s->pw == NULL)          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);          debug("session_open: session %d: link with channel %d", s->self, chanid);
         s->chanid = chanid;          s->chanid = chanid;
         return 1;          return 1;
Line 1266 
Line 1156 
 int  int
 session_pty_req(Session *s)  session_pty_req(Session *s)
 {  {
         u_int len;          unsigned int len;
         char *term_modes;       /* encoded terminal modes */          char *term_modes;       /* encoded terminal modes */
   
         if (no_pty_flag)  
                 return 0;  
         if (s->ttyfd != -1)          if (s->ttyfd != -1)
                 return 0;                  return 0;
         s->term = packet_get_string(&len);          s->term = packet_get_string(&len);
Line 1315 
Line 1203 
 int  int
 session_subsystem_req(Session *s)  session_subsystem_req(Session *s)
 {  {
         u_int len;          unsigned int len;
         int success = 0;          int success = 0;
         char *subsys = packet_get_string(&len);          char *subsys = packet_get_string(&len);
         int i;  
   
         packet_done();          packet_done();
         log("subsystem request for %s", subsys);          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);          xfree(subsys);
         return success;          return success;
 }  }
Line 1341 
Line 1217 
 int  int
 session_x11_req(Session *s)  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) {          if (!options.x11_forwarding) {
                 debug("X11 forwarding disabled in server configuration file.");                  debug("X11 forwarding disabled in server configuration file.");
                 return 0;                  return 0;
Line 1386 
Line 1257 
                 return 0;                  return 0;
         }          }
         strlcat(xauthfile, "/cookies", MAXPATHLEN);          strlcat(xauthfile, "/cookies", MAXPATHLEN);
         fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);          open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
         if (fd >= 0)  
                 close(fd);  
         restore_uid();          restore_uid();
         fatal_add_cleanup(xauthfile_cleanup_proc, s);          fatal_add_cleanup(xauthfile_cleanup_proc, s);
         return 1;          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  void
 session_input_channel_req(int id, void *arg)  session_input_channel_req(int id, void *arg)
 {  {
         u_int len;          unsigned int len;
         int reply;          int reply;
         int success = 0;          int success = 0;
         char *rtype;          char *rtype;
Line 1475 
Line 1292 
          */           */
         if (c->type == SSH_CHANNEL_LARVAL) {          if (c->type == SSH_CHANNEL_LARVAL) {
                 if (strcmp(rtype, "shell") == 0) {                  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) {                  } 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) {                  } else if (strcmp(rtype, "pty-req") == 0) {
                         success =  session_pty_req(s);                          success =  session_pty_req(s);
                 } else if (strcmp(rtype, "x11-req") == 0) {                  } else if (strcmp(rtype, "x11-req") == 0) {
                         success = session_x11_req(s);                          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) {                  } else if (strcmp(rtype, "subsystem") == 0) {
                         success = session_subsystem_req(s);                          success = session_subsystem_req(s);
                 }                  }
Line 1514 
Line 1343 
                 fatal("no channel for session %d", s->self);                  fatal("no channel for session %d", s->self);
         channel_set_fds(s->chanid,          channel_set_fds(s->chanid,
             fdout, fdin, fderr,              fdout, fdin, fderr,
             fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,              fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ);
             1);  
 }  }
   
 void  void
Line 1524 
Line 1352 
         if (s == NULL || s->ttyfd == -1)          if (s == NULL || s->ttyfd == -1)
                 return;                  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. */          /* Cancel the cleanup function. */
         fatal_remove_cleanup(pty_cleanup_proc, (void *)s);          fatal_remove_cleanup(pty_cleanup_proc, (void *)s);
Line 1682 
Line 1510 
 }  }
   
 void  void
 do_authenticated2(Authctxt *authctxt)  do_authenticated2(void)
 {  {
         /*          /*
          * Cancel the alarm we set to limit the time taken for           * Cancel the alarm we set to limit the time taken for
          * authentication.           * authentication.
          */           */
         alarm(0);          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();          server_loop2();
         if (xauthfile)          if (xauthfile)
                 xauthfile_cleanup_proc(NULL);                  xauthfile_cleanup_proc(NULL);

Legend:
Removed from v.1.12.2.5  
changed lines
  Added in v.1.13