📄 clientloop.c
字号:
if (compat20 && session_closed && !channel_still_open()) break; rekeying = (xxx_kex != NULL && !xxx_kex->done); if (rekeying) { debug("rekeying in progress"); } else { /* * Make packets of buffered stdin data, and buffer * them for sending to the server. */ if (!compat20) client_make_packets_from_stdin_data(); /* * Make packets from buffered channel data, and * enqueue them for sending to the server. */ if (packet_not_very_much_data_to_write()) channel_output_poll(); /* * Check if the window size has changed, and buffer a * message about it to the server if so. */ client_check_window_change(); if (quit_pending) break; } /* * Wait until we have something to do (something becomes * available on one of the descriptors). */ max_fd2 = max_fd; client_wait_until_can_do_something(&readset, &writeset, &max_fd2, &nalloc, rekeying); if (quit_pending) break; /* Do channel operations unless rekeying in progress. */ if (!rekeying) { channel_after_select(readset, writeset); if (need_rekeying) { debug("user requests rekeying"); xxx_kex->done = 0; kex_send_kexinit(xxx_kex); need_rekeying = 0; } } /* Buffer input from the connection. */ client_process_net_input(readset); if (quit_pending) break; if (!compat20) { /* Buffer data from stdin */ client_process_input(readset); /* * Process output to stdout and stderr. Output to * the connection is processed elsewhere (above). */ client_process_output(writeset); } /* Send as much buffered packet data as possible to the sender. */ if (FD_ISSET(connection_out, writeset)) packet_write_poll(); } if (readset) xfree(readset); if (writeset) xfree(writeset); /* Terminate the session. */ /* Stop watching for window change. */ if (have_pty) signal(SIGWINCH, SIG_DFL); channel_free_all(); if (have_pty) leave_raw_mode(); /* restore blocking io */ if (!isatty(fileno(stdin))) unset_nonblock(fileno(stdin)); if (!isatty(fileno(stdout))) unset_nonblock(fileno(stdout)); if (!isatty(fileno(stderr))) unset_nonblock(fileno(stderr)); if (received_signal) { if (in_non_blocking_mode) /* XXX */ leave_non_blocking(); fatal("Killed by signal %d.", (int) received_signal); } /* * In interactive mode (with pseudo tty) display a message indicating * that the connection has been closed. */ if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); buffer_append(&stderr_buffer, buf, strlen(buf)); } /* Output any buffered data for stdout. */ while (buffer_len(&stdout_buffer) > 0) { len = write(fileno(stdout), buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer)); if (len <= 0) { error("Write failed flushing stdout buffer."); break; } buffer_consume(&stdout_buffer, len); stdout_bytes += len; } /* Output any buffered data for stderr. */ while (buffer_len(&stderr_buffer) > 0) { len = write(fileno(stderr), buffer_ptr(&stderr_buffer), buffer_len(&stderr_buffer)); if (len <= 0) { error("Write failed flushing stderr buffer."); break; } buffer_consume(&stderr_buffer, len); stderr_bytes += len; } /* Clear and free any buffers. */ memset(buf, 0, sizeof(buf)); buffer_free(&stdin_buffer); buffer_free(&stdout_buffer); buffer_free(&stderr_buffer); /* Report bytes transferred, and transfer rates. */ total_time = get_current_time() - start_time; debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds", stdin_bytes, stdout_bytes, stderr_bytes, total_time); if (total_time > 0) debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f", stdin_bytes / total_time, stdout_bytes / total_time, stderr_bytes / total_time); /* Return the exit status of the program. */ debug("Exit status %d", exit_status); return exit_status;}/*********/static voidclient_input_stdout_data(int type, u_int32_t seq, void *ctxt){ u_int data_len; char *data = packet_get_string(&data_len); packet_check_eom(); buffer_append(&stdout_buffer, data, data_len); memset(data, 0, data_len); xfree(data);}static voidclient_input_stderr_data(int type, u_int32_t seq, void *ctxt){ u_int data_len; char *data = packet_get_string(&data_len); packet_check_eom(); buffer_append(&stderr_buffer, data, data_len); memset(data, 0, data_len); xfree(data);}static voidclient_input_exit_status(int type, u_int32_t seq, void *ctxt){ exit_status = packet_get_int(); packet_check_eom(); /* Acknowledge the exit. */ packet_start(SSH_CMSG_EXIT_CONFIRMATION); packet_send(); /* * Must wait for packet to be sent since we are * exiting the loop. */ packet_write_wait(); /* Flag that we want to exit. */ quit_pending = 1;}static Channel *client_request_forwarded_tcpip(const char *request_type, int rchan){ Channel* c = NULL; char *listen_address, *originator_address; int listen_port, originator_port; int sock; /* Get rest of the packet */ listen_address = packet_get_string(NULL); listen_port = packet_get_int(); originator_address = packet_get_string(NULL); originator_port = packet_get_int(); packet_check_eom(); debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d", listen_address, listen_port, originator_address, originator_port); sock = channel_connect_by_listen_address(listen_port); if (sock < 0) { xfree(originator_address); xfree(listen_address); return NULL; } c = channel_new("forwarded-tcpip", SSH_CHANNEL_CONNECTING, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, xstrdup(originator_address), 1); xfree(originator_address); xfree(listen_address); return c;}static Channel*client_request_x11(const char *request_type, int rchan){ Channel *c = NULL; char *originator; int originator_port; int sock; if (!options.forward_x11) { error("Warning: ssh server tried X11 forwarding."); error("Warning: this is probably a break in attempt by a malicious server."); return NULL; } originator = packet_get_string(NULL); if (datafellows & SSH_BUG_X11FWD) { debug2("buggy server: x11 request w/o originator_port"); originator_port = 0; } else { originator_port = packet_get_int(); } packet_check_eom(); /* XXX check permission */ debug("client_request_x11: request from %s %d", originator, originator_port); xfree(originator); sock = x11_connect_display(); if (sock < 0) return NULL; c = channel_new("x11", SSH_CHANNEL_X11_OPEN, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, xstrdup("x11"), 1); c->force_drain = 1; return c;}static Channel*client_request_agent(const char *request_type, int rchan){ Channel *c = NULL; int sock; if (!options.forward_agent) { error("Warning: ssh server tried agent forwarding."); error("Warning: this is probably a break in attempt by a malicious server."); return NULL; } sock = ssh_get_authentication_socket(); if (sock < 0) return NULL; c = channel_new("authentication agent connection", SSH_CHANNEL_OPEN, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, xstrdup("authentication agent connection"), 1); c->force_drain = 1; return c;}/* XXXX move to generic input handler */static voidclient_input_channel_open(int type, u_int32_t seq, void *ctxt){ Channel *c = NULL; char *ctype; u_int len; int rchan; int rmaxpack; int rwindow; ctype = packet_get_string(&len); rchan = packet_get_int(); rwindow = packet_get_int(); rmaxpack = packet_get_int(); debug("client_input_channel_open: ctype %s rchan %d win %d max %d", ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "forwarded-tcpip") == 0) { c = client_request_forwarded_tcpip(ctype, rchan); } else if (strcmp(ctype, "x11") == 0) { c = client_request_x11(ctype, rchan); } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { c = client_request_agent(ctype, rchan); }/* XXX duplicate : */ if (c != NULL) { debug("confirm %s", ctype); c->remote_id = rchan; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; if (c->type != SSH_CHANNEL_CONNECTING) { packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); packet_put_int(c->remote_id); packet_put_int(c->self); packet_put_int(c->local_window); packet_put_int(c->local_maxpacket); packet_send(); } } else { debug("failure %s", ctype); packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); packet_put_int(rchan); packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); if (!(datafellows & SSH_BUG_OPENFAILURE)) { packet_put_cstring("open failed"); packet_put_cstring(""); } packet_send(); } xfree(ctype);}static voidclient_input_channel_req(int type, u_int32_t seq, void *ctxt){ Channel *c = NULL; int id, reply, success = 0; char *rtype; id = packet_get_int(); rtype = packet_get_string(NULL); reply = packet_get_char(); debug("client_input_channel_req: channel %d rtype %s reply %d", id, rtype, reply); if (session_ident == -1) { error("client_input_channel_req: no channel %d", session_ident); } else if (id != session_ident) { error("client_input_channel_req: channel %d: wrong channel: %d", session_ident, id); } c = channel_lookup(id); if (c == NULL) { error("client_input_channel_req: channel %d: unknown channel", id); } else if (strcmp(rtype, "exit-status") == 0) { success = 1; exit_status = packet_get_int(); packet_check_eom(); } if (reply) { packet_start(success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); packet_put_int(c->remote_id); packet_send(); } xfree(rtype);}static voidclient_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 voidclient_init_dispatch_20(void){ dispatch_init(&dispatch_protocol_error); dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open); dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); 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_WINDOW_ADJUST, &channel_input_window_adjust); dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request); /* rekeying */ 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 voidclient_init_dispatch_13(void){ dispatch_init(NULL); dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close); dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation); dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status); dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data); dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data); dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ? &auth_input_open_request : &deny_input_open); dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? &x11_input_open : &deny_input_open);}static voidclient_init_dispatch_15(void){ client_init_dispatch_13(); dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);}static voidclient_init_dispatch(void){ if (compat20) client_init_dispatch_20(); else if (compat13) client_init_dispatch_13(); else client_init_dispatch_15();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -