2 * winproxy.c: Windows implementation of platform_new_connection(),
3 * supporting an OpenSSH-like proxy command via the winhandl.c
10 #define DEFINE_PLUG_METHOD_MACROS
16 typedef struct Socket_localproxy_tag
*Local_Proxy_Socket
;
18 struct Socket_localproxy_tag
{
19 const struct socket_function_table
*fn
;
20 /* the above variable absolutely *must* be the first in this structure */
22 HANDLE to_cmd_H
, from_cmd_H
;
23 struct handle
*to_cmd_h
, *from_cmd_h
;
32 int localproxy_gotdata(struct handle
*h
, void *data
, int len
)
34 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) handle_get_privdata(h
);
37 return plug_closing(ps
->plug
, "Read error from local proxy command",
39 } else if (len
== 0) {
40 return plug_closing(ps
->plug
, NULL
, 0, 0);
42 return plug_receive(ps
->plug
, 1, data
, len
);
46 void localproxy_sentdata(struct handle
*h
, int new_backlog
)
48 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) handle_get_privdata(h
);
50 plug_sent(ps
->plug
, new_backlog
);
53 static Plug
sk_localproxy_plug (Socket s
, Plug p
)
55 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
62 static void sk_localproxy_close (Socket s
)
64 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
66 handle_free(ps
->to_cmd_h
);
67 handle_free(ps
->from_cmd_h
);
68 CloseHandle(ps
->to_cmd_H
);
69 CloseHandle(ps
->from_cmd_H
);
74 static int sk_localproxy_write (Socket s
, const char *data
, int len
)
76 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
78 return handle_write(ps
->to_cmd_h
, data
, len
);
81 static int sk_localproxy_write_oob(Socket s
, const char *data
, int len
)
84 * oob data is treated as inband; nasty, but nothing really
87 return sk_localproxy_write(s
, data
, len
);
90 static void sk_localproxy_flush(Socket s
)
92 /* Local_Proxy_Socket ps = (Local_Proxy_Socket) s; */
96 static void sk_localproxy_set_private_ptr(Socket s
, void *ptr
)
98 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
102 static void *sk_localproxy_get_private_ptr(Socket s
)
104 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
108 static void sk_localproxy_set_frozen(Socket s
, int is_frozen
)
110 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
117 static const char *sk_localproxy_socket_error(Socket s
)
119 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
123 Socket
platform_new_connection(SockAddr addr
, char *hostname
,
124 int port
, int privport
,
125 int oobinline
, int nodelay
, int keepalive
,
126 Plug plug
, const Config
*cfg
)
130 static const struct socket_function_table socket_fn_table
= {
134 sk_localproxy_write_oob
,
136 sk_localproxy_set_private_ptr
,
137 sk_localproxy_get_private_ptr
,
138 sk_localproxy_set_frozen
,
139 sk_localproxy_socket_error
142 Local_Proxy_Socket ret
;
143 HANDLE us_to_cmd
, us_from_cmd
, cmd_to_us
, cmd_from_us
;
144 SECURITY_ATTRIBUTES sa
;
146 PROCESS_INFORMATION pi
;
148 if (cfg
->proxy_type
!= PROXY_CMD
)
151 cmd
= format_telnet_command(addr
, port
, cfg
);
154 char *msg
= dupprintf("Starting local proxy command: %s", cmd
);
155 /* We're allowed to pass NULL here, because we're part of the Windows
156 * front end so we know logevent doesn't expect any data. */
161 ret
= snew(struct Socket_localproxy_tag
);
162 ret
->fn
= &socket_fn_table
;
167 * Create the pipes to the proxy command, and spawn the proxy
170 sa
.nLength
= sizeof(sa
);
171 sa
.lpSecurityDescriptor
= NULL
; /* default */
172 sa
.bInheritHandle
= TRUE
;
173 if (!CreatePipe(&us_from_cmd
, &cmd_to_us
, &sa
, 0)) {
174 ret
->error
= dupprintf("Unable to create pipes for proxy command");
178 if (!CreatePipe(&cmd_from_us
, &us_to_cmd
, &sa
, 0)) {
179 CloseHandle(us_from_cmd
);
180 CloseHandle(cmd_to_us
);
181 ret
->error
= dupprintf("Unable to create pipes for proxy command");
185 SetHandleInformation(us_to_cmd
, HANDLE_FLAG_INHERIT
, 0);
186 SetHandleInformation(us_from_cmd
, HANDLE_FLAG_INHERIT
, 0);
189 si
.lpReserved
= NULL
;
192 si
.dwFlags
= STARTF_USESTDHANDLES
;
194 si
.lpReserved2
= NULL
;
195 si
.hStdInput
= cmd_from_us
;
196 si
.hStdOutput
= cmd_to_us
;
198 CreateProcess(NULL
, cmd
, NULL
, NULL
, TRUE
,
199 CREATE_NO_WINDOW
| NORMAL_PRIORITY_CLASS
,
200 NULL
, NULL
, &si
, &pi
);
202 CloseHandle(cmd_from_us
);
203 CloseHandle(cmd_to_us
);
205 ret
->to_cmd_H
= us_to_cmd
;
206 ret
->from_cmd_H
= us_from_cmd
;
208 ret
->from_cmd_h
= handle_input_new(ret
->from_cmd_H
, localproxy_gotdata
,
210 ret
->to_cmd_h
= handle_output_new(ret
->to_cmd_H
, localproxy_sentdata
,
213 /* We are responsible for this and don't need it any more */