X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=unix%2Fuxproxy.c;h=8c916dc99d7111eb8b898b4b14827555c048c0f5;hb=af1460d6e5044a3344aaacd15c91cfdcb58578e7;hp=cd256fdb66e1985ae18d0d57fea494afb5db4449;hpb=03fa61025b27384c5d64aee63f9b0a7fd917bb24;p=PuTTY.git diff --git a/unix/uxproxy.c b/unix/uxproxy.c index cd256fdb..8c916dc9 100644 --- a/unix/uxproxy.c +++ b/unix/uxproxy.c @@ -29,8 +29,7 @@ struct Socket_localproxy_tag { bufchain pending_output_data; bufchain pending_input_data; - - void *privptr; + enum { EOF_NO, EOF_PENDING, EOF_SENT } outgoingeof; }; static int localproxy_select_result(int fd, int event); @@ -95,10 +94,14 @@ static void sk_localproxy_close (Socket s) { Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - del234(localproxy_by_fromfd, ps); - del234(localproxy_by_tofd, ps); + if (ps->to_cmd >= 0) { + del234(localproxy_by_tofd, ps); + uxsel_del(ps->to_cmd); + close(ps->to_cmd); + } - close(ps->to_cmd); + del234(localproxy_by_fromfd, ps); + uxsel_del(ps->from_cmd); close(ps->from_cmd); sfree(ps); @@ -127,6 +130,14 @@ static int localproxy_try_send(Local_Proxy_Socket ps) } } + if (ps->outgoingeof == EOF_PENDING) { + del234(localproxy_by_tofd, ps); + close(ps->to_cmd); + uxsel_del(ps->to_cmd); + ps->to_cmd = -1; + ps->outgoingeof = EOF_SENT; + } + if (bufchain_size(&ps->pending_output_data) == 0) uxsel_del(ps->to_cmd); else @@ -139,6 +150,8 @@ static int sk_localproxy_write (Socket s, const char *data, int len) { Local_Proxy_Socket ps = (Local_Proxy_Socket) s; + assert(ps->outgoingeof == EOF_NO); + bufchain_add(&ps->pending_output_data, data, len); localproxy_try_send(ps); @@ -155,22 +168,20 @@ static int sk_localproxy_write_oob (Socket s, const char *data, int len) return sk_localproxy_write(s, data, len); } -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) +static void sk_localproxy_write_eof (Socket s) { Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - ps->privptr = ptr; + + assert(ps->outgoingeof == EOF_NO); + ps->outgoingeof = EOF_PENDING; + + localproxy_try_send(ps); } -static void * sk_localproxy_get_private_ptr (Socket s) +static void sk_localproxy_flush (Socket s) { - Local_Proxy_Socket ps = (Local_Proxy_Socket) s; - return ps->privptr; + /* Local_Proxy_Socket ps = (Local_Proxy_Socket) s; */ + /* do nothing */ } static void sk_localproxy_set_frozen (Socket s, int is_frozen) @@ -207,7 +218,7 @@ static int localproxy_select_result(int fd, int event) } else if (ret == 0) { return plug_closing(s->plug, NULL, 0, 0); } else { - return plug_receive(s->plug, 1, buf, ret); + return plug_receive(s->plug, 0, buf, ret); } } else if (event == 2) { assert(fd == s->to_cmd); @@ -219,10 +230,10 @@ static int localproxy_select_result(int fd, int event) return 1; } -Socket platform_new_connection(SockAddr addr, char *hostname, +Socket platform_new_connection(SockAddr addr, const char *hostname, int port, int privport, - int oobinline, int nodelay, Plug plug, - const Config *cfg) + int oobinline, int nodelay, int keepalive, + Plug plug, Conf *conf) { char *cmd; @@ -231,63 +242,87 @@ Socket platform_new_connection(SockAddr addr, char *hostname, 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 + sk_localproxy_socket_error, + NULL, /* peer_info */ }; Local_Proxy_Socket ret; - int to_cmd_pipe[2], from_cmd_pipe[2], pid; + int to_cmd_pipe[2], from_cmd_pipe[2], pid, proxytype; - if (cfg->proxy_type != PROXY_CMD) + proxytype = conf_get_int(conf, CONF_proxy_type); + if (proxytype != PROXY_CMD && proxytype != PROXY_FUZZ) return NULL; - cmd = format_telnet_command(addr, port, cfg); - ret = snew(struct Socket_localproxy_tag); ret->fn = &socket_fn_table; ret->plug = plug; ret->error = NULL; + ret->outgoingeof = EOF_NO; bufchain_init(&ret->pending_input_data); bufchain_init(&ret->pending_output_data); - /* - * Create the pipes to the proxy command, and spawn the proxy - * command process. - */ - if (pipe(to_cmd_pipe) < 0 || - pipe(from_cmd_pipe) < 0) { - ret->error = dupprintf("pipe: %s", strerror(errno)); - return (Socket)ret; - } + if (proxytype == PROXY_CMD) { + cmd = format_telnet_command(addr, port, conf); + + /* + * Create the pipes to the proxy command, and spawn the proxy + * command process. + */ + if (pipe(to_cmd_pipe) < 0 || + pipe(from_cmd_pipe) < 0) { + ret->error = dupprintf("pipe: %s", strerror(errno)); + sfree(cmd); + return (Socket)ret; + } + cloexec(to_cmd_pipe[1]); + cloexec(from_cmd_pipe[0]); + + pid = fork(); + + if (pid < 0) { + ret->error = dupprintf("fork: %s", strerror(errno)); + sfree(cmd); + return (Socket)ret; + } else 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]); + noncloexec(0); + noncloexec(1); + execl("/bin/sh", "sh", "-c", cmd, (void *)NULL); + _exit(255); + } - pid = fork(); - - if (pid < 0) { - ret->error = dupprintf("fork: %s", strerror(errno)); - return (Socket)ret; - } else if (pid == 0) { - int i; - close(0); - close(1); - dup2(to_cmd_pipe[0], 0); - dup2(from_cmd_pipe[1], 1); - for (i = 3; i < 127; i++) - close(i); - fcntl(0, F_SETFD, 0); - fcntl(1, F_SETFD, 0); - execl("/bin/sh", "sh", "-c", cmd, NULL); - _exit(255); - } + sfree(cmd); - close(to_cmd_pipe[0]); - close(from_cmd_pipe[1]); + close(to_cmd_pipe[0]); + close(from_cmd_pipe[1]); - ret->to_cmd = to_cmd_pipe[1]; - ret->from_cmd = from_cmd_pipe[0]; + ret->to_cmd = to_cmd_pipe[1]; + ret->from_cmd = from_cmd_pipe[0]; + } else { + cmd = format_telnet_command(addr, port, conf); + ret->to_cmd = open("/dev/null", O_WRONLY); + if (ret->to_cmd == -1) { + ret->error = dupprintf("/dev/null: %s", strerror(errno)); + sfree(cmd); + return (Socket)ret; + } + ret->from_cmd = open(cmd, O_RDONLY); + if (ret->from_cmd == -1) { + ret->error = dupprintf("%s: %s", cmd, strerror(errno)); + sfree(cmd); + return (Socket)ret; + } + sfree(cmd); + } if (!localproxy_by_fromfd) localproxy_by_fromfd = newtree234(localproxy_fromfd_cmp); @@ -299,5 +334,8 @@ Socket platform_new_connection(SockAddr addr, char *hostname, uxsel_set(ret->from_cmd, 1, localproxy_select_result); + /* We are responsible for this and don't need it any more */ + sk_addr_free(addr); + return (Socket) ret; }