1 /*
2  * winproxy.c: Windows implementation of platform_new_connection(),
3  * supporting an OpenSSH-like proxy command via the winhandl.c
4  * mechanism.
5  */
6 
7 #include <stdio.h>
8 #include <assert.h>
9 
10 #include "tree234.h"
11 #include "putty.h"
12 #include "network.h"
13 #include "proxy.h"
14 
platform_new_connection(SockAddr * addr,const char * hostname,int port,bool privport,bool oobinline,bool nodelay,bool keepalive,Plug * plug,Conf * conf)15 Socket *platform_new_connection(SockAddr *addr, const char *hostname,
16                                 int port, bool privport,
17                                 bool oobinline, bool nodelay, bool keepalive,
18                                 Plug *plug, Conf *conf)
19 {
20     char *cmd;
21     HANDLE us_to_cmd, cmd_from_us;
22     HANDLE us_from_cmd, cmd_to_us;
23     HANDLE us_from_cmd_err, cmd_err_to_us;
24     SECURITY_ATTRIBUTES sa;
25     STARTUPINFO si;
26     PROCESS_INFORMATION pi;
27 
28     if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD)
29         return NULL;
30 
31     cmd = format_telnet_command(addr, port, conf);
32 
33     /* We are responsible for this and don't need it any more */
34     sk_addr_free(addr);
35 
36     {
37         char *msg = dupprintf("Starting local proxy command: %s", cmd);
38         plug_log(plug, PLUGLOG_PROXY_MSG, NULL, 0, msg, 0);
39         sfree(msg);
40     }
41 
42     /*
43      * Create the pipes to the proxy command, and spawn the proxy
44      * command process.
45      */
46     sa.nLength = sizeof(sa);
47     sa.lpSecurityDescriptor = NULL;    /* default */
48     sa.bInheritHandle = true;
49     if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) {
50         sfree(cmd);
51         return new_error_socket_fmt(
52             plug, "Unable to create pipes for proxy command: %s",
53             win_strerror(GetLastError()));
54     }
55 
56     if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) {
57         sfree(cmd);
58         CloseHandle(us_from_cmd);
59         CloseHandle(cmd_to_us);
60         return new_error_socket_fmt(
61             plug, "Unable to create pipes for proxy command: %s",
62             win_strerror(GetLastError()));
63     }
64 
65     if (!CreatePipe(&us_from_cmd_err, &cmd_err_to_us, &sa, 0)) {
66         sfree(cmd);
67         CloseHandle(us_from_cmd);
68         CloseHandle(cmd_to_us);
69         CloseHandle(us_to_cmd);
70         CloseHandle(cmd_from_us);
71         return new_error_socket_fmt(
72             plug, "Unable to create pipes for proxy command: %s",
73             win_strerror(GetLastError()));
74     }
75 
76     SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0);
77     SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0);
78     if (us_from_cmd_err != NULL)
79         SetHandleInformation(us_from_cmd_err, HANDLE_FLAG_INHERIT, 0);
80 
81     si.cb = sizeof(si);
82     si.lpReserved = NULL;
83     si.lpDesktop = NULL;
84     si.lpTitle = NULL;
85     si.dwFlags = STARTF_USESTDHANDLES;
86     si.cbReserved2 = 0;
87     si.lpReserved2 = NULL;
88     si.hStdInput = cmd_from_us;
89     si.hStdOutput = cmd_to_us;
90     si.hStdError = cmd_err_to_us;
91     CreateProcess(NULL, cmd, NULL, NULL, true,
92                   CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
93                   NULL, NULL, &si, &pi);
94     CloseHandle(pi.hProcess);
95     CloseHandle(pi.hThread);
96 
97     sfree(cmd);
98 
99     CloseHandle(cmd_from_us);
100     CloseHandle(cmd_to_us);
101 
102     if (cmd_err_to_us != NULL)
103         CloseHandle(cmd_err_to_us);
104 
105     return make_handle_socket(us_to_cmd, us_from_cmd, us_from_cmd_err,
106                               plug, false);
107 }
108