ssh.c
来自「OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它」· C语言 代码 · 共 1,431 行 · 第 1/3 页
C
1,431 行
/* Send the packet, and wait for it to leave. */ packet_send(); packet_write_wait(); /* Read response from the server. */ type = packet_read(); if (type == SSH_SMSG_SUCCESS) { interactive = 1; have_tty = 1; } else if (type == SSH_SMSG_FAILURE) logit("Warning: Remote host failed or refused to allocate a pseudo tty."); else packet_disconnect("Protocol error waiting for pty request response."); } /* Request X11 forwarding if enabled and DISPLAY is set. */ if (options.forward_x11 && getenv("DISPLAY") != NULL) { char *proto, *data; /* Get reasonable local authentication information. */ x11_get_proto(&proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication spoofing."); x11_request_forwarding_with_spoofing(0, proto, data); /* Read response from the server. */ type = packet_read(); if (type == SSH_SMSG_SUCCESS) { interactive = 1; } else if (type == SSH_SMSG_FAILURE) { logit("Warning: Remote host denied X11 forwarding."); } else { packet_disconnect("Protocol error waiting for X11 forwarding"); } } /* Tell the packet module whether this is an interactive session. */ packet_set_interactive(interactive); /* Request authentication agent forwarding if appropriate. */ check_agent_present(); if (options.forward_agent) { debug("Requesting authentication agent forwarding."); auth_request_forwarding(); /* Read response from the server. */ type = packet_read(); packet_check_eom(); if (type != SSH_SMSG_SUCCESS) logit("Warning: Remote host denied authentication agent forwarding."); } /* Initiate port forwardings. */ ssh_init_forwarding(); /* If requested, let ssh continue in the background. */ if (fork_after_authentication_flag) if (daemon(1, 1) < 0) fatal("daemon() failed: %.200s", strerror(errno)); /* * If a command was specified on the command line, execute the * command now. Otherwise request the server to start a shell. */ if (buffer_len(&command) > 0) { int len = buffer_len(&command); if (len > 900) len = 900; debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); packet_start(SSH_CMSG_EXEC_CMD); packet_put_string(buffer_ptr(&command), buffer_len(&command)); packet_send(); packet_write_wait(); } else { debug("Requesting shell."); packet_start(SSH_CMSG_EXEC_SHELL); packet_send(); packet_write_wait(); } /* Enter the interactive session. */ return client_loop(have_tty, tty_flag ? options.escape_char : SSH_ESCAPECHAR_NONE, 0);}static voidssh_subsystem_reply(int type, u_int32_t seq, void *ctxt){ int id, len; id = packet_get_int(); len = buffer_len(&command); if (len > 900) len = 900; packet_check_eom(); if (type == SSH2_MSG_CHANNEL_FAILURE) fatal("Request for subsystem '%.*s' failed on channel %d", len, (u_char *)buffer_ptr(&command), id);}voidclient_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt){ int i; i = client_global_request_id++; if (i >= options.num_remote_forwards) return; debug("remote forward %s for: listen %d, connect %s:%d", type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", options.remote_forwards[i].listen_port, options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_port); if (type == SSH2_MSG_REQUEST_FAILURE) logit("Warning: remote port forwarding failed for listen " "port %d", options.remote_forwards[i].listen_port);}static voidssh_control_listener(void){ struct sockaddr_un addr; mode_t old_umask; int addr_len; if (options.control_path == NULL || options.control_master <= 0) return; memset(&addr, '\0', sizeof(addr)); addr.sun_family = AF_UNIX; addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(options.control_path) + 1; if (strlcpy(addr.sun_path, options.control_path, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) fatal("ControlPath too long"); if ((control_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) fatal("%s socket(): %s\n", __func__, strerror(errno)); old_umask = umask(0177); if (bind(control_fd, (struct sockaddr*)&addr, addr_len) == -1) { control_fd = -1; if (errno == EINVAL) fatal("ControlSocket %s already exists", options.control_path); else fatal("%s bind(): %s\n", __func__, strerror(errno)); } umask(old_umask); if (listen(control_fd, 64) == -1) fatal("%s listen(): %s\n", __func__, strerror(errno)); set_nonblock(control_fd);}/* request pty/x11/agent/tcpfwd/shell for channel */static voidssh_session2_setup(int id, void *arg){ extern char **environ; int interactive = tty_flag; if (options.forward_x11 && getenv("DISPLAY") != NULL) { char *proto, *data; /* Get reasonable local authentication information. */ x11_get_proto(&proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication spoofing."); x11_request_forwarding_with_spoofing(id, proto, data); interactive = 1; /* XXX wait for reply */ } check_agent_present(); if (options.forward_agent) { debug("Requesting authentication agent forwarding."); channel_request_start(id, "auth-agent-req@openssh.com", 0); packet_send(); } client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply); packet_set_interactive(interactive);}/* open new channel for a session */static intssh_session2_open(void){ Channel *c; int window, packetmax, in, out, err; if (stdin_null_flag) { in = open(_PATH_DEVNULL, O_RDONLY); } else { in = dup(STDIN_FILENO); } out = dup(STDOUT_FILENO); err = dup(STDERR_FILENO); if (in < 0 || out < 0 || err < 0) fatal("dup() in/out/err failed"); /* enable nonblocking unless tty */ if (!isatty(in)) set_nonblock(in); if (!isatty(out)) set_nonblock(out); if (!isatty(err)) set_nonblock(err); window = CHAN_SES_WINDOW_DEFAULT; packetmax = CHAN_SES_PACKET_DEFAULT; if (tty_flag) { window >>= 1; packetmax >>= 1; } c = channel_new( "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); debug3("ssh_session2_open: channel_new: %d", c->self); channel_send_open(c->self); if (!no_shell_flag) channel_register_confirm(c->self, ssh_session2_setup, NULL); return c->self;}static intssh_session2(void){ int id = -1; /* XXX should be pre-session */ ssh_init_forwarding(); ssh_control_listener(); if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) id = ssh_session2_open(); /* If requested, let ssh continue in the background. */ if (fork_after_authentication_flag) if (daemon(1, 1) < 0) fatal("daemon() failed: %.200s", strerror(errno)); return client_loop(tty_flag, tty_flag ? options.escape_char : SSH_ESCAPECHAR_NONE, id);}static voidload_public_identity_files(void){ char *filename; int i = 0; Key *public;#ifdef SMARTCARD Key **keys; if (options.smartcard_device != NULL && options.num_identity_files < SSH_MAX_IDENTITY_FILES && (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) { int count = 0; for (i = 0; keys[i] != NULL; i++) { count++; memmove(&options.identity_files[1], &options.identity_files[0], sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1)); memmove(&options.identity_keys[1], &options.identity_keys[0], sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1)); options.num_identity_files++; options.identity_keys[0] = keys[i]; options.identity_files[0] = sc_get_key_label(keys[i]); } if (options.num_identity_files > SSH_MAX_IDENTITY_FILES) options.num_identity_files = SSH_MAX_IDENTITY_FILES; i = count; xfree(keys); }#endif /* SMARTCARD */ for (; i < options.num_identity_files; i++) { filename = tilde_expand_filename(options.identity_files[i], original_real_uid); public = key_load_public(filename, NULL); debug("identity file %s type %d", filename, public ? public->type : -1); xfree(options.identity_files[i]); options.identity_files[i] = filename; options.identity_keys[i] = public; }}static voidcontrol_client_sighandler(int signo){ control_client_terminate = signo;}static voidcontrol_client_sigrelay(int signo){ if (control_server_pid > 1) kill(control_server_pid, signo);}static intenv_permitted(char *env){ int i; char name[1024], *cp; strlcpy(name, env, sizeof(name)); if ((cp = strchr(name, '=')) == NULL) return (0); *cp = '\0'; for (i = 0; i < options.num_send_env; i++) if (match_pattern(name, options.send_env[i])) return (1); return (0);}static voidcontrol_client(const char *path){ struct sockaddr_un addr; int i, r, fd, sock, exitval, num_env, addr_len; Buffer m; char *term; extern char **environ; u_int flags; if (stdin_null_flag) { if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1) fatal("open(/dev/null): %s", strerror(errno)); if (dup2(fd, STDIN_FILENO) == -1) fatal("dup2: %s", strerror(errno)); if (fd > STDERR_FILENO) close(fd); } memset(&addr, '\0', sizeof(addr)); addr.sun_family = AF_UNIX; addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(path) + 1; if (strlcpy(addr.sun_path, path, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) fatal("ControlPath too long"); if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) fatal("%s socket(): %s", __func__, strerror(errno)); if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1) fatal("Couldn't connect to %s: %s", path, strerror(errno)); if ((term = getenv("TERM")) == NULL) term = ""; flags = 0; if (tty_flag) flags |= SSHMUX_FLAG_TTY; if (subsystem_flag) flags |= SSHMUX_FLAG_SUBSYS; buffer_init(&m); /* Send our command to server */ buffer_put_int(&m, mux_command); buffer_put_int(&m, flags); if (ssh_msg_send(sock, /* version */1, &m) == -1) fatal("%s: msg_send", __func__); buffer_clear(&m); /* Get authorisation status and PID of controlee */ if (ssh_msg_recv(sock, &m) == -1) fatal("%s: msg_recv", __func__); if (buffer_get_char(&m) != 1) fatal("%s: wrong version", __func__); if (buffer_get_int(&m) != 1) fatal("Connection to master denied"); control_server_pid = buffer_get_int(&m); buffer_clear(&m); switch (mux_command) { case SSHMUX_COMMAND_ALIVE_CHECK: fprintf(stderr, "Master running (pid=%d)\r\n", control_server_pid); exit(0); case SSHMUX_COMMAND_TERMINATE: fprintf(stderr, "Exit request sent.\r\n"); exit(0); case SSHMUX_COMMAND_OPEN: /* continue below */ break; default: fatal("silly mux_command %d", mux_command); } /* SSHMUX_COMMAND_OPEN */ buffer_put_cstring(&m, term); buffer_append(&command, "\0", 1); buffer_put_cstring(&m, buffer_ptr(&command)); if (options.num_send_env == 0 || environ == NULL) { buffer_put_int(&m, 0); } else { /* Pass environment */ num_env = 0; for (i = 0; environ[i] != NULL; i++) if (env_permitted(environ[i])) num_env++; /* Count */ buffer_put_int(&m, num_env); for (i = 0; environ[i] != NULL && num_env >= 0; i++) if (env_permitted(environ[i])) { num_env--; buffer_put_cstring(&m, environ[i]); } } if (ssh_msg_send(sock, /* version */1, &m) == -1) fatal("%s: msg_send", __func__); mm_send_fd(sock, STDIN_FILENO); mm_send_fd(sock, STDOUT_FILENO); mm_send_fd(sock, STDERR_FILENO); /* Wait for reply, so master has a chance to gather ttymodes */ buffer_clear(&m); if (ssh_msg_recv(sock, &m) == -1) fatal("%s: msg_recv", __func__); if (buffer_get_char(&m) != 1) fatal("%s: wrong version", __func__); buffer_free(&m); signal(SIGHUP, control_client_sighandler); signal(SIGINT, control_client_sighandler); signal(SIGTERM, control_client_sighandler); signal(SIGWINCH, control_client_sigrelay); if (tty_flag) enter_raw_mode(); /* Stick around until the controlee closes the client_fd */ exitval = 0; for (;!control_client_terminate;) { r = read(sock, &exitval, sizeof(exitval)); if (r == 0) { debug2("Received EOF from master"); break; } if (r > 0) debug2("Received exit status from master %d", exitval); if (r == -1 && errno != EINTR) fatal("%s: read %s", __func__, strerror(errno)); } if (control_client_terminate) debug2("Exiting on signal %d", control_client_terminate); close(sock); leave_raw_mode(); if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET) fprintf(stderr, "Connection to master closed.\r\n"); exit(exitval);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?