/* * Connect to the given ssh server using a proxy command. */ static int ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) { /* * Win32 code. */ #ifdef WIN32_FIXME PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {0}; char *fullCmd = NULL; char strport[NI_MAXSERV] = {0}; int sockin[2] = {-1, -1}; int sockout[2] = {-1, -1}; int exitCode = -1; /* * Create command to execute as proxy. */ debug("Creating proxy command..."); snprintf(strport, sizeof strport, "%hu", port); fullCmd = percent_expand(proxy_command, "h", host, "p", strport, (char *) NULL); FAIL(fullCmd == NULL); /* * Create socket pairs for stdin and stdout. */ debug("Creating socket pairs for proxy process..."); socketpair(sockin); socketpair(sockout); debug("sockin[0]: %d sockin[1]: %d", sockin[0], sockin[1]); debug("sockout[0]: %d sockout[1]: %d", sockout[0], sockout[1]); permanently_drop_suid(original_real_uid); /* * Assign sockets to StartupInfo */ si.cb = sizeof(STARTUPINFO); si.hStdInput = (HANDLE) sfd_to_handle(sockin[0]); si.hStdOutput = (HANDLE) sfd_to_handle(sockout[0]); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); si.wShowWindow = SW_HIDE; si.dwFlags = STARTF_USESTDHANDLES; si.lpDesktop = NULL; /* * Create proxy process with given stdout/stdin. */ debug("Executing proxy command: \"%.500s\"...\n", fullCmd); FAIL(CreateProcess(NULL, fullCmd, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi) == FALSE); proxy_command_handle = pi.hProcess; proxy_command_pid = pi.dwProcessId; /* * Redirect network in/out to proxy sockets. */ packet_set_connection(sockout[1], sockin[1]); exitCode = 0; fail: /* / Clean up. */ close(sockout[0]); close(sockin[0]); CloseHandle(pi.hThread); free(fullCmd); /* * Error handler. */ if (exitCode) { debug("Error cannot create proxy process (%u).\n", (unsigned int) GetLastError()); close(sockout[1]); close(sockin[1]); CloseHandle(pi.hProcess); } return exitCode; #else /* * Original OpenSSH code. */ char *command_string; int pin[2], pout[2]; pid_t pid; char *shell; if ((shell = getenv("SHELL")) == NULL || *shell == '\0') shell = _PATH_BSHELL; /* Create pipes for communicating with the proxy. */ if (pipe(pin) < 0 || pipe(pout) < 0) fatal("Could not create pipes to communicate with the proxy: %.100s", strerror(errno)); command_string = expand_proxy_command(proxy_command, options.user, host, port); debug("Executing proxy command: %.500s", command_string); /* Fork and execute the proxy command. */ if ((pid = fork()) == 0) { char *argv[10]; /* Child. Permanently give up superuser privileges. */ permanently_drop_suid(original_real_uid); /* Redirect stdin and stdout. */ close(pin[1]); if (pin[0] != 0) { if (dup2(pin[0], 0) < 0) perror("dup2 stdin"); close(pin[0]); } close(pout[0]); if (dup2(pout[1], 1) < 0) perror("dup2 stdout"); /* Cannot be 1 because pin allocated two descriptors. */ close(pout[1]); /* Stderr is left as it is so that error messages get printed on the user's terminal. */ argv[0] = shell; argv[1] = "-c"; argv[2] = command_string; argv[3] = NULL; /* Execute the proxy command. Note that we gave up any extra privileges above. */ signal(SIGPIPE, SIG_DFL); execv(argv[0], argv); perror(argv[0]); exit(1); } /* Parent. */ if (pid < 0) fatal("fork failed: %.100s", strerror(errno)); else proxy_command_pid = pid; /* save pid to clean up later */ /* Close child side of the descriptors. */ close(pin[0]); close(pout[1]); /* Free the command name. */ free(command_string); /* Set the connection file descriptors. */ packet_set_connection(pout[0], pin[1]); /* Indicate OK return */ return 0; #endif /* else WIN32_FIXME */ }
/* * Connect to the given ssh server using a proxy command that passes a * a connected fd back to us. */ static int ssh_proxy_fdpass_connect(const char *host, u_short port, const char *proxy_command) { #ifdef WIN32_FIXME //PRAGMA:TODO return 0; #else char *command_string; int sp[2], sock; pid_t pid; char *shell; if ((shell = getenv("SHELL")) == NULL) shell = _PATH_BSHELL; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0) fatal("Could not create socketpair to communicate with " "proxy dialer: %.100s", strerror(errno)); command_string = expand_proxy_command(proxy_command, options.user, host, port); debug("Executing proxy dialer command: %.500s", command_string); /* Fork and execute the proxy command. */ if ((pid = fork()) == 0) { char *argv[10]; /* Child. Permanently give up superuser privileges. */ permanently_drop_suid(original_real_uid); close(sp[1]); /* Redirect stdin and stdout. */ if (sp[0] != 0) { if (dup2(sp[0], 0) < 0) perror("dup2 stdin"); } if (sp[0] != 1) { if (dup2(sp[0], 1) < 0) perror("dup2 stdout"); } if (sp[0] >= 2) close(sp[0]); /* * Stderr is left as it is so that error messages get * printed on the user's terminal. */ argv[0] = shell; argv[1] = "-c"; argv[2] = command_string; argv[3] = NULL; /* * Execute the proxy command. * Note that we gave up any extra privileges above. */ execv(argv[0], argv); perror(argv[0]); exit(1); } /* Parent. */ if (pid < 0) fatal("fork failed: %.100s", strerror(errno)); close(sp[0]); free(command_string); if ((sock = mm_receive_fd(sp[1])) == -1) fatal("proxy dialer did not pass back a connection"); while (waitpid(pid, NULL, 0) == -1) if (errno != EINTR) fatal("Couldn't wait for child: %s", strerror(errno)); /* Set the connection file descriptors. */ packet_set_connection(sock, sock); return 0; #endif }
/* * Connect to the given ssh server using a proxy command. */ static struct ssh * ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) { struct ssh *ssh; char *command_string, *tmp; int pin[2], pout[2]; pid_t pid; char *shell, strport[NI_MAXSERV]; if ((shell = getenv("SHELL")) == NULL || *shell == '\0') shell = _PATH_BSHELL; /* Convert the port number into a string. */ snprintf(strport, sizeof strport, "%hu", port); /* * Build the final command string in the buffer by making the * appropriate substitutions to the given proxy command. * * Use "exec" to avoid "sh -c" processes on some platforms * (e.g. Solaris) */ xasprintf(&tmp, "exec %s", proxy_command); command_string = percent_expand(tmp, "h", host, "p", strport, "r", options.user, (char *)NULL); xfree(tmp); /* Create pipes for communicating with the proxy. */ if (pipe(pin) < 0 || pipe(pout) < 0) fatal("Could not create pipes to communicate with the proxy: %.100s", strerror(errno)); debug("Executing proxy command: %.500s", command_string); /* Fork and execute the proxy command. */ if ((pid = fork()) == 0) { char *argv[10]; /* Child. Permanently give up superuser privileges. */ permanently_drop_suid(original_real_uid); /* Redirect stdin and stdout. */ close(pin[1]); if (pin[0] != 0) { if (dup2(pin[0], 0) < 0) perror("dup2 stdin"); close(pin[0]); } close(pout[0]); if (dup2(pout[1], 1) < 0) perror("dup2 stdout"); /* Cannot be 1 because pin allocated two descriptors. */ close(pout[1]); /* Stderr is left as it is so that error messages get printed on the user's terminal. */ argv[0] = shell; argv[1] = "-c"; argv[2] = command_string; argv[3] = NULL; /* Execute the proxy command. Note that we gave up any extra privileges above. */ signal(SIGPIPE, SIG_DFL); execv(argv[0], argv); perror(argv[0]); exit(1); } /* Parent. */ if (pid < 0) fatal("fork failed: %.100s", strerror(errno)); else proxy_command_pid = pid; /* save pid to clean up later */ /* Close child side of the descriptors. */ close(pin[0]); close(pout[1]); /* Free the command name. */ xfree(command_string); /* Set the connection file descriptors. */ ssh = ssh_packet_set_connection(NULL, pout[0], pin[1]); ssh_packet_set_timeout(ssh, options.server_alive_interval, options.server_alive_count_max); /* Indicate OK return */ return (ssh); }
/* * Connect to the given ssh server using a proxy command. */ static int ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) { char *command_string; int pin[2], pout[2]; pid_t pid; char *shell; if ((shell = getenv("SHELL")) == NULL || *shell == '\0') shell = _PATH_BSHELL; /* Create pipes for communicating with the proxy. */ if (pipe(pin) < 0 || pipe(pout) < 0) fatal("Could not create pipes to communicate with the proxy: %.100s", strerror(errno)); command_string = expand_proxy_command(proxy_command, options.user, host, port); debug("Executing proxy command: %.500s", command_string); /* Fork and execute the proxy command. */ if ((pid = fork()) == 0) { char *argv[10]; /* Child. Permanently give up superuser privileges. */ permanently_drop_suid(original_real_uid); /* Redirect stdin and stdout. */ close(pin[1]); if (pin[0] != 0) { if (dup2(pin[0], 0) < 0) perror("dup2 stdin"); close(pin[0]); } close(pout[0]); if (dup2(pout[1], 1) < 0) perror("dup2 stdout"); /* Cannot be 1 because pin allocated two descriptors. */ close(pout[1]); /* Stderr is left as it is so that error messages get printed on the user's terminal. */ argv[0] = shell; argv[1] = "-c"; argv[2] = command_string; argv[3] = NULL; /* Execute the proxy command. Note that we gave up any extra privileges above. */ signal(SIGPIPE, SIG_DFL); execv(argv[0], argv); perror(argv[0]); exit(1); } /* Parent. */ if (pid < 0) fatal("fork failed: %.100s", strerror(errno)); else proxy_command_pid = pid; /* save pid to clean up later */ /* Close child side of the descriptors. */ close(pin[0]); close(pout[1]); /* Free the command name. */ free(command_string); /* Set the connection file descriptors. */ packet_set_connection(pout[0], pin[1]); /* Indicate OK return */ return 0; }
static char * ssh_askpass(char *askpass, const char *msg) { pid_t pid, ret; size_t len; char *pass; int p[2], status; char buf[1024]; void (*osigchld)(int); if (fflush(stdout) != 0) error("ssh_askpass: fflush: %s", strerror(errno)); if (askpass == NULL) fatal("internal error: askpass undefined"); if (pipe(p) < 0) { error("ssh_askpass: pipe: %s", strerror(errno)); return NULL; } osigchld = signal(SIGCHLD, SIG_DFL); if ((pid = fork()) < 0) { error("ssh_askpass: fork: %s", strerror(errno)); signal(SIGCHLD, osigchld); return NULL; } if (pid == 0) { permanently_drop_suid(getuid()); close(p[0]); if (dup2(p[1], STDOUT_FILENO) < 0) fatal("ssh_askpass: dup2: %s", strerror(errno)); execlp(askpass, askpass, msg, (char *) 0); fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno)); } close(p[1]); len = 0; do { ssize_t r = read(p[0], buf + len, sizeof(buf) - 1 - len); if (r == -1 && errno == EINTR) continue; if (r <= 0) break; len += r; } while (sizeof(buf) - 1 - len > 0); buf[len] = '\0'; close(p[0]); while ((ret = waitpid(pid, &status, 0)) < 0) if (errno != EINTR) break; signal(SIGCHLD, osigchld); if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { memset(buf, 0, sizeof(buf)); return NULL; } buf[strcspn(buf, "\r\n")] = '\0'; pass = xstrdup(buf); memset(buf, 0, sizeof(buf)); return pass; }