static void plug_proxy_log(Plug plug, int type, SockAddr addr, int port, const char *error_msg, int error_code) { Proxy_Plug pp = (Proxy_Plug) plug; Proxy_Socket ps = pp->proxy_socket; plug_log(ps->plug, type, addr, port, error_msg, error_code); }
static void plug_proxy_log(Plug plug, int type, SockAddr addr, int port, const char *error_msg, int error_code) { ProxySocket *ps = FROMFIELD(plug, ProxySocket, plugvt); plug_log(ps->plug, type, addr, port, error_msg, error_code); }
static void plug_proxy_log(Plug *plug, int type, SockAddr *addr, int port, const char *error_msg, int error_code) { ProxySocket *ps = container_of(plug, ProxySocket, plugimpl); plug_log(ps->plug, type, addr, port, error_msg, error_code); }
void log_proxy_stderr(Plug plug, bufchain *buf, const void *vdata, int len) { const char *data = (const char *)vdata; int pos = 0; int msglen; char *nlpos, *msg, *fullmsg; /* * This helper function allows us to collect the data written to a * local proxy command's standard error in whatever size chunks we * happen to get from its pipe, and whenever we have a complete * line, we pass it to plug_log. * * Prerequisites: a plug to log to, and a bufchain stored * somewhere to collect the data in. */ while (pos < len && (nlpos = memchr(data+pos, '\n', len-pos)) != NULL) { /* * Found a newline in the current input buffer. Append it to * the bufchain (which may contain a partial line from last * time). */ bufchain_add(buf, data + pos, nlpos - (data + pos)); /* * Collect the resulting line of data and pass it to plug_log. */ msglen = bufchain_size(buf); msg = snewn(msglen+1, char); bufchain_fetch(buf, msg, msglen); bufchain_consume(buf, msglen); msg[msglen] = '\0'; fullmsg = dupprintf("proxy: %s", msg); plug_log(plug, 2, NULL, 0, fullmsg, 0); sfree(fullmsg); sfree(msg); /* * Advance past the newline. */ pos += (int)(nlpos+1 - (data + pos)); } /* * Now any remaining data is a partial line, which we save for * next time. */ bufchain_add(buf, data + pos, len - pos); }
Socket new_connection(SockAddr addr, const char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { static const struct socket_function_table socket_fn_table = { sk_proxy_plug, sk_proxy_close, sk_proxy_write, sk_proxy_write_oob, sk_proxy_write_eof, sk_proxy_flush, sk_proxy_set_frozen, sk_proxy_socket_error, NULL, /* peer_info */ }; static const struct plug_function_table plug_fn_table = { plug_proxy_log, plug_proxy_closing, plug_proxy_receive, plug_proxy_sent, plug_proxy_accepting}; if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE && proxy_for_destination(addr, hostname, port, conf)) { Proxy_Socket ret; Proxy_Plug pplug; SockAddr proxy_addr; char *proxy_canonical_name; const char *proxy_type; Socket sret; int type; if ((sret = platform_new_connection(addr, hostname, port, privport, oobinline, nodelay, keepalive, plug, conf)) != NULL) return sret; ret = snew(struct Socket_proxy_tag); ret->fn = &socket_fn_table; ret->conf = conf_copy(conf); ret->plug = plug; ret->remote_addr = addr; /* will need to be freed on close */ ret->remote_port = port; ret->error = NULL; ret->pending_flush = 0; ret->pending_eof = 0; ret->freeze = 0; bufchain_init(&ret->pending_input_data); bufchain_init(&ret->pending_output_data); bufchain_init(&ret->pending_oob_output_data); ret->sub_socket = NULL; ret->state = PROXY_STATE_NEW; ret->negotiate = NULL; type = conf_get_int(conf, CONF_proxy_type); if (type == PROXY_HTTP) { ret->negotiate = proxy_http_negotiate; proxy_type = "HTTP"; } else if (type == PROXY_SOCKS4) { ret->negotiate = proxy_socks4_negotiate; proxy_type = "SOCKS 4"; } else if (type == PROXY_SOCKS5) { ret->negotiate = proxy_socks5_negotiate; proxy_type = "SOCKS 5"; } else if (type == PROXY_TELNET) { ret->negotiate = proxy_telnet_negotiate; proxy_type = "Telnet"; } else { ret->error = "Proxy error: Unknown proxy method"; return (Socket)ret; } { char *logmsg = dupprintf("Will use %s proxy at %s:%d to connect" " to %s:%d", proxy_type, conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_proxy_port), hostname, port); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* create the proxy plug to map calls from the actual * socket into our proxy socket layer */ pplug = snew(struct Plug_proxy_tag); pplug->fn = &plug_fn_table; pplug->proxy_socket = ret; { char *logmsg = dns_log_msg(conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_addressfamily), "proxy"); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* look-up proxy */ proxy_addr = sk_namelookup(conf_get_str(conf, CONF_proxy_host), &proxy_canonical_name, conf_get_int(conf, CONF_addressfamily)); if (sk_addr_error(proxy_addr) != NULL) { ret->error = "Proxy error: Unable to resolve proxy host name"; sfree(pplug); sk_addr_free(proxy_addr); return (Socket)ret; } sfree(proxy_canonical_name); { char addrbuf[256], *logmsg; sk_getaddr(proxy_addr, addrbuf, lenof(addrbuf)); logmsg = dupprintf("Connecting to %s proxy at %s port %d", proxy_type, addrbuf, conf_get_int(conf, CONF_proxy_port)); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* create the actual socket we will be using, * connected to our proxy server and port. */ ret->sub_socket = sk_new(proxy_addr, conf_get_int(conf, CONF_proxy_port), privport, oobinline, nodelay, keepalive, (Plug)pplug); if (sk_socket_error(ret->sub_socket) != NULL) return (Socket)ret; /* start the proxy negotiation process... */ sk_set_frozen(ret->sub_socket, 0); ret->negotiate(ret, PROXY_CHANGE_NEW); return (Socket)ret; }
Socket platform_new_connection(SockAddr addr, const char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, 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_frozen, sk_localproxy_socket_error, NULL, /* peer_info */ }; Local_Proxy_Socket ret; int to_cmd_pipe[2], from_cmd_pipe[2], cmd_err_pipe[2], pid, proxytype; proxytype = conf_get_int(conf, CONF_proxy_type); if (proxytype != PROXY_CMD && proxytype != PROXY_FUZZ) return NULL; 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); bufchain_init(&ret->pending_error_data); if (proxytype == PROXY_CMD) { cmd = format_telnet_command(addr, port, conf); if (flags & FLAG_STDERR) { /* If we have a sensible stderr, the proxy command can * send its own standard error there, so we won't * interfere. */ cmd_err_pipe[0] = cmd_err_pipe[1] = -1; } else { /* If we don't have a sensible stderr, we should catch the * proxy command's standard error to put in our event * log. */ cmd_err_pipe[0] = cmd_err_pipe[1] = 0; } { char *logmsg = dupprintf("Starting local proxy command: %s", cmd); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ if (pipe(to_cmd_pipe) < 0 || pipe(from_cmd_pipe) < 0 || (cmd_err_pipe[0] == 0 && pipe(cmd_err_pipe) < 0)) { ret->error = dupprintf("pipe: %s", strerror(errno)); sfree(cmd); return (Socket)ret; } cloexec(to_cmd_pipe[1]); cloexec(from_cmd_pipe[0]); if (cmd_err_pipe[0] >= 0) cloexec(cmd_err_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]); if (cmd_err_pipe[0] >= 0) { dup2(cmd_err_pipe[1], 2); close(cmd_err_pipe[1]); } noncloexec(0); noncloexec(1); execl("/bin/sh", "sh", "-c", cmd, (void *)NULL); _exit(255); } sfree(cmd); close(to_cmd_pipe[0]); close(from_cmd_pipe[1]); if (cmd_err_pipe[0] >= 0) close(cmd_err_pipe[1]); ret->to_cmd = to_cmd_pipe[1]; ret->from_cmd = from_cmd_pipe[0]; ret->cmd_err = cmd_err_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); ret->cmd_err = -1; } if (!localproxy_by_fromfd) localproxy_by_fromfd = newtree234(localproxy_fromfd_cmp); if (!localproxy_by_tofd) localproxy_by_tofd = newtree234(localproxy_tofd_cmp); if (!localproxy_by_errfd) localproxy_by_errfd = newtree234(localproxy_errfd_cmp); add234(localproxy_by_fromfd, ret); add234(localproxy_by_tofd, ret); if (ret->cmd_err >= 0) add234(localproxy_by_errfd, ret); uxsel_set(ret->from_cmd, 1, localproxy_select_result); if (ret->cmd_err >= 0) uxsel_set(ret->cmd_err, 1, localproxy_select_result); /* We are responsible for this and don't need it any more */ sk_addr_free(addr); return (Socket) ret; }
Socket platform_new_connection(SockAddr addr, const char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { char *cmd; HANDLE us_to_cmd, cmd_from_us; HANDLE us_from_cmd, cmd_to_us; HANDLE us_from_cmd_err, cmd_err_to_us; SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD) return NULL; 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); plug_log(plug, 2, NULL, 0, msg, 0); sfree(msg); } /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; /* default */ sa.bInheritHandle = TRUE; if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { Socket ret = new_error_socket("Unable to create pipes for proxy command", plug); sfree(cmd); 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); return ret; } if (flags & FLAG_STDERR) { /* If we have a sensible stderr, the proxy command can send * its own standard error there, so we won't interfere. */ us_from_cmd_err = cmd_err_to_us = NULL; } else { /* If we don't have a sensible stderr, we should catch the * proxy command's standard error to put in our event log. */ if (!CreatePipe(&us_from_cmd_err, &cmd_err_to_us, &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); CloseHandle(us_to_cmd); CloseHandle(cmd_from_us); return ret; } } SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0); if (us_from_cmd_err != NULL) SetHandleInformation(us_from_cmd_err, HANDLE_FLAG_INHERIT, 0); si.cb = sizeof(si); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = NULL; si.dwFlags = STARTF_USESTDHANDLES; si.cbReserved2 = 0; si.lpReserved2 = NULL; si.hStdInput = cmd_from_us; si.hStdOutput = cmd_to_us; si.hStdError = cmd_err_to_us; CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); sfree(cmd); CloseHandle(cmd_from_us); CloseHandle(cmd_to_us); if (cmd_err_to_us != NULL) CloseHandle(cmd_err_to_us); return make_handle_socket( us_to_cmd, us_from_cmd, us_from_cmd_err, plug, FALSE); }
Socket *new_connection(SockAddr *addr, const char *hostname, int port, bool privport, bool oobinline, bool nodelay, bool keepalive, Plug *plug, Conf *conf) { if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE && proxy_for_destination(addr, hostname, port, conf)) { ProxySocket *ret; SockAddr *proxy_addr; char *proxy_canonical_name; const char *proxy_type; Socket *sret; int type; if ((sret = platform_new_connection(addr, hostname, port, privport, oobinline, nodelay, keepalive, plug, conf)) != NULL) return sret; ret = snew(ProxySocket); ret->sock.vt = &ProxySocket_sockvt; ret->plugimpl.vt = &ProxySocket_plugvt; ret->conf = conf_copy(conf); ret->plug = plug; ret->remote_addr = addr; /* will need to be freed on close */ ret->remote_port = port; ret->error = NULL; ret->pending_flush = false; ret->pending_eof = false; ret->freeze = false; bufchain_init(&ret->pending_input_data); bufchain_init(&ret->pending_output_data); bufchain_init(&ret->pending_oob_output_data); ret->sub_socket = NULL; ret->state = PROXY_STATE_NEW; ret->negotiate = NULL; type = conf_get_int(conf, CONF_proxy_type); if (type == PROXY_HTTP) { ret->negotiate = proxy_http_negotiate; proxy_type = "HTTP"; } else if (type == PROXY_SOCKS4) { ret->negotiate = proxy_socks4_negotiate; proxy_type = "SOCKS 4"; } else if (type == PROXY_SOCKS5) { ret->negotiate = proxy_socks5_negotiate; proxy_type = "SOCKS 5"; } else if (type == PROXY_TELNET) { ret->negotiate = proxy_telnet_negotiate; proxy_type = "Telnet"; } else { ret->error = "Proxy error: Unknown proxy method"; return &ret->sock; } { char *logmsg = dupprintf("Will use %s proxy at %s:%d to connect" " to %s:%d", proxy_type, conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_proxy_port), hostname, port); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } { char *logmsg = dns_log_msg(conf_get_str(conf, CONF_proxy_host), conf_get_int(conf, CONF_addressfamily), "proxy"); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* look-up proxy */ proxy_addr = sk_namelookup(conf_get_str(conf, CONF_proxy_host), &proxy_canonical_name, conf_get_int(conf, CONF_addressfamily)); if (sk_addr_error(proxy_addr) != NULL) { ret->error = "Proxy error: Unable to resolve proxy host name"; sk_addr_free(proxy_addr); return &ret->sock; } sfree(proxy_canonical_name); { char addrbuf[256], *logmsg; sk_getaddr(proxy_addr, addrbuf, lenof(addrbuf)); logmsg = dupprintf("Connecting to %s proxy at %s port %d", proxy_type, addrbuf, conf_get_int(conf, CONF_proxy_port)); plug_log(plug, 2, NULL, 0, logmsg, 0); sfree(logmsg); } /* create the actual socket we will be using, * connected to our proxy server and port. */ ret->sub_socket = sk_new(proxy_addr, conf_get_int(conf, CONF_proxy_port), privport, oobinline, nodelay, keepalive, &ret->plugimpl); if (sk_socket_error(ret->sub_socket) != NULL) return &ret->sock; /* start the proxy negotiation process... */ sk_set_frozen(ret->sub_socket, 0); ret->negotiate(ret, PROXY_CHANGE_NEW); return &ret->sock; } /* no proxy, so just return the direct socket */ return sk_new(addr, port, privport, oobinline, nodelay, keepalive, plug); }