📄 clientloop.c
字号:
/* 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 voidclient_input_agent_open(int type, u_int32_t seq, void *ctxt){ Channel *c = NULL; int remote_id, sock; /* Read the remote channel number from the message. */ remote_id = packet_get_int(); packet_check_eom(); /* * Get a connection to the local authentication agent (this may again * get forwarded). */ sock = ssh_get_authentication_socket(); /* * If we could not connect the agent, send an error message back to * the server. This should never happen unless the agent dies, * because authentication forwarding is only enabled if we have an * agent. */ if (sock >= 0) { c = channel_new("", SSH_CHANNEL_OPEN, sock, sock, -1, 0, 0, 0, "authentication agent connection", 1); c->remote_id = remote_id; c->force_drain = 1; } if (c == NULL) { packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); packet_put_int(remote_id); } else { /* Send a confirmation to the remote host. */ debug("Forwarding authentication connection."); packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); packet_put_int(remote_id); packet_put_int(c->self); } packet_send();}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, 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, "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, "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; int rchan; u_int rmaxpack, rwindow, len; 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 exitval, 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 (id == -1) { error("client_input_channel_req: request for channel -1"); } else if ((c = channel_lookup(id)) == NULL) { error("client_input_channel_req: channel %d: unknown channel", id); } else if (strcmp(rtype, "exit-status") == 0) { exitval = packet_get_int(); if (id == session_ident) { success = 1; exit_status = exitval; } else if (c->ctl_fd == -1) { error("client_input_channel_req: unexpected channel %d", session_ident); } else { atomicio(vwrite, c->ctl_fd, &exitval, sizeof(exitval)); success = 1; } packet_check_eom(); } if (reply) { packet_start(success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); packet_put_int(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);}voidclient_session2_setup(int id, int want_tty, int want_subsystem, const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env, dispatch_fn *subsys_repl){ int len; Channel *c = NULL; debug2("%s: id %d", __func__, id); if ((c = channel_lookup(id)) == NULL) fatal("client_session2_setup: channel %d: unknown channel", id); if (want_tty) { struct winsize ws; struct termios tio; /* Store window size in the packet. */ if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) memset(&ws, 0, sizeof(ws)); channel_request_start(id, "pty-req", 0); packet_put_cstring(term != NULL ? term : ""); packet_put_int(ws.ws_col); packet_put_int(ws.ws_row); packet_put_int(ws.ws_xpixel); packet_put_int(ws.ws_ypixel); tio = get_saved_tio(); tty_make_modes(-1, tiop != NULL ? tiop : &tio); packet_send(); /* XXX wait for reply */ c->client_tty = 1; } /* Transfer any environment variables from client to server */ if (options.num_send_env != 0 && env != NULL) { int i, j, matched; char *name, *val; debug("Sending environment."); for (i = 0; env[i] != NULL; i++) { /* Split */ name = xstrdup(env[i]); if ((val = strchr(name, '=')) == NULL) { free(name); continue; } *val++ = '\0'; matched = 0; for (j = 0; j < options.num_send_env; j++) { if (match_pattern(name, options.send_env[j])) { matched = 1; break; } } if (!matched) { debug3("Ignored env %s", name); free(name); continue; } debug("Sending env %s = %s", name, val); channel_request_start(id, "env", 0); packet_put_cstring(name); packet_put_cstring(val); packet_send(); free(name); } } len = buffer_len(cmd); if (len > 0) { if (len > 900) len = 900; if (want_subsystem) { debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd)); channel_request_start(id, "subsystem", subsys_repl != NULL); if (subsys_repl != NULL) { /* register callback for reply */ /* XXX we assume that client_loop has already been called */ dispatch_set(SSH2_MSG_CHANNEL_FAILURE, subsys_repl); dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, subsys_repl); } } else { debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd)); channel_request_start(id, "exec", 0); } packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); packet_send(); } else { channel_request_start(id, "shell", 0); packet_send(); }}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 ? &client_input_agent_open : &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();}/* client specific fatal cleanup */voidcleanup_exit(int i){ leave_raw_mode(); leave_non_blocking(); if (options.control_path != NULL && control_fd != -1) unlink(options.control_path); _exit(i);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -