diff options
Diffstat (limited to 'sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch')
-rw-r--r-- | sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch b/sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch new file mode 100644 index 000000000000..256a16ffd5ba --- /dev/null +++ b/sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch @@ -0,0 +1,191 @@ +From fdd93b1e9545b66d1b3a2a1ec24d4c8613ee43fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= <mgorny@gentoo.org> +Date: Sat, 24 Jan 2015 23:59:21 +0100 +Subject: [PATCH] Support SOCKSv5 proxy + +Support using a SOCKSv5 proxy specified as DISTCC_SOCKS_PROXY. +The variable can either a hostname, a host:port pair or an absolute path +to a UNIX socket. When SOCKS is used, the hostname is passed to +the proxy and therefore the name resolution is done remotely. +--- + src/clinet.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 135 insertions(+), 2 deletions(-) + +diff --git a/src/clinet.c b/src/clinet.c +index 010a884..4773d8b 100644 +--- a/src/clinet.c ++++ b/src/clinet.c +@@ -31,6 +31,7 @@ + + #include <stdio.h> + #include <stdlib.h> ++#include <stddef.h> + #include <unistd.h> + #include <string.h> + #include <fcntl.h> +@@ -42,8 +43,10 @@ + #include <sys/types.h> + #include <sys/socket.h> + ++#include <arpa/inet.h> + #include <netinet/in.h> + #include <netinet/tcp.h> ++#include <sys/un.h> + + #include <netdb.h> + +@@ -161,7 +164,7 @@ out_failed: + /** + * Open a socket to a tcp remote host with the specified port. + **/ +-int dcc_connect_by_name(const char *host, int port, int *p_fd) ++static int dcc_connect_by_name_real(const char *host, int port, int *p_fd) + { + struct addrinfo hints; + struct addrinfo *res; +@@ -201,7 +204,7 @@ int dcc_connect_by_name(const char *host, int port, int *p_fd) + * + * @todo Don't try for too long to connect. + **/ +-int dcc_connect_by_name(const char *host, int port, int *p_fd) ++static int dcc_connect_by_name_real(const char *host, int port, int *p_fd) + { + struct sockaddr_in sock_out; + struct hostent *hp; +@@ -224,3 +227,133 @@ int dcc_connect_by_name(const char *host, int port, int *p_fd) + } + + #endif /* not ENABLE_RFC2553 */ ++ ++static int dcc_connect_via_socks5(const char *host, int port, int *p_fd, const char *proxy) ++{ ++ int ret; ++ char *proxy_host, *proxy_it; ++ int proxy_port; ++ char buf[262]; ++ int host_length; ++ struct sockaddr_in addr_buf; ++ int skip_bytes; ++ ++ host_length = strlen(host); ++ if (host_length > 255) { ++ rs_log_error("hostname \"%s\" too long for SOCKSv5 (over 255 chars)", host); ++ return EXIT_CONNECT_FAILED; ++ } ++ ++ if (proxy[0] == '/') { /* UNIX socket */ ++ struct sockaddr_un unix_addr; ++ ++ if (strlen(proxy) >= sizeof(unix_addr.sun_path)) ++ { ++ rs_log_error("UNIX socket path \"%s\" too long", proxy); ++ return EXIT_CONNECT_FAILED; ++ } ++ ++ unix_addr.sun_family = AF_UNIX; ++ strcpy(unix_addr.sun_path, proxy); ++ ++ ret = dcc_connect_by_addr((struct sockaddr *) &unix_addr, ++ offsetof(struct sockaddr_un, sun_path) + strlen(proxy) + 1, ++ p_fd); ++ ++ } else { /* hostname? IP address? */ ++ proxy_host = strdup(proxy); ++ if (proxy_host == NULL) return EXIT_OUT_OF_MEMORY; ++ ++ proxy_it = strrchr(proxy_host, ':'); ++ if (proxy_it) { ++ *(proxy_it++) = 0; ++ proxy_port = atoi(proxy_it); ++ ++ if (proxy_port <= 0) { ++ rs_log_error("invalid proxy port \"%s\"", proxy_it); ++ free(proxy_host); ++ return EXIT_CONNECT_FAILED; ++ } ++ } ++ else ++ proxy_port = 1080; ++ ++ ret = dcc_connect_by_name_real(proxy_host, proxy_port, p_fd); ++ free(proxy_host); ++ } ++ ++ if (ret != 0) ++ return ret; ++ ++ /* connected to proxy, now identifier/method selection */ ++ buf[0] = 0x05; /* SOCKSv5 */ ++ buf[1] = 0x01; /* one method */ ++ buf[2] = 0x00; /* NO AUTHENTICATION REQUIRED */ ++ ret = dcc_writex(*p_fd, buf, 3); ++ if (ret != 0) ++ return ret; ++ ++ /* wait for method selection */ ++ ret = dcc_readx(*p_fd, buf, 2); ++ if (ret != 0) ++ return ret; ++ if (buf[0] != 0x05 || buf[1] != 0x00) { /* version, method */ ++ rs_log_error("invalid proxy reply (version 0x%02x, method 0x%02x)", ++ buf[0], buf[1]); ++ return EXIT_CONNECT_FAILED; ++ } ++ ++ /* send connect request */ ++ buf[0] = 0x05; /* SOCKSv5 */ ++ buf[1] = 0x01; /* CONNECT command */ ++ buf[2] = 0x00; /* reserved */ ++ buf[3] = 0x03; /* DOMAINNAME address type */ ++ buf[4] = host_length; ++ memcpy(&buf[5], host, host_length); ++ addr_buf.sin_port = htons(port); ++ memcpy(&buf[5 + host_length], &addr_buf.sin_port, 2); ++ ret = dcc_writex(*p_fd, buf, 7 + host_length); ++ if (ret != 0) ++ return ret; ++ ++ /* wait for the connection */ ++ /* read first 4 bytes of reply + 2 extra bytes we know will be there */ ++ ret = dcc_readx(*p_fd, buf, 6); ++ if (ret != 0) ++ return ret; ++ if (buf[0] != 0x05 || buf[2] != 0x00) { /* version, reserved */ ++ rs_log_error("invalid proxy reply (version 0x%02x, reserved 0x%02x)", ++ buf[0], buf[2]); ++ return EXIT_CONNECT_FAILED; ++ } ++ if (buf[1] != 0x00) { /* reply */ ++ rs_log_error("proxy connection failed, reason=0x%02x", buf[1]); ++ return EXIT_CONNECT_FAILED; ++ } ++ ++ /* now read the remaining (packet size - 6) bytes */ ++ switch (buf[3]) { /* address type */ ++ case 0x01: skip_bytes = 4; break; /* IPv4 */ ++ case 0x03: skip_bytes = buf[4] + 1; break; /* hostname with length field */ ++ case 0x04: skip_bytes = 16; break; /* IPv6 */ ++ default: ++ rs_log_error("invalid proxy reply (address type 0x%02x)", buf[3]); ++ return EXIT_CONNECT_FAILED; ++ } ++ ret = dcc_readx(*p_fd, buf, skip_bytes); ++ if (ret != 0) ++ return ret; ++ ++ return 0; ++} ++ ++int dcc_connect_by_name(const char *host, int port, int *p_fd) ++{ ++ const char *proxy; ++ ++ proxy = getenv("DISTCC_SOCKS_PROXY"); ++ if (proxy) ++ return dcc_connect_via_socks5(host, port, p_fd, proxy); ++ else ++ return dcc_connect_by_name_real(host, port, p_fd); ++} +-- +2.3.0 + |