File: local-proxy.c

package info (click to toggle)
putty 0.78-2%2Bdeb12u2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 13,964 kB
  • sloc: ansic: 137,777; python: 7,775; perl: 1,798; makefile: 133; sh: 111
file content (116 lines) | stat: -rw-r--r-- 3,256 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * 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;
}