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

Diff for /src/usr.bin/ssh/clientloop.c between version 1.84 and 1.84.2.3

version 1.84, 2001/10/11 15:24:00 version 1.84.2.3, 2002/05/17 00:03:23
Line 81 
Line 81 
 #include "atomicio.h"  #include "atomicio.h"
 #include "sshtty.h"  #include "sshtty.h"
 #include "misc.h"  #include "misc.h"
   #include "readpass.h"
   
 /* import options */  /* import options */
 extern Options options;  extern Options options;
Line 101 
Line 102 
  * window size to be sent to the server a little later.  This is volatile   * window size to be sent to the server a little later.  This is volatile
  * because this is updated in a signal handler.   * because this is updated in a signal handler.
  */   */
 static volatile int received_window_change_signal = 0;  static volatile sig_atomic_t received_window_change_signal = 0;
 static volatile int received_signal = 0;  static volatile sig_atomic_t received_signal = 0;
   
 /* Flag indicating whether the user\'s terminal is in non-blocking mode. */  /* Flag indicating whether the user\'s terminal is in non-blocking mode. */
 static int in_non_blocking_mode = 0;  static int in_non_blocking_mode = 0;
Line 254 
Line 255 
   
         /* Send buffered stdin data to the server. */          /* Send buffered stdin data to the server. */
         while (buffer_len(&stdin_buffer) > 0 &&          while (buffer_len(&stdin_buffer) > 0 &&
                packet_not_very_much_data_to_write()) {              packet_not_very_much_data_to_write()) {
                 len = buffer_len(&stdin_buffer);                  len = buffer_len(&stdin_buffer);
                 /* Keep the packets at reasonable size. */                  /* Keep the packets at reasonable size. */
                 if (len > packet_get_maxsize())                  if (len > packet_get_maxsize())
Line 346 
Line 347 
                 if (session_closed && !channel_still_open() &&                  if (session_closed && !channel_still_open() &&
                     !packet_have_data_to_write()) {                      !packet_have_data_to_write()) {
                         /* clear mask since we did not call select() */                          /* clear mask since we did not call select() */
                         memset(*readsetp, 0, *maxfdp);                          memset(*readsetp, 0, *nallocp);
                         memset(*writesetp, 0, *maxfdp);                          memset(*writesetp, 0, *nallocp);
                         return;                          return;
                 } else {                  } else {
                         FD_SET(connection_in, *readsetp);                          FD_SET(connection_in, *readsetp);
Line 375 
Line 376 
                  * We have to return, because the mainloop checks for the flags                   * We have to return, because the mainloop checks for the flags
                  * set by the signal handlers.                   * set by the signal handlers.
                  */                   */
                 memset(*readsetp, 0, *maxfdp);                  memset(*readsetp, 0, *nallocp);
                 memset(*writesetp, 0, *maxfdp);                  memset(*writesetp, 0, *nallocp);
   
                 if (errno == EINTR)                  if (errno == EINTR)
                         return;                          return;
Line 417 
Line 418 
         /* Check if the window size has changed. */          /* Check if the window size has changed. */
         if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&          if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
             (oldws.ws_row != newws.ws_row ||              (oldws.ws_row != newws.ws_row ||
              oldws.ws_col != newws.ws_col ||              oldws.ws_col != newws.ws_col ||
              oldws.ws_xpixel != newws.ws_xpixel ||              oldws.ws_xpixel != newws.ws_xpixel ||
              oldws.ws_ypixel != newws.ws_ypixel))              oldws.ws_ypixel != newws.ws_ypixel))
                 received_window_change_signal = 1;                  received_window_change_signal = 1;
   
         /* OK, we have been continued by the user. Reinitialize buffers. */          /* OK, we have been continued by the user. Reinitialize buffers. */
Line 470 
Line 471 
         }          }
 }  }
   
   static void
   process_cmdline(void)
   {
           void (*handler)(int);
           char *s, *cmd;
           u_short fwd_port, fwd_host_port;
           char buf[1024], sfwd_port[6], sfwd_host_port[6];
           int local = 0;
   
           leave_raw_mode();
           handler = signal(SIGINT, SIG_IGN);
           cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
           if (s == NULL)
                   goto out;
           while (*s && isspace(*s))
                   s++;
           if (*s == 0)
                   goto out;
           if (strlen(s) < 2 || s[0] != '-' || !(s[1] == 'L' || s[1] == 'R')) {
                   log("Invalid command.");
                   goto out;
           }
           if (s[1] == 'L')
                   local = 1;
           if (!local && !compat20) {
                   log("Not supported for SSH protocol version 1.");
                   goto out;
           }
           s += 2;
           while (*s && isspace(*s))
                   s++;
   
           if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]",
               sfwd_port, buf, sfwd_host_port) != 3 &&
               sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
               sfwd_port, buf, sfwd_host_port) != 3) {
                   log("Bad forwarding specification.");
                   goto out;
           }
           if ((fwd_port = a2port(sfwd_port)) == 0 ||
               (fwd_host_port = a2port(sfwd_host_port)) == 0) {
                   log("Bad forwarding port(s).");
                   goto out;
           }
           if (local) {
                   if (channel_setup_local_fwd_listener(fwd_port, buf,
                       fwd_host_port, options.gateway_ports) < 0) {
                           log("Port forwarding failed.");
                           goto out;
                   }
           } else
                   channel_request_remote_forwarding(fwd_port, buf,
                       fwd_host_port);
           log("Forwarding port.");
   out:
           signal(SIGINT, handler);
           enter_raw_mode();
           if (cmd)
                   xfree(cmd);
   }
   
 /* process the characters one by one */  /* process the characters one by one */
 static int  static int
 process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)  process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
Line 522 
Line 584 
                                 continue;                                  continue;
   
                         case '&':                          case '&':
                                 /* XXX does not work yet with proto 2 */  
                                 if (compat20)  
                                         continue;  
                                 /*                                  /*
                                  * Detach the program (continue to serve connections,                                   * Detach the program (continue to serve connections,
                                  * but put in background and no more new connections).                                   * but put in background and no more new connections).
                                  */                                   */
                                 if (!stdin_eof) {  
                                         /*  
                                          * Sending SSH_CMSG_EOF alone does not always appear  
                                          * to be enough.  So we try to send an EOF character  
                                          * first.  
                                          */  
                                         packet_start(SSH_CMSG_STDIN_DATA);  
                                         packet_put_string("\004", 1);  
                                         packet_send();  
                                         /* Close stdin. */  
                                         stdin_eof = 1;  
                                         if (buffer_len(bin) == 0) {  
                                                 packet_start(SSH_CMSG_EOF);  
                                                 packet_send();  
                                         }  
                                 }  
                                 /* Restore tty modes. */                                  /* Restore tty modes. */
                                 leave_raw_mode();                                  leave_raw_mode();
   
                                 /* Stop listening for new connections. */                                  /* Stop listening for new connections. */
                                 channel_close_all();    /* proto1 only XXXX */                                  channel_stop_listening();
   
                                 printf("%c& [backgrounded]\n", escape_char);                                  snprintf(string, sizeof string,
                                       "%c& [backgrounded]\n", escape_char);
                                   buffer_append(berr, string, strlen(string));
   
                                 /* Fork into background. */                                  /* Fork into background. */
                                 pid = fork();                                  pid = fork();
Line 564 
Line 609 
                                         exit(0);                                          exit(0);
                                 }                                  }
                                 /* The child continues serving connections. */                                  /* The child continues serving connections. */
                                 continue; /*XXX ? */                                  if (compat20) {
                                           buffer_append(bin, "\004", 1);
                                           /* fake EOF on stdin */
                                           return -1;
                                   } else if (!stdin_eof) {
                                           /*
                                            * Sending SSH_CMSG_EOF alone does not always appear
                                            * to be enough.  So we try to send an EOF character
                                            * first.
                                            */
                                           packet_start(SSH_CMSG_STDIN_DATA);
                                           packet_put_string("\004", 1);
                                           packet_send();
                                           /* Close stdin. */
                                           stdin_eof = 1;
                                           if (buffer_len(bin) == 0) {
                                                   packet_start(SSH_CMSG_EOF);
                                                   packet_send();
                                           }
                                   }
                                   continue;
   
                         case '?':                          case '?':
                                 snprintf(string, sizeof string,                                  snprintf(string, sizeof string,
 "%c?\r\n\  "%c?\r\n\
 Supported escape sequences:\r\n\  Supported escape sequences:\r\n\
 ~.  - terminate connection\r\n\  ~.  - terminate connection\r\n\
   ~C  - open a command line\r\n\
 ~R  - Request rekey (SSH protocol 2 only)\r\n\  ~R  - Request rekey (SSH protocol 2 only)\r\n\
 ~^Z - suspend ssh\r\n\  ~^Z - suspend ssh\r\n\
 ~#  - list forwarded connections\r\n\  ~#  - list forwarded connections\r\n\
Line 590 
Line 656 
                                 xfree(s);                                  xfree(s);
                                 continue;                                  continue;
   
                           case 'C':
                                   process_cmdline();
                                   continue;
   
                         default:                          default:
                                 if (ch != escape_char) {                                  if (ch != escape_char) {
                                         buffer_put_char(bin, escape_char);                                          buffer_put_char(bin, escape_char);
Line 820 
Line 890 
         signal(SIGINT, signal_handler);          signal(SIGINT, signal_handler);
         signal(SIGQUIT, signal_handler);          signal(SIGQUIT, signal_handler);
         signal(SIGTERM, signal_handler);          signal(SIGTERM, signal_handler);
         signal(SIGPIPE, SIG_IGN);  
         if (have_pty)          if (have_pty)
                 signal(SIGWINCH, window_change_handler);                  signal(SIGWINCH, window_change_handler);
   
Line 947 
Line 1016 
         if (received_signal) {          if (received_signal) {
                 if (in_non_blocking_mode)       /* XXX */                  if (in_non_blocking_mode)       /* XXX */
                         leave_non_blocking();                          leave_non_blocking();
                 fatal("Killed by signal %d.", received_signal);                  fatal("Killed by signal %d.", (int) received_signal);
         }          }
   
         /*          /*
Line 992 
Line 1061 
         /* Report bytes transferred, and transfer rates. */          /* Report bytes transferred, and transfer rates. */
         total_time = get_current_time() - start_time;          total_time = get_current_time() - start_time;
         debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",          debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",
               stdin_bytes, stdout_bytes, stderr_bytes, total_time);              stdin_bytes, stdout_bytes, stderr_bytes, total_time);
         if (total_time > 0)          if (total_time > 0)
                 debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",                  debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",
                       stdin_bytes / total_time, stdout_bytes / total_time,                      stdin_bytes / total_time, stdout_bytes / total_time,
                       stderr_bytes / total_time);                      stderr_bytes / total_time);
   
         /* Return the exit status of the program. */          /* Return the exit status of the program. */
         debug("Exit status %d", exit_status);          debug("Exit status %d", exit_status);
Line 1006 
Line 1075 
 /*********/  /*********/
   
 static void  static void
 client_input_stdout_data(int type, int plen, void *ctxt)  client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
 {  {
         u_int data_len;          u_int data_len;
         char *data = packet_get_string(&data_len);          char *data = packet_get_string(&data_len);
         packet_integrity_check(plen, 4 + data_len, type);          packet_check_eom();
         buffer_append(&stdout_buffer, data, data_len);          buffer_append(&stdout_buffer, data, data_len);
         memset(data, 0, data_len);          memset(data, 0, data_len);
         xfree(data);          xfree(data);
 }  }
 static void  static void
 client_input_stderr_data(int type, int plen, void *ctxt)  client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
 {  {
         u_int data_len;          u_int data_len;
         char *data = packet_get_string(&data_len);          char *data = packet_get_string(&data_len);
         packet_integrity_check(plen, 4 + data_len, type);          packet_check_eom();
         buffer_append(&stderr_buffer, data, data_len);          buffer_append(&stderr_buffer, data, data_len);
         memset(data, 0, data_len);          memset(data, 0, data_len);
         xfree(data);          xfree(data);
 }  }
 static void  static void
 client_input_exit_status(int type, int plen, void *ctxt)  client_input_exit_status(int type, u_int32_t seq, void *ctxt)
 {  {
         packet_integrity_check(plen, 4, type);  
         exit_status = packet_get_int();          exit_status = packet_get_int();
           packet_check_eom();
         /* Acknowledge the exit. */          /* Acknowledge the exit. */
         packet_start(SSH_CMSG_EXIT_CONFIRMATION);          packet_start(SSH_CMSG_EXIT_CONFIRMATION);
         packet_send();          packet_send();
Line 1055 
Line 1124 
         listen_port = packet_get_int();          listen_port = packet_get_int();
         originator_address = packet_get_string(NULL);          originator_address = packet_get_string(NULL);
         originator_port = packet_get_int();          originator_port = packet_get_int();
         packet_done();          packet_check_eom();
   
         debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d",          debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d",
             listen_address, listen_port, originator_address, originator_port);              listen_address, listen_port, originator_address, originator_port);
Line 1070 
Line 1139 
             SSH_CHANNEL_CONNECTING, sock, sock, -1,              SSH_CHANNEL_CONNECTING, sock, sock, -1,
             CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,              CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
             xstrdup(originator_address), 1);              xstrdup(originator_address), 1);
         if (c == NULL) {  
                 error("client_request_forwarded_tcpip: channel_new failed");  
                 close(sock);  
         }  
         xfree(originator_address);          xfree(originator_address);
         xfree(listen_address);          xfree(listen_address);
         return c;          return c;
Line 1099 
Line 1164 
         } else {          } else {
                 originator_port = packet_get_int();                  originator_port = packet_get_int();
         }          }
         packet_done();          packet_check_eom();
         /* XXX check permission */          /* XXX check permission */
         debug("client_request_x11: request from %s %d", originator,          debug("client_request_x11: request from %s %d", originator,
             originator_port);              originator_port);
Line 1111 
Line 1176 
             SSH_CHANNEL_X11_OPEN, sock, sock, -1,              SSH_CHANNEL_X11_OPEN, sock, sock, -1,
             CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0,              CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0,
             xstrdup("x11"), 1);              xstrdup("x11"), 1);
         if (c == NULL) {  
                 error("client_request_x11: channel_new failed");  
                 close(sock);  
         }  
         c->force_drain = 1;          c->force_drain = 1;
         return c;          return c;
 }  }
Line 1137 
Line 1198 
             SSH_CHANNEL_OPEN, sock, sock, -1,              SSH_CHANNEL_OPEN, sock, sock, -1,
             CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,              CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
             xstrdup("authentication agent connection"), 1);              xstrdup("authentication agent connection"), 1);
         if (c == NULL) {  
                 error("client_request_agent: channel_new failed");  
                 close(sock);  
         }  
         c->force_drain = 1;          c->force_drain = 1;
         return c;          return c;
 }  }
   
 /* XXXX move to generic input handler */  /* XXXX move to generic input handler */
 static void  static void
 client_input_channel_open(int type, int plen, void *ctxt)  client_input_channel_open(int type, u_int32_t seq, void *ctxt)
 {  {
         Channel *c = NULL;          Channel *c = NULL;
         char *ctype;          char *ctype;
Line 1199 
Line 1256 
         xfree(ctype);          xfree(ctype);
 }  }
 static void  static void
 client_input_channel_req(int type, int plen, void *ctxt)  client_input_channel_req(int type, u_int32_t seq, void *ctxt)
 {  {
         Channel *c = NULL;          Channel *c = NULL;
         int id, reply, success = 0;          int id, reply, success = 0;
Line 1224 
Line 1281 
         } else if (strcmp(rtype, "exit-status") == 0) {          } else if (strcmp(rtype, "exit-status") == 0) {
                 success = 1;                  success = 1;
                 exit_status = packet_get_int();                  exit_status = packet_get_int();
                 packet_done();                  packet_check_eom();
         }          }
         if (reply) {          if (reply) {
                 packet_start(success ?                  packet_start(success ?
Line 1234 
Line 1291 
         }          }
         xfree(rtype);          xfree(rtype);
 }  }
   static void
   client_input_global_request(int type, u_int32_t seq, void *ctxt)
   {
           char *rtype;
           int want_reply;
           int success = 0;
   
           rtype = packet_get_string(NULL);
           want_reply = packet_get_char();
           debug("client_input_global_request: rtype %s want_reply %d", rtype, want_reply);
           if (want_reply) {
                   packet_start(success ?
                       SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
                   packet_send();
                   packet_write_wait();
           }
           xfree(rtype);
   }
   
 static void  static void
 client_init_dispatch_20(void)  client_init_dispatch_20(void)
 {  {
         dispatch_init(&dispatch_protocol_error);          dispatch_init(&dispatch_protocol_error);
   
         dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);          dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
         dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);          dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
         dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);          dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
Line 1248 
Line 1324 
         dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);          dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
         dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);          dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
         dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);          dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
           dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
   
         /* rekeying */          /* rekeying */
         dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);          dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
   
           /* global request reply messages */
           dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
           dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
 }  }
 static void  static void
 client_init_dispatch_13(void)  client_init_dispatch_13(void)

Legend:
Removed from v.1.84  
changed lines
  Added in v.1.84.2.3