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
, 0, 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_write_eof(Socket s
)
92 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
94 handle_write_eof(ps
->to_cmd_h
);
97 static void sk_localproxy_flush(Socket s
)
99 /* Local_Proxy_Socket ps = (Local_Proxy_Socket) s; */
103 static void sk_localproxy_set_private_ptr(Socket s
, void *ptr
)
105 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
109 static void *sk_localproxy_get_private_ptr(Socket s
)
111 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
115 static void sk_localproxy_set_frozen(Socket s
, int is_frozen
)
117 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
124 static const char *sk_localproxy_socket_error(Socket s
)
126 Local_Proxy_Socket ps
= (Local_Proxy_Socket
) s
;
130 Socket
platform_new_connection(SockAddr addr
, char *hostname
,
131 int port
, int privport
,
132 int oobinline
, int nodelay
, int keepalive
,
133 Plug plug
, Conf
*conf
)
137 static const struct socket_function_table socket_fn_table
= {
141 sk_localproxy_write_oob
,
142 sk_localproxy_write_eof
,
144 sk_localproxy_set_private_ptr
,
145 sk_localproxy_get_private_ptr
,
146 sk_localproxy_set_frozen
,
147 sk_localproxy_socket_error
150 Local_Proxy_Socket ret
;
151 HANDLE us_to_cmd
, us_from_cmd
, cmd_to_us
, cmd_from_us
;
152 SECURITY_ATTRIBUTES sa
;
154 PROCESS_INFORMATION pi
;
156 if (conf_get_int(conf
, CONF_proxy_type
) != PROXY_CMD
)
159 cmd
= format_telnet_command(addr
, port
, conf
);
162 char *msg
= dupprintf("Starting local proxy command: %s", cmd
);
163 /* We're allowed to pass NULL here, because we're part of the Windows
164 * front end so we know logevent doesn't expect any data. */
169 ret
= snew(struct Socket_localproxy_tag
);
170 ret
->fn
= &socket_fn_table
;
175 * Create the pipes to the proxy command, and spawn the proxy
178 sa
.nLength
= sizeof(sa
);
179 sa
.lpSecurityDescriptor
= NULL
; /* default */
180 sa
.bInheritHandle
= TRUE
;
181 if (!CreatePipe(&us_from_cmd
, &cmd_to_us
, &sa
, 0)) {
182 ret
->error
= dupprintf("Unable to create pipes for proxy command");
186 if (!CreatePipe(&cmd_from_us
, &us_to_cmd
, &sa
, 0)) {
187 CloseHandle(us_from_cmd
);
188 CloseHandle(cmd_to_us
);
189 ret
->error
= dupprintf("Unable to create pipes for proxy command");
193 SetHandleInformation(us_to_cmd
, HANDLE_FLAG_INHERIT
, 0);
194 SetHandleInformation(us_from_cmd
, HANDLE_FLAG_INHERIT
, 0);
197 si
.lpReserved
= NULL
;
200 si
.dwFlags
= STARTF_USESTDHANDLES
;
202 si
.lpReserved2
= NULL
;
203 si
.hStdInput
= cmd_from_us
;
204 si
.hStdOutput
= cmd_to_us
;
206 CreateProcess(NULL
, cmd
, NULL
, NULL
, TRUE
,
207 CREATE_NO_WINDOW
| NORMAL_PRIORITY_CLASS
,
208 NULL
, NULL
, &si
, &pi
);
209 CloseHandle(pi
.hProcess
);
210 CloseHandle(pi
.hThread
);
214 CloseHandle(cmd_from_us
);
215 CloseHandle(cmd_to_us
);
217 ret
->to_cmd_H
= us_to_cmd
;
218 ret
->from_cmd_H
= us_from_cmd
;
220 ret
->from_cmd_h
= handle_input_new(ret
->from_cmd_H
, localproxy_gotdata
,
222 ret
->to_cmd_h
= handle_output_new(ret
->to_cmd_H
, localproxy_sentdata
,
225 /* We are responsible for this and don't need it any more */