Gentoo Archives: gentoo-commits

From: "Michal Gorny (mgorny)" <mgorny@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in sys-devel/distcc/files: distcc-3.2_rc1-socks5.patch
Date: Fri, 27 Feb 2015 21:14:26
Message-Id: 20150227211421.4F21112B07@oystercatcher.gentoo.org
1 mgorny 15/02/27 21:14:21
2
3 Added: distcc-3.2_rc1-socks5.patch
4 Log:
5 Add support for SOCKSv5 proxy, bug #537616. Needed for network-sandbox support in Portage.
6
7 (Portage version: 2.2.17/cvs/Linux x86_64, signed Manifest commit with key EFB4464E!)
8
9 Revision Changes Path
10 1.1 sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch
11
12 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch?rev=1.1&view=markup
13 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
14
15 Index: distcc-3.2_rc1-socks5.patch
16 ===================================================================
17 From fdd93b1e9545b66d1b3a2a1ec24d4c8613ee43fb Mon Sep 17 00:00:00 2001
18 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= <mgorny@g.o>
19 Date: Sat, 24 Jan 2015 23:59:21 +0100
20 Subject: [PATCH] Support SOCKSv5 proxy
21
22 Support using a SOCKSv5 proxy specified as DISTCC_SOCKS_PROXY.
23 The variable can either a hostname, a host:port pair or an absolute path
24 to a UNIX socket. When SOCKS is used, the hostname is passed to
25 the proxy and therefore the name resolution is done remotely.
26 ---
27 src/clinet.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
28 1 file changed, 135 insertions(+), 2 deletions(-)
29
30 diff --git a/src/clinet.c b/src/clinet.c
31 index 010a884..4773d8b 100644
32 --- a/src/clinet.c
33 +++ b/src/clinet.c
34 @@ -31,6 +31,7 @@
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 +#include <stddef.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <fcntl.h>
42 @@ -42,8 +43,10 @@
43 #include <sys/types.h>
44 #include <sys/socket.h>
45
46 +#include <arpa/inet.h>
47 #include <netinet/in.h>
48 #include <netinet/tcp.h>
49 +#include <sys/un.h>
50
51 #include <netdb.h>
52
53 @@ -161,7 +164,7 @@ out_failed:
54 /**
55 * Open a socket to a tcp remote host with the specified port.
56 **/
57 -int dcc_connect_by_name(const char *host, int port, int *p_fd)
58 +static int dcc_connect_by_name_real(const char *host, int port, int *p_fd)
59 {
60 struct addrinfo hints;
61 struct addrinfo *res;
62 @@ -201,7 +204,7 @@ int dcc_connect_by_name(const char *host, int port, int *p_fd)
63 *
64 * @todo Don't try for too long to connect.
65 **/
66 -int dcc_connect_by_name(const char *host, int port, int *p_fd)
67 +static int dcc_connect_by_name_real(const char *host, int port, int *p_fd)
68 {
69 struct sockaddr_in sock_out;
70 struct hostent *hp;
71 @@ -224,3 +227,133 @@ int dcc_connect_by_name(const char *host, int port, int *p_fd)
72 }
73
74 #endif /* not ENABLE_RFC2553 */
75 +
76 +static int dcc_connect_via_socks5(const char *host, int port, int *p_fd, const char *proxy)
77 +{
78 + int ret;
79 + char *proxy_host, *proxy_it;
80 + int proxy_port;
81 + char buf[262];
82 + int host_length;
83 + struct sockaddr_in addr_buf;
84 + int skip_bytes;
85 +
86 + host_length = strlen(host);
87 + if (host_length > 255) {
88 + rs_log_error("hostname \"%s\" too long for SOCKSv5 (over 255 chars)", host);
89 + return EXIT_CONNECT_FAILED;
90 + }
91 +
92 + if (proxy[0] == '/') { /* UNIX socket */
93 + struct sockaddr_un unix_addr;
94 +
95 + if (strlen(proxy) >= sizeof(unix_addr.sun_path))
96 + {
97 + rs_log_error("UNIX socket path \"%s\" too long", proxy);
98 + return EXIT_CONNECT_FAILED;
99 + }
100 +
101 + unix_addr.sun_family = AF_UNIX;
102 + strcpy(unix_addr.sun_path, proxy);
103 +
104 + ret = dcc_connect_by_addr((struct sockaddr *) &unix_addr,
105 + offsetof(struct sockaddr_un, sun_path) + strlen(proxy) + 1,
106 + p_fd);
107 +
108 + } else { /* hostname? IP address? */
109 + proxy_host = strdup(proxy);
110 + if (proxy_host == NULL) return EXIT_OUT_OF_MEMORY;
111 +
112 + proxy_it = strrchr(proxy_host, ':');
113 + if (proxy_it) {
114 + *(proxy_it++) = 0;
115 + proxy_port = atoi(proxy_it);
116 +
117 + if (proxy_port <= 0) {
118 + rs_log_error("invalid proxy port \"%s\"", proxy_it);
119 + free(proxy_host);
120 + return EXIT_CONNECT_FAILED;
121 + }
122 + }
123 + else
124 + proxy_port = 1080;
125 +
126 + ret = dcc_connect_by_name_real(proxy_host, proxy_port, p_fd);
127 + free(proxy_host);
128 + }
129 +
130 + if (ret != 0)
131 + return ret;
132 +
133 + /* connected to proxy, now identifier/method selection */
134 + buf[0] = 0x05; /* SOCKSv5 */
135 + buf[1] = 0x01; /* one method */
136 + buf[2] = 0x00; /* NO AUTHENTICATION REQUIRED */
137 + ret = dcc_writex(*p_fd, buf, 3);
138 + if (ret != 0)
139 + return ret;
140 +
141 + /* wait for method selection */
142 + ret = dcc_readx(*p_fd, buf, 2);
143 + if (ret != 0)
144 + return ret;
145 + if (buf[0] != 0x05 || buf[1] != 0x00) { /* version, method */
146 + rs_log_error("invalid proxy reply (version 0x%02x, method 0x%02x)",
147 + buf[0], buf[1]);
148 + return EXIT_CONNECT_FAILED;
149 + }
150 +
151 + /* send connect request */
152 + buf[0] = 0x05; /* SOCKSv5 */
153 + buf[1] = 0x01; /* CONNECT command */
154 + buf[2] = 0x00; /* reserved */
155 + buf[3] = 0x03; /* DOMAINNAME address type */
156 + buf[4] = host_length;
157 + memcpy(&buf[5], host, host_length);
158 + addr_buf.sin_port = htons(port);
159 + memcpy(&buf[5 + host_length], &addr_buf.sin_port, 2);
160 + ret = dcc_writex(*p_fd, buf, 7 + host_length);
161 + if (ret != 0)
162 + return ret;
163 +
164 + /* wait for the connection */
165 + /* read first 4 bytes of reply + 2 extra bytes we know will be there */
166 + ret = dcc_readx(*p_fd, buf, 6);
167 + if (ret != 0)
168 + return ret;
169 + if (buf[0] != 0x05 || buf[2] != 0x00) { /* version, reserved */
170 + rs_log_error("invalid proxy reply (version 0x%02x, reserved 0x%02x)",
171 + buf[0], buf[2]);
172 + return EXIT_CONNECT_FAILED;
173 + }
174 + if (buf[1] != 0x00) { /* reply */
175 + rs_log_error("proxy connection failed, reason=0x%02x", buf[1]);
176 + return EXIT_CONNECT_FAILED;
177 + }
178 +
179 + /* now read the remaining (packet size - 6) bytes */
180 + switch (buf[3]) { /* address type */
181 + case 0x01: skip_bytes = 4; break; /* IPv4 */
182 + case 0x03: skip_bytes = buf[4] + 1; break; /* hostname with length field */
183 + case 0x04: skip_bytes = 16; break; /* IPv6 */
184 + default:
185 + rs_log_error("invalid proxy reply (address type 0x%02x)", buf[3]);
186 + return EXIT_CONNECT_FAILED;
187 + }
188 + ret = dcc_readx(*p_fd, buf, skip_bytes);
189 + if (ret != 0)
190 + return ret;
191 +
192 + return 0;
193 +}
194 +
195 +int dcc_connect_by_name(const char *host, int port, int *p_fd)
196 +{
197 + const char *proxy;
198 +
199 + proxy = getenv("DISTCC_SOCKS_PROXY");
200 + if (proxy)
201 + return dcc_connect_via_socks5(host, port, p_fd, proxy);
202 + else
203 + return dcc_connect_by_name_real(host, port, p_fd);
204 +}
205 --
206 2.3.0