public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] gentoo-x86 commit in sys-devel/distcc/files: distcc-3.2_rc1-socks5.patch
@ 2015-02-27 21:14 Michal Gorny (mgorny)
  0 siblings, 0 replies; only message in thread
From: Michal Gorny (mgorny) @ 2015-02-27 21:14 UTC (permalink / raw
  To: gentoo-commits

mgorny      15/02/27 21:14:21

  Added:                distcc-3.2_rc1-socks5.patch
  Log:
  Add support for SOCKSv5 proxy, bug #537616. Needed for network-sandbox support in Portage.
  
  (Portage version: 2.2.17/cvs/Linux x86_64, signed Manifest commit with key EFB4464E!)

Revision  Changes    Path
1.1                  sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch

file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch?rev=1.1&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch?rev=1.1&content-type=text/plain

Index: distcc-3.2_rc1-socks5.patch
===================================================================
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






^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2015-02-27 21:14 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-27 21:14 [gentoo-commits] gentoo-x86 commit in sys-devel/distcc/files: distcc-3.2_rc1-socks5.patch Michal Gorny (mgorny)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox