diff --git a/Recipe b/Recipe index 5eb07de4..36b753b4 100644 --- a/Recipe +++ b/Recipe @@ -300,7 +300,7 @@ SSH = ssh sshcrc sshdes sshmd5 sshrsa sshrand sshsha sshblowf + sshdh sshcrcda sshpubk sshzlib sshdss x11fwd portfwd + sshaes sshsh256 sshsh512 sshbn wildcard pinger ssharcf + sshgssc pgssapi -WINSSH = SSH winnoise winpgntc wingss errsock +WINSSH = SSH winnoise winpgntc wingss winhsock errsock UXSSH = SSH uxnoise uxagentc uxgss # SFTP implementation (pscp, psftp). @@ -310,7 +310,7 @@ SFTP = sftp int64 logging # Pageant or PuTTYgen). MISC = timing callback misc version settings tree234 proxy conf WINMISC = MISC winstore winnet winhandl cmdline windefs winmisc winproxy - + wintime errsock + + wintime winhsock errsock UXMISC = MISC uxstore uxsel uxnet cmdline uxmisc uxproxy time OSXMISC = MISC uxstore uxsel osxsel uxnet uxmisc uxproxy time diff --git a/windows/winhsock.c b/windows/winhsock.c new file mode 100644 index 00000000..d0330dac --- /dev/null +++ b/windows/winhsock.c @@ -0,0 +1,159 @@ +/* + * General mechanism for wrapping up reading/writing of Windows + * HANDLEs into a PuTTY Socket abstraction. + */ + +#include +#include + +#define DEFINE_PLUG_METHOD_MACROS +#include "tree234.h" +#include "putty.h" +#include "network.h" + +typedef struct Socket_handle_tag *Handle_Socket; + +struct Socket_handle_tag { + const struct socket_function_table *fn; + /* the above variable absolutely *must* be the first in this structure */ + + HANDLE send_H, recv_H; + struct handle *send_h, *recv_h; + + char *error; + + Plug plug; + + void *privptr; +}; + +static int handle_gotdata(struct handle *h, void *data, int len) +{ + Handle_Socket ps = (Handle_Socket) handle_get_privdata(h); + + if (len < 0) { + return plug_closing(ps->plug, "Read error from handle", + 0, 0); + } else if (len == 0) { + return plug_closing(ps->plug, NULL, 0, 0); + } else { + return plug_receive(ps->plug, 0, data, len); + } +} + +static void handle_sentdata(struct handle *h, int new_backlog) +{ + Handle_Socket ps = (Handle_Socket) handle_get_privdata(h); + + plug_sent(ps->plug, new_backlog); +} + +static Plug sk_handle_plug(Socket s, Plug p) +{ + Handle_Socket ps = (Handle_Socket) s; + Plug ret = ps->plug; + if (p) + ps->plug = p; + return ret; +} + +static void sk_handle_close(Socket s) +{ + Handle_Socket ps = (Handle_Socket) s; + + handle_free(ps->send_h); + handle_free(ps->recv_h); + CloseHandle(ps->send_H); + if (ps->recv_H != ps->send_H) + CloseHandle(ps->recv_H); + + sfree(ps); +} + +static int sk_handle_write(Socket s, const char *data, int len) +{ + Handle_Socket ps = (Handle_Socket) s; + + return handle_write(ps->send_h, data, len); +} + +static int sk_handle_write_oob(Socket s, const char *data, int len) +{ + /* + * oob data is treated as inband; nasty, but nothing really + * better we can do + */ + return sk_handle_write(s, data, len); +} + +static void sk_handle_write_eof(Socket s) +{ + Handle_Socket ps = (Handle_Socket) s; + + handle_write_eof(ps->send_h); +} + +static void sk_handle_flush(Socket s) +{ + /* Handle_Socket ps = (Handle_Socket) s; */ + /* do nothing */ +} + +static void sk_handle_set_private_ptr(Socket s, void *ptr) +{ + Handle_Socket ps = (Handle_Socket) s; + ps->privptr = ptr; +} + +static void *sk_handle_get_private_ptr(Socket s) +{ + Handle_Socket ps = (Handle_Socket) s; + return ps->privptr; +} + +static void sk_handle_set_frozen(Socket s, int is_frozen) +{ + Handle_Socket ps = (Handle_Socket) s; + + /* + * FIXME + */ +} + +static const char *sk_handle_socket_error(Socket s) +{ + Handle_Socket ps = (Handle_Socket) s; + return ps->error; +} + +Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug, + int overlapped) +{ + static const struct socket_function_table socket_fn_table = { + sk_handle_plug, + sk_handle_close, + sk_handle_write, + sk_handle_write_oob, + sk_handle_write_eof, + sk_handle_flush, + sk_handle_set_private_ptr, + sk_handle_get_private_ptr, + sk_handle_set_frozen, + sk_handle_socket_error + }; + + Handle_Socket ret; + int flags = (overlapped ? HANDLE_FLAG_OVERLAPPED : 0); + + ret = snew(struct Socket_handle_tag); + ret->fn = &socket_fn_table; + ret->plug = plug; + ret->error = NULL; + + ret->recv_H = recv_H; + ret->recv_h = handle_input_new(ret->recv_H, handle_gotdata, ret, flags); + ret->send_H = send_H; + ret->send_h = handle_output_new(ret->send_H, handle_sentdata, ret, flags); + + return (Socket) ret; +} diff --git a/windows/winproxy.c b/windows/winproxy.c index 7bbd18f0..aa14b91a 100644 --- a/windows/winproxy.c +++ b/windows/winproxy.c @@ -13,119 +13,8 @@ #include "network.h" #include "proxy.h" -typedef struct Socket_localproxy_tag *Local_Proxy_Socket; - -struct Socket_localproxy_tag { - const struct socket_function_table *fn; - /* the above variable absolutely *must* be the first in this structure */ - - HANDLE to_cmd_H, from_cmd_H; - struct handle *to_cmd_h, *from_cmd_h; - - char *error; - - Plug plug; - - void *privptr; -}; - -int localproxy_gotdata(struct handle *h, void *data, int len) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) handle_get_privdata(h); - - if (len < 0) { - return plug_closing(ps->plug, "Read error from local proxy command", - 0, 0); - } else if (len == 0) { - return plug_closing(ps->plug, NULL, 0, 0); - } else { - return plug_receive(ps->plug, 0, data, len); - } -} - -void localproxy_sentdata(struct handle *h, int new_backlog) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) handle_get_privdata(h); - - plug_sent(ps->plug, new_backlog); -} - -static Plug sk_localproxy_plug (Socket s, Plug p) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - Plug ret = ps->plug; - if (p) - ps->plug = p; - return ret; -} - -static void sk_localproxy_close (Socket s) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - - handle_free(ps->to_cmd_h); - handle_free(ps->from_cmd_h); - CloseHandle(ps->to_cmd_H); - CloseHandle(ps->from_cmd_H); - - sfree(ps); -} - -static int sk_localproxy_write (Socket s, const char *data, int len) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - - return handle_write(ps->to_cmd_h, data, len); -} - -static int sk_localproxy_write_oob(Socket s, const char *data, int len) -{ - /* - * oob data is treated as inband; nasty, but nothing really - * better we can do - */ - return sk_localproxy_write(s, data, len); -} - -static void sk_localproxy_write_eof(Socket s) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - - handle_write_eof(ps->to_cmd_h); -} - -static void sk_localproxy_flush(Socket s) -{ - /* Local_Proxy_Socket ps = (Local_Proxy_Socket) s; */ - /* do nothing */ -} - -static void sk_localproxy_set_private_ptr(Socket s, void *ptr) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - ps->privptr = ptr; -} - -static void *sk_localproxy_get_private_ptr(Socket s) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - return ps->privptr; -} - -static void sk_localproxy_set_frozen(Socket s, int is_frozen) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - - /* - * FIXME - */ -} - -static const char *sk_localproxy_socket_error(Socket s) -{ - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - return ps->error; -} +Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug, + int overlapped); Socket platform_new_connection(SockAddr addr, char *hostname, int port, int privport, @@ -133,21 +22,6 @@ Socket platform_new_connection(SockAddr addr, char *hostname, Plug plug, Conf *conf) { char *cmd; - - static const struct socket_function_table socket_fn_table = { - sk_localproxy_plug, - sk_localproxy_close, - sk_localproxy_write, - sk_localproxy_write_oob, - sk_localproxy_write_eof, - sk_localproxy_flush, - sk_localproxy_set_private_ptr, - sk_localproxy_get_private_ptr, - sk_localproxy_set_frozen, - sk_localproxy_socket_error - }; - - Local_Proxy_Socket ret; HANDLE us_to_cmd, us_from_cmd, cmd_to_us, cmd_from_us; SECURITY_ATTRIBUTES sa; STARTUPINFO si; @@ -158,6 +32,9 @@ Socket platform_new_connection(SockAddr addr, char *hostname, cmd = format_telnet_command(addr, port, conf); + /* We are responsible for this and don't need it any more */ + sk_addr_free(addr); + { char *msg = dupprintf("Starting local proxy command: %s", cmd); /* We're allowed to pass NULL here, because we're part of the Windows @@ -166,11 +43,6 @@ Socket platform_new_connection(SockAddr addr, char *hostname, sfree(msg); } - ret = snew(struct Socket_localproxy_tag); - ret->fn = &socket_fn_table; - ret->plug = plug; - ret->error = NULL; - /* * Create the pipes to the proxy command, and spawn the proxy * command process. @@ -179,17 +51,19 @@ Socket platform_new_connection(SockAddr addr, char *hostname, sa.lpSecurityDescriptor = NULL; /* default */ sa.bInheritHandle = TRUE; if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { - ret->error = dupprintf("Unable to create pipes for proxy command"); + Socket ret = + new_error_socket("Unable to create pipes for proxy command", plug); sfree(cmd); - return (Socket)ret; + return ret; } if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) { + Socket ret = + new_error_socket("Unable to create pipes for proxy command", plug); + sfree(cmd); CloseHandle(us_from_cmd); CloseHandle(cmd_to_us); - ret->error = dupprintf("Unable to create pipes for proxy command"); - sfree(cmd); - return (Socket)ret; + return ret; } SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0); @@ -216,16 +90,5 @@ Socket platform_new_connection(SockAddr addr, char *hostname, CloseHandle(cmd_from_us); CloseHandle(cmd_to_us); - ret->to_cmd_H = us_to_cmd; - ret->from_cmd_H = us_from_cmd; - - ret->from_cmd_h = handle_input_new(ret->from_cmd_H, localproxy_gotdata, - ret, 0); - ret->to_cmd_h = handle_output_new(ret->to_cmd_H, localproxy_sentdata, - ret, 0); - - /* We are responsible for this and don't need it any more */ - sk_addr_free(addr); - - return (Socket) ret; + return make_handle_socket(us_to_cmd, us_from_cmd, plug, FALSE); }