123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- /*
- * local-proxy.c: Unix implementation of platform_new_connection(),
- * supporting an OpenSSH-like proxy command.
- */
- #include <stdio.h>
- #include <assert.h>
- #include <errno.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include "tree234.h"
- #include "putty.h"
- #include "network.h"
- #include "proxy/proxy.h"
- char *platform_setup_local_proxy(Socket *socket, const char *cmd)
- {
- /*
- * Create the pipes to the proxy command, and spawn the proxy
- * command process.
- */
- int to_cmd_pipe[2], from_cmd_pipe[2], cmd_err_pipe[2];
- if (pipe(to_cmd_pipe) < 0 ||
- pipe(from_cmd_pipe) < 0 ||
- pipe(cmd_err_pipe) < 0) {
- return dupprintf("pipe: %s", strerror(errno));
- }
- cloexec(to_cmd_pipe[1]);
- cloexec(from_cmd_pipe[0]);
- cloexec(cmd_err_pipe[0]);
- int pid = fork();
- if (pid == 0) {
- close(0);
- close(1);
- dup2(to_cmd_pipe[0], 0);
- dup2(from_cmd_pipe[1], 1);
- close(to_cmd_pipe[0]);
- close(from_cmd_pipe[1]);
- dup2(cmd_err_pipe[1], 2);
- noncloexec(0);
- noncloexec(1);
- execl("/bin/sh", "sh", "-c", cmd, (void *)NULL);
- _exit(255);
- }
- if (pid < 0) {
- return dupprintf("fork: %s", strerror(errno));
- }
- close(to_cmd_pipe[0]);
- close(from_cmd_pipe[1]);
- close(cmd_err_pipe[1]);
- setup_fd_socket(socket, from_cmd_pipe[0], to_cmd_pipe[1], cmd_err_pipe[0]);
- return NULL;
- }
- Socket *platform_new_connection(SockAddr *addr, const char *hostname,
- int port, bool privport,
- bool oobinline, bool nodelay, bool keepalive,
- Plug *plug, Conf *conf, Interactor *itr)
- {
- switch (conf_get_int(conf, CONF_proxy_type)) {
- case PROXY_CMD: {
- DeferredSocketOpener *opener = local_proxy_opener(
- addr, port, plug, conf, itr);
- Socket *socket = make_deferred_fd_socket(opener, addr, port, plug);
- local_proxy_opener_set_socket(opener, socket);
- return socket;
- }
- case PROXY_FUZZ: {
- char *cmd = format_telnet_command(addr, port, conf, NULL);
- int outfd = open("/dev/null", O_WRONLY);
- if (outfd == -1) {
- sfree(cmd);
- return new_error_socket_fmt(
- plug, "/dev/null: %s", strerror(errno));
- }
- int infd = open(cmd, O_RDONLY);
- if (infd == -1) {
- Socket *toret = new_error_socket_fmt(
- plug, "%s: %s", cmd, strerror(errno));
- sfree(cmd);
- close(outfd);
- return toret;
- }
- sfree(cmd);
- return make_fd_socket(infd, outfd, -1, addr, port, plug);
- }
- default:
- return NULL;
- }
- }
- Socket *platform_start_subprocess(const char *cmd, Plug *plug,
- const char *prefix)
- {
- Socket *socket = make_deferred_fd_socket(
- null_deferred_socket_opener(),
- sk_nonamelookup("<local command>"), 0, plug);
- char *err = platform_setup_local_proxy(socket, cmd);
- fd_socket_set_psb_prefix(socket, prefix);
- if (err) {
- sk_close(socket);
- socket = new_error_socket_fmt(plug, "%s", err);
- sfree(err);
- }
- return socket;
- }
|